4 Commits

Author SHA1 Message Date
410571a802 Update version number to 2.4.0 2025-04-14 11:58:44 -06:00
2dfe5ae78a Update build 2025-04-14 11:47:23 -06:00
d3e1f2896a Prep for release 2025-04-14 11:45:51 -06:00
d88e50df38 Prep Plugin for release on WordPress.org (#23)
* Update translation text domain
* Escape everything that should be escaped.
* Add nonce checks where needed.
* Sanitize all inputs.
* Apply Code style changes across the codebase.
* Correct many deprecation notices.
* Optimize load order of many filters.
* Add Proper Build script
* Use emojii flags
* Fix i18n deprecation  notice for translating too early
* Put all scripts in footer and load async
2025-04-14 11:36:46 -06:00
44 changed files with 521 additions and 425 deletions

View File

@ -2,7 +2,7 @@
"name": "devstone/wp-multisite-waas",
"url": "https://wpmultisitewaas.org",
"description": "The WordPress Multisite Website as a Service (WaaS) plugin.",
"version": "2.3.3",
"version": "2.4.0",
"authors": [
{
"name": "Arindo Duque",
@ -93,7 +93,11 @@
"build.sh",
"package.json",
"package-lock.json",
"setuptest.sh"
"setuptest.sh",
"utils",
"update.sh",
"phpstan.neon.dist",
"rector.php"
]
},
"extra": {

View File

@ -59,7 +59,10 @@ class Scripts {
* }
* @return void
*/
public function register_script($handle, $src, $deps = [], $args = ['async' => true, 'in_footer' => true]): void {
public function register_script($handle, $src, $deps = [], $args = [
'async' => true,
'in_footer' => true,
]): void {
wp_register_script($handle, $src, $deps, wu_get_version(), $args);
}

View File

@ -115,6 +115,7 @@ class Sunrise {
require_once __DIR__ . '/functions/array-helpers.php';
require_once __DIR__ . '/traits/trait-singleton.php';
require_once __DIR__ . '/objects/class-limitations.php';
require_once __DIR__ . '/models/interface-limitable.php';
require_once __DIR__ . '/models/traits/trait-limitable.php';
require_once __DIR__ . '/models/traits/trait-notable.php';
require_once __DIR__ . '/models/traits/trait-billable.php';
@ -138,6 +139,7 @@ class Sunrise {
require_once __DIR__ . '/limits/class-theme-limits.php';
require_once __DIR__ . '/limits/class-theme-limits.php';
require_once __DIR__ . '/models/class-membership.php';
}
/**

View File

@ -29,7 +29,7 @@ final class WP_Ultimo {
* @since 2.1.0
* @var string
*/
const VERSION = '2.3.4';
const VERSION = '2.4.0';
/**
* Version of the Plugin.
@ -37,7 +37,7 @@ final class WP_Ultimo {
* @deprecated use the const version instead.
* @var string
*/
public $version = '2.3.4';
public $version = self::VERSION;
/**
* Tables registered by WP Multisite WaaS.

View File

@ -413,7 +413,7 @@ class WU_Multi_Network {
*/
public static function __callStatic($method_name, $args) {
_deprecated_function(self::class . "::$method_name()", '2.0.0');
_deprecated_function(self::class . esc_html("::$method_name()"), '2.0.0');
return false;
}
@ -710,21 +710,21 @@ class WU_Site extends \WP_Ultimo\Models\Site {
*
* @since 2.0.0
*
* @param mixed $object Object containing the parameters.
* @param mixed $object_model Object containing the parameters.
*/
public function __construct($object = null) {
public function __construct($object_model = null) {
_deprecated_function(self::class, '2.0.0', \WP_Ultimo\Models\Site::class);
_deprecated_function(self::class, '2.0.0', esc_html(\WP_Ultimo\Models\Site::class));
if (is_numeric($object)) {
$object = wu_get_site($object);
if (is_numeric($object_model)) {
$object_model = wu_get_site($object_model);
}
if ($object) {
$object = get_object_vars($object);
if ( $object_model) {
$object_model = get_object_vars($object_model);
}
parent::__construct($object);
parent::__construct($object_model);
}
}
@ -740,21 +740,21 @@ class WU_Site_Template extends \WP_Ultimo\Models\Site {
*
* @deprecated 2.0.0
*
* @param mixed $object Object containing the parameters.
* @param mixed $object_model Object containing the parameters.
*/
public function __construct($object = null) {
public function __construct($object_model = null) {
_deprecated_function(self::class, '2.0.0', \WP_Ultimo\Models\Site::class);
_deprecated_function(self::class, '2.0.0', esc_html(\WP_Ultimo\Models\Site::class));
if (is_numeric($object)) {
$object = wu_get_site($object);
if (is_numeric($object_model)) {
$object_model = wu_get_site($object_model);
}
if ($object) {
$object = get_object_vars($object);
if ( $object_model) {
$object_model = get_object_vars($object_model);
}
parent::__construct($object);
parent::__construct($object_model);
}
}
@ -843,22 +843,22 @@ class WU_Coupon extends \WP_Ultimo\Models\Discount_Code {
*
* @deprecated 2.0.0
*
* @param mixed $object Object containing the parameters.
* @param mixed $object_model Object containing the parameters.
*/
public function __construct($object = null) {
public function __construct($object_model = null) {
_deprecated_function(self::class, '2.0.0', \WP_Ultimo\Models\Discount_Code::class);
if (is_numeric($object)) {
$object = wu_get_discount_code($object);
if (is_numeric($object_model) ) {
$object_model = wu_get_discount_code($object_model);
}
if ($object) {
$object = get_object_vars($object);
if ( $object_model ) {
$object_model = get_object_vars($object_model);
}
if (is_array($object)) {
foreach ($object as $att => $value) {
if (is_array($object_model)) {
foreach ( $object_model as $att => $value) {
$this->{$att} = $value;
}
}
@ -898,29 +898,29 @@ class WU_Plan extends \WP_Ultimo\Models\Product {
*
* @deprecated 2.0.0
*
* @param mixed $object Object containing the parameters.
* @param mixed $object_model Object containing the parameters.
*/
public function __construct($object = null) {
public function __construct($object_model = null) {
_deprecated_function(self::class, '2.0.0', \WP_Ultimo\Models\Product::class);
_deprecated_function(self::class, '2.0.0', esc_html(\WP_Ultimo\Models\Product::class));
if (is_numeric($object)) {
$object = wu_get_product($object);
if (is_numeric($object_model)) {
$object_model = wu_get_product($object_model);
}
if ($object) {
$object = get_object_vars($object);
if ($object_model ) {
$object_model = get_object_vars($object_model);
}
if (is_array($object)) {
foreach ($object as $att => $value) {
if (is_array($object_model)) {
foreach ($object_model as $att => $value) {
$this->{$att} = $value;
}
}
$this->set_slug(uniqid());
parent::__construct($object);
parent::__construct($object_model);
}
/**
@ -973,21 +973,21 @@ class WU_Subscription extends \WP_Ultimo\Models\Membership {
*
* @deprecated 2.0.0
*
* @param mixed $object Object containing the parameters.
* @param mixed $object_model Object containing the parameters.
*/
public function __construct($object = null) {
public function __construct($object_model = null) {
_deprecated_function(self::class, '2.0.0', \WP_Ultimo\Models\Membership::class);
_deprecated_function(self::class, '2.0.0', esc_html(\WP_Ultimo\Models\Membership::class));
if (is_numeric($object)) {
$object = wu_get_membership($object);
if (is_numeric($object_model)) {
$object_model = wu_get_membership($object_model);
}
if ($object) {
$object = get_object_vars($object);
if ($object_model ) {
$object_model = get_object_vars($object_model);
}
parent::__construct($object);
parent::__construct($object_model);
}
/**

View File

@ -48,7 +48,6 @@ class Arr {
*
* @return mixed
* @since 2.0.11
*
*/
public static function filter_by_property($array_to_filter, $property, $expected_value, $flag = 0) {
@ -75,7 +74,6 @@ class Arr {
*
* @return array
* @since 2.0.11
*
*/
public static function filter($array_to_search, $closure) {
@ -99,13 +97,12 @@ class Arr {
*
* @param array $array_target The array to get the value from.
* @param string $key The array key to get. Supports dot notation.
* @param mixed $default The value to return ibn the case the key does not exist.
* @param mixed $default_value The value to return ibn the case the key does not exist.
*
* @return mixed
* @since 2.0.11
*
*/
public static function get($array_target, $key, $default = null) {
public static function get($array_target, $key, $default_value = null) {
if (is_null($key)) {
return $array_target;
@ -117,7 +114,7 @@ class Arr {
foreach (explode('.', $key) as $segment) {
if ( ! is_array($array_target) || ! array_key_exists($segment, $array_target)) {
return $default;
return $default_value;
}
$array_target = $array_target[ $segment ];
@ -135,7 +132,6 @@ class Arr {
*
* @return array
* @since 2.0.11
*
*/
public static function set(&$array_to_modify, $key, $value) {

View File

@ -10,7 +10,6 @@
namespace WP_Ultimo\Integrations\Host_Providers;
use Psr\Log\LogLevel;
use WP_Ultimo\Integrations\Host_Providers\Base_Host_Provider;
use WP_Ultimo\Integrations\Host_Providers\CPanel_API\CPanel_API;
// Exit if accessed directly
@ -85,7 +84,7 @@ class CPanel_Host_Provider extends Base_Host_Provider {
* Holds the API object.
*
* @since 2.0.0
* @var WP_Ultimo\Integrations\Host_Providers\CPanel_API\CPanel_API
* @var \WP_Ultimo\Integrations\Host_Providers\CPanel_API\CPanel_API
*/
protected $api = null;
@ -237,7 +236,7 @@ class CPanel_Host_Provider extends Base_Host_Provider {
* Load the CPanel API.
*
* @since 2.0.0
* @return WU_CPanel
* @return CPanel_API
*/
public function load_api() {
@ -293,17 +292,19 @@ class CPanel_Host_Provider extends Base_Host_Provider {
*
* @since 1.6.2
* @param object $results Results of the cPanel call.
* @return bool
* @return void
*/
public function log_calls($results) {
if (is_object($results->cpanelresult->data)) {
return wu_log_add('integration-cpanel', $results->cpanelresult->data->reason);
wu_log_add('integration-cpanel', $results->cpanelresult->data->reason);
return;
} elseif ( ! isset($results->cpanelresult->data[0])) {
return wu_log_add('integration-cpanel', __('Unexpected error ocurred trying to sync domains with CPanel', 'wp-multisite-waas'), LogLevel::ERROR);
wu_log_add('integration-cpanel', __('Unexpected error ocurred trying to sync domains with CPanel', 'wp-multisite-waas'), LogLevel::ERROR);
return;
}
return wu_log_add('integration-cpanel', $results->cpanelresult->data[0]->reason);
wu_log_add('integration-cpanel', $results->cpanelresult->data[0]->reason);
}
/**

View File

@ -250,33 +250,33 @@ class Payment_List_Table extends Base_List_Table {
'label' => __('All Payments', 'wp-multisite-waas'),
'count' => 0,
],
Payment_Status::COMPLETED() => [
Payment_Status::COMPLETED => [
'field' => 'status',
'url' => add_query_arg('status', Payment_Status::COMPLETED()),
'url' => add_query_arg('status', Payment_Status::COMPLETED),
'label' => __('Completed', 'wp-multisite-waas'),
'count' => 0,
],
Payment_Status::PENDING() => [
Payment_Status::PENDING => [
'field' => 'status',
'url' => add_query_arg('status', Payment_Status::PENDING()),
'url' => add_query_arg('status', Payment_Status::PENDING),
'label' => __('Pending', 'wp-multisite-waas'),
'count' => 0,
],
Payment_Status::PARTIAL_REFUND() => [
Payment_Status::PARTIAL_REFUND => [
'field' => 'status',
'url' => add_query_arg('status', Payment_Status::PARTIAL_REFUND()),
'url' => add_query_arg('status', Payment_Status::PARTIAL_REFUND),
'label' => __('Partially Refunded', 'wp-multisite-waas'),
'count' => 0,
],
Payment_Status::REFUND() => [
Payment_Status::REFUND => [
'field' => 'status',
'url' => add_query_arg('status', Payment_Status::REFUND()),
'url' => add_query_arg('status', Payment_Status::REFUND),
'label' => __('Refunded', 'wp-multisite-waas'),
'count' => 0,
],
Payment_Status::FAILED() => [
Payment_Status::FAILED => [
'field' => 'status',
'url' => add_query_arg('status', Payment_Status::FAILED()),
'url' => add_query_arg('status', Payment_Status::FAILED),
'label' => __('Failed', 'wp-multisite-waas'),
'count' => 0,
],

View File

@ -228,22 +228,22 @@ class Limitation_Manager {
*
* @since 2.0.0
*
* @param \WP_Ultimo\Models\Trait\Trait_Limitable $object Model to test.
* @param \WP_Ultimo\Models\Limitable $object_model Model to test.
* @return string
*/
public function get_object_type($object) {
public function get_object_type($object_model) {
$model = false;
if (is_a($object, \WP_Ultimo\Models\Site::class)) {
if (is_a($object_model, \WP_Ultimo\Models\Site::class)) {
$model = 'site';
} elseif (is_a($object, WP_Ultimo\Models\Membership::class)) {
} elseif (is_a($object_model, \WP_Ultimo\Models\Membership::class)) {
$model = 'membership';
} elseif (is_a($object, \WP_Ultimo\Models\Product::class)) {
} elseif (is_a($object_model, \WP_Ultimo\Models\Product::class)) {
$model = 'product';
}
return apply_filters('wu_limitations_get_object_type', $model);
return apply_filters('wu_limitations_get_object_type', $model, $object_model);
}
/**
@ -252,12 +252,12 @@ class Limitation_Manager {
* @since 2.0.0
*
* @param array $sections List of tabbed widget sections.
* @param \WP_Ultimo\Models\Trait\Trait_Limitable $object The model being edited.
* @param \WP_Ultimo\Models\Limitable $object_model The model being edited.
* @return array
*/
public function add_limitation_sections($sections, $object) {
public function add_limitation_sections($sections, $object_model) {
if ($this->get_object_type($object) === 'site' && $object->get_type() !== Site_Type::CUSTOMER_OWNED) {
if ( $this->get_object_type($object_model) === 'site' && $object_model->get_type() !== Site_Type::CUSTOMER_OWNED) {
$html = sprintf('<span class="wu--mt-4 wu-p-2 wu-bg-blue-100 wu-text-blue-600 wu-rounded wu-block">%s</span>', __('Limitations are only available for customer-owned sites. You need to change the type to Customer-owned and save this site before the options are shown.', 'wp-multisite-waas'));
$sections['sites'] = [
@ -275,15 +275,15 @@ class Limitation_Manager {
return $sections;
}
if ($this->get_object_type($object) !== 'site') {
if ( $this->get_object_type($object_model) !== 'site') {
$sections['sites'] = [
'title' => __('Sites', 'wp-multisite-waas'),
'desc' => __('Control limitations imposed to the number of sites allowed for memberships attached to this product.', 'wp-multisite-waas'),
'icon' => 'dashicons-wu-browser',
'fields' => $this->get_sites_fields($object),
'fields' => $this->get_sites_fields($object_model),
'v-show' => "get_state_value('product_type', 'none') !== 'service'",
'state' => [
'limit_sites' => $object->get_limitations()->sites->is_enabled(),
'limit_sites' => $object_model->get_limitations()->sites->is_enabled(),
],
];
}
@ -298,7 +298,7 @@ class Limitation_Manager {
'icon' => 'dashicons-wu-man',
'v-show' => "get_state_value('product_type', 'none') !== 'service'",
'state' => [
'limit_visits' => $object->get_limitations()->visits->is_enabled(),
'limit_visits' => $object_model->get_limitations()->visits->is_enabled(),
],
'fields' => [
'modules[visits][enabled]' => [
@ -313,8 +313,8 @@ class Limitation_Manager {
],
];
if ('product' !== $object->model) {
$sections['visits']['fields']['modules_visits_overwrite'] = $this->override_notice($object->get_limitations(false)->visits->has_own_enabled());
if ( 'product' !== $object_model->model) {
$sections['visits']['fields']['modules_visits_overwrite'] = $this->override_notice($object_model->get_limitations(false)->visits->has_own_enabled());
}
$sections['visits']['fields']['modules[visits][limit]'] = [
@ -322,7 +322,7 @@ class Limitation_Manager {
'title' => __('Unique Visits Quota', 'wp-multisite-waas'),
'desc' => __('Set a top limit for the number of monthly unique visits. Leave empty or 0 to allow for unlimited visits.', 'wp-multisite-waas'),
'placeholder' => __('e.g. 10000', 'wp-multisite-waas'),
'value' => $object->get_limitations()->visits->get_limit(),
'value' => $object_model->get_limitations()->visits->get_limit(),
'wrapper_html_attr' => [
'v-show' => 'limit_visits',
'v-cloak' => '1',
@ -332,20 +332,20 @@ class Limitation_Manager {
],
];
if ('product' !== $object->model) {
$sections['visits']['fields']['allowed_visits_overwrite'] = $this->override_notice($object->get_limitations(false)->visits->has_own_limit(), ['limit_visits']);
if ( 'product' !== $object_model->model) {
$sections['visits']['fields']['allowed_visits_overwrite'] = $this->override_notice($object_model->get_limitations(false)->visits->has_own_limit(), ['limit_visits']);
}
/*
* If this is a site edit screen, show the current values
* for visits and the reset date
*/
if ($this->get_object_type($object) === 'site') {
if ( $this->get_object_type($object_model) === 'site') {
$sections['visits']['fields']['visits_count'] = [
'type' => 'text-display',
'title' => __('Current Unique Visits Count this Month', 'wp-multisite-waas'),
'desc' => __('Current visits count for this particular site.', 'wp-multisite-waas'),
'display_value' => sprintf('%s visit(s)', $object->get_visits_count()),
'display_value' => sprintf('%s visit(s)', $object_model->get_visits_count()),
'wrapper_html_attr' => [
'v-show' => 'limit_visits',
'v-cloak' => '1',
@ -360,7 +360,7 @@ class Limitation_Manager {
'icon' => 'dashicons-wu-users',
'v-show' => "get_state_value('product_type', 'none') !== 'service'",
'state' => [
'limit_users' => $object->get_limitations()->users->is_enabled(),
'limit_users' => $object_model->get_limitations()->users->is_enabled(),
],
'fields' => [
'modules[users][enabled]' => [
@ -374,11 +374,11 @@ class Limitation_Manager {
],
];
if ('product' !== $object->model) {
$sections['users']['fields']['modules_user_overwrite'] = $this->override_notice($object->get_limitations(false)->users->has_own_enabled());
if ( 'product' !== $object_model->model) {
$sections['users']['fields']['modules_user_overwrite'] = $this->override_notice($object_model->get_limitations(false)->users->has_own_enabled());
}
$this->register_user_fields($sections, $object);
$this->register_user_fields($sections, $object_model);
$sections['post_types'] = [
'title' => __('Post Types', 'wp-multisite-waas'),
@ -386,7 +386,7 @@ class Limitation_Manager {
'icon' => 'dashicons-wu-book',
'v-show' => "get_state_value('product_type', 'none') !== 'service'",
'state' => [
'limit_post_types' => $object->get_limitations()->post_types->is_enabled(),
'limit_post_types' => $object_model->get_limitations()->post_types->is_enabled(),
],
'fields' => [
'modules[post_types][enabled]' => [
@ -401,8 +401,8 @@ class Limitation_Manager {
],
];
if ('product' !== $object->model) {
$sections['post_types']['fields']['post_quota_overwrite'] = $this->override_notice($object->get_limitations(false)->post_types->has_own_enabled());
if ( 'product' !== $object_model->model) {
$sections['post_types']['fields']['post_quota_overwrite'] = $this->override_notice($object_model->get_limitations(false)->post_types->has_own_enabled());
}
$sections['post_types']['post_quota_note'] = [
@ -414,7 +414,7 @@ class Limitation_Manager {
],
];
$this->register_post_type_fields($sections, $object);
$this->register_post_type_fields($sections, $object_model);
$sections['limit_disk_space'] = [
'title' => __('Disk Space', 'wp-multisite-waas'),
@ -422,7 +422,7 @@ class Limitation_Manager {
'icon' => 'dashicons-wu-drive',
'v-show' => "get_state_value('product_type', 'none') !== 'service'",
'state' => [
'limit_disk_space' => $object->get_limitations()->disk_space->is_enabled(),
'limit_disk_space' => $object_model->get_limitations()->disk_space->is_enabled(),
],
'fields' => [
'modules[disk_space][enabled]' => [
@ -437,8 +437,8 @@ class Limitation_Manager {
],
];
if ('product' !== $object->model) {
$sections['limit_disk_space']['fields']['disk_space_modules_overwrite'] = $this->override_notice($object->get_limitations(false)->disk_space->has_own_enabled());
if ( 'product' !== $object_model->model) {
$sections['limit_disk_space']['fields']['disk_space_modules_overwrite'] = $this->override_notice($object_model->get_limitations(false)->disk_space->has_own_enabled());
}
$sections['limit_disk_space']['fields']['modules[disk_space][limit]'] = [
@ -447,15 +447,15 @@ class Limitation_Manager {
'desc' => __('Set a limit in MBs for the disk space for <strong>each</strong> individual site.', 'wp-multisite-waas'),
'min' => 0,
'placeholder' => 100,
'value' => $object->get_limitations()->disk_space->get_limit(),
'value' => $object_model->get_limitations()->disk_space->get_limit(),
'wrapper_html_attr' => [
'v-show' => "get_state_value('product_type', 'none') !== 'service' && limit_disk_space",
'v-cloak' => '1',
],
];
if ('product' !== $object->model) {
$sections['limit_disk_space']['fields']['disk_space_override'] = $this->override_notice($object->get_limitations(false)->disk_space->has_own_limit(), ['limit_disk_space']);
if ( 'product' !== $object_model->model) {
$sections['limit_disk_space']['fields']['disk_space_override'] = $this->override_notice($object_model->get_limitations(false)->disk_space->has_own_limit(), ['limit_disk_space']);
}
$sections['custom_domain'] = [
@ -464,14 +464,14 @@ class Limitation_Manager {
'icon' => 'dashicons-wu-link1',
'v-show' => "get_state_value('product_type', 'none') !== 'service'",
'state' => [
'allow_domain_mapping' => $object->get_limitations()->domain_mapping->is_enabled(),
'allow_domain_mapping' => $object_model->get_limitations()->domain_mapping->is_enabled(),
],
'fields' => [
'modules[domain_mapping][enabled]' => [
'type' => 'toggle',
'title' => __('Allow Custom Domains', 'wp-multisite-waas'),
'desc' => __('Toggle this option on to allow this plan to enable custom domains for sign-ups on this plan.', 'wp-multisite-waas'),
'value' => $object->get_limitations()->domain_mapping->is_enabled(),
'value' => $object_model->get_limitations()->domain_mapping->is_enabled(),
'wrapper_html_attr' => [
'v-cloak' => '1',
],
@ -482,8 +482,8 @@ class Limitation_Manager {
],
];
if ('product' !== $object->model) {
$sections['custom_domain']['fields']['custom_domain_override'] = $this->override_notice($object->get_limitations(false)->domain_mapping->has_own_enabled(), ['allow_domain_mapping']);
if ( 'product' !== $object_model->model) {
$sections['custom_domain']['fields']['custom_domain_override'] = $this->override_notice($object_model->get_limitations(false)->domain_mapping->has_own_enabled(), ['allow_domain_mapping']);
}
$sections['allowed_themes'] = [
@ -499,7 +499,7 @@ class Limitation_Manager {
'type' => 'html',
'title' => __('Themes', 'wp-multisite-waas'),
'desc' => __('Select how the themes installed on the network should behave.', 'wp-multisite-waas'),
'content' => fn() => $this->get_theme_selection_list($object, $sections['allowed_themes']),
'content' => fn() => $this->get_theme_selection_list($object_model, $sections['allowed_themes']),
],
],
];
@ -514,7 +514,7 @@ class Limitation_Manager {
'type' => 'html',
'title' => __('Plugins', 'wp-multisite-waas'),
'desc' => __('Select how the plugins installed on the network should behave.', 'wp-multisite-waas'),
'content' => fn() => $this->get_plugin_selection_list($object),
'content' => fn() => $this->get_plugin_selection_list($object_model),
],
],
];
@ -522,8 +522,8 @@ class Limitation_Manager {
$reset_url = wu_get_form_url(
'confirm_limitations_reset',
[
'id' => $object->get_id(),
'model' => $object->model,
'id' => $object_model->get_id(),
'model' => $object_model->model,
]
);
@ -574,17 +574,17 @@ class Limitation_Manager {
* @since 2.0.0
*
* @param array $sections Sections and fields.
* @param \WP_Ultimo\Models\Trait\Trait_Limitable $object The object being edit.
* @param \WP_Ultimo\Models\Limitable $object_model The object being edit.
* @return void
*/
public function register_user_fields(&$sections, $object): void {
public function register_user_fields(&$sections, $object_model): void {
$user_roles = get_editable_roles();
$sections['users']['state']['roles'] = [];
foreach ($user_roles as $user_role_slug => $user_role) {
$sections['users']['state']['roles'][ $user_role_slug ] = $object->get_limitations()->users->{$user_role_slug};
$sections['users']['state']['roles'][ $user_role_slug ] = $object_model->get_limitations()->users->{$user_role_slug};
$sections['users']['fields'][ "control_{$user_role_slug}" ] = [
'type' => 'group',
@ -620,8 +620,8 @@ class Limitation_Manager {
/*
* Add override notice.
*/
if ('product' !== $object->model) {
$sections['users']['fields'][ "override_{$user_role_slug}" ] = $this->override_notice($object->get_limitations(false)->users->exists($user_role_slug), ['limit_users']);
if ('product' !== $object_model->model) {
$sections['users']['fields'][ "override_{$user_role_slug}" ] = $this->override_notice($object_model->get_limitations(false)->users->exists($user_role_slug), ['limit_users']);
}
}
}
@ -632,17 +632,17 @@ class Limitation_Manager {
* @since 2.0.0
*
* @param array $sections Sections and fields.
* @param \WP_Ultimo\Models\Trait\Trait_Limitable $object The object being edit.
* @param \WP_Ultimo\Models\Limitable $object_model The object being edit.
* @return void
*/
public function register_post_type_fields(&$sections, $object): void {
public function register_post_type_fields(&$sections, $object_model): void {
$post_types = get_post_types([], 'objects');
$sections['post_types']['state']['types'] = [];
foreach ($post_types as $post_type_slug => $post_type) {
$sections['post_types']['state']['types'][ $post_type_slug ] = $object->get_limitations()->post_types->{$post_type_slug};
$sections['post_types']['state']['types'][ $post_type_slug ] = $object_model->get_limitations()->post_types->{$post_type_slug};
$sections['post_types']['fields'][ "control_{$post_type_slug}" ] = [
'type' => 'group',
@ -678,9 +678,9 @@ class Limitation_Manager {
/*
* Add override notice.
*/
if ('product' !== $object->model) {
if ('product' !== $object_model->model) {
$sections['post_types']['fields'][ "override_{$post_type_slug}" ] = $this->override_notice(
$object->get_limitations(false)->post_types->exists($post_type_slug),
$object_model->get_limitations(false)->post_types->exists($post_type_slug),
[
'limit_post_types',
]
@ -694,25 +694,25 @@ class Limitation_Manager {
*
* @since 2.0.0
*
* @param \WP_Ultimo\Models\Trait\Trait_Limitable $object The model being edited.
* @param \WP_Ultimo\Models\Limitable $object_model The model being edited.
* @return array
*/
protected function get_sites_fields($object) {
protected function get_sites_fields($object_model) {
$fields = [
'modules[sites][enabled]' => [
'type' => 'toggle',
'title' => __('Limit Sites', 'wp-multisite-waas'),
'desc' => __('Enable site limitations for this product.', 'wp-multisite-waas'),
'value' => $object->get_limitations()->sites->is_enabled(),
'value' => $object_model->get_limitations()->sites->is_enabled(),
'html_attr' => [
'v-model' => 'limit_sites',
],
],
];
if ('product' !== $object->model) {
$fields['sites_overwrite'] = $this->override_notice($object->get_limitations(false)->sites->has_own_enabled());
if ('product' !== $object_model->model) {
$fields['sites_overwrite'] = $this->override_notice($object_model->get_limitations(false)->sites->has_own_enabled());
}
/*
@ -734,18 +734,18 @@ class Limitation_Manager {
'title' => __('Site Allowance', 'wp-multisite-waas'),
'desc' => __('This is the number of sites the customer will be able to create under this membership.', 'wp-multisite-waas'),
'placeholder' => 1,
'value' => $object->get_limitations()->sites->get_limit(),
'value' => $object_model->get_limitations()->sites->get_limit(),
'wrapper_html_attr' => [
'v-show' => "get_state_value('product_type', 'none') !== 'service' && limit_sites",
'v-cloak' => '1',
],
];
if ('product' !== $object->model) {
$fields['sites_overwrite_2'] = $this->override_notice($object->get_limitations(false)->sites->has_own_limit(), ["get_state_value('product_type', 'none') !== 'service' && limit_sites"]);
if ('product' !== $object_model->model) {
$fields['sites_overwrite_2'] = $this->override_notice($object_model->get_limitations(false)->sites->has_own_limit(), ["get_state_value('product_type', 'none') !== 'service' && limit_sites"]);
}
return apply_filters('wu_limitations_get_sites_fields', $fields, $object, $this);
return apply_filters('wu_limitations_get_sites_fields', $fields, $object_model, $this);
}
/**
@ -753,10 +753,10 @@ class Limitation_Manager {
*
* @since 2.0.0
*
* @param \WP_Ultimo\Models\Trait\Trait_Limitable $object The model being edited.
* @param \WP_Ultimo\Models\Limitable $object_model The model being edited.
* @return string
*/
public function get_plugin_selection_list($object) {
public function get_plugin_selection_list($object_model) {
$all_plugins = $this->get_all_plugins();
@ -764,7 +764,7 @@ class Limitation_Manager {
'limitations/plugin-selector',
[
'plugins' => $all_plugins,
'object' => $object,
'object' => $object_model,
]
);
}
@ -774,7 +774,7 @@ class Limitation_Manager {
*
* @since 2.0.0
*
* @param \WP_Ultimo\Models\Traits\Limitable $obj The model being edited.
* @param \WP_Ultimo\Models\Limitable $obj The model being edited.
* @param array $section The section array.
* @return string
*/

View File

@ -9,6 +9,8 @@
namespace WP_Ultimo\Models;
use stdClass;
use WP_Ultimo\Database\Engine\Schema;
use WP_Ultimo\Helpers\Hash;
// Exit if accessed directly
@ -132,22 +134,21 @@ abstract class Base_Model implements \JsonSerializable {
* Constructs the object via the constructor arguments
*
* @since 2.0.0
*
* @param mixed $object Std object with model parameters.
* @param mixed $object_model Std object with model parameters.
*/
public function __construct($object = null) {
public function __construct($object_model = null) {
$this->model = sanitize_key((new \ReflectionClass($this))->getShortName());
if (is_array($object)) {
$object = (object) $object;
if (is_array($object_model)) {
$object_model = (object) $object_model;
}
if ( ! is_object($object)) {
if ( ! is_object($object_model)) {
return;
}
$this->setup_model($object);
$this->setup_model($object_model);
}
/**
@ -182,7 +183,7 @@ abstract class Base_Model implements \JsonSerializable {
$value = call_user_func([$this, "get_{$field}"]);
if ( ! is_numeric($value)) {
_doing_it_wrong(__METHOD__, __('You can only use numeric fields to generate hashes.', 'wp-multisite-waas'), '2.0.0');
_doing_it_wrong(__METHOD__, esc_html__('You can only use numeric fields to generate hashes.', 'wp-multisite-waas'), '2.0.0');
return false;
}
@ -193,19 +194,18 @@ abstract class Base_Model implements \JsonSerializable {
/**
* Setup properties.
*
* @param object $object Row from the database.
* @param object $object_model Row from the database.
*
* @access private
* @since 2.0.0
* @return bool
*/
private function setup_model($object) {
private function setup_model($object_model) {
if ( ! is_object($object)) {
if ( ! is_object($object_model)) {
return false;
}
$vars = get_object_vars($object);
$vars = get_object_vars($object_model);
$this->attributes($vars);
return ! empty($this->id);
@ -256,6 +256,7 @@ abstract class Base_Model implements \JsonSerializable {
*
* @since 2.0.0
* @return Schema
* @throws \ReflectionException
*/
public static function get_schema() {
@ -696,14 +697,14 @@ abstract class Base_Model implements \JsonSerializable {
* @since 2.0.0
*
* @param string $key The meta key.
* @param mixed $default The default value to be passed.
* @param mixed $default_value The default value to be passed.
* @param bool $single To return single values or not.
* @return mixed
*/
public function get_meta($key, $default = false, $single = true) {
public function get_meta($key, $default_value = false, $single = true) {
if ( ! $this->is_meta_available()) {
return $default;
return $default_value;
}
$meta_type = $this->get_meta_type_name();
@ -712,7 +713,7 @@ abstract class Base_Model implements \JsonSerializable {
return get_metadata($meta_type, $this->get_id(), $key, $single);
}
return $default;
return $default_value;
}
/**
@ -730,7 +731,7 @@ abstract class Base_Model implements \JsonSerializable {
}
if ( ! is_array($meta)) {
_doing_it_wrong(__METHOD__, __('This method expects an array as argument.', 'wp-multisite-waas'), '2.0.0');
_doing_it_wrong(__METHOD__, esc_html__('This method expects an array as argument.', 'wp-multisite-waas'), '2.0.0');
return false;
}
@ -838,7 +839,7 @@ abstract class Base_Model implements \JsonSerializable {
* Allows use as a callback, such as in `array_map`
*
* @param stdClass $data Raw mapping data.
* @return Mapping
* @return Base_model
*/
protected static function to_instance($data) {
@ -1038,7 +1039,7 @@ abstract class Base_Model implements \JsonSerializable {
* Creates a copy of the given model adn resets it's id to a 'new' state.
*
* @since 2.0.0
* @return \WP_Ultimo\Model\Base_Model
* @return Base_Model
*/
public function duplicate() {

View File

@ -82,17 +82,17 @@ class Broadcast extends Post_Base_Model {
*
* @since 2.0.7
*
* @param mixed $object Std object with model parameters.
* @param mixed $object_model Std object with model parameters.
*/
public function __construct($object = null) {
public function __construct($object_model = null) {
$object = (array) $object;
$object_model = (array) $object_model;
if ( ! wu_get_isset($object, 'migrated_from_id')) {
unset($object['migrated_from_id']);
if ( ! wu_get_isset($object_model, 'migrated_from_id')) {
unset($object_model['migrated_from_id']);
}
parent::__construct($object);
parent::__construct($object_model);
}
/**

View File

@ -317,11 +317,11 @@ class Membership extends Base_Model {
*
* @since 2.0.0
*
* @param object $object Std object with model parameters.
* @param object $object_model Std object with model parameters.
*/
public function __construct($object = null) {
public function __construct($object_model = null) {
parent::__construct($object);
parent::__construct($object_model);
$this->_gateway_info = [
'gateway' => $this->get_gateway(),

View File

@ -23,7 +23,7 @@ defined('ABSPATH') || exit;
*
* @since 2.0.0
*/
class Site extends Base_Model {
class Site extends Base_Model implements Limitable {
use Traits\Limitable;
use \WP_Ultimo\Traits\WP_Ultimo_Site_Deprecated;
@ -1255,14 +1255,14 @@ class Site extends Base_Model {
*
* @since 2.0.0
*
* @param mixed $object Object containing the parameters.
* @param mixed $object_model Object containing the parameters.
*/
public function __construct($object = null) {
public function __construct($object_model = null) {
parent::__construct($object);
parent::__construct($object_model);
if (is_array($object)) {
$object = (object) $object;
if (is_array($object_model)) {
$object_model = (object) $object_model;
}
$details = get_blog_details($this->get_blog_id());
@ -1274,11 +1274,11 @@ class Site extends Base_Model {
/*
* Quick fix for WP CLI, since it uses the --path arg to do other things.
*/
if ( ! $this->path && is_object($object) && isset($object->site_path)) {
$this->path = $object->site_path;
if ( ! $this->path && is_object($object_model) && isset($object_model->site_path)) {
$this->path = $object_model->site_path;
}
$object = (object) $object;
$object_model = (object) $object_model;
}
/**

View File

@ -0,0 +1,99 @@
<?php
/**
* Limitable interface.
*
* @package WP_Ultimo
* @subpackage Models
*/
namespace WP_Ultimo\Models;
interface Limitable {
/**
* List of limitations that need to be merged.
*
* Every model that is limitable (imports this trait)
* needs to declare explicitly the limitations that need to be
* merged. This allows us to chain the merges, and gives us
* a final list of limitations at the end of the process.
*
* @since 2.0.0
* @return array
*/
public function limitations_to_merge();
/**
* Returns the limitations of this particular blog.
*
* @since 2.0.0
*
* @param bool $waterfall If we should construct the limitations object recursively.
* @param bool $skip_self If we should skip the current limitations.
* @return \WP_Ultimo\Objects\Limitations
*/
public function get_limitations($waterfall = true, $skip_self = false);
/**
* Checks if this site has limitations or not.
*
* @since 2.0.0
* @return boolean
*/
public function has_limitations();
/**
* Checks if a particular module is being limited.
*
* @since 2.0.0
*
* @param string $module Module to check.
* @return boolean
*/
public function has_module_limitation($module);
/**
* Returns all user role quotas.
*
* @since 2.0.0
* @return array
*/
public function get_user_role_quotas();
/**
* Proxy method to retrieve the allowed user roles.
*
* @since 2.0.0
* @return array
*/
public function get_allowed_user_roles();
/**
* Schedules plugins to be activated or deactivated based on the current limitations;
*
* @since 2.0.5
* @return void
*/
public function sync_plugins(): void;
/**
* Makes sure we save limitations when we are supposed to.
*
* This is called on the handle_save method of the inc/admin-pages/class-edit-admin-page.php
* for all models that have the trait Limitable.
*
* @see inc/admin-pages/class-edit-admin-page.php
*
* @since 2.0.0
* @return void
*/
public function handle_limitations(): void;
/**
* Returns the list of product slugs associated with this model.
*
* @since 2.0.0
* @return array
*/
public function get_applicable_product_slugs();
}

View File

@ -26,26 +26,12 @@ trait Limitable {
protected $_limitations = [];
/**
* List of limitations that need to be merged.
*
* Every model that is limitable (imports this trait)
* needs to declare explicitly the limitations that need to be
* merged. This allows us to chain the merges, and gives us
* a final list of limitations at the end of the process.
*
* @since 2.0.0
* @return array
* @inheritDoc
*/
abstract public function limitations_to_merge();
/**
* Returns the limitations of this particular blog.
*
* @since 2.0.0
*
* @param bool $waterfall If we should construct the limitations object recursively.
* @param bool $skip_self If we should skip the current limitations.
* @return \WP_Ultimo\Objects\Limitations
* @inheritdoc
*/
public function get_limitations($waterfall = true, $skip_self = false) {
@ -104,10 +90,7 @@ trait Limitable {
}
/**
* Checks if this site has limitations or not.
*
* @since 2.0.0
* @return boolean
* @inheritdoc
*/
public function has_limitations() {
@ -191,15 +174,7 @@ trait Limitable {
}
/**
* Makes sure we save limitations when we are supposed to.
*
* This is called on the handle_save method of the inc/admin-pages/class-edit-admin-page.php
* for all models that have the trait Limitable.
*
* @see inc/admin-pages/class-edit-admin-page.php
*
* @since 2.0.0
* @return void
* @inheritdoc
*/
public function handle_limitations(): void {
/*
@ -247,7 +222,7 @@ trait Limitable {
* Set the new permissions, based on the diff.
*/
$limitations = wu_array_recursive_diff($modules_to_save, $current_limitations->to_array());
} elseif ('product' === $this->model && $this->get_type() !== 'plan') {
} elseif ($this->get_type() !== 'plan') {
$limitations = wu_array_recursive_diff($modules_to_save, Limitations::get_empty()->to_array());
} else {
$limitations = $modules_to_save;
@ -257,10 +232,7 @@ trait Limitable {
}
/**
* Returns the list of product slugs associated with this model.
*
* @since 2.0.0
* @return array
* @inheritdoc
*/
public function get_applicable_product_slugs() {

View File

@ -30,7 +30,7 @@ class Limitations {
* @since 2.0.0
* @var array
*/
static $limitations_cache = [];
private static $limitations_cache = [];
/**
* Version of the limitation schema.

View File

@ -19,16 +19,16 @@ trait Singleton {
*
* @var object
*/
public static $instance;
public static object $instance;
/**
* Returns the instance of WP_Ultimo
*
* @return object
*/
public static function get_instance() {
public static function get_instance(): object {
if ( ! static::$instance instanceof static) {
if ( ! isset(static::$instance) || ! static::$instance instanceof static) {
static::$instance = new static();
static::$instance->init();
@ -54,7 +54,7 @@ trait Singleton {
* @since 2.0.11
* @return boolean
*/
public function has_parents() {
public function has_parents(): bool {
return (bool) class_parents($this);
}

View File

@ -9,7 +9,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: 2025-04-07T17:38:26+00:00\n"
"POT-Creation-Date: 2025-04-14T17:47:37+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.11.0\n"
"X-Domain: wp-multisite-waas\n"
@ -1241,7 +1241,7 @@ msgstr ""
#: inc/models/class-payment.php:557
#: views/admin-pages/fields/field-text-display.php:43
#: views/admin-pages/fields/field-text-edit.php:47
#: views/base/customers/grid-item.php:118
#: views/base/customers/grid-item.php:130
msgid "None"
msgstr ""
@ -4357,12 +4357,12 @@ msgid "Activated"
msgstr ""
#: inc/admin-pages/class-setup-wizard-admin-page.php:853
#: inc/class-scripts.php:177
#: inc/class-scripts.php:180
msgid "Select an Image."
msgstr ""
#: inc/admin-pages/class-setup-wizard-admin-page.php:854
#: inc/class-scripts.php:178
#: inc/class-scripts.php:181
msgid "Use this image"
msgstr ""
@ -6345,7 +6345,7 @@ msgstr ""
#: inc/api/trait-rest-api.php:169
#: inc/api/trait-rest-api.php:242
#: inc/api/trait-rest-api.php:300
#: inc/models/class-base-model.php:610
#: inc/models/class-base-model.php:611
#: inc/models/class-site.php:1440
msgid "Item not found."
msgstr ""
@ -7684,16 +7684,16 @@ msgid "here"
msgstr ""
#. translators: the day/month/year date format used by WP Multisite WaaS. You can changed it to localize this date format to your language. the default value is d/m/Y, which is the format 31/12/2021.
#: inc/class-scripts.php:274
#: inc/class-scripts.php:277
msgid "d/m/Y"
msgstr ""
#: inc/class-scripts.php:284
#: inc/class-scripts.php:287
msgid "in %s"
msgstr ""
#. translators: %s a unit of time.
#: inc/class-scripts.php:285
#: inc/class-scripts.php:288
#: inc/functions/date.php:155
#: inc/list-tables/class-base-list-table.php:830
#: inc/list-tables/class-membership-list-table.php:209
@ -7702,59 +7702,59 @@ msgstr ""
msgid "%s ago"
msgstr ""
#: inc/class-scripts.php:286
#: inc/class-scripts.php:289
msgid "a few seconds"
msgstr ""
#: inc/class-scripts.php:287
#: inc/class-scripts.php:290
msgid "%d seconds"
msgstr ""
#: inc/class-scripts.php:288
#: inc/class-scripts.php:291
msgid "a minute"
msgstr ""
#: inc/class-scripts.php:289
#: inc/class-scripts.php:292
msgid "%d minutes"
msgstr ""
#: inc/class-scripts.php:290
#: inc/class-scripts.php:293
msgid "an hour"
msgstr ""
#: inc/class-scripts.php:291
#: inc/class-scripts.php:294
msgid "%d hours"
msgstr ""
#: inc/class-scripts.php:292
#: inc/class-scripts.php:295
msgid "a day"
msgstr ""
#: inc/class-scripts.php:293
#: inc/class-scripts.php:296
msgid "%d days"
msgstr ""
#: inc/class-scripts.php:294
#: inc/class-scripts.php:297
msgid "a week"
msgstr ""
#: inc/class-scripts.php:295
#: inc/class-scripts.php:298
msgid "%d weeks"
msgstr ""
#: inc/class-scripts.php:296
#: inc/class-scripts.php:299
msgid "a month"
msgstr ""
#: inc/class-scripts.php:297
#: inc/class-scripts.php:300
msgid "%d months"
msgstr ""
#: inc/class-scripts.php:298
#: inc/class-scripts.php:301
msgid "a year"
msgstr ""
#: inc/class-scripts.php:299
#: inc/class-scripts.php:302
msgid "%d years"
msgstr ""
@ -8418,11 +8418,11 @@ msgid "Remove all saved data for WP Multisite WaaS when the plugin is uninstalle
msgstr ""
#. translators: the placeholder is an error message
#: inc/class-sunrise.php:274
#: inc/class-sunrise.php:276
msgid "Sunrise copy failed: %s"
msgstr ""
#: inc/class-sunrise.php:277
#: inc/class-sunrise.php:279
msgid "Sunrise upgrade attempt succeeded."
msgstr ""
@ -14782,43 +14782,43 @@ msgstr ""
msgid "Focus on your business and avoid all the web hosting hassles. Our managed hosting guarantees unmatched performance, reliability and choice with 24/7 support that acts as your extended team, making Cloudways an ultimate choice for growing agencies and e-commerce businesses."
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:115
#: inc/integrations/host-providers/class-cpanel-host-provider.php:114
msgid "cPanel Username"
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:116
#: inc/integrations/host-providers/class-cpanel-host-provider.php:115
msgid "e.g. username"
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:120
#: inc/integrations/host-providers/class-cpanel-host-provider.php:119
msgid "cPanel Password"
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:121
#: inc/integrations/host-providers/class-cpanel-host-provider.php:120
msgid "password"
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:124
#: inc/integrations/host-providers/class-cpanel-host-provider.php:123
msgid "cPanel Host"
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:125
#: inc/integrations/host-providers/class-cpanel-host-provider.php:124
msgid "e.g. yourdomain.com"
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:128
#: inc/integrations/host-providers/class-cpanel-host-provider.php:127
msgid "cPanel Port"
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:129
#: inc/integrations/host-providers/class-cpanel-host-provider.php:128
msgid "Defaults to 2083"
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:133
#: inc/integrations/host-providers/class-cpanel-host-provider.php:132
msgid "Root Directory"
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:134
#: inc/integrations/host-providers/class-cpanel-host-provider.php:133
msgid "Defaults to /public_html"
msgstr ""
@ -14826,15 +14826,15 @@ msgstr ""
msgid "Unexpected error ocurred trying to sync domains with CPanel"
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:317
#: inc/integrations/host-providers/class-cpanel-host-provider.php:318
msgid "cPanel is the management panel being used on a large number of shared and dedicated hosts across the globe."
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:362
#: inc/integrations/host-providers/class-cpanel-host-provider.php:363
msgid "Add a new Addon Domain on cPanel whenever a new domain mapping gets created on your network"
msgstr ""
#: inc/integrations/host-providers/class-cpanel-host-provider.php:368
#: inc/integrations/host-providers/class-cpanel-host-provider.php:369
msgid "Add a new SubDomain on cPanel whenever a new site gets created on your network"
msgstr ""
@ -15256,7 +15256,7 @@ msgid "Send an email to this customer"
msgstr ""
#: inc/list-tables/class-customer-list-table.php:152
#: views/base/customers/grid-item.php:115
#: views/base/customers/grid-item.php:127
msgid "Switch To"
msgstr ""
@ -15265,7 +15265,7 @@ msgstr ""
#: inc/list-tables/class-payment-list-table.php:143
#: inc/list-tables/class-site-list-table.php:256
#: views/admin-pages/fields/field-text.php:44
#: views/base/customers/grid-item.php:95
#: views/base/customers/grid-item.php:107
#: views/base/responsive-table-row.php:130
msgid "View"
msgstr ""
@ -15297,7 +15297,7 @@ msgstr ""
#: inc/list-tables/class-customer-list-table.php:363
#: inc/list-tables/class-site-customer-list-table.php:62
#: views/base/customers/grid-item.php:64
#: views/base/customers/grid-item.php:76
msgid "Online"
msgstr ""
@ -16588,11 +16588,11 @@ msgstr ""
msgid "You do not have enough permissions to read the logs of this webhook."
msgstr ""
#: inc/models/class-base-model.php:185
#: inc/models/class-base-model.php:186
msgid "You can only use numeric fields to generate hashes."
msgstr ""
#: inc/models/class-base-model.php:733
#: inc/models/class-base-model.php:734
msgid "This method expects an array as argument."
msgstr ""
@ -17980,7 +17980,7 @@ msgid "Preview Image"
msgstr ""
#: views/admin-pages/fields/field-image.php:90
#: views/settings/fields/field-image.php:50
#: views/settings/fields/field-image.php:47
msgid "Remove Image"
msgstr ""
@ -18083,48 +18083,48 @@ msgstr ""
msgid "Your browser doesn't support iframes"
msgstr ""
#: views/base/customers/grid-item.php:45
#: views/base/customers/grid-item.php:57
msgid "No email address"
msgstr ""
#: views/base/customers/grid-item.php:50
#: views/base/customers/grid-item.php:62
msgid "VIP Customer"
msgstr ""
#: views/base/customers/grid-item.php:50
#: views/base/customers/grid-item.php:62
msgid "Regular Customer"
msgstr ""
#: views/base/customers/grid-item.php:59
#: views/base/customers/grid-item.php:71
msgid "Last Login:"
msgstr ""
#: views/base/customers/grid-item.php:66
#: views/base/customers/grid-item.php:78
#: views/base/customers/grid-item.php:90
msgid "ago"
msgstr ""
#: views/base/customers/grid-item.php:68
#: views/base/customers/grid-item.php:80
msgid "Never logged in"
msgstr ""
#: views/base/customers/grid-item.php:75
#: views/base/customers/grid-item.php:87
msgid "Customer Since:"
msgstr ""
#: views/base/customers/grid-item.php:84
#: views/base/customers/grid-item.php:96
msgid "Memberships:"
msgstr ""
#: views/base/customers/grid-item.php:106
#: views/base/customers/grid-item.php:118
msgid "Actions:"
msgstr ""
#: views/base/customers/grid-item.php:134
#: views/base/customers/grid-item.php:146
msgid "Select Customer"
msgstr ""
#: views/base/customers/grid-item.php:138
#: views/base/customers/grid-item.php:150
#: views/base/sites/grid-item.php:67
#: views/dashboard-widgets/my-sites.php:151
msgid "Manage"

View File

@ -14,7 +14,7 @@
"translate": true
},
"scripts": {
"prebuild": "composer install --no-dev",
"prebuild": "composer install -o --no-dev",
"prebuild:dev": "composer install",
"build": "npm run uglify && npm run makepot && npm run cleancss && npm run archive",
"build:dev": "npm run uglify && npm run makepot && npm run cleancss",

View File

@ -1,12 +1,12 @@
includes:
- vendor/szepeviktor/phpstan-wordpress/extension.neon
parameters:
level: max
level: 0
inferPrivatePropertyTypeFromConstructor: true
checkMissingIterableValueType: false
treatPhpDocTypesAsCertain: false
paths:
- /
- ./views
- ./inc
- ./wp-multisite-waas.php
ignoreErrors:
# Uses func_get_args()
- '/^Function apply_filters(_ref_array)? invoked with [34567] parameters, 2 required\.$/'
-
message: '#Variable \$.* might not be defined.#'
path: ./views/*

View File

@ -1,7 +1,7 @@
=== WP Multisite WaaS ===
Requires at least: 5.3
Requires PHP: 7.4.30
Tested up to: 6.7.1
Tested up to: 6.7.2
License: GPLv2
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Contributors: aanduque, superdav42
@ -84,6 +84,20 @@ For support, please open an issue on the [GitHub repository](https://github.com/
We recommend running this in a staging environment before updating your production environment.
== Changelog ==
Version [2.4.0] - Released on 2025-XX-XX
- Improved: Prep Plugin for release on WordPress.org
- Improved: Update translation text domain
- Fixed: Escape everything that should be escaped.
- Fixed: Add nonce checks where needed.
- Fixed: Sanitize all inputs.
- Improved: Apply Code style changes across the codebase.
- Fixed: Many deprecation notices.
- Improved: Load order of many filters.
- Improved: Add Proper Build script
- Improved: Use emojii flags
- Fixed: i18n deprecation notice for translating too early
- Improved: Put all scripts in footer and load async
Version [2.3.4] - Released on 2024-01-31
- Fixed: Unable to checkout with any payment gateway
- Fixed: Warning Undefined global variable $pagenow

View File

@ -18,21 +18,19 @@ use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
/**
* @see \Rector\Tests\TypeDeclaration\Rector\YodaConditionsRector\YodaConditionsRectorTest
*/
final class YodaConditionsRector extends AbstractRector
{
final class YodaConditionsRector extends AbstractRector {
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
public function getNodeTypes(): array {
return [Equal::class, NotEqual::class, Identical::class, NotIdentical::class];
}
/**
* @param \PhpParser\Node\Stmt\Class_ $node
*/
public function refactor(Node $node): ?Node
{
public function refactor(Node $node): ?Node {
// Ensure the left operand is not a constant
if ((
$node->left instanceof Node\Expr\Variable ||

View File

@ -6,23 +6,20 @@ namespace Rector\Tests\TypeDeclaration\Rector\YodaConditionsRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
final class YodaConditionsRectorTest extends AbstractRectorTestCase
{
final class YodaConditionsRectorTest extends AbstractRectorTestCase {
/**
* @dataProvider provideData()
*/
public function test(string $filePath): void
{
public function test(string $filePath): void {
$this->doTestFile($filePath);
}
public static function provideData(): \Iterator
{
public static function provideData(): \Iterator {
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
public function provideConfigFilePath(): string
{
public function provideConfigFilePath(): string {
return __DIR__ . '/config/configured_rule.php';
}
}

View File

@ -5,7 +5,7 @@
* @since 2.0.0
*/
?>
<li class="<?php echo esc_attr(trim($field->wrapper_classes)); ?>" <?php echo($field->get_wrapper_html_attributes(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
<li class="<?php echo esc_attr(trim($field->wrapper_classes)); ?>" <?php echo($field->get_wrapper_html_attributes()); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
<div class="wu-block wu-w-full">

View File

@ -11,7 +11,19 @@
<div
class="wu--mt-8 wu-py-8 wu-bg-gray-100 wu-bg-cover wu-bg-center"
style="opacity: 0.15; background-image: url(<?php echo esc_url(get_avatar_url($item->get_user_id(), array('default' => 'identicon', 'size' => 320))); ?>)"
style="opacity: 0.15; background-image: url(
<?php
echo esc_url(
get_avatar_url(
$item->get_user_id(),
array(
'default' => 'identicon',
'size' => 320,
)
)
);
?>
)"
>
&nbsp;
</div>

View File

@ -11,14 +11,12 @@
wp_enqueue_media();
wp_enqueue_script('media');
$suffix = WU_Scripts()->suffix();
wp_enqueue_script('wu-field-button-upload', WP_Ultimo()->get_asset("wu-field-image$suffix.js", 'js'));
wp_enqueue_script('wu-field-button-upload', wu_get_asset('wu-field-image.js', 'js'), [], wu_get_version(), true);
?>
<tr>
<th scope="row"><label for="<?php echo $field_slug; ?>"><?php echo $field['title']; ?></label></th>
<th scope="row"><label for="<?php echo esc_attr($field_slug); ?>"><?php echo esc_html($field['title']); ?></label></th>
<td>
<?php
@ -29,33 +27,32 @@ wp_enqueue_script('wu-field-button-upload', WP_Ultimo()->get_asset("wu-field-ima
}
if ( $image_url ) {
$image = '<img id="%s" src="%s" alt="%s" style="width:%s; height:auto">';
printf(
$image,
$field_slug . '-preview',
$image_url,
get_bloginfo('name'),
$field['width'] . 'px'
'<img id="%s" src="%s" alt="%s" style="width:%s; height:auto">',
esc_attr($field_slug . '-preview'),
esc_attr($image_url),
esc_attr(get_bloginfo('name')),
esc_attr($field['width'] . 'px')
);
}
?>
<br>
<a href="#" class="button wu-field-button-upload" data-target="<?php echo $field_slug; ?>">
<?php echo $field['button']; ?>
<a href="#" class="button wu-field-button-upload" data-target="<?php echo esc_attr($field_slug); ?>">
<?php echo esc_html($field['button']); ?>
</a>
<a data-default="<?php echo $field['default']; ?>" href="#" class="button wu-field-button-upload-remove" data-target="<?php echo $field_slug; ?>">
<a data-default="<?php echo esc_attr($field['default']); ?>" href="#" class="button wu-field-button-upload-remove" data-target="<?php echo esc_attr($field_slug); ?>">
<?php esc_html_e('Remove Image', 'wp-multisite-waas'); ?>
</a>
<?php if ( ! empty($field['desc'])) : ?>
<p class="description" id="<?php echo $field_slug; ?>-desc">
<?php echo $field['desc']; ?>
<p class="description" id="<?php echo esc_attr($field_slug); ?>-desc">
<?php echo esc_html($field['desc']); ?>
</p>
<input type="hidden" name="<?php echo $field_slug; ?>" id="<?php echo $field_slug; ?>" value="<?php echo wu_get_setting($field_slug) ?: $field['default']; ?>">
<input type="hidden" name="<?php echo esc_attr($field_slug); ?>" id="<?php echo esc_attr($field_slug); ?>" value="<?php echo esc_attr(wu_get_setting($field_slug) ?: $field['default']); ?>">
<?php endif; ?>

View File

@ -54,7 +54,7 @@
<div>
<span class="wu-text-sm wu-text-gray-800 wu-inline-block wu-py-4">
<?php esc_html_e('This integration will <strong>not</strong>:', 'wp-multisite-waas'); ?>
<?php echo wp_kses(__('This integration will <strong>not</strong>:', 'wp-multisite-waas'), ['strong' => []]); ?>
</span>
<ul class="wu--mx-5 wu-my-0 wu-border-t wu-border-solid wu-border-l-0 wu-border-r-0 wu-border-b-0 wu-border-gray-300">

View File

@ -4,7 +4,7 @@
* Description: The WordPress Multisite Website as a Service (WaaS) plugin.
* Plugin URI: https://wpmultisitewaas.org
* Text Domain: wp-multisite-waas
* Version: 2.3.4
* Version: 2.4.0
* Author: WP Multisite Community
* Author URI: https://github.com/superdav42/wp-multisite-waas
* GitHub Plugin URI: https://github.com/superdav42/wp-multisite-waas
@ -27,10 +27,10 @@
* You should have received a copy of the GNU General Public License
* along with WP Multisite WaaS. If not, see <http://www.gnu.org/licenses/>.
*
* @author Arindo Duque and NextPress
* @author Arindo Duque and NextPress and WP Multisite Community
* @category Core
* @package WP_Ultimo
* @version 2.3.4
* @version 2.4.0
*/
// Exit if accessed directly
@ -81,9 +81,9 @@ if ( ! function_exists('WP_Ultimo')) {
* @return WP_Ultimo
* @since 2.0.0
*/
function WP_Ultimo() { // phpcs:ignore
function WP_Ultimo() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid
return WP_Ultimo::get_instance();
} // end WP_Ultimo;
}
}
// Initialize and set to global for back-compat
$GLOBALS['WP_Ultimo'] = WP_Ultimo();