About The Universal Module

The Universal Module is the module to use when no other module will do. In some cases you may find that you need a module to request fields from a client for a particular service that will be provisioned manually. Dedicated servers are a perfect example of this. With the Universal Module you can create these fields dynamically, and even have them send a post or email notification when the package or service is created or changes.

Using the Universal Module

Installing the Universal Module

  1. Visit [Settings] > [Company] > [Modules] > Available.
  2.  Click the "Install" button within the Universal Module module listing.

When the module is installed, it should automatically load the "Manage" screen for the module. You can get back here any time by visiting [Settings] > [Company] > [Modules] > Installed and by clicking the "Manage" button for the module.

Products

A Universal Module Product is a collection of package and service request fields, along with a few rules that apply to the product. The product acts as a template for creating packages and services.

Module Options

OptionDescription
NameThe name for the product, shown when creating or editing a package.

Package Options

Package options are fields that are requested when a package is added or updated. A product can have any number of package options.

OptionDescription
LabelThe display name of the form field.
Name

The name of the input field. This is the name of the value sent in all post and email notifications, and is also used when validating input rules.

If you've set the label to Email address then you'd likely want to set the name to email_address.

Type

The type of form field.

OptionDescription
TextA regular text input field.
TextareaA large text area field, for inserting multiple lines of text.
PasswordA password input field, masking the user's input.
SelectA drop-down menu.
RadioA radio field.
CheckboxA checkbox field.
HiddenA hidden field not visible to the user.
SecretA field that is never rendered or stored for the package, but is sent in all post and email notifications.
RequiredIf enabled, will require that some value is given for the field.
EncryptIf enabled, will store input values encrypted in the database.
ValuesSee Values Format.
Input RulesSee Input Rules.
NotificationsSee Notifications.

Service Options

Service options are fields that are requested when a service is added or updated. A product can have any number of service options.


OptionDescription
LabelThe display name of the form field.
Name

The name of the input field. This is the name of the value sent in all post and email notifications, and is also used when validating input rules.

If you've set the label to Email address then you'd likely want to set the name to email_address.

A field name of qty has special meaning. It will set the quantity recorded for the service.

Type

The type of form field.

OptionDescription
TextA regular text input field.
TextareaA large text area field, for inserting multiple lines of text.
PasswordA password input field, masking the user's input.
SelectA drop-down menu.
RadioA radio field.
CheckboxA checkbox field.
HiddenA hidden field not visible to the user.
SecretA field that is never rendered or stored for the service, but is sent in all post and email notifications.
RequiredIf enabled, will require that some value is given for the field.
EncryptIf enabled, will store input values encrypted in the database.
ValuesSee Values Format.
Input RulesSee Input Rules.
NotificationsSee Notifications.

Values Format

The values field is a serialized list of field data in the format of name:value, delimited by the | (pipe) character. The name is the value stored for the field and value is the value displayed. For example, if you would like to request a list of check boxes of various flavors of ice cream you might enter: vanilla:Vanilla|chocolate:Chocolate|strawberry:Strawberry|rocky_road:Rocky Road

Using ':' or '|' in your fields

Both : and | are reserved characters, so if you'd like to use them in your value entry you must escape those characters with a \ (back slash).

Input Rules

Input rules are a JSON encoded object of input validation rules. They allow you to specify how each field should be validated against errors on input. For additional details on input rules see Error Checking. Let's take a look at an example:

Example Input Rules
{
	"hostname":{
		"valid":{
			"rule":"isEmpty",
			"negate":true,
			"message":"Hostname must not be empty."
		}
	},
	"password":{
		"valid":{
			"rule":["matches", "/^[a-z0-9\\$\\%\\^]{10,20}$/i"],
			"message":"Please enter a password using alphanumeric characters between 10 and 20 characters in length. You may also include special characters like '$%^'."
		}
	}
}

In the above example we're validating the hostname field using the isEmpty rule and negating it using the negate attribute. This ensures that the hostname field is not empty when submitted. If the rule validation fails (hostname is empty) the message we defined using the message attribute will be displayed to the user. We are also validating the password field at the same time using the matches rule, which evaluates a given regular expression. This rule requires that the password contain between 10 and 20 characters, inclusive, all of which must be characters of any combination from A through Z, upper or lower case, the digits 0 through 9, and the special characters $, %, and ^.

