If no one else has that problem, then it might be your computer. Have you tried clearing your web browser cache? Have you tried using a different web browser? Are you sure all of the files exist on the file system, in particular, the CSS files? Do you have any custom code that might conflict with the CSS?
Blesta version 4.5.0-b2 (BETA 2) is now available. You can download it from right here (Client Area Login Required). Read the blog post announcement at https://www.blesta.com/2019/01/31/blesta-4.5-beta-released/
This is a BETA release. Beta releases are not considered stable enough for production use, and are UNSUPPORTED. DO NOT INSTALL IN A PRODUCTION ENVIRONMENT.
Please report any bugs you find in the v4.5 beta bug forum.
Installing Blesta
See Installing Blesta in the User Manual for instructions.
Upgrading Blesta
See Upgrading Blesta in the User Manual for instructions.
We're almost ready for the Beta 1 of the BlestaForums. Myself and Timothy (our collaboration together) are testing everything to try and keep bugs to a minimum. We're testing everything and when it's ready for Beta 1, we will update everyone here. We will be having a trial for 14 days to try it and then you can purchase a license from either Blesta.Store or CubeData. Each has their own licensing system. We've agreed on doing what I did with the BlestaCMS in the beginning and that will be that it will be open-code minus the bits for licensing.
We will be adding features as we go along and I'm looking into a way to integrate this forum plugin into the CMS so it can be a paid addon or free if you have the forums and the cms.
You can view my forums alpha version if you're a customer of ours: https://blesta.store/client/plugin/blesta_forums/
Please note if you find a bug please let us know here and I'll get us onto it to fix it.
<?php
/**
* Universal Module
*
* A module that can be customized to request any fields and post them to any
* URL or email address
*
* @package blesta
* @subpackage blesta.components.modules.universal_module
* @copyright Copyright (c) 2010, Phillips Data, Inc.
* @license http://www.blesta.com/license/ The Blesta License Agreement
* @link http://www.blesta.com/ Blesta
*/
class UniversalModule extends Module {
/**
* @var string The version of this module
*/
private static $version = "1.2.0";
/**
* @var string The authors of this module
*/
private static $authors = array(array('name' => "Phillips Data, Inc.", 'url' => "http://www.blesta.com"));
/**
* @var string A set of reserved form fields that will not be wrapped in a meta[] array
*/
private static $reserved_fields = array('qty');
/**
* Initializes the module
*/
public function __construct() {
// Load components required by this module
Loader::loadComponents($this, array("Input"));
// Load the language required by this module
Language::loadLang("universal_module", null, dirname(__FILE__) . DS . "language" . DS);
}
/**
* Returns the name of this module
*
* @return string The common name of this module
*/
public function getName() {
if ($row = $this->getModuleRow())
return $row->meta->name;
/**
* Returns the version of this gateway
*
* @return string The current version of this module
*/
public function getVersion() {
return self::$version;
}
/**
* Returns the name and url of the authors of this module
*
* @return array The name and url of the authors of this module
*/
public function getAuthors() {
return self::$authors;
}
/**
* Returns the value used to identify a particular service
*
* @param stdClass $service A stdClass object representing the service
* @return string A value used to identify this service amongst other similar services
*/
public function getServiceName($service) {
static $rows = array();
if (!isset($rows[$service->module_row_id]))
$row[$service->module_row_id] = $this->getModuleRow($service->module_row_id);
$key = null;
if (isset($row[$service->module_row_id]->meta->service_field_name_0))
$key = $row[$service->module_row_id]->meta->service_field_name_0;
// If key is set, attempt to return value if it is scalar
if ($key != null) {
$fields = $this->serviceFieldsToObject($service->fields);
if (isset($fields->{$key}) && is_scalar($fields->{$key}))
return $fields->{$key};
}
// Return 1st scalar field
foreach ($service->fields as $field) {
if (is_scalar($field->value))
return $field->value;
}
return null;
}
/**
* Returns a noun used to refer to a module row
*
* @return string The noun used to refer to a module row
*/
public function moduleRowName() {
return Language::_("UniversalModule.module_row", true);
}
/**
* Returns a noun used to refer to a module row in plural form
*
* @return string The noun used to refer to a module row in plural form
*/
public function moduleRowNamePlural() {
return Language::_("UniversalModule.module_row_plural", true);
}
/**
* Returns a noun used to refer to a module group
*
* @return string The noun used to refer to a module group
*/
public function moduleGroupName() {
return Language::_("UniversalModule.module_group", true);
}
/**
* Returns the key used to identify the primary field from the set of module row meta fields.
*
* @return string The key used to identify the primary field from the set of module row meta fields
*/
public function moduleRowMetaKey() {
return "name";
}
/**
* Returns the value used to identify a particular package service which has
* not yet been made into a service. This may be used to uniquely identify
* an uncreated services of the same package (i.e. in an order form checkout)
*
* @param stdClass $package A stdClass object representing the selected package
* @param array $vars An array of user supplied info to satisfy the request
* @return string The value used to identify this package service
* @see Module::getServiceName()
*/
public function getPackageServiceName($package, array $vars=null) {
if (isset($vars['meta']) && is_array($vars['meta'])) {
foreach ($vars['meta'] as $value) {
if (is_scalar($value))
return $value;
}
}
return $package->name;
}
/**
* Adds the service to the remote server. Sets Input errors on failure,
* preventing the service from being added.
*
* @param stdClass $package A stdClass object representing the selected package
* @param array $vars An array of user supplied info to satisfy the request
* @param stdClass $parent_package A stdClass object representing the parent service's selected package (if the current service is an addon service)
* @param stdClass $parent_service A stdClass object representing the parent service of the service being added (if the current service is an addon service service and parent service has already been provisioned)
* @param string $status The status of the service being added. These include:
* - active
* - canceled
* - pending
* - suspended
* @return array A numerically indexed array of meta fields to be stored for this service containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
* @see Module::getModule()
* @see Module::getModuleRow()
*/
public function addService($package, array $vars=null, $parent_package=null, $parent_service=null, $status="pending") {
$meta = $this->processService("add", $vars, $package);
if ($this->Input->errors())
return;
return $meta;
}
/**
* Edits the service on the remote server. Sets Input errors on failure,
* preventing the service from being edited.
*
* @param stdClass $package A stdClass object representing the current package
* @param stdClass $service A stdClass object representing the current service
* @param array $vars An array of user supplied info to satisfy the request
* @param stdClass $parent_package A stdClass object representing the parent service's selected package (if the current service is an addon service)
* @param stdClass $parent_service A stdClass object representing the parent service of the service being edited (if the current service is an addon service)
* @return array A numerically indexed array of meta fields to be stored for this service containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
* @see Module::getModule()
* @see Module::getModuleRow()
*/
public function editService($package, $service, array $vars=array(), $parent_package=null, $parent_service=null) {
$meta = $this->processService("edit", $vars, $package);
if ($this->Input->errors())
return;
return $meta;
}
/**
* Cancels the service on the remote server. Sets Input errors on failure,
* preventing the service from being canceled.
*
* @param stdClass $package A stdClass object representing the current package
* @param stdClass $service A stdClass object representing the current service
* @param stdClass $parent_package A stdClass object representing the parent service's selected package (if the current service is an addon service)
* @param stdClass $parent_service A stdClass object representing the parent service of the service being canceled (if the current service is an addon service)
* @return mixed null to maintain the existing meta fields or a numerically indexed array of meta fields to be stored for this service containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
* @see Module::getModule()
* @see Module::getModuleRow()
*/
public function cancelService($package, $service, $parent_package=null, $parent_service=null) {
/**
* Suspends the service on the remote server. Sets Input errors on failure,
* preventing the service from being suspended.
*
* @param stdClass $package A stdClass object representing the current package
* @param stdClass $service A stdClass object representing the current service
* @param stdClass $parent_package A stdClass object representing the parent service's selected package (if the current service is an addon service)
* @param stdClass $parent_service A stdClass object representing the parent service of the service being suspended (if the current service is an addon service)
* @return mixed null to maintain the existing meta fields or a numerically indexed array of meta fields to be stored for this service containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
* @see Module::getModule()
* @see Module::getModuleRow()
*/
public function suspendService($package, $service, $parent_package=null, $parent_service=null) {
/**
* Unsuspends the service on the remote server. Sets Input errors on failure,
* preventing the service from being unsuspended.
*
* @param stdClass $package A stdClass object representing the current package
* @param stdClass $service A stdClass object representing the current service
* @param stdClass $parent_package A stdClass object representing the parent service's selected package (if the current service is an addon service)
* @param stdClass $parent_service A stdClass object representing the parent service of the service being unsuspended (if the current service is an addon service)
* @return mixed null to maintain the existing meta fields or a numerically indexed array of meta fields to be stored for this service containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
* @see Module::getModule()
* @see Module::getModuleRow()
*/
public function unsuspendService($package, $service, $parent_package=null, $parent_service=null) {
/**
* Allows the module to perform an action when the service is ready to renew.
* Sets Input errors on failure, preventing the service from renewing.
*
* @param stdClass $package A stdClass object representing the current package
* @param stdClass $service A stdClass object representing the current service
* @param stdClass $parent_package A stdClass object representing the parent service's selected package (if the current service is an addon service)
* @param stdClass $parent_service A stdClass object representing the parent service of the service being renewed (if the current service is an addon service)
* @return mixed null to maintain the existing meta fields or a numerically indexed array of meta fields to be stored for this service containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
* @see Module::getModule()
* @see Module::getModuleRow()
*/
public function renewService($package, $service, $parent_package=null, $parent_service=null) {
/**
* Updates the package for the service on the remote server. Sets Input
* errors on failure, preventing the service's package from being changed.
*
* @param stdClass $package_from A stdClass object representing the current package
* @param stdClass $package_to A stdClass object representing the new package
* @param stdClass $service A stdClass object representing the current service
* @param stdClass $parent_package A stdClass object representing the parent service's selected package (if the current service is an addon service)
* @param stdClass $parent_service A stdClass object representing the parent service of the service being changed (if the current service is an addon service)
* @return mixed null to maintain the existing meta fields or a numerically indexed array of meta fields to be stored for this service containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
* @see Module::getModule()
* @see Module::getModuleRow()
*/
public function changeServicePackage($package_from, $package_to, $service, $parent_package=null, $parent_service=null) {
/**
* Validates input data when attempting to add a package, returns the meta
* data to save when adding a package. Performs any action required to add
* the package on the remote server. Sets Input errors on failure,
* preventing the package from being added.
*
* @param array An array of key/value pairs used to add the package
* @return array A numerically indexed array of meta fields to be stored for this package containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
* @see Module::getModule()
* @see Module::getModuleRow()
*/
public function addPackage(array $vars=null) {
$meta = $this->processPackage("add", $vars);
if ($this->Input->errors())
return;
return $meta;
}
/**
* Validates input data when attempting to edit a package, returns the meta
* data to save when editing a package. Performs any action required to edit
* the package on the remote server. Sets Input errors on failure,
* preventing the package from being edited.
*
* @param stdClass $package A stdClass object representing the selected package
* @param array An array of key/value pairs used to edit the package
* @return array A numerically indexed array of meta fields to be stored for this package containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
* @see Module::getModule()
* @see Module::getModuleRow()
*/
public function editPackage($package, array $vars=null) {
$meta = $this->processPackage("edit", $vars, $package);
if ($this->Input->errors())
return;
return $meta;
}
/**
* Returns the rendered view of the manage module page
*
* @param mixed $module A stdClass object representing the module and its rows
* @param array $vars An array of post data submitted to or on the manager module page (used to repopulate fields after an error)
* @return string HTML content containing information to display when viewing the manager module page
*/
public function manageModule($module, array &$vars) {
// Load the view into this object, so helpers can be automatically added to the view
$this->view = new View("manage", "default");
$this->view->base_uri = $this->base_uri;
$this->view->setDefaultView("components" . DS . "modules" . DS . "universal_module" . DS);
// Load the helpers required for this view
Loader::loadHelpers($this, array("Form", "Html", "Widget"));
$this->view->set("module", $module);
return $this->view->fetch();
}
/**
* Returns the rendered view of the add module row page
*
* @param array $vars An array of post data submitted to or on the add module row page (used to repopulate fields after an error)
* @return string HTML content containing information to display when viewing the add module row page
*/
public function manageAddRow(array &$vars) {
// Load the view into this object, so helpers can be automatically added to the view
$this->view = new View("add_row", "default");
$this->view->base_uri = $this->base_uri;
$this->view->setDefaultView("components" . DS . "modules" . DS . "universal_module" . DS);
// Load the helpers required for this view
Loader::loadHelpers($this, array("Form", "Html", "Widget"));
if (!isset($vars['package_email_html']))
$vars['package_email_html'] = "{% debug %}";
if (!isset($vars['package_email_text']))
$vars['package_email_text'] = "{% debug %}";
if (!isset($vars['service_email_html']))
$vars['service_email_html'] = "{% debug %}";
if (!isset($vars['service_email_text']))
$vars['service_email_text'] = "{% debug %}";
/**
* Returns the rendered view of the edit module row page
*
* @param stdClass $module_row The stdClass representation of the existing module row
* @param array $vars An array of post data submitted to or on the edit module row page (used to repopulate fields after an error)
* @return string HTML content containing information to display when viewing the edit module row page
*/
public function manageEditRow($module_row, array &$vars) {
// Load the view into this object, so helpers can be automatically added to the view
$this->view = new View("edit_row", "default");
$this->view->base_uri = $this->base_uri;
$this->view->setDefaultView("components" . DS . "modules" . DS . "universal_module" . DS);
// Load the helpers required for this view
Loader::loadHelpers($this, array("Form", "Html", "Widget"));
/**
* Adds the module row on the remote server. Sets Input errors on failure,
* preventing the row from being added.
*
* @param array $vars An array of module info to add
* @return array A numerically indexed array of meta fields for the module row containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
*/
public function addModuleRow(array &$vars) {
$this->Input->setRules($this->getModuleRowRules($vars));
if ($this->Input->validates($vars))
return $this->formatRowMeta($vars);
}
/**
* Edits the module row on the remote server. Sets Input errors on failure,
* preventing the row from being updated.
*
* @param stdClass $module_row The stdClass representation of the existing module row
* @param array $vars An array of module info to update
* @return array A numerically indexed array of meta fields for the module row containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
*/
public function editModuleRow($module_row, array &$vars) {
$this->Input->setRules($this->getModuleRowRules($vars));
if ($this->Input->validates($vars))
return $this->formatRowMeta($vars);
}
/**
* Returns all fields used when adding/editing a package, including any
* javascript to execute when the page is rendered with these fields.
*
* @param $vars stdClass A stdClass object representing a set of post fields
* @return ModuleFields A ModuleFields object, containg the fields to render as well as any additional HTML markup to include
*/
public function getPackageFields($vars=null) {
$fields = new ModuleFields();
if (isset($vars->module_row) && $vars->module_row > 0) {
$row = $this->getModuleRow($vars->module_row);
$row_fields = array();
if ($row->meta) {
$row_fields = $this->formatModuleRowFields($row->meta);
$field_data = array();
// Reformat package fields into a more usable format
foreach ($row_fields['package_fields'] as $key => $values) {
foreach ($values as $i => $value) {
$field_data[$i][$key] = $value;
}
}
/**
* Returns an array of key values for fields stored for a module, package,
* and service under this module, used to substitute those keys with their
* actual module, package, or service meta values in related emails.
*
* @return array A multi-dimensional array of key/value pairs where each key is one of 'module', 'package', or 'service' and each value is a numerically indexed array of key values that match meta fields under that category.
* @see Modules::addModuleRow()
* @see Modules::editModuleRow()
* @see Modules::addPackage()
* @see Modules::editPackage()
* @see Modules::addService()
* @see Modules::editService()
*/
public function getEmailTags() {
return array('module' => array("*"), 'package' => array("*"), 'service' => array("*"));
}
/**
* Returns all fields to display to an admin attempting to add a service with the module
*
* @param stdClass $package A stdClass object representing the selected package
* @param $vars stdClass A stdClass object representing a set of post fields
* @return ModuleFields A ModuleFields object, containg the fields to render as well as any additional HTML markup to include
*/
public function getAdminAddFields($package, $vars=null) {
$fields = new ModuleFields();
if (!isset($vars->meta))
$vars->meta = array();
if (isset($package->module_row) && $package->module_row > 0) {
$row = $this->getModuleRow($package->module_row);
// Set the module row, which will allow us to reference it later when getName() is invoked
$this->setModuleRow($row);
$row_fields = array();
if ($row->meta) {
$row_fields = $this->formatModuleRowFields($row->meta);
$field_data = array();
// Reformat package fields into a more usable format
foreach ($row_fields['service_fields'] as $key => $values) {
foreach ($values as $i => $value) {
$field_data[$i][$key] = $value;
}
}
/**
* Returns all fields to display to a client attempting to add a service with the module
*
* @param stdClass $package A stdClass object representing the selected package
* @param $vars stdClass A stdClass object representing a set of post fields
* @return ModuleFields A ModuleFields object, containg the fields to render as well as any additional HTML markup to include
*/
public function getClientAddFields($package, $vars=null) {
// Same as admin
return $this->getAdminAddFields($package, $vars);
}
/**
* Returns all fields to display to an admin attempting to edit a service with the module
*
* @param stdClass $package A stdClass object representing the selected package
* @param $vars stdClass A stdClass object representing a set of post fields
* @return ModuleFields A ModuleFields object, containg the fields to render as well as any additional HTML markup to include
*/
public function getAdminEditFields($package, $vars=null) {
// Same as adding
return $this->getAdminAddFields($package, $vars);
}
/**
* Fetches the HTML content to display when viewing the service info in the
* admin interface.
*
* @param stdClass $service A stdClass object representing the service
* @param stdClass $package A stdClass object representing the service's package
* @return string HTML content containing information to display when viewing the service info
*/
public function getAdminServiceInfo($service, $package) {
return null;
}
/**
* Fetches the HTML content to display when viewing the service info in the
* client interface.
*
* @param stdClass $service A stdClass object representing the service
* @param stdClass $package A stdClass object representing the service's package
* @return string HTML content containing information to display when viewing the service info
*/
public function getClientServiceInfo($service, $package) {
return null;
}
/**
* Attempts to validate service info. This is the top-level error checking method. Sets Input errors on failure.
*
* @param stdClass $package A stdClass object representing the selected package
* @param array $vars An array of user supplied info to satisfy the request
* @param boolean $edit True if this is an edit, false otherwise
* @return boolean True if the service validates, false otherwise. Sets Input errors when false.
*/
public function validateService($package, array $vars=null, $edit=false) {
if ($package)
$module_row_id = $package->module_row;
else
$module_row_id = isset($vars['module_row']) ? $vars['module_row'] : null;
$row = $this->getModuleRow($module_row_id);
if (!array_key_exists("meta", (array)$vars))
$vars['meta'] = $vars;
/**
* Process Packages add/edit
*
* @param string $type The type of process (add/edit)
* @param array $vars An array of key/value pairs
* @return array A numerically indexed array of meta fields to be stored for this package containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
*/
private function processPackage($type, array $vars, $package = null) {
$module_row_id = null;
if (isset($vars['module_row']) && $vars['module_row'])
$module_row_id = $vars['module_row'];
elseif ($package)
$module_row_id = $package->module_row;
$row = $this->getModuleRow($module_row_id);
if (!$row) {
$this->Input->setErrors(array(
'module_row' => array(
'invalid' => Language::_("UniversalModule.!error.module_row.invalid", true)
)
));
return;
}
/**
* Process Services add/edit
*
* @param string $type The type of process (add/edit)
* @param array $vars An array of key/value pairs
* @return array A numerically indexed array of meta fields to be stored for this service containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
*/
private function processService($type, array $vars, $package = null) {
if ($package)
$module_row_id = $package->module_row;
else
$module_row_id = isset($vars['module_row']) ? $vars['module_row'] : null;
$this->validateService($package, $vars, $type == "edit");
/**
* Sends notification for the given action if supported by the module row
*
* @param string $action The action to send a notification for
* @param array $meta A numerically indexed array of meta fields containing:
* - key The key for this meta field
* - value The value for this key
* @param int $module_row_id The ID of the module row to send the notification for
* @param array $additional_fields An array of key/value pairs to send in the notification
* @param stdClass $package_meta A stdClass object of package meta data (if any)
* @return boolean True if the notice was successful, false otherwise
*/
private function sendNotification($action, $meta, $module_row_id = null, $additional_fields = null, $package_meta = null) {
$row = $this->getModuleRow($module_row_id);
if ($row) {
$tags = $this->serviceFieldsToObject((array)$meta);
if ($package_meta) {
foreach ($package_meta as $key => $value) {
if (!isset($tags->{$key}))
$tags->{$key} = $value;
}
}
// Look for 'secret' package fields to append
$meta_fields = $this->formatModuleRowFields($row->meta);
if (isset($meta_fields['package_fields']['type'])) {
foreach ($meta_fields['package_fields']['type'] as $i => $type) {
$key = $meta_fields['package_fields']['name'][$i];
if ($type == "secret" && !isset($tags->{$key}))
$tags->{$key} = $meta_fields['package_fields']['values'][$i];
}
}
// Look for 'secret' service fields to append if this is a service notice
if (strpos($action, "service") !== false && isset($meta_fields['service_fields']['type'])) {
foreach ($meta_fields['service_fields']['type'] as $i => $type) {
if ($type == "secret")
$tags->{$meta_fields['service_fields']['name'][$i]} = $meta_fields['service_fields']['values'][$i];
}
}
$tags->_other = $additional_fields;
if (isset($row->meta->{$action}) && trim($row->meta->{$action}) != "") {
/**
* Sends an email notification to the given address with the given tags
*
* @param string $action The action to send the notification for
* @param array $tags A key/value pairs of tags and their replacement data
* @param stdClass $meta A stdClass object of module row meta field data
* @return boolean True if the email was successfully sent, false otherwise
*/
private function sendEmailNotice($action, $tags, $meta) {
/**
* Sends an HTTP POST request to the given URL with the given arguments
*
* @param string $url The URL to post
* @param array $args An array of key/value post fields
* @param string $response_code The response code to accept for successful responses
* @param string $response The response to expect for successful responses, may be a regular expression
* @return boolean True on success, false on error
*/
private function sendHttpNotice($url, $args, $response_code = null, $response = null) {
// Log request
$this->log($url, serialize($args), "input", true);
/**
* Formats module row input fields into a proper format required by Module::addModuleRow() and Module::editModuleRow().
*
* @param array An array of input key/value pairs
* @return array A numerically indexed array of meta fields for the module row containing:
* - key The key for this meta field
* - value The value for this key
* - encrypted Whether or not this field should be encrypted (default 0, not encrypted)
*/
private function formatRowMeta(array &$vars) {
$meta = array();
$meta_fields = array("name", "package_rules", "service_rules",
"package_email_from", "package_email_subject", "package_email_html", "package_email_text",
"service_email_from", "service_email_subject", "service_email_html", "service_email_text");
/**
* Returns all tabs to display to a client when managing a service whose
* package uses this module
*
* @param stdClass $package A stdClass object representing the selected package
* @return array An array of tabs in the format of method => title. Example: array('methodName' => "Title", 'methodName2' => "Title2")
*/
public function getClientTabs($package) {
return array(
'moreinfo' => array('name' => "管理中心", 'icon' => "fa fa-gears")
// 'console' => array('name' => Language::_("Multicraft.tab_client_console", true), 'icon' => "fa fa-terminal")
);
}
/**
* The More Info tab
*
* @param stdClass $package A stdClass object representing the current package
* @param stdClass $service A stdClass object representing the current service
* @param array $get Any GET parameters
* @param array $post Any POST parameters
* @param array $files Any FILES parameters
* @return string The string representing the contents of this tab
*/
public function moreinfo($package, $service, array $get=null, array $post=null, array $files=null) {
$row = $this->getModuleRow($package->module_row);
$out = '';
$servicefields = array();
foreach ($row->meta as $key=>$value ) {
if (strpos($key, "service_field_name") !== false) {
// Here we match the service field label with their key and value
foreach($service->fields as $field) {
if($field->key == $value) {
$name = 'service_field_label_' . str_replace('service_field_name_', '', $key);
$servicefields[] = array("label" => $row->meta->$name,
"key" => $value,
"value" => $field->value);
}
}
}
}
foreach($servicefields as $field) {
// Filter out for showing only public fields
if(strpos($field['key'], "public_") === 0 ) {
$out .= "<p><b>". $field['label'] . ":</b> " . $field['value'] . "</p>";
}
}
return "<h4>服务器参数</h4><br />" . $out ;
}
/**
* Converts module row meta fields from key/value pairs to array sets suitable
* for use in forms.
*
* @param stdClass $module_row_meta An object of module row meta fields
* @return array An array of formatted module row meta fields
*/
private function formatModuleRowFields($module_row_meta) {
$fields = array('package_fields' => array(), 'service_fields' => array());
foreach ($module_row_meta as $key => $value) {
$index = ltrim(strrchr($key, "_"), "_");
if (substr($key, 0, 14) == "package_field_") {
$key = str_replace("_" . $index, "", str_replace("package_field_", "", $key));
$fields['package_fields'][$key][$index] = $value;
}
elseif (substr($key, 0, 14) == "service_field_") {
$key = str_replace("_" . $index, "", str_replace("service_field_", "", $key));
$fields['service_fields'][$key][$index] = $value;
}
else {
$fields[$key] = $value;
}
}
return $fields;
}
/**
* Unserialize meta values of the format key2:value|key2:value2
*
* @param string $values A serialized set of values
* @return array An array of key/value pairs
*/
private function unserializeMetaValues($values) {
if ($values == "")
return array();
/**
* Returns a key/value pair of package notices, which are events that trigger
* a HTTP POST or Email to a given location
*
* @return array An array of key/value pair package notices, where each key is the notice type and each value is its name
*/
private function getPackageNotices() {
return array(
'add' => Language::_("UniversalModule.getpackagenotices.add", true),
'edit' => Language::_("UniversalModule.getpackagenotices.edit", true)
);
}
/**
* Returns a key/value pair of service notices, which are events that trigger
* a HTTP POST or Email to a given location
*
* @return array An array of key/value pair service notices, where each key is the notice type and each value is its name
*/
private function getServiceNotices() {
return array(
'add' => Language::_("UniversalModule.getservicenotices.add", true),
'edit' => Language::_("UniversalModule.getservicenotices.edit", true),
'suspend' => Language::_("UniversalModule.getservicenotices.suspend", true),
'unsuspend' => Language::_("UniversalModule.getservicenotices.unsuspend", true),
'cancel' => Language::_("UniversalModule.getservicenotices.cancel", true),
'renew' => Language::_("UniversalModule.getservicenotices.renew", true),
'package_change' => Language::_("UniversalModule.getservicenotices.package_change", true),
);
}
/**
* Returns a key/value pair of all input field types supported
*
* @return array An array of key/value pairs of input field types supported, where each key is the field type and each value it its name
*/
private function getFieldTypes() {
return array(
'text' => Language::_("UniversalModule.getfieldtypes.text", true),
'textarea' => Language::_("UniversalModule.getfieldtypes.textarea", true),
'password' => Language::_("UniversalModule.getfieldtypes.password", true),
'select' => Language::_("UniversalModule.getfieldtypes.select", true),
'radio' => Language::_("UniversalModule.getfieldtypes.radio", true),
'checkbox' => Language::_("UniversalModule.getfieldtypes.checkbox", true),
'hidden' => Language::_("UniversalModule.getfieldtypes.hidden", true),
'secret' => Language::_("UniversalModule.getfieldtypes.secret", true),
);
}
/**
* Returns all rules to validate when adding/edit a module row
*
* @return array An array of rules to validate when adding/editing a module row
*/
private function getModuleRowRules(array $vars) {
$rules = array(
'name' => array(
'empty' => array(
'rule' => "isEmpty",
'negate' => true,
'message' => Language::_("UniversalModule.!error.name.empty", true)
)
)
);
/**
* Verifies whether or not the givne str is a URL
*
* @param string $str A string
* @return boolean True if $str is a URL, false otherwise
*/
private function isUrl($str) {
return preg_match("#^\S+://\S+\.\S+.+$#", $str);
}
}
?>
Is the member verification code only available for Google? Google's verification code can't be used in China. China is blocking Google's website. Is there any other verification code? No verification code was swiped by 6000 members for an hour.
Version 4.4.0 is now available. You can download directly right here.
Installing Blesta
See Installing Blesta in the User Manual for instructions.
Upgrading Blesta
See Upgrading Blesta in the User Manual for instructions.
Migrating to Blesta
See Migrating to Blesta in the User Manual for instructions.
Overview
New config option field types: text, textarea, password
Markdown editor where markdown is supported
Client payment type overrides for credit card and ACH
Improved addon service management
New Modules: cWatch, WHMSonic
New Gateway: GoCardless
Upgraded TCPDF, reduced file size of invoices and added new fonts
Upgraded client area and front facing pages to latest Bootstrap 3.3.7
Improvements for PHP 7.2
Release Notes