Initial Commit
This commit is contained in:
392
inc/objects/class-billing-address.php
Normal file
392
inc/objects/class-billing-address.php
Normal file
@ -0,0 +1,392 @@
|
||||
<?php
|
||||
/**
|
||||
* Billing Address class
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage Models
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\Objects;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Billing Address class
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Billing_Address {
|
||||
|
||||
/**
|
||||
* The Billing Address content.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var array
|
||||
*/
|
||||
protected $attributes = array();
|
||||
|
||||
/**
|
||||
* Initializes the object.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $data Array of key => values billing address fields.
|
||||
*/
|
||||
public function __construct($data = array()) {
|
||||
|
||||
$this->attributes($data);
|
||||
|
||||
} // end __construct;
|
||||
|
||||
/**
|
||||
* Loops through allowed fields and loads them.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $data Array of key => values billing address fields.
|
||||
* @return void
|
||||
*/
|
||||
public function attributes($data) {
|
||||
|
||||
$allowed_attributes = array_keys(self::fields());
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
|
||||
if (in_array($key, $allowed_attributes, true)) {
|
||||
|
||||
$this->attributes[$key] = $value;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
} // end attributes;
|
||||
|
||||
/**
|
||||
* Checks if this billing address has any content at all.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function exists() {
|
||||
|
||||
return !empty(array_filter($this->attributes));
|
||||
|
||||
} // end exists;
|
||||
|
||||
/**
|
||||
* Checks if a parameter exists.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $name The parameter to check.
|
||||
* @return boolean
|
||||
*/
|
||||
public function __isset($name) {
|
||||
|
||||
return wu_get_isset($this->attributes, $name, '');
|
||||
|
||||
} // end __isset;
|
||||
|
||||
/**
|
||||
* Gets a billing address field.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $name The parameter to return.
|
||||
* @return string
|
||||
*/
|
||||
public function __get($name) {
|
||||
|
||||
$value = wu_get_isset($this->attributes, $name, '');
|
||||
|
||||
return apply_filters("wu_billing_address_get_{$name}", $value, $this);
|
||||
|
||||
} // end __get;
|
||||
|
||||
/**
|
||||
* Sets a billing address field.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $name Field name.
|
||||
* @param string $value The field value.
|
||||
*/
|
||||
public function __set($name, $value) {
|
||||
|
||||
$value = apply_filters("wu_billing_address_set_{$name}", $value, $this);
|
||||
|
||||
$this->attributes[$name] = $value;
|
||||
|
||||
} // end __set;
|
||||
/**
|
||||
* Returns the validation rules for the billing address fields.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected function validation_rules(): array {
|
||||
|
||||
$fields = self::fields();
|
||||
|
||||
$keys = array_keys(array_filter($fields, fn($item) => wu_get_isset($item, 'validation_rules')));
|
||||
|
||||
return array_combine($keys, array_column($fields, 'validation_rules'));
|
||||
|
||||
} // end validation_rules;
|
||||
|
||||
/**
|
||||
* Validates the fields following the validation rules.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return true|\WP_Error
|
||||
*/
|
||||
public function validate() {
|
||||
|
||||
$validator = new \WP_Ultimo\Helpers\Validator;
|
||||
|
||||
$validator->validate($this->to_array(), $this->validation_rules());
|
||||
|
||||
if ($validator->fails()) {
|
||||
|
||||
return $validator->get_errors();
|
||||
|
||||
} // end if;
|
||||
|
||||
return true;
|
||||
|
||||
} // end validate;
|
||||
|
||||
/**
|
||||
* Returns a key => value representation of the billing address.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param boolean $labels Wether or not to return labels as keys or the actual keys.
|
||||
* @return array
|
||||
*/
|
||||
public function to_array($labels = false) {
|
||||
|
||||
$address_array = array();
|
||||
|
||||
$fields = self::fields();
|
||||
|
||||
foreach ($fields as $field_key => $field) {
|
||||
|
||||
if (!empty($this->{$field_key})) {
|
||||
|
||||
$key = $labels ? $field['title'] : $field_key;
|
||||
|
||||
$address_array[$key] = $this->{$field_key};
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return $address_array;
|
||||
|
||||
} // end to_array;
|
||||
/**
|
||||
* Returns a string representation of the billing address.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Company Name
|
||||
* Tax ID
|
||||
* Address 1
|
||||
* ...
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $delimiter Delimiter to glue address pieces together.
|
||||
*/
|
||||
public function to_string($delimiter = PHP_EOL): string {
|
||||
|
||||
return implode($delimiter, $this->to_array());
|
||||
|
||||
} // end to_string;
|
||||
|
||||
/**
|
||||
* Returns the field array with values added.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param bool $zip_only If we only need zip and country.
|
||||
* @return array
|
||||
*/
|
||||
public function get_fields($zip_only = false) {
|
||||
|
||||
$fields = self::fields($zip_only);
|
||||
|
||||
foreach ($fields as $field_key => &$field) {
|
||||
|
||||
$field['value'] = $this->{$field_key};
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end get_fields;
|
||||
|
||||
/**
|
||||
* Billing Address field definitions.
|
||||
*
|
||||
* This is used to determine fields allowed on the billing address.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param bool $zip_only If we only need zip and country.
|
||||
* @param \WP_Ultimo\Models\Checkout_Form $checkout_form The current checkout form.
|
||||
* @return array
|
||||
*/
|
||||
public static function fields($zip_only = false, $checkout_form = false) {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$countries = wu_get_countries_as_options();
|
||||
|
||||
// Get allowed countries in form
|
||||
if ($checkout_form && $checkout_form->has_country_lock()) {
|
||||
|
||||
$allowed_countries = $checkout_form->get_allowed_countries();
|
||||
|
||||
// Allow the Select Country field
|
||||
$allowed_countries[] = '';
|
||||
|
||||
foreach ($countries as $country_code => $country) {
|
||||
|
||||
if (!in_array($country_code, $allowed_countries, true)) {
|
||||
|
||||
unset($countries[$country_code]);
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
} // end if;
|
||||
|
||||
$fields['company_name'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Company Name', 'wp-ultimo'),
|
||||
'default_placeholder' => __('E.g. Google (optional)', 'wp-ultimo'),
|
||||
'wrapper_classes' => 'sm:wu-col-span-1',
|
||||
);
|
||||
|
||||
$fields['billing_email'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Billing Email', 'wp-ultimo'),
|
||||
'default_placeholder' => __('E.g. john@company.com', 'wp-ultimo'),
|
||||
'wrapper_classes' => 'sm:wu-col-span-1',
|
||||
'required' => true,
|
||||
);
|
||||
|
||||
$fields['billing_address_line_1'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Address Line 1', 'wp-ultimo'),
|
||||
'default_placeholder' => __('E.g. 555 1st Avenue', 'wp-ultimo'),
|
||||
'wrapper_classes' => 'wu-col-span-2',
|
||||
'required' => true,
|
||||
);
|
||||
|
||||
$fields['billing_address_line_2'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Address Line 2', 'wp-ultimo'),
|
||||
'default_placeholder' => __('E.g. Apartment 10a', 'wp-ultimo'),
|
||||
'wrapper_classes' => 'wu-col-span-2',
|
||||
);
|
||||
|
||||
$fields['billing_country'] = array(
|
||||
'type' => 'select',
|
||||
'title' => __('Country', 'wp-ultimo'),
|
||||
'default_placeholder' => __('E.g. US', 'wp-ultimo'),
|
||||
'wrapper_classes' => 'sm:wu-col-span-1',
|
||||
'value' => ' ',
|
||||
'options' => $countries,
|
||||
'required' => true,
|
||||
);
|
||||
|
||||
$fields['billing_state'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('State / Province', 'wp-ultimo'),
|
||||
'default_placeholder' => __('E.g. NY', 'wp-ultimo'),
|
||||
'wrapper_classes' => 'sm:wu-col-span-1',
|
||||
);
|
||||
|
||||
$fields['billing_city'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('City / Town', 'wp-ultimo'),
|
||||
'default_placeholder' => __('E.g. New York City', 'wp-ultimo'),
|
||||
'wrapper_classes' => 'sm:wu-col-span-1',
|
||||
);
|
||||
|
||||
$fields['billing_zip_code'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('ZIP / Postal Code', 'wp-ultimo'),
|
||||
'default_placeholder' => __('E.g. 10009', 'wp-ultimo'),
|
||||
'wrapper_classes' => 'sm:wu-col-span-1',
|
||||
'required' => true,
|
||||
);
|
||||
|
||||
$fields = wu_set_order_from_index($fields); // Adds missing order attributes
|
||||
|
||||
if ($zip_only) {
|
||||
|
||||
$fields = array(
|
||||
'billing_zip_code' => $fields['billing_zip_code'],
|
||||
'billing_country' => $fields['billing_country'],
|
||||
);
|
||||
|
||||
} // end if;
|
||||
|
||||
/**
|
||||
* Allow plugin developers to filter the billing address fields.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $fields Billing Address array.
|
||||
* @param bool $zip_only If we only need zip and country.
|
||||
* @return array
|
||||
*/
|
||||
$fields = apply_filters('wu_billing_address_fields', $fields, $zip_only);
|
||||
|
||||
uasort($fields, 'wu_sort_by_order');
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* Billing Address fields array for REST API.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param bool $zip_only If we only need zip and country.
|
||||
* @return array
|
||||
*/
|
||||
public static function fields_for_rest($zip_only = false) {
|
||||
|
||||
$fields_for_rest = array();
|
||||
|
||||
foreach (self::fields($zip_only) as $field_key => $field) {
|
||||
|
||||
$options = wu_get_isset($field, 'options', false);
|
||||
|
||||
$enum = is_callable($options) ? call_user_func($options) : false;
|
||||
|
||||
$fields_for_rest[$field_key] = array(
|
||||
'description' => wu_get_isset($field, 'title', false) . '. ' . wu_get_isset($field, 'default_placeholder', false),
|
||||
'type' => 'string',
|
||||
'required' => wu_get_isset($field, 'required', false),
|
||||
);
|
||||
|
||||
if ($enum) {
|
||||
|
||||
$fields_for_rest[$field_key]['enum'] = array_keys($enum);
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return $fields_for_rest;
|
||||
|
||||
} // end fields_for_rest;
|
||||
|
||||
} // end class Billing_Address;
|
576
inc/objects/class-limitations.php
Normal file
576
inc/objects/class-limitations.php
Normal file
@ -0,0 +1,576 @@
|
||||
<?php
|
||||
/**
|
||||
* Limitation manager.
|
||||
*
|
||||
* This class centralizes the limitation modules.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage Limitations
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\Objects;
|
||||
|
||||
use WP_Ultimo\Objects\Limitations;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Limitation manager.
|
||||
*
|
||||
* This class centralizes the limitation modules.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Limitations {
|
||||
|
||||
/**
|
||||
* Caches early limitation queries to prevent
|
||||
* to many database hits.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var array
|
||||
*/
|
||||
static $limitations_cache = array();
|
||||
|
||||
/**
|
||||
* Version of the limitation schema.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var integer
|
||||
*/
|
||||
protected $version = 2;
|
||||
|
||||
/**
|
||||
* Limitation modules.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var array
|
||||
*/
|
||||
protected $modules = array();
|
||||
|
||||
/**
|
||||
* The current limitation being merged in merge_recursive.
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @var string
|
||||
*/
|
||||
protected $current_merge_id = '';
|
||||
|
||||
/**
|
||||
* Constructs the limitation class with module data.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $modules_data Array of modules data.
|
||||
*/
|
||||
public function __construct($modules_data = array()) {
|
||||
|
||||
$this->build_modules($modules_data);
|
||||
|
||||
} // end __construct;
|
||||
|
||||
/**
|
||||
* Returns the module via magic getter.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $name The module name.
|
||||
* @return \WP_Ultimo\Limitations\Limit
|
||||
*/
|
||||
public function __get($name) {
|
||||
|
||||
$module = wu_get_isset($this->modules, $name, false);
|
||||
|
||||
if ($module === false) {
|
||||
|
||||
$repo = self::repository();
|
||||
|
||||
$class_name = wu_get_isset($repo, $name, false);
|
||||
|
||||
if (class_exists($class_name)) {
|
||||
|
||||
$module = new $class_name(array());
|
||||
|
||||
$this->modules[$name] = $module;
|
||||
|
||||
return $module;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
return $module;
|
||||
|
||||
} // end __get;
|
||||
|
||||
/**
|
||||
* Prepare to serialization.
|
||||
*
|
||||
* @see requires php 7.3
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize() { // phpcs:ignore
|
||||
|
||||
return $this->to_array();
|
||||
|
||||
} // end __serialize;
|
||||
|
||||
/**
|
||||
* Handles un-serialization.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @see requires php 7.3
|
||||
* @param array $modules_data Array of modules data.
|
||||
* @return void
|
||||
*/
|
||||
public function __unserialize($modules_data) { // phpcs:ignore
|
||||
|
||||
$this->build_modules($modules_data);
|
||||
|
||||
} // end __unserialize;
|
||||
|
||||
/**
|
||||
* Builds the module list based on the module data.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $modules_data Array of modules data.
|
||||
* @return self
|
||||
*/
|
||||
public function build_modules($modules_data) {
|
||||
|
||||
foreach ($modules_data as $type => $data) {
|
||||
|
||||
$module = self::build($data, $type);
|
||||
|
||||
if ($module) {
|
||||
|
||||
$this->modules[$type] = $module;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return $this;
|
||||
|
||||
} // end build_modules;
|
||||
/**
|
||||
* Build a module, based on the data.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string|array $data The module data.
|
||||
* @param string $module_name The module_name.
|
||||
* @return false|\WP_Ultimo\Limitations\Limit
|
||||
*/
|
||||
static public function build($data, $module_name) {
|
||||
|
||||
$class = wu_get_isset(self::repository(), $module_name);
|
||||
|
||||
if (class_exists($class)) {
|
||||
|
||||
if (is_string($data)) {
|
||||
|
||||
$data = json_decode($data, true);
|
||||
|
||||
}
|
||||
|
||||
return new $class($data);
|
||||
|
||||
} // end if;
|
||||
|
||||
return false;
|
||||
|
||||
} // end build;
|
||||
|
||||
/**
|
||||
* Checks if a limitation model exists in this limitations.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $module The module name.
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($module) {
|
||||
|
||||
return wu_get_isset($this->modules, $module, false);
|
||||
|
||||
} // end exists;
|
||||
|
||||
/**
|
||||
* Checks if we have any limitation modules setup at all.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function has_limitations() {
|
||||
|
||||
$has_limitations = false;
|
||||
|
||||
foreach ($this->modules as $module) {
|
||||
|
||||
if ($module->is_enabled()) {
|
||||
|
||||
return true;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return $has_limitations;
|
||||
|
||||
} // end has_limitations;
|
||||
|
||||
/**
|
||||
* Checks if a particular module is enabled.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $module_name Module name.
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_module_enabled($module_name) {
|
||||
|
||||
$module = $this->{$module_name};
|
||||
|
||||
return $module ? $module->is_enabled() : false;
|
||||
|
||||
} // end is_module_enabled;
|
||||
|
||||
/**
|
||||
* Merges limitations from other entities.
|
||||
*
|
||||
* This is what we use to combine different limitations from
|
||||
* different sources. For example: we override the limitations
|
||||
* of site with restrictions coming from the membership,
|
||||
* products, etc.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array|bool $override A limitation array or a boolean to override the values from first to last limitation.
|
||||
* @param array ...$limitations Limitation arrays.
|
||||
* @return self
|
||||
*/
|
||||
public function merge($override = false, ...$limitations) {
|
||||
|
||||
if (!is_bool($override)) {
|
||||
|
||||
$limitations[] = $override;
|
||||
|
||||
$override = false;
|
||||
|
||||
} // end if;
|
||||
|
||||
$results = $this->to_array();
|
||||
|
||||
foreach ($limitations as $limitation) {
|
||||
|
||||
if (is_a($limitation, \WP_Ultimo\Objects\Limitations::class)) { // @phpstan-ignore-line
|
||||
|
||||
$limitation = $limitation->to_array();
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!is_array($limitation)) {
|
||||
|
||||
continue;
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->merge_recursive($results, $limitation, !$override);
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return new self($results);
|
||||
|
||||
} // end merge;
|
||||
|
||||
/**
|
||||
* Merges a limitation array
|
||||
*
|
||||
* @since 2.0.20
|
||||
*
|
||||
* @param array $array1 The arrays original.
|
||||
* @param array $array2 The array to be merged in.
|
||||
* @param bool $should_sum If we should add up numeric values instead of replacing the original.
|
||||
* @return void
|
||||
*/
|
||||
protected function merge_recursive(array &$array1, array &$array2, $should_sum = true) {
|
||||
|
||||
$current_id = $this->current_merge_id;
|
||||
|
||||
$force_enabled_list = array(
|
||||
'plugins',
|
||||
'themes',
|
||||
);
|
||||
|
||||
$force_enabled = in_array($current_id, $force_enabled_list, true);
|
||||
|
||||
if ($force_enabled && (!wu_get_isset($array1, 'enabled', true) || !wu_get_isset($array2, 'enabled', true))) {
|
||||
|
||||
$array1['enabled'] = true;
|
||||
$array2['enabled'] = true;
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!wu_get_isset($array1, 'enabled', true)) {
|
||||
|
||||
$array1 = array(
|
||||
'enabled' => false,
|
||||
);
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!wu_get_isset($array2, 'enabled', true) && $should_sum) {
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
foreach ($array2 as $key => &$value) {
|
||||
/**
|
||||
* Here we need to work with arrays and some limits
|
||||
* as themes and plugins have stdClass values.
|
||||
*/
|
||||
$value = is_object($value) ? get_object_vars($value) : $value;
|
||||
|
||||
if (isset($array1[$key])) {
|
||||
|
||||
$array1[$key] = is_object($array1[$key]) ? get_object_vars($array1[$key]) : $array1[$key];
|
||||
|
||||
} // end if;
|
||||
|
||||
if (is_array($value) && isset($array1[$key]) && is_array($array1[$key])) {
|
||||
|
||||
$array1_id = wu_get_isset($array1[$key], 'id', $current_id);
|
||||
|
||||
$this->current_merge_id = wu_get_isset($value, 'id', $array1_id);
|
||||
|
||||
$this->merge_recursive($array1[$key], $value, $should_sum);
|
||||
|
||||
$this->current_merge_id = $current_id;
|
||||
|
||||
} else {
|
||||
|
||||
$original_value = wu_get_isset($array1, $key);
|
||||
|
||||
// If the value is 0 or '' it can be a unlimited value
|
||||
$is_unlimited = (is_numeric($value) || $value === '') && (int) $value === 0;
|
||||
|
||||
if ($should_sum && ($original_value === '' || $original_value === 0)) {
|
||||
/**
|
||||
* We use values 0 or '' as unlimited in our limits
|
||||
*/
|
||||
continue;
|
||||
|
||||
} elseif (isset($array1[$key]) && is_numeric($array1[$key]) && is_numeric($value) && $should_sum && !$is_unlimited) {
|
||||
|
||||
$array1[$key] = ((int) $array1[$key]) + $value;
|
||||
|
||||
} elseif ($key === 'visibility' && isset($array1[$key]) && $should_sum) {
|
||||
|
||||
$key_priority = array(
|
||||
'hidden' => 0,
|
||||
'visible' => 1,
|
||||
);
|
||||
|
||||
$array1[$key] = $key_priority[$value] > $key_priority[$array1[$key]] ? $value : $array1[$key];
|
||||
|
||||
} elseif ($key === 'behavior' && isset($array1[$key]) && $should_sum) {
|
||||
|
||||
$key_priority_list = array(
|
||||
'plugins' => array(
|
||||
'default' => 10,
|
||||
'force_inactive_locked' => 20,
|
||||
'force_inactive' => 30,
|
||||
'force_active_locked' => 40,
|
||||
'force_active' => 50,
|
||||
),
|
||||
'site' => array(
|
||||
'not_available' => 10,
|
||||
'available' => 20,
|
||||
'pre_selected' => 30,
|
||||
),
|
||||
'themes' => array(
|
||||
'not_available' => 10,
|
||||
'available' => 20,
|
||||
'force_active' => 30,
|
||||
),
|
||||
);
|
||||
|
||||
$key_priority = apply_filters("wu_limitation_{$current_id}_priority", $key_priority_list[$current_id]);
|
||||
|
||||
$array1[$key] = $key_priority[$value] > $key_priority[$array1[$key]] ? $value : $array1[$key];
|
||||
|
||||
} else {
|
||||
|
||||
// Avoid change true values
|
||||
$array1[$key] = $original_value !== true || !$should_sum ? $value : true;
|
||||
|
||||
$array1[$key] = $original_value !== true || !$should_sum ? $value : true;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
} // end merge_recursive;
|
||||
/**
|
||||
* Converts the limitations list to an array.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function to_array(): array {
|
||||
|
||||
return array_map(fn($module) => method_exists($module, 'to_array') ? $module->to_array() : (array) $module, $this->modules);
|
||||
|
||||
} // end to_array;
|
||||
|
||||
/**
|
||||
* Static method to return limitations in very early stages of the WordPress lifecycle.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $slug Slug of the model.
|
||||
* @param int $id ID of the model.
|
||||
* @return \WP_Ultimo\Objects\Limitations
|
||||
*/
|
||||
public static function early_get_limitations($slug, $id) {
|
||||
|
||||
$wu_prefix = 'wu_';
|
||||
|
||||
/*
|
||||
* Reset the slug and prefixes
|
||||
* for the native tables of blogs.
|
||||
*/
|
||||
if ($slug === 'site') {
|
||||
|
||||
$slug = 'blog';
|
||||
|
||||
$wu_prefix = '';
|
||||
|
||||
} // end if;
|
||||
|
||||
$cache = static::$limitations_cache;
|
||||
|
||||
$key = sprintf('%s-%s', $slug, $id);
|
||||
|
||||
if (isset($cache[$key])) {
|
||||
|
||||
return $cache[$key];
|
||||
|
||||
} // end if;
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$limitations = array();
|
||||
|
||||
$table_name = "{$wpdb->base_prefix}{$wu_prefix}{$slug}meta";
|
||||
|
||||
$sql = $wpdb->prepare("SELECT meta_value FROM {$table_name} WHERE meta_key = 'wu_limitations' AND {$wu_prefix}{$slug}_id = %d LIMIT 1", $id); // phpcs:ignore
|
||||
|
||||
$results = $wpdb->get_var($sql); // phpcs:ignore
|
||||
|
||||
if (!empty($results)) {
|
||||
|
||||
$limitations = unserialize($results);
|
||||
|
||||
} // end if;
|
||||
|
||||
/*
|
||||
* Caches the results.
|
||||
*/
|
||||
static::$limitations_cache[$key] = $limitations;
|
||||
|
||||
return $limitations;
|
||||
|
||||
} // end early_get_limitations;
|
||||
|
||||
/**
|
||||
* Delete limitations.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $slug The slug of the model.
|
||||
* @param int $id The id of the meta id.
|
||||
* @return void
|
||||
*/
|
||||
public static function remove_limitations($slug, $id) {
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$wu_prefix = 'wu_';
|
||||
|
||||
/*
|
||||
* Site apis are already available,
|
||||
* so no need to use low-level sql calls.
|
||||
*/
|
||||
if ($slug === 'site') {
|
||||
|
||||
$wu_prefix = '';
|
||||
|
||||
$slug = 'blog';
|
||||
|
||||
} // end if;
|
||||
|
||||
$table_name = "{$wpdb->base_prefix}{$wu_prefix}{$slug}meta";
|
||||
|
||||
$sql = $wpdb->prepare("DELETE FROM {$table_name} WHERE meta_key = 'wu_limitations' AND {$wu_prefix}{$slug}_id = %d LIMIT 1", $id); // phpcs:ignore
|
||||
|
||||
$wpdb->get_var($sql); // phpcs:ignore
|
||||
|
||||
} // end remove_limitations;
|
||||
|
||||
/**
|
||||
* Returns an empty permission set, with modules.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return self
|
||||
*/
|
||||
static public function get_empty() {
|
||||
|
||||
$limitations = new self();
|
||||
|
||||
foreach (array_keys(self::repository()) as $module_name) {
|
||||
|
||||
$limitations->{$module_name};
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return $limitations;
|
||||
|
||||
} // end get_empty;
|
||||
|
||||
/**
|
||||
* Repository of the limitation modules.
|
||||
*
|
||||
* @see wu_register_limit_module()
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
static public function repository() {
|
||||
|
||||
$classes = array(
|
||||
'post_types' => \WP_Ultimo\Limitations\Limit_Post_Types::class,
|
||||
'plugins' => \WP_Ultimo\Limitations\Limit_Plugins::class,
|
||||
'sites' => \WP_Ultimo\Limitations\Limit_Sites::class,
|
||||
'themes' => \WP_Ultimo\Limitations\Limit_Themes::class,
|
||||
'visits' => \WP_Ultimo\Limitations\Limit_Visits::class,
|
||||
'disk_space' => \WP_Ultimo\Limitations\Limit_Disk_Space::class,
|
||||
'users' => \WP_Ultimo\Limitations\Limit_Users::class,
|
||||
'site_templates' => \WP_Ultimo\Limitations\Limit_Site_Templates::class,
|
||||
'domain_mapping' => \WP_Ultimo\Limitations\Limit_Domain_Mapping::class,
|
||||
'customer_user_role' => \WP_Ultimo\Limitations\Limit_Customer_User_Role::class,
|
||||
);
|
||||
|
||||
return apply_filters('wu_limit_classes', $classes);
|
||||
|
||||
} // end repository;
|
||||
|
||||
} // end class Limitations;
|
236
inc/objects/class-note.php
Normal file
236
inc/objects/class-note.php
Normal file
@ -0,0 +1,236 @@
|
||||
<?php
|
||||
/**
|
||||
* Note class
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage Models
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\Objects;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Note class
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Note {
|
||||
|
||||
/**
|
||||
* The Note content.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var array
|
||||
*/
|
||||
protected $attributes = array();
|
||||
|
||||
/**
|
||||
* Initializes the object.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $data Array of key => values note fields.
|
||||
*/
|
||||
public function __construct($data = array()) {
|
||||
|
||||
$this->attributes($data);
|
||||
|
||||
} // end __construct;
|
||||
|
||||
/**
|
||||
* Loops through allowed fields and loads them.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $data Array of key => values note fields.
|
||||
* @return void
|
||||
*/
|
||||
public function attributes($data) {
|
||||
|
||||
$allowed_attributes = array_keys(self::fields());
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
|
||||
if (in_array($key, $allowed_attributes, true)) {
|
||||
|
||||
$this->attributes[$key] = $value;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
$this->attributes['date_created'] = wu_get_current_time('mysql', true);
|
||||
|
||||
} // end attributes;
|
||||
|
||||
/**
|
||||
* Checks if this note has any content at all.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function exists() {
|
||||
|
||||
return !empty(array_filter($this->attributes));
|
||||
|
||||
} // end exists;
|
||||
|
||||
/**
|
||||
* Checks if a parameter exists.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $name The parameter to check.
|
||||
* @return boolean
|
||||
*/
|
||||
public function __isset($name) {
|
||||
|
||||
return wu_get_isset($this->attributes, $name, '');
|
||||
|
||||
} // end __isset;
|
||||
|
||||
/**
|
||||
* Gets a note field.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $name The parameter to return.
|
||||
* @return string
|
||||
*/
|
||||
public function __get($name) {
|
||||
|
||||
$value = wu_get_isset($this->attributes, $name, '');
|
||||
|
||||
return apply_filters("wu_note_get_{$name}", $value, $this);
|
||||
|
||||
} // end __get;
|
||||
|
||||
/**
|
||||
* Sets a note field.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $name Field name.
|
||||
* @param string $value The field value.
|
||||
*/
|
||||
public function __set($name, $value) {
|
||||
|
||||
$value = apply_filters("wu_note_set_{$name}", $value, $this);
|
||||
|
||||
$this->attributes[$name] = $value;
|
||||
|
||||
} // end __set;
|
||||
|
||||
/**
|
||||
* Returns the validation rules for new notes.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
protected function validation_rules() {
|
||||
|
||||
return array();
|
||||
|
||||
} // end validation_rules;
|
||||
|
||||
/**
|
||||
* Validates the fields following the validation rules.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return true|\WP_Error
|
||||
*/
|
||||
public function validate() {
|
||||
|
||||
$validator = new \WP_Ultimo\Helpers\Validator;
|
||||
|
||||
$validator->validate($this->to_array(), $this->validation_rules());
|
||||
|
||||
if ($validator->fails()) {
|
||||
|
||||
return $validator->get_errors();
|
||||
|
||||
} // end if;
|
||||
|
||||
return true;
|
||||
|
||||
} // end validate;
|
||||
|
||||
/**
|
||||
* Returns a key => value representation of the notes fields.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param boolean $labels Wether or not to return labels as keys or the actual keys.
|
||||
* @return array
|
||||
*/
|
||||
public function to_array($labels = false) {
|
||||
|
||||
$address_array = array();
|
||||
|
||||
$fields = self::fields();
|
||||
|
||||
foreach ($fields as $field_key => $field) {
|
||||
|
||||
if (!empty($this->{$field_key})) {
|
||||
|
||||
$key = $labels ? $field['title'] : $field_key;
|
||||
|
||||
$address_array[$key] = $this->{$field_key};
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return $address_array;
|
||||
|
||||
} // end to_array;
|
||||
/**
|
||||
* Returns the contents of the note.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $delimiter Delimiter to glue address pieces together.
|
||||
*/
|
||||
public function to_string($delimiter = PHP_EOL): string {
|
||||
|
||||
return implode($delimiter, $this->to_array());
|
||||
|
||||
} // end to_string;
|
||||
|
||||
/**
|
||||
* Note field definitions.
|
||||
*
|
||||
* This is used to determine fields allowed on the note.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public static function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['text'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Text', 'wp-ultimo'),
|
||||
);
|
||||
|
||||
$fields['author_id'] = array(
|
||||
'type' => 'number',
|
||||
'title' => __('Author ID', 'wp-ultimo'),
|
||||
);
|
||||
|
||||
$fields['note_id'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Note ID', 'wp-ultimo'),
|
||||
);
|
||||
|
||||
uasort($fields, 'wu_sort_by_order');
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
} // end class Note;
|
206
inc/objects/class-visits.php
Normal file
206
inc/objects/class-visits.php
Normal file
@ -0,0 +1,206 @@
|
||||
<?php
|
||||
/**
|
||||
* Visit manager for sites.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage Objects
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\Objects;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Visit manager for sites.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Visits {
|
||||
|
||||
/**
|
||||
* Key to save on the database.
|
||||
*/
|
||||
const KEY = 'wu_visits';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $site_id;
|
||||
|
||||
/**
|
||||
* Sets the current site to manage.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param int $site_id The current site id.
|
||||
*/
|
||||
public function __construct($site_id)
|
||||
{
|
||||
$this->site_id = $site_id;
|
||||
} // end __construct;
|
||||
/**
|
||||
* Returns the meta key to save visits.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param boolean $day The day in the Ymd format. E.g. 20210211.
|
||||
*/
|
||||
protected function get_meta_key($day): string {
|
||||
|
||||
return sprintf('%s_%s', self::KEY, $day);
|
||||
|
||||
} // end get_meta_key;
|
||||
|
||||
/**
|
||||
* Adds visits to a site count.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param integer $count Counts to add.
|
||||
* @param boolean $day The day in the Ymd format. E.g. 20210211.
|
||||
* @return bool
|
||||
*/
|
||||
public function add_visit($count = 1, $day = false) {
|
||||
|
||||
if (!$day) {
|
||||
|
||||
$day = gmdate('Ymd');
|
||||
|
||||
} // end if;
|
||||
|
||||
$key = $this->get_meta_key($day);
|
||||
|
||||
$current_value = (int) get_site_meta($this->site_id, $key, true);
|
||||
|
||||
$new_value = $current_value + $count;
|
||||
|
||||
return update_site_meta($this->site_id, $key, $new_value);
|
||||
|
||||
} // end add_visit;
|
||||
|
||||
/**
|
||||
* Returns an array of the dates and counts by day.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param bool|string $start_date The start date. Any strtotime-compatible string works.
|
||||
* @param bool|string $end_date The end date. Any strtotime-compatible string works.
|
||||
* @return array
|
||||
*/
|
||||
public function get_visits($start_date = false, $end_date = false) {
|
||||
|
||||
global $wpdb;
|
||||
|
||||
if (!$start_date) {
|
||||
|
||||
$start_date = wu_get_current_time('mysql', true);
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!$end_date) {
|
||||
|
||||
$end_date = wu_get_current_time('mysql', true);
|
||||
|
||||
} // end if;
|
||||
|
||||
$query = $wpdb->prepare("
|
||||
SELECT meta_value as count, str_to_date(meta_key, 'wu_visits_%%Y%%m%%d') as day, blog_id as site_id
|
||||
FROM {$wpdb->base_prefix}blogmeta
|
||||
WHERE blog_id = %d
|
||||
", $this->site_id);
|
||||
|
||||
$query .= $wpdb->prepare(" AND str_to_date(meta_key, 'wu_visits_%%Y%%m%%d') BETWEEN %s AND %s", gmdate('Y-m-d', strtotime($start_date)), gmdate('Y-m-d', strtotime($end_date)));
|
||||
|
||||
return $wpdb->get_results($query); // phpcs:ignore
|
||||
|
||||
} // end get_visits;
|
||||
|
||||
/**
|
||||
* The total visits for the current site.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param bool|string $start_date The start date. Any strtotime-compatible string works.
|
||||
* @param bool|string $end_date The end date. Any strtotime-compatible string works.
|
||||
* @return int
|
||||
*/
|
||||
public function get_visit_total($start_date = false, $end_date = false) {
|
||||
|
||||
global $wpdb;
|
||||
|
||||
if (!$start_date) {
|
||||
|
||||
$start_date = wu_get_current_time('mysql', true);
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!$end_date) {
|
||||
|
||||
$end_date = wu_get_current_time('mysql', true);
|
||||
|
||||
} // end if;
|
||||
|
||||
$query = $wpdb->prepare("
|
||||
SELECT SUM(meta_value) as count
|
||||
FROM {$wpdb->base_prefix}blogmeta
|
||||
WHERE blog_id = %d
|
||||
", $this->site_id);
|
||||
|
||||
$query .= $wpdb->prepare(" AND str_to_date(meta_key, 'wu_visits_%%Y%%m%%d') BETWEEN %s AND %s", gmdate('Y-m-d', strtotime($start_date)), gmdate('Y-m-d', strtotime($end_date)));
|
||||
|
||||
return (int) $wpdb->get_var($query); // phpcs:ignore
|
||||
|
||||
} // end get_visit_total;
|
||||
|
||||
/**
|
||||
* Get sites by visit count.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param bool|string $start_date The start date. Any strtotime-compatible string works.
|
||||
* @param bool|string $end_date The end date. Any strtotime-compatible string works.
|
||||
* @param integer $limit The number of sites to return.
|
||||
* @return array
|
||||
*/
|
||||
public static function get_sites_by_visit_count($start_date = false, $end_date = false, $limit = 5) {
|
||||
|
||||
global $wpdb;
|
||||
|
||||
if (!$start_date) {
|
||||
|
||||
$start_date = wu_get_current_time('mysql', true);
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!$end_date) {
|
||||
|
||||
$end_date = wu_get_current_time('mysql', true);
|
||||
|
||||
} // end if;
|
||||
|
||||
$sub_query = "
|
||||
SELECT SUM(meta_value) as count, blog_id
|
||||
FROM {$wpdb->base_prefix}blogmeta as m
|
||||
";
|
||||
|
||||
$sub_query .= $wpdb->prepare(" WHERE str_to_date(meta_key, 'wu_visits_%%Y%%m%%d') BETWEEN %s AND %s", gmdate('Y-m-d', strtotime($start_date)), gmdate('Y-m-d', strtotime($end_date)));
|
||||
|
||||
$sub_query .= ' GROUP BY blog_id';
|
||||
|
||||
// phpcs:disable
|
||||
$query = $wpdb->prepare("
|
||||
SELECT b.blog_id as site_id, s.count
|
||||
FROM {$wpdb->base_prefix}blogs as b
|
||||
JOIN ({$sub_query}) as s
|
||||
ON s.blog_id = b.blog_id
|
||||
ORDER BY count DESC
|
||||
LIMIT %d
|
||||
", $limit);
|
||||
// phpcs:enable
|
||||
|
||||
return $wpdb->get_results($query); // phpcs:ignore
|
||||
|
||||
} // end get_sites_by_visit_count;
|
||||
|
||||
} // end class Visits;
|
Reference in New Issue
Block a user