Note that special character literals like $, %, and ^ should be escaped where appropriate in the regular expression via double backslashes. Additionally, so should special characters in JSON format, like quotes (") and back slashes (\)themselves. Creating invalid JSON will cause all fields to pass validation because the JSON cannot be parsed to retrieve the rules. Creating invalid regular expressions will cause unexpected behavior.

Notifications

Notifications allow the universal module to post to a given URL or email a given address when a certain action occurs.

Package Option Notifications

Package option notifications are executed when an action is performed on the package.

OptionDescription
Notice

The action triggers the notification.

OptionDescription
AddExecuted when a package is created.
EditExecuted when a package is updated.
Post URL/EmailThe URL to post to, or the email address to email, when the notice is triggered
HTTP CodeThe HTTP Response Code returned by the URL that signifies a successful transmission.
Response ContainsSome portion of the output returned by the URL that signifies a successful transmission. This can be used separately, or in conjunction with the HTTP Code for more refined control over successful responses.
From EmailThe address to send email notifications from.
SubjectThe subject of the email notification.
HTML/TextThe HTML and Text body content for the email notification.

Package Option Notification Tags

The package option notification emails allow for the following tags:

TagsDescriptionNotesVersion

{*}

The value submitted for this custom field{*} is NOT an actual tag. Every custom package field has a tag associated with it, this tag is labeled by the fields name represented here by * (e.g. {my_field})
{*_name}The label associated with the submitted value for fields of type select or radioThis tag is only available for radio and select fields (e.g. {my_field_name})4.1
{*_values}A list of checked boxes for this field each containing the box's label and valueThis tag is only available for checkbox fields (e.g. {my_field_values})4.1
{_action}The code of the action for which this notification is being sent
4.1
{_package.id}The system-level service IDThe _package tag is not available for the package addition notification4.1
{_package.description}The package's description
4.1
{_package.module_row}The ID of the module row the package is associated with
4.1
{_package.status}

The status of the package
4.1

Email Tags

The {*_values} tag contains data in the following format. For a guide on using email tags in Blesta see the Customizing Emails page.


custom_1_values = array(
    array(
         'value' => '1',
         'name' => 'Option 1'
    ),
    array(
         'value' => '2',
         'name' => 'Option 2'
    )
);

Due to the nature of tag objects containing several fields, many of which are likely irrelevant for use in email templates, but may be useful to you in certain circumstances, a dump of the tags are shown below.

The {package} object
stdClass Object
    (
        [id] => '94'
        [id_format] => '{num}'
        [id_value] => '92'
        [module_id] => '2'
        [name] => 'Test Universal Package'
        [description] => 'A test package for the universal module.'
        [description_html] => '<p>A test package for the Universal Module.</p>'
        [qty] => null
        [module_row] => '1'
        [module_group] => null
        [taxable] => '1'
        [single_term] => '0'
        [status] => 'active'
        [company_id] => '1'
        [prorata_day] => null
        [prorata_cutoff] => null
        [id_code] => '92'
        [email_content] => Array
            (
                [0] => stdClass Object
                    (
                        [lang] => 'en_us'
                        [html] => '<p>Welcome email for the Universal Module.</p>'
                        [text] => 'Welcome email for the Universal Module.'
                    )
            )
        [pricing] => Array
            (
                [0] => stdClass Object
                    (
                        [id] => '628'
                        [pricing_id] => '875'
                        [package_id] => '94'
                        [term] => '1'
                        [period] => 'month'
                        [price] => '2500.0000'
                        [setup_fee] => '0.0000'
                        [cancel_fee] => '0.0000'
                        [currency] => 'USD'
                    )
            )
        [meta] => stdClass Object
        [groups] => Array
            (
                [0] => stdClass Object
                    (
                        [id] => '10'
                        [name] => 'Test Universal Package Group'
                        [description] => null
                        [type] => 'standard'
                        [company_id] => '1'
                        [allow_upgrades] => '1'
                    )
            )
        [option_groups] => Array
            (
                [0] => stdClass Object
                    (
                        [id] => '26'
                        [name] => 'Test Universal Option Group'
                        [description] => 'A list of options'
                    )
            )
    )

Service Option Notifications

Service option notifications are executed when an action is performed on the service.

OptionDescription
Notice

The action triggers the notification.

OptionDescription
AddExecuted when a service is created.
EditExecuted when a service is updated.
SuspendExecuted when a service is suspended.
UnsuspendExecuted when a service is unsuspended.
CancelExecuted when a service is canceled.
RenewExecuted when a service is renewed. That is, the invoice generated for the service renewal is paid.
Package ChangeExecuted when the package is changed for the service.
Post URL/EmailThe URL to post to, or the email address to email, when the notice is triggered
HTTP CodeThe HTTP Response Code returned by the URL that signifies a successful transmission.
Response ContainsSome portion of the output returned by the URL that signifies a successful transmission. This can be used separately, or in conjunction with the HTTP Code for more refined control over successful responses.
From EmailThe address to send email notifications from.
SubjectThe subject of the email notification.
HTML/TextThe HTML and Text body content for the email notification.

Service Option Notification Tags

The service option notification emails allow for the following tags:

TagsDescriptionNotesVersion

{*}

The value submitted for this custom field{*} is NOT an actual tag. It is only a placeholder in this documentation. Every custom service field has a tag associated with it, this tag is labeled by the fields name represented here by * (e.g. {my_field})
{*_name}The label associated with the submitted value for fields of type select or radioThis tag is only available for radio and select fields (e.g. {my_field_name})4.1
{*_values}A list of checked boxes for this field each containing the box's label and valueThis tag is only available for checkbox fields (e.g. {my_field_values})4.1
{_action}The code of the action for which this notification is being sent
4.1
{_service.id}The system-level service IDThe _service tag is not available for the service addition notification4.1
{_service.status}The service status
4.1
{_service.date_added}The UTC datetime stamp of the date the service was addedFormatted as "YYYY-MM-DD HH:MM:SS"4.1
{_service.date_renews}The UTC datetime stamp of the service renew dateFormatted as "YYYY-MM-DD HH:MM:SS"4.1
{_service.date_last_renewed}The UTC datetime stamp of the service's last renew dateFormatted as "YYYY-MM-DD HH:MM:SS"4.1
{_service.date_suspended}The UTC datetime stamp of the date the service was suspendedFormatted as "YYYY-MM-DD HH:MM:SS"4.1
{_service.date_canceled}The UTC datetime stamp of the date the service was canceledFormatted as "YYYY-MM-DD HH:MM:SS"4.1
{_package.id}The system-level service ID
4.1
{_package.description}The package's description
4.1
{_package.module_row}The ID of the module row the package is associated with
4.1
{_package.status}The status of the package
4.1
{_other.*}The _other tag contains additional information, most of which is received through user inputHere * is the name of the field to access from the other tag (e.g. pricing_id)

Email Tags

The {*_values} tag contains data in the following format. For a guide on using email tags in Blesta see the Customizing Emails page.


custom_1_values = array(
    array(
         'value' => '1',
         'name' => 'Option 1'
    ),
    array(
         'value' => '2',
         'name' => 'Option 2'
    )
);

Due to the nature of tag objects containing several fields, many of which are likely irrelevant for use in email templates, but may be useful to you in certain circumstances, a dump of the tags are shown below.


The {service} object
stdClass Object
    (
        [id] => 234
        [parent_service_id] => 
        [package_group_id] => 1
        [id_format] => PD-{num}
        [id_value] => 229
        [pricing_id] => 22
        [client_id] => 3
        [module_row_id] => 6
        [coupon_id] => 
        [qty] => 1
        [status] => in_review
        [date_added] => 2013-05-13 18:33:14
        [date_renews] => 2013-06-13 18:33:14
        [date_last_renewed] => 
        [date_suspended] => 
        [date_canceled] => 
        [id_code] => PD-229
        [fields] => Array
            (
                [0] => stdClass Object
                    (
                        [key] => cpanel_confirm_password
                        [value] => password
                        [serialized] => 0
                        [encrypted] => 1
                    )
                [1] => stdClass Object
                    (
                        [key] => cpanel_domain
                        [value] => domain.com
                        [serialized] => 0
                        [encrypted] => 0
                    )
                [2] => stdClass Object
                    (
                        [key] => cpanel_password
                        [value] => password
                        [serialized] => 0
                        [encrypted] => 1
                    )
                [3] => stdClass Object
                    (
                        [key] => cpanel_username
                        [value] => domainco
                        [serialized] => 0
                        [encrypted] => 0
                    )
            )
        [package_pricing] => stdClass Object
            (
                [id] => 22
                [package_id] => 13
                [term] => 1
                [period] => month
                [price] => 8.0000
                [setup_fee] => 0.0000
                [cancel_fee] => 0.0000
                [currency] => USD
            )
        [package] => stdClass Object
            (
                [id] => 13
                [id_format] => {num}
                [id_value] => 1
                [module_id] => 4
                [name] => Bronze Standard
                [description] => 
                [description_html] => <p>
	<span style="color:#008000;"><em>Good Value!</em></span></p>
                [qty] => 
                [module_row] => 6
                [module_group] => 
                [taxable] => 0
                [status] => active
                [company_id] => 1
            )
        [name] => domain.com
 
        [coupon] => stdClass Object
            (
                [id] => 2
                [code] => knW3Lesn
                [company_id] => 1
                [used_qty] => 16
                [max_qty] => 0
                [start_date] => 2017-02-02 08:00:00
                [end_date] => 2018-02-03 07:59:59
                [status] => active
                [recurring] => 0
                [limit_recurring] => 0
                [apply_package_options] => 1
                [internal_use_only] => 0
                [type] => exclusive
                [amounts] => Array
                    (
                        [0] => stdClass Object
                            (
                                [coupon_id] => 2
                                [currency] => USD
                                [amount] => 5.0000
                                [type] => amount
                            )
                    )
                [packages] => Array
                    (
                        [0] => stdClass Object
                            (
                                [coupon_id] => 2
                                [package_id] => 80
                            )
                    )
            )
    )
The {package} object
stdClass Object
    (
        [id] => '94'
        [id_format] => '{num}'
        [id_value] => '92'
        [module_id] => '2'
        [name] => 'Test Universal Package'
        [description] => 'A test package for the universal module.'
        [description_html] => '<p>A test package for the Universal Module.</p>'
        [qty] => null
        [module_row] => '1'
        [module_group] => null
        [taxable] => '1'
        [single_term] => '0'
        [status] => 'active'
        [company_id] => '1'
        [prorata_day] => null
        [prorata_cutoff] => null
        [id_code] => '92'
        [email_content] => Array
            (
                [0] => stdClass Object
                    (
                        [lang] => 'en_us'
                        [html] => '<p>Welcome email for the Universal Module.</p>'
                        [text] => 'Welcome email for the Universal Module.'
                    )
            )
        [pricing] => Array
            (
                [0] => stdClass Object
                    (
                        [id] => '628'
                        [pricing_id] => '875'
                        [package_id] => '94'
                        [term] => '1'
                        [period] => 'month'
                        [price] => '2500.0000'
                        [setup_fee] => '0.0000'
                        [cancel_fee] => '0.0000'
                        [currency] => 'USD'
                    )
            )
        [meta] => stdClass Object
        [groups] => Array
            (
                [0] => stdClass Object
                    (
                        [id] => '10'
                        [name] => 'Test Universal Package Group'
                        [description] => null
                        [type] => 'standard'
                        [company_id] => '1'
                        [allow_upgrades] => '1'
                    )
            )
        [option_groups] => Array
            (
                [0] => stdClass Object
                    (
                        [id] => '26'
                        [name] => 'Test Universal Option Group'
                        [description] => 'A list of options'
                    )
            )
    )

Client Service Info

Client Service Info renders the information shown in the expandable area and on the Information tab when clicking to manage the service within the client area when clicking on the service row.

Example Code (Replace tags with appropriate service or package tags. In this example, we have service fields called vpnuser, vpnpass, vpnhost)

	<div class="table-responsive">
	<table class="table table-curved table-striped">
		<thead><tr>
			<th>VPN USer</th>
			<th>VPN Pass</th>
			<th>VPN Host</th>
		</tr>
		</thead>
		<tbody>
		<tr>
			<td>{service.fields.vpnuser}</td>
			<td>{service.fields.vpnpass}</td>
			<td>Login at <a href="https://{service.fields.vpnhost}">{service.fields.vpnhost}</a></td>
		</tr>
		</tbody>
	</table>
	</div>


Admin Service Info

Admin Service Info renders the information shown in the expandable area within the client profile when clicking on the service row in the admin area.

Example Code (Replace tags with appropriate service or package tags. In this example, we have service fields called vpnuser, vpnpass, vpnhost)

	<table class="table">
		<tbody><tr class="heading_row">
			<td class="border_left">VPN USer</td>
			<td>VPN Pass</td>
			<td>VPN Host</td>
		</tr>
		<tr>
			<td>{service.fields.vpnuser}</td>
			<td>{service.fields.vpnpass}</td>
			<td>Login at <a href="https://{service.fields.vpnhost}">{service.fields.vpnhost}</a></td>
		</tr>
		</tbody>
	</table>


Creating Packages

Email Tags

 Universal Module product service field names are used for the email tag. For example, a service field with the name "hostname" would result in a tag available to the welcome email of {service.hostname}. Universal module products are unique in this regard because each product may have different tags, defined by the staff member who created them.

Tools

Here's a sample PHP script you can use as a test endpoint to see the data that is received via POST when defining a Post URL instead of an email for any of the Package or Service Notices.

Create a file called post.php and test.txt that is writable by the web server, upload those files to a location such as yourdomain.com/post.php and use this URL as your Post URL in your Universal Module Product configuration.

<?php
// Check if the request method is POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Get the POST data
    $postData = file_get_contents('php://input');

    // Parse the URL-encoded data into an associative array
    parse_str($postData, $dataArray);

    // Specify the file name
    $fileName = 'test.txt';

    // Convert the array to a readable string format
    $formattedData = print_r($dataArray, true);

    // Attempt to write the formatted data to the file
    if (file_put_contents($fileName, $formattedData) !== false) {
        // Send a success response
        http_response_code(200);
        echo "Data successfully written to $fileName.";
    } else {
        // Send an error response if unable to write
        http_response_code(500);
        echo "Failed to write data to $fileName.";
    }
} else {
    // Send a method not allowed response if the request is not POST
    http_response_code(405);
    echo "Method not allowed. Please use a POST request.";
}
?>

Set the URL for the notice to the location of post.php and perform the action. Then check the test.txt file for the results. You should see something like this in the file:


Array
(
    [_package] => Array
        (
            [id] => 4
            [id_format] => {num}
            [id_value] => 4
            [id_code] => 4
            [module_id] => 4
            [name] => Package Test
            [module_row] => 2
            [module_group_client] => 0
            [taxable] => 0
            [single_term] => 0
            [status] => active
            [hidden] => 0
            [company_id] => 1
            [upgrades_use_renewal] => 1
            [manual_activation] => 0
            [override_price] => 0
            [email_content] => Array
                (
                    [0] => Array
                        (
                            [lang] => de_de
                            [html] =>
                            [text] =>
                        )

                    [1] => Array
                        (
                            [lang] => en_us
                            [html] =>
                            [text] =>
                        )

                )

            [pricing] => Array
                (
                    [0] => Array
                        (
                            [id] => 4
                            [pricing_id] => 34
                            [package_id] => 4
                            [term] => 1
                            [period] => month
                            [price] => 5.0000
                            [price_renews] => 5.0000
                            [setup_fee] => 0.0000
                            [cancel_fee] => 0.0000
                            [currency] => USD
                            [precision] => 2
                            [in_use] => 1
                            [default] => 0
                        )

                )

            [groups] => Array
                (
                    [0] => Array
                        (
                            [id] => 4
                            [type] => standard
                            [company_id] => 1
                            [allow_upgrades] => 1
                            [names] => Array
                                (
                                    [0] => Array
                                        (
                                            [lang] => de_de
                                            [name] => Test
                                        )

                                    [1] => Array
                                        (
                                            [lang] => en_us
                                            [name] => Test
                                        )

                                )

                            [name] => Test
                        )

                )

            [names] => Array
                (
                    [0] => Array
                        (
                            [lang] => de_de
                            [name] => Package Test
                        )

                    [1] => Array
                        (
                            [lang] => en_us
                            [name] => Package Test
                        )

                )

            [descriptions] => Array
                (
                    [0] => Array
                        (
                            [lang] => de_de
                            [html] =>
                            [text] =>
                        )

                    [1] => Array
                        (
                            [lang] => en_us
                            [html] =>
                            [text] =>
                        )

                )

            [description] =>
            [description_html] =>
        )

    [_action] => service_notice_add
    [_other] => Array
        (
            [pricing_id] => 4
            [status] => active
            [use_module] => true
            [module_row_id] => 2
            [save] => Continue
            [package_group_id] => 4
            [qty] => 1
            [client_id] => 2
            [staff_id] => 1
            [coupon_packages] => Array
                (
                    [4] => 4
                )

            [date_added] => 2024-08-02 19:13:13
            [date_renews] => 2024-09-02 19:13:13
        )

)


  • No labels