Initial Commit
This commit is contained in:
80
inc/models/traits/trait-billable.php
Normal file
80
inc/models/traits/trait-billable.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* A trait to handle billable models.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage Models\Traits
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\Models\Traits;
|
||||
|
||||
use \WP_Ultimo\Objects\Billing_Address;
|
||||
|
||||
/**
|
||||
* Singleton trait.
|
||||
*/
|
||||
trait Billable {
|
||||
|
||||
/**
|
||||
* The billing address.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var \WP_Ultimo\Objects\Billing_Address
|
||||
*/
|
||||
protected $billing_address;
|
||||
|
||||
/**
|
||||
* Returns the default billing address.
|
||||
*
|
||||
* Classes that implement this trait need to implement
|
||||
* this method.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return \WP_Ultimo\Objects\Billing_Address
|
||||
*/
|
||||
abstract public function get_default_billing_address();
|
||||
|
||||
/**
|
||||
* Gets the billing address for this object.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return \WP_Ultimo\Objects\Billing_Address
|
||||
*/
|
||||
public function get_billing_address() {
|
||||
|
||||
if ($this->billing_address === null) {
|
||||
|
||||
$billing_address = $this->get_meta('wu_billing_address');
|
||||
|
||||
$this->billing_address = is_a($billing_address, '\WP_Ultimo\Objects\Billing_Address') ? $billing_address : $this->get_default_billing_address();
|
||||
|
||||
} // end if;
|
||||
|
||||
return $this->billing_address;
|
||||
|
||||
} // end get_billing_address;
|
||||
|
||||
/**
|
||||
* Sets the billing address.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array|\WP_Ultimo\Objects\Billing_Address $billing_address The billing address.
|
||||
* @return void
|
||||
*/
|
||||
public function set_billing_address($billing_address) {
|
||||
|
||||
if (is_array($billing_address)) {
|
||||
|
||||
$billing_address = new Billing_Address($billing_address);
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->meta['wu_billing_address'] = $billing_address;
|
||||
|
||||
$this->billing_address = $billing_address;
|
||||
|
||||
} // end set_billing_address;
|
||||
|
||||
} // end trait Billable;
|
348
inc/models/traits/trait-limitable.php
Normal file
348
inc/models/traits/trait-limitable.php
Normal file
@ -0,0 +1,348 @@
|
||||
<?php
|
||||
/**
|
||||
* A trait to handle limitable models.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage Models\Traits
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\Models\Traits;
|
||||
|
||||
use \WP_Ultimo\Database\Sites\Site_Type;
|
||||
use \WP_Ultimo\Objects\Limitations;
|
||||
|
||||
/**
|
||||
* Singleton trait.
|
||||
*/
|
||||
trait Limitable {
|
||||
|
||||
/**
|
||||
* Internal limitations cache.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var array
|
||||
*/
|
||||
protected $_limitations = array();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
public function get_limitations($waterfall = true, $skip_self = false) {
|
||||
|
||||
/**
|
||||
* If this is a site, and it's not a customer owned site, we don't have limitations.
|
||||
* This is because we don't want to limit sites other than the customer owned ones.
|
||||
*/
|
||||
if ($this->model === 'site' && $this->get_type() !== Site_Type::CUSTOMER_OWNED) {
|
||||
|
||||
return new Limitations(array());
|
||||
|
||||
} // end if;
|
||||
|
||||
$cache_key = $waterfall ? '_composite_limitations_' : '_limitations_';
|
||||
|
||||
$cache_key = $skip_self ? $cache_key . '_no_self_' : $cache_key;
|
||||
|
||||
$cache_key = $this->get_id() . $cache_key . $this->model;
|
||||
|
||||
$cached_version = wu_get_isset($this->_limitations, $cache_key);
|
||||
|
||||
if (!empty($cached_version)) {
|
||||
|
||||
return $cached_version;
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!is_array($this->meta)) {
|
||||
|
||||
$this->meta = array();
|
||||
|
||||
} // end if;
|
||||
|
||||
if (did_action('muplugins_loaded') === false) {
|
||||
|
||||
$modules_data = $this->get_meta('wu_limitations', array());
|
||||
|
||||
} else {
|
||||
|
||||
$modules_data = Limitations::early_get_limitations($this->model, $this->get_id());
|
||||
|
||||
} // end if;
|
||||
|
||||
$limitations = new Limitations(array());
|
||||
|
||||
if ($waterfall) {
|
||||
|
||||
$limitations = $limitations->merge(...$this->limitations_to_merge());
|
||||
|
||||
/**
|
||||
* If we don't want to take into consideration our own permissions
|
||||
* we set this flag to true.
|
||||
*
|
||||
* This will return only the parents permissions and is super useful for
|
||||
* comparisons.
|
||||
*/
|
||||
if (!$skip_self) {
|
||||
|
||||
$limitations = $limitations->merge(true, $modules_data);
|
||||
|
||||
} // end if;
|
||||
|
||||
} else {
|
||||
|
||||
$limitations = $limitations->merge($modules_data);
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->_limitations[$cache_key] = $limitations;
|
||||
|
||||
return $limitations;
|
||||
|
||||
} // end get_limitations;
|
||||
|
||||
/**
|
||||
* Checks if this site has limitations or not.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function has_limitations() {
|
||||
|
||||
return $this->get_limitations()->has_limitations();
|
||||
|
||||
} // end 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) {
|
||||
|
||||
return $this->get_limitations()->is_module_enabled($module);
|
||||
|
||||
} // end has_module_limitation;
|
||||
|
||||
/**
|
||||
* Returns all user role quotas.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_user_role_quotas() {
|
||||
|
||||
return $this->get_limitations()->get_user_role_quotas();
|
||||
|
||||
} // end get_user_role_quotas;
|
||||
|
||||
/**
|
||||
* Proxy method to retrieve the allowed user roles.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_allowed_user_roles() {
|
||||
|
||||
return $this->get_limitations()->get_allowed_user_roles();
|
||||
|
||||
} // end 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() {
|
||||
|
||||
$sites = array();
|
||||
|
||||
if ($this->model === 'site') {
|
||||
|
||||
$sites[] = $this;
|
||||
|
||||
} elseif ($this->model === 'membership') {
|
||||
|
||||
$sites = $this->get_sites();
|
||||
|
||||
} // end if;
|
||||
|
||||
foreach ($sites as $site_object) {
|
||||
|
||||
if (!$site_object->get_id() || $site_object->get_type() !== Site_Type::CUSTOMER_OWNED) {
|
||||
|
||||
continue;
|
||||
|
||||
} // end if;
|
||||
|
||||
$site_id = $site_object->get_id();
|
||||
$limitations = $site_object->get_limitations();
|
||||
|
||||
if (!$limitations->plugins->is_enabled()) {
|
||||
|
||||
continue;
|
||||
|
||||
} // end if;
|
||||
|
||||
$plugins_to_deactivate = $limitations->plugins->get_by_type('force_inactive');
|
||||
$plugins_to_activate = $limitations->plugins->get_by_type('force_active');
|
||||
|
||||
if ($plugins_to_deactivate) {
|
||||
|
||||
wu_async_deactivate_plugins($site_id, array_keys($plugins_to_deactivate));
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($plugins_to_activate) {
|
||||
|
||||
wu_async_activate_plugins($site_id, array_keys($plugins_to_activate));
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
} // end sync_plugins;
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
/*
|
||||
* Only handle limitations if there are to handle in the first place.
|
||||
*/
|
||||
if (!wu_request('modules')) {
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
$object_limitations = $this->get_limitations(false);
|
||||
|
||||
$saved_limitations = $object_limitations->to_array();
|
||||
|
||||
$modules_to_save = array();
|
||||
|
||||
$limitations = Limitations::repository();
|
||||
|
||||
$current_limitations = $this->get_limitations(true, true);
|
||||
|
||||
foreach ($limitations as $limitation_id => $class_name) {
|
||||
|
||||
$module = wu_get_isset($saved_limitations, $limitation_id, array());
|
||||
|
||||
try {
|
||||
|
||||
if (is_string($module)) {
|
||||
|
||||
$module = json_decode($module, true);
|
||||
|
||||
} // end if;
|
||||
|
||||
} catch (\Throwable $exception) {
|
||||
|
||||
// Silence is golden.
|
||||
|
||||
} // end try;
|
||||
|
||||
$module['enabled'] = $object_limitations->{$limitation_id}->handle_enabled();
|
||||
|
||||
$module['limit'] = $object_limitations->{$limitation_id}->handle_limit();
|
||||
|
||||
$module = $object_limitations->{$limitation_id}->handle_others($module);
|
||||
|
||||
if ($module) {
|
||||
|
||||
$modules_to_save[$limitation_id] = $module;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
if ($this->model !== 'product') {
|
||||
/*
|
||||
* Set the new permissions, based on the diff.
|
||||
*/
|
||||
$limitations = wu_array_recursive_diff($modules_to_save, $current_limitations->to_array());
|
||||
|
||||
} elseif ($this->model === 'product' && $this->get_type() !== 'plan') {
|
||||
|
||||
$limitations = wu_array_recursive_diff($modules_to_save, Limitations::get_empty()->to_array());
|
||||
|
||||
} else {
|
||||
|
||||
$limitations = $modules_to_save;
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->meta['wu_limitations'] = $limitations;
|
||||
|
||||
} // end handle_limitations;
|
||||
|
||||
/**
|
||||
* Returns the list of product slugs associated with this model.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_applicable_product_slugs() {
|
||||
|
||||
if ($this->model === 'product') {
|
||||
|
||||
return array($this->get_slug());
|
||||
|
||||
} // end if;
|
||||
|
||||
$slugs = array();
|
||||
|
||||
if ($this->model === 'membership') {
|
||||
|
||||
$membership = $this;
|
||||
|
||||
} elseif ($this->model === 'site') {
|
||||
|
||||
$membership = $this->get_membership();
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!empty($membership)) {
|
||||
|
||||
$slugs = array_column(array_map('wu_cast_model_to_array', array_column($membership->get_all_products(), 'product')), 'slug'); // WOW
|
||||
|
||||
} // end if;
|
||||
|
||||
return $slugs;
|
||||
|
||||
} // end get_applicable_product_slugs;
|
||||
|
||||
} // end trait Limitable;
|
171
inc/models/traits/trait-notable.php
Normal file
171
inc/models/traits/trait-notable.php
Normal file
@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/**
|
||||
* A trait to handle notable models.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage Models\Traits
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\Models\Traits;
|
||||
|
||||
use \WP_Ultimo\Objects\Note;
|
||||
|
||||
/**
|
||||
* Singleton trait.
|
||||
*/
|
||||
trait Notable {
|
||||
|
||||
/**
|
||||
* The notes saved.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var \WP_Ultimo\Objects\Note[]
|
||||
*/
|
||||
protected $notes;
|
||||
|
||||
/**
|
||||
* Get all the notes saved for this model.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return \WP_Ultimo\Objects\Note[]
|
||||
*/
|
||||
public function get_notes() {
|
||||
|
||||
if ($this->notes === null) {
|
||||
|
||||
$this->notes = get_metadata($this->get_meta_data_table_name(), $this->get_id(), 'wu_note', false);
|
||||
|
||||
} // end if;
|
||||
|
||||
return $this->notes;
|
||||
|
||||
} // end get_notes;
|
||||
|
||||
/**
|
||||
* Adds a new note to this model.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array|\WP_Ultimo|Objects\Note $note The note to add.
|
||||
* @return bool
|
||||
*/
|
||||
public function add_note($note) {
|
||||
|
||||
if (!is_a($note, 'Note')) {
|
||||
|
||||
$note = new Note($note);
|
||||
|
||||
} // end if;
|
||||
|
||||
$status = $note->validate();
|
||||
|
||||
if (is_wp_error($status)) {
|
||||
|
||||
return $status;
|
||||
|
||||
} // end if;
|
||||
|
||||
$status = add_metadata($this->get_meta_data_table_name(), $this->get_id(), 'wu_note', $note, false);
|
||||
|
||||
return $status;
|
||||
|
||||
} // end add_note;
|
||||
|
||||
/**
|
||||
* Remove all notes related to this model.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return bool
|
||||
*/
|
||||
public function clear_notes() {
|
||||
|
||||
$status = delete_metadata($this->get_meta_data_table_name(), $this->get_id(), 'wu_note', '', true);
|
||||
|
||||
return $status;
|
||||
|
||||
} // end clear_notes;
|
||||
|
||||
/**
|
||||
* Remove one note related to this model.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $note_id The Note ID.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete_note($note_id) {
|
||||
|
||||
$model = $this->model;
|
||||
|
||||
$notes = $this->get_notes();
|
||||
|
||||
$mid = false;
|
||||
|
||||
foreach ($notes as $note) {
|
||||
|
||||
if ($note->note_id && $note->note_id === $note_id) {
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$prefix = $wpdb->base_prefix;
|
||||
|
||||
$table_name = "{$prefix}wu_{$model}meta";
|
||||
|
||||
$column_name = "wu_{$model}_id";
|
||||
|
||||
if ($model === 'site') {
|
||||
|
||||
$table_name = "{$wpdb->base_prefix}blogmeta";
|
||||
|
||||
$column_name = 'blog_id';
|
||||
|
||||
} // end if;
|
||||
|
||||
$mid = $wpdb->get_row($wpdb->prepare("SELECT meta_id FROM $table_name WHERE $column_name = %d AND meta_key = %s AND meta_value = %s", $this->get_id(), 'wu_note', maybe_serialize($note)), ARRAY_A); // phpcs:ignore
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
if (!$mid) {
|
||||
|
||||
return false;
|
||||
|
||||
} // end if;
|
||||
|
||||
$status = delete_metadata_by_mid("wu_{$model}", $mid['meta_id']);
|
||||
|
||||
if ($model === 'site') {
|
||||
|
||||
$status = delete_metadata_by_mid('blog', $mid['meta_id']);
|
||||
|
||||
} // end if;
|
||||
|
||||
return $status;
|
||||
|
||||
} // end delete_note;
|
||||
|
||||
/**
|
||||
* Returns the meta data meta table.
|
||||
*
|
||||
* This is redundant, but it is better than changing the access of the original method.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
protected function get_meta_data_table_name() {
|
||||
|
||||
$query_class = new $this->query_class();
|
||||
|
||||
// Maybe apply table prefix
|
||||
$table = !empty($query_class->prefix)
|
||||
? "{$query_class->prefix}_{$query_class->item_name}"
|
||||
: $query_class->item_name;
|
||||
|
||||
return $table;
|
||||
|
||||
} // end get_meta_data_table_name;
|
||||
|
||||
} // end trait Notable;
|
Reference in New Issue
Block a user