get_options())); return array( 'categories' => 'default:', 'featured_image_id' => 'integer|default:', 'site_id' => 'required|integer', 'title' => 'required', 'name' => 'required', 'description' => 'required|min:2', 'domain' => 'domain', 'path' => 'required|default:', 'registered' => "default:{$date}", 'last_updated' => 'default:', 'public' => 'boolean|default:1', 'archived' => 'boolean|default:0', 'mature' => 'boolean|default:0', 'spam' => 'boolean|default:0', 'deleted' => 'boolean|default:0', 'is_publishing' => 'boolean|default:0', 'land_id' => 'integer|default:', 'customer_id' => 'required|integer|exists:\WP_Ultimo\Models\Customer,id', 'membership_id' => 'required|integer|exists:\WP_Ultimo\Models\Membership,id', 'template_id' => 'integer|default:', 'type' => "required|in:{$site_types}", 'signup_options' => 'default:', ); } // end validation_rules; /** * Get the visits for this particular sites. * * @since 2.0.0 * @return int */ public function get_visits_count() { $visits_manager = new \WP_Ultimo\Objects\Visits($this->get_id()); return $visits_manager->get_visit_total('first day of this month', 'last day of this month'); } // end get_visits_count; /** * Set the categories for the site. * * @since 2.0.0 * * @param array $categories The categories this site belongs to. * @return void */ public function set_categories($categories) { $this->meta['wu_categories'] = $categories; $this->categories = $categories; } // end set_categories; /** * Get the list of categories. * * @since 2.0.0 * @return string */ public function get_categories() { if ($this->categories === null) { $this->categories = $this->get_meta('wu_categories', array()); } // end if; if (!is_array($this->categories)) { return array(); } // end if; return array_filter($this->categories); } // end get_categories; /** * Get featured image ID. * * @since 2.0.0 * @return int */ public function get_featured_image_id() { if ($this->featured_image_id === null) { return $this->get_meta('wu_featured_image_id'); } // end if; return $this->featured_image_id; } // end get_featured_image_id; /** * Get featured image url. * * @since 2.0.0 * @param string $size The size of the image to retrieve. * @return string */ public function get_featured_image($size = 'wu-thumb-medium') { if ($this->get_type() === 'external') { return wu_get_asset('wp-ultimo-screenshot.png'); } // end if; is_multisite() && switch_to_blog(wu_get_main_site_id()); $size = apply_filters('wu_site_featured_image_size', $size, $this); $image_attributes = wp_get_attachment_image_src($this->get_featured_image_id(), $size); is_multisite() && restore_current_blog(); if ($image_attributes) { return $image_attributes[0]; } // end if; return wu_get_asset('site-placeholder-image.png', 'img'); } // end get_featured_image; /** * Set featured image ID. * * @since 2.0.0 * @param int $image_id The ID of the feature image of the site. * @return void */ public function set_featured_image_id($image_id) { $this->meta['wu_featured_image_id'] = $image_id; $this->featured_image_id = $image_id; } // end set_featured_image_id; /** * Get the preview URL. * * @since 2.0.0 * @return string */ public function get_preview_url() { return Template_Previewer::get_instance()->get_preview_url($this->get_id()); } // end get_preview_url; /** * Get the preview URL attrs. * * @since 2.0.0 */ public function get_preview_url_attrs(): string { $is_enabled = Template_Previewer::get_instance()->get_setting('enabled'); $href = 'href="%s" target="_blank"'; if (!$is_enabled) { return sprintf($href, $this->get_active_site_url()); } // end if; $onclick = 'onclick="window.open(\'%s\')"'; return sprintf($onclick, add_query_arg('open', 1, $this->get_preview_url())); } // end get_preview_url_attrs; /** * Get blog ID. Should be accessed via id. * * @since 2.0.0 * @return int */ public function get_id() { return $this->get_blog_id(); } // end get_id; /** * Get blog ID. Should be accessed via id.. * * @since 2.0.0 * @return int */ public function get_blog_id() { return (int) $this->blog_id; } // end get_blog_id; /** * Set blog ID. Should be accessed via id.. * * @since 2.0.0 * @param int $blog_id The blog ID. Should be accessed via id. * @return void */ public function set_blog_id($blog_id) { $this->blog_id = $blog_id; } // end set_blog_id; /** * Get network ID for this site.. * * @since 2.0.0 * @return int */ public function get_site_id() { return $this->site_id; } // end get_site_id; /** * Set network ID for this site.. * * @since 2.0.0 * @param int $site_id The network ID for this site. * @return void */ public function set_site_id($site_id) { $this->site_id = $site_id; } // end set_site_id; /** * Get title of the site.. * * @since 2.0.0 */ public function get_title(): string { return stripslashes($this->title); } // end get_title; /** * Set title of the site. * * @since 2.0.0 * * @param string $title The site title. * @return void */ public function set_title($title) { $this->title = sanitize_text_field($title); } // end set_title; /** * Alias to get name. * * @since 2.0.0 * @return string */ public function get_name() { return $this->get_title(); } // end get_name; /** * Alias to set title. * * @since 2.0.0 * @param string $title The site name. * @return void */ public function set_name($title) { $this->set_title($title); } // end set_name; /** * Gets the site description. * * @since 2.0.0 * @return string */ public function get_description() { if ($this->description) { return $this->description; } // end if; return get_blog_option($this->get_id(), 'blogdescription'); } // end get_description; /** * Sets the site description. * * @todo This is not yet persistent. * * @since 2.0.0 * @param string $description A description for the site, usually a short text. * @return void */ public function set_description($description) { $this->description = $description; } // end set_description; /** * Get domain name used by this site.. * * @since 2.0.0 * @return string */ public function get_domain() { return $this->domain; } // end get_domain; /** * Set domain name used by this site.. * * @since 2.0.0 * @param string $domain The site domain. You don't need to put http or https in front of your domain in this field. e.g: example.com. * @return void */ public function set_domain($domain) { $this->domain = $domain; } // end set_domain; /** * Get path of the site. Used when in sub-directory mode.. * * @since 2.0.0 */ public function get_path(): string { return trim($this->path, '/'); } // end get_path; /** * Set path of the site. Used when in sub-directory mode.. * * @since 2.0.0 * @param string $path Path of the site. Used when in sub-directory mode. * @return void */ public function set_path($path) { $this->path = $path; } // end set_path; /** * Get date when the site was registered.. * * @since 2.0.0 * @return string */ public function get_registered() { return $this->registered; } // end get_registered; /** * Proxy for a common API. * * @since 2.0.0 * @return string */ public function get_date_registered() { return $this->get_registered(); } // end get_date_registered; /** * Set date when the site was registered.. * * @since 2.0.0 * @param string $registered Date when the site was registered. * @return void */ public function set_registered($registered) { $this->registered = $registered; } // end set_registered; /** * Get date of the last update on this site. * * @since 2.0.0 * @return string */ public function get_last_updated() { return $this->last_updated; } // end get_last_updated; /** * Proxy to last_updated. * * @since 2.0.0 * @return string */ public function get_date_modified() { return $this->get_last_updated(); } // end get_date_modified; /** * Set date of the last update on this site.. * * @since 2.0.0 * @param string $last_updated Date of the last update on this site. * @return void */ public function set_last_updated($last_updated) { $this->last_updated = $last_updated; } // end set_last_updated; /** * Get if the site is being published. * * @since 2.0.11 * @return int */ public function is_publishing() { return $this->is_publishing; } // end is_publishing; /** * Set if the site is being published. * * @since 2.0.11 * @param int $publishing Holds the ID of the customer that owns this site. * @return void */ public function set_publishing($publishing) { $this->is_publishing = $publishing; } // end set_publishing; /** * Get holds the ID of the customer that owns this site. * * @since 2.0.0 * @return int */ public function is_active() { if ($this->active === null) { $this->active = $this->get_meta('wu_active', true); } // end if; return $this->active; } // end is_active; /** * Set holds the ID of the customer that owns this site.. * * @since 2.0.0 * @param int $active Holds the ID of the customer that owns this site. * @return void */ public function set_active($active) { $this->meta['wu_active'] = $active; $this->active = $active; } // end set_active; /** * Get is this a public site?. * * @since 2.0.0 * @return bool */ public function get_public() { return $this->public; } // end get_public; /** * Set is this a public site?. * * @since 2.0.0 * @param bool $public Set true if this site is a public one, false if not. * @return void */ public function set_public($public) { $this->public = $public; } // end set_public; /** * Get is this an archived site. * * @since 2.0.0 * @return bool */ public function is_archived() { return $this->archived; } // end is_archived; /** * Set is this an archived site?. * * @since 2.0.0 * @param bool $archived Is this an archived site. * @return void */ public function set_archived($archived) { $this->archived = $archived; } // end set_archived; /** * Get is this a site with mature content. * * @since 2.0.0 * @return bool */ public function is_mature() { return $this->mature; } // end is_mature; /** * Set is this a site with mature content?. * * @since 2.0.0 * @param bool $mature Is this a site with mature content. * @return void */ public function set_mature($mature) { $this->mature = $mature; } // end set_mature; /** * Get is this an spam site. * * @since 2.0.0 * @return bool */ public function is_spam() { return $this->spam; } // end is_spam; /** * Set is this an spam site?. * * @since 2.0.0 * @param bool $spam Is this an spam site. * @return void */ public function set_spam($spam) { $this->spam = $spam; } // end set_spam; /** * Get is this site deleted. * * @since 2.0.0 * @return bool */ public function is_deleted() { return $this->deleted; } // end is_deleted; /** * Set is this site deleted?. * * @since 2.0.0 * @param bool $deleted Is this site deleted. * @return void */ public function set_deleted($deleted) { $this->deleted = $deleted; } // end set_deleted; /** * Get iD of the language being used on this site. * * @since 2.0.0 * @return int */ public function get_lang_id() { return $this->lang_id; } // end get_lang_id; /** * Set iD of the language being used on this site. * * @since 2.0.0 * @param int $lang_id The ID of the language being used on this site. * @return void */ public function set_lang_id($lang_id) { $this->lang_id = $lang_id; } // end set_lang_id; /** * Get holds the ID of the customer that owns this site.. * * @since 2.0.0 * @return int */ public function get_customer_id() { if ($this->customer_id === null) { $this->customer_id = $this->get_meta('wu_customer_id'); } // end if; return (int) $this->customer_id; } // end get_customer_id; /** * Set holds the ID of the customer that owns this site.. * * @since 2.0.0 * @param int $customer_id The ID of the customer that owns this site. * @return void */ public function set_customer_id($customer_id) { $this->meta['wu_customer_id'] = $customer_id; $this->customer_id = $customer_id; } // end set_customer_id; /** * Gets the customer object associated with this membership. * * @since 2.0.0 * @return \WP_Ultimo\Models\Customer|false; */ public function get_customer() { return wu_get_customer($this->get_customer_id()); } // end get_customer; /** * Checks if a given customer should have access to this site options. * * @since 2.0.0 * * @param int $customer_id The customer id to check. * @return boolean */ public function is_customer_allowed($customer_id = false) { if (current_user_can('manage_network')) { return true; } // end if; if (!$customer_id) { $customer = WP_Ultimo()->currents->get_customer(); $customer_id = $customer ? $customer->get_id() : 0; } // end if; $allowed = absint($customer_id) === absint($this->get_customer_id()); return apply_filters('wu_site_is_customer_allowed', $allowed, $customer_id, $this); } // end is_customer_allowed; /** * Get holds the ID of the membership associated with this site, if any.. * * @since 2.0.0 * @return int */ public function get_membership_id() { if ($this->membership_id === null) { $this->membership_id = $this->get_meta('wu_membership_id'); } // end if; return $this->membership_id; } // end get_membership_id; /** * Set holds the ID of the membership associated with this site, if any.. * * @since 2.0.0 * @param int $membership_id The ID of the membership associated with this site, if any. * @return void */ public function set_membership_id($membership_id) { $this->meta['wu_membership_id'] = $membership_id; $this->membership_id = $membership_id; } // end set_membership_id; /** * Checks if this site has a membership. * * @since 2.0.0 * @return boolean */ public function has_membership() { return !empty($this->get_membership()); } // end has_membership; /** * Checks if the site has a product. * * @since 2.0.0 * @return boolean */ public function has_product() { return $this->has_membership() && $this->get_membership()->has_product(); } // end has_product; /** * Gets the membership object associated with this membership. * * @since 2.0.0 * @return \WP_Ultimo\Models\Membership|false; */ public function get_membership() { if ($this->_membership !== null) { return $this->_membership; } // end if; if (function_exists('wu_get_membership')) { $this->_membership = wu_get_membership($this->get_membership_id()); return $this->_membership; } // end if; global $wpdb; $table_name = "{$wpdb->base_prefix}wu_memberships"; $membership_id = $this->get_membership_id(); if (!$membership_id) { return false; } // end if; $query = $wpdb->prepare("SELECT * FROM {$table_name} WHERE id = %d LIMIT 1", $membership_id); // phpcs:ignore $results = $wpdb->get_row($query); // phpcs:ignore if (!$results) { return false; } // end if; $this->_membership = new \WP_Ultimo\Models\Membership($results); return $this->_membership; } // end get_membership; /** * Returns the plan that created this site. * * @since 2.0.0 * @return \WP_Ultimo\Models\Product|false */ public function get_plan() { if ($this->has_membership()) { return $this->get_membership()->get_plan(); } // end if; return false; } // end get_plan; /** * Get template ID. * * @since 2.0.0 * @return int|bool */ public function get_template_id() { if ($this->template_id === null) { $this->template_id = $this->get_meta('wu_template_id'); } // end if; return $this->template_id; } // end get_template_id; /** * Set the template ID. * * @since 2.0.0 * @param int $template_id The ID of the templated used to create this site. * @return void */ public function set_template_id($template_id) { $this->meta['wu_template_id'] = absint($template_id); $this->template_id = $template_id; } // end set_template_id; /** * Gets the site object associated with this membership. * * @since 2.0.0 * @return \WP_Ultimo\Models\Site|false; */ public function get_template() { return wu_get_site($this->get_template_id()); } // end get_template; /** * Returns the default duplication arguments. * * @since 2.0.0 * @return array */ protected function get_default_duplication_arguments() { return array( 'keep_users' => true, 'copy_files' => true, 'public' => true, ); } // end get_default_duplication_arguments; /** * Convert the Ultimo instance to a WP_Site. * * @since 2.0.11 * @return \WP_Site */ public function to_wp_site() { return get_site($this->get_id()); } // end to_wp_site; /** * Get duplication arguments.. * * @since 2.0.0 * @return array */ public function get_duplication_arguments() { $args = wp_parse_args($this->duplication_arguments, $this->get_default_duplication_arguments()); return $args; } // end get_duplication_arguments; /** * Set duplication arguments.. * * @since 2.0.0 * @param array $duplication_arguments Duplication arguments. * @return void */ public function set_duplication_arguments($duplication_arguments) { $this->duplication_arguments = $duplication_arguments; } // end set_duplication_arguments; /** * Get the site type of this particular site.. * * @since 2.0.0 * @return string */ public function get_type() { if ($this->get_id() && is_main_site($this->get_id())) { return 'main'; } // end if; if ($this->type === null) { $type = $this->get_meta('wu_type'); $this->type = $type ? $type : 'default'; } // end if; return $this->type; } // end get_type; /** * Set the site type of this particular site. * * @since 2.0.0 * @param string $type The type of this particular site. Can be default, site_template, customer_owned, pending, external, main or other values added by third-party add-ons. * @options \WP_Ultimo\Database\Sites\Site_Type * @return void */ public function set_type($type) { $this->meta = (array) $this->meta; $this->meta['wu_type'] = $type; $this->type = $type; } // end set_type; /** * Get the primary mapped domain for this site. * * @since 2.0.0 * @return \WP_Ultimo\Models\Domain|false */ public function get_primary_mapped_domain() { if (!function_exists('wu_get_domains')) { return false; } // end if; $domains = wu_get_domains(array( 'primary_domain' => true, 'blog_id' => $this->get_id(), 'stage__not_in' => \WP_Ultimo\Models\Domain::INACTIVE_STAGES, 'number' => 1, )); return empty($domains) ? false : $domains[0]; } // end get_primary_mapped_domain; /** * Returns the active site URL, which can be a mapped domain. * * @since 2.0.0 * @return string */ public function get_active_site_url() { if (!$this->get_id()) { return $this->get_site_url(); } // end if; $domain = $this->get_primary_mapped_domain(); if ($domain) { return $domain->get_url(); } // end if; return $this->get_site_url(); } // end get_active_site_url; /** * Returns the original URL for the blog. * * This is useful when we need to know the original URL, without * mapping applied. * * @since 2.0.0 * @return string */ public function get_site_url() { $url = set_url_scheme(esc_url(sprintf($this->get_domain() . '/' . $this->get_path()))); return $url; } // end get_site_url; /** * Checks if this model was already saved to the database. * * @since 2.0.0 * @return bool */ public function exists() { return !empty($this->blog_id); } // end exists; /** * Override te constructor due to this being a native table. * * @since 2.0.0 * * @param mixed $object Object containing the parameters. */ public function __construct($object = null) { parent::__construct($object); if (is_array($object)) { $object = (object) $object; } // end if; $details = get_blog_details($this->get_blog_id()); if ($details && $this->title === null) { $this->set_title($details->blogname); } // end if; /* * 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; } // end if; $object = (object) $object; } // end __construct; /** * Gets the form data saved at the time of the site creation. * * @since 2.0.0 * @return array */ public function get_transient() { if ($this->transient === null) { $this->transient = $this->get_meta('wu_transient'); } // end if; return $this->transient; } // end get_transient; /** * Holds the form data at the time of registration. * * @since 2.0.0 * @param array $transient Form data. * @return void */ public function set_transient($transient) { $this->meta['wu_transient'] = $transient; $this->transient = $transient; } // end set_transient; /** * Get signup options for the site. * * @since 2.0.0 * @return array */ public function get_signup_options() { return is_array($this->signup_options) ? $this->signup_options : array(); } // end get_signup_options; /** * Set signup options for the site. * * @since 2.0.0 * @param array $signup_options Keeps signup options for the site. * @return void */ public function set_signup_options($signup_options) { $this->signup_options = $signup_options; } // end set_signup_options; /** * Get signup meta for the site. * * @since 2.0.0 * @return array */ public function get_signup_meta() { return is_array($this->signup_meta) ? $this->signup_meta : array(); } // end get_signup_meta; /** * Set signup meta for the site. * * @since 2.0.0 * @param array $signup_meta Keeps signup meta for the site. * @return void */ public function set_signup_meta($signup_meta) { $this->signup_meta = $signup_meta; } // end set_signup_meta; /** * Returns the Label for a given type. * * @since 2.0.0 * @return string */ public function get_type_label() { $type = new Site_Type($this->get_type()); return $type->get_label(); } // end get_type_label; /** * Gets the classes for a given class. * * @since 2.0.0 * @return string */ public function get_type_class() { $type = new Site_Type($this->get_type()); return $type->get_classes(); } // end get_type_class; /** * Adds magic methods to return options. * * @since 2.0.0 * * @param string $name Method name. * @param array $args List of arguments. * @throws \BadMethodCallException Throws exception when method is not found. * @return mixed */ public function __call($name, $args) { if (strpos($name, 'get_option_') !== false) { $option = str_replace('get_option_', '', $name); return get_blog_option($this->get_id(), $option, false); } // end if; throw new \BadMethodCallException(__CLASS__ . "::$name()"); } // end __call; /** * Checks if this is the primary site of the customer. * * @since 2.0.0 * @return boolean */ public function is_customer_primary_site() { $customer = $this->get_customer(); if (!$customer) { return false; } // end if; $user_id = $customer->get_user_id(); if (!$user_id) { return false; } // end if; $primary_site_id = get_user_option('primary_blog', $user_id); return absint($primary_site_id) === absint($this->get_id()); } // end is_customer_primary_site; /** * Delete the model from the database. * * @since 2.0.0 * @return \WP_Error|bool */ public function delete() { if (!$this->get_id()) { return new \WP_Error("wu_{$this->model}_delete_unsaved_item", __('Item not found.', 'wp-ultimo')); } // end if; /** * Fires after an object is stored into the database. * * @since 2.0.0 * * @param \WP_Ultimo\Models\Base_Model $this The object instance. */ do_action("wu_{$this->model}_pre_delete", $this); // @phpstan-ignore-line try { $result = (bool) wp_delete_site($this->get_id()); } catch (\Throwable $e) { $result = false; wu_log_add('fatal-error', $e->getMessage(), LogLevel::ERROR); } // end try; /** * Fires after an object is stored into the database. * * @since 2.0.0 * * @param bool $result True if the object was successfully deleted. * @param Base_Model $this The object instance. */ do_action("wu_{$this->model}_post_delete", $result, $this); // @phpstan-ignore-line wp_cache_flush(); return $result; } // end delete; /** * Replaces meta fields with the data collected during signup. * * @since 2.0.0 * @return void */ protected function handles_existing_search_and_replace() { $transient = $this->get_transient(); if ($transient) { add_filter('wu_search_and_replace_on_duplication', function($replace_list, $from_site_id, $to_site_id) use ($transient) { foreach ($transient as $transient_key => $transient_value) { $key = sprintf('{{%s}}', $transient_key); $replace_list[$key] = $transient_value; } // end foreach; return $replace_list; }, 9, 3); } // end if; } // end handles_existing_search_and_replace; /** * Save (create or update) the model on the database. * * @since 2.0.0 * * @return bool */ public function save() { /* * Prepares the substitutions. */ $this->handles_existing_search_and_replace(); /** * In order to be backwards compatible here, we'll have to do some crazy stuff, * like overload the form session with the meta data saved on the pending site. */ if (has_filter('wu_search_and_replace_on_duplication')) { $transient = $this->get_transient(); $session = wu_get_session('signup'); $session->set('form', $transient); $session->commit(); } // end if; $data = get_object_vars($this); $original_site = new self($data['_original']); $original_customer_id = $original_site->get_customer_id(); unset($data['_original']); $data_unserialized = $data; $saved = true; $new = !$this->exists(); if ($new) { $network = get_network(); $domain = $this->get_domain() ? $this->get_domain() : $network->domain; $network_id = $this->get_site_id() ? $this->get_site_id() : get_current_network_id(); $user_id = get_current_user_id(); $customer = wu_get_customer($this->get_customer_id()); /* * By default, use the current user email address. */ $email = wp_get_current_user() ? wp_get_current_user()->user_email : get_network_option(null, 'admin_email'); if ($customer) { $user_id = $customer->get_user_id(); $email = $customer->get_email_address(); } // end if; /* * Decide if we need to duplicate this site, or create a new one. */ if ($this->get_template()) { $saved = \WP_Ultimo\Helpers\Site_Duplicator::duplicate_site($this->get_template_id(), $this->get_title(), array( 'email' => $email, 'path' => $this->get_path(), 'domain' => $domain, 'meta' => $this->get_signup_options(), 'user_id' => $user_id ? $user_id : 0, )); if (is_wp_error($saved)) { // Here we check if the site was created and if so, get the ID to finish the execution to ensure the customer is set. $error = $saved; $saved = get_blog_id_from_url($domain, $this->get_path()); if ($saved === 0 || $saved === wu_get_main_site_id()) { return $error; } // end if; } // end if; } else { $saved = wpmu_create_blog($domain, $this->get_path(), $this->get_title(), $user_id, $this->get_signup_options(), $network_id); if ($saved && $this->get_public()) { $site_id = $saved; wp_update_site($site_id, array( 'public' => $this->get_public(), )); } // end if; /** * Fires after a site is created for the first time. * * @since 2.0.0 * * @param array $data The object data that will be stored. * @param \WP_Ultimo\Models\Base_Model $this The object instance. */ do_action('wu_site_created', $data, $this); // @phpstan-ignore-line } // end if; if (!is_wp_error($saved) && wu_get_setting('enable_screenshot_generator', true)) { wu_enqueue_async_action('wu_async_take_screenshot', array( 'site_id' => $saved, ), 'site'); } // end if; } else { $saved = wp_update_site($this->get_id(), $this->to_array()); } // end if; if (is_wp_error($saved)) { return $saved; } // end if; $this->blog_id = $saved; switch_to_blog($this->blog_id); foreach ($this->get_signup_options() as $key => $value) { update_option($key, $value); } // end foreach; restore_current_blog(); foreach ($this->get_signup_meta() as $key => $value) { update_site_meta($saved, $key, $value); } // end foreach; foreach ($this->meta as $key => $value) { update_site_meta($saved, $key, $value); } // end foreach; /** * Handles membership */ $membership = $this->get_membership(); if ($membership) { $customer_id = $membership->get_customer_id(); $this->set_customer_id($customer_id); } // end if; /** * Handles customers. */ $customer = $this->get_customer(); if ($customer) { $role = wu_get_setting('default_role', 'administrator'); if ($membership && $membership->has_limitations()) { $role = $membership->get_limitations()->customer_user_role->get_limit(); } // end if; update_site_meta($this->get_id(), 'wu_customer_id', $customer->get_id()); $user_id = $customer->get_user_id(); add_user_to_blog($this->get_id(), $user_id, $role); } elseif ($this->get_type() !== Site_Type::CUSTOMER_OWNED && $original_customer_id) { $user_id = wu_get_customer($original_customer_id)->get_user_id(); remove_user_from_blog($user_id, $this->get_id()); } // end if; update_blog_option($this->get_id(), 'blogname', $this->get_name()); update_blog_option($this->get_id(), 'blogdescription', $this->get_description()); /** * Fires after an object is stored into the database. * * @since 2.0.0 * * @param array $model The model slug. * @param array $data The object data that will be stored, serialized. * @param array $data_unserialized The object data that will be stored. * @param \WP_Ultimo\Models\Base_Model $this The object instance. * @param array $new If this object is a new one. */ do_action('wu_model_post_save', $this->model, $data, $data_unserialized, $this, $new); // @phpstan-ignore-line /** * Fires after an object is stored into the database. * * @since 2.0.0 * * @param array $data The object data that will be stored. * @param \WP_Ultimo\Models\Base_Model $this The object instance. * @param array $new If this object is a new one. */ do_action("wu_{$this->model}_post_save", $data, $this, $new); // @phpstan-ignore-line if (isset($session)) { $session->destroy(); } // end if; return $saved; } // end save; /** * By default, we just use the to_array method, but you can rewrite this. * * @since 2.0.0 * @return array */ public function to_search_results() { $search_result = $this->to_array(); $search_result['siteurl'] = $this->get_active_site_url(); return $search_result; } // end to_search_results; /** * Returns a list of sites based on the type. * * Type can be customer_owned or template. * * @since 2.0.0 * * @param string $type Type to return. Can be customer_owned or template. * @param array $query_args Additional query args. * @return array */ public static function get_all_by_type($type = 'customer_owned', $query_args = array()) { global $wpdb; if ($type === 'pending') { $table_name = "{$wpdb->base_prefix}wu_membershipmeta"; $customer_id = (int) wu_get_isset($query_args, 'customer_id'); $customer_id_query = ''; if ($customer_id) { $memberships = wu_get_memberships(array( 'fields' => array('id'), 'customer_id' => $customer_id, )); $memberships_str = ''; foreach ($memberships as $membership) { $memberships_str = !empty($memberships_str) ? $memberships_str . ', ' . $membership->id : $membership->id; } // end foreach; $customer_id_query = !empty($memberships_str) ? "AND wu_membership_id IN ($memberships_str)" : ''; } // end if; $sql = "SELECT meta_value FROM {$table_name} WHERE meta_key = 'pending_site' $customer_id_query ORDER BY meta_id DESC"; // phpcs:ignore $results = array_column($wpdb->get_results($sql), 'meta_value'); // phpcs:ignore $results = array_map(function($item) { $pending_site = unserialize($item); $pending_site->set_type('pending'); return $pending_site; }, $results); return $results; } // end if; $query = $query_args; $query['meta_query'] = array( array( 'key' => 'wu_type', 'value' => $type, ), ); return static::query($query); } // end get_all_by_type; /** * Returns a list of sites of given categories * * @since 2.1.3 * * @param array $categories Array of categories names. * @param array $query_args Additional query args. * @return array */ public static function get_all_by_categories($categories = array(), $query_args = array()) { global $wpdb; $query = $query_args; $query['meta_query'] = array( array( 'key' => 'wu_categories', 'value' => maybe_serialize($categories), 'compare' => 'LIKE', ), ); return static::query($query); } // end get_all_by_categories; /** * Get the list of all Site Template Categories. * * @since 2.0.0 * @param array $sites An array of selected site ids or site objects. * @return array */ public static function get_all_categories($sites = array()) { global $wpdb; $cache = wp_cache_get('site_categories', 'sites'); if (is_array($cache)) { return $cache; } // end if; $final_array = array(); $query = "SELECT DISTINCT meta_value FROM {$wpdb->base_prefix}blogmeta WHERE meta_key = %s"; if (!empty($sites)) { // Ensures that $sites is a indexed array $sites = array_values($sites); if (is_a($sites[0], \WP_Ultimo\Models\Site::class)) { $array_sites = json_decode(json_encode($sites), true); $sites = array_values(array_column($array_sites, 'blog_id')); } // end if; $query .= ' AND blog_id IN (' . implode(', ', $sites) . ')'; } // end if; $results = $wpdb->get_results($wpdb->prepare($query, 'wu_categories'), ARRAY_A); // phpcs:ignore $all_arrays = array_column($results, 'meta_value'); $all_arrays = array_map('maybe_unserialize', $all_arrays); if ($all_arrays) { $filtered_array = array(); foreach ($all_arrays as $array) { if (is_array($array)) { $filtered_array = array_merge($filtered_array, $array); } // end if; } // end foreach; $all_arrays = array_filter($filtered_array); $all_arrays = array_unique($all_arrays); $final_array = array_combine($all_arrays, $all_arrays); } // end if; wp_cache_set('site_categories', $final_array, 'sites'); return $final_array; } // end get_all_categories; /** * 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. * * In the case of sites, we need to get the membership * limitations. * * @see \WP_Ultimo\Models\Traits\Trait_Limitable * @since 2.0.0 * @return array */ public function limitations_to_merge() { $limitations_to_merge = array(); $membership = $this->get_membership(); if ($membership) { $membership_limitations = $membership->get_limitations(); $limitations_to_merge[] = $membership_limitations; } // end if; return $limitations_to_merge; } // end limitations_to_merge; } // end class Site;