Jump to content

Configurable options


Recommended Posts

  • 1 month later...

Essentially you would need to duplicate the product yes WHMCS doesn't provide a way to allocate servers based on configurable options.

There are addons that do this and are quite costly. You could use a hook to achieve allocating of servers based on configurable option location. 

Would you be using this for allocating cPanel hosting accounts if so I have a hook I use myself that achieves this.

Link to comment
Share on other sites

  • 2 months later...
On 2/12/2025 at 4:54 PM, Mytihost said:

Essentially you would need to duplicate the product yes WHMCS doesn't provide a way to allocate servers based on configurable options.

There are addons that do this and are quite costly. You could use a hook to achieve allocating of servers based on configurable option location. 

Would you be using this for allocating cPanel hosting accounts if so I have a hook I use myself that achieves this.

can you please share it

Link to comment
Share on other sites

Posted (edited)

Hello

Sure the hook is below and consists of two files the hook and a config file.

I have only tested this for cPanel related hosting I have not had chance to test if it works for DirectAdmin or Plesk. 

This works on configurable options Location only. When client selects location the hook will allocate the same selected plan with the updated server location. If you have multiple servers in the same locations this hook will also allocate a random server for that same selected location. This hook does not currently run any  auto set ups it just allocates a server

To use.

Only one product group is required such as Shared Hosting. Product group should only include the hosting plans that you would consider to be your default/recommended location. If your company is say UK based then you would have the plans that are on your UK server as the default showing all others can be hidden or will no longer be needed.

WHM package names must be identical on each individual server. If for example you have package names Personal and Business  on your default location then they must all be named Personal and Business on each server regardless of location any package name miss matches will cause an error

 

Create a configurable option group. Such as cPanel shared location.

Add new configurable option called Location

Add options 

UK (Change this to your default location)

Location 2

Location 3

Assign configurable option to default hosting plans

 

Hook file server_allocator.php

<?php

use WHMCS\Database\Capsule;

add_hook('AfterShoppingCartCheckout', 1, function($vars) {
    // Load configuration
    $configPath = ROOTDIR . '/includes/hooks/server_allocator_config.php';
    if (!file_exists($configPath)) {
        logActivity('ServerAllocator Hook Error: Config file not found at ' . $configPath);
        return;
    }

    $config = include $configPath;

    // Validate configuration keys
    if (empty($config['productGroups'])) {
        logActivity("ServerAllocator Hook Error: Configuration missing required keys.");
        return;
    }

    // Get the order ID
    $orderId = isset($vars['OrderID']) ? (int)$vars['OrderID'] : 0;
    if ($orderId === 0) {
        logActivity('ServerAllocator Hook Error: Invalid Order ID.');
        return;
    }

    try {
        // Fetch all hosting products associated with the order
        $hostingItems = Capsule::table('tblhosting')
            ->where('orderid', $orderId)
            ->get();

        if ($hostingItems->isEmpty()) {
            logActivity("ServerAllocator Hook: No hosting items found for Order ID {$orderId}.");
            return;
        }

        foreach ($hostingItems as $hostingItem) {
            $productId = $hostingItem->packageid;

            // Fetch the product group name
            $productData = Capsule::table('tblproducts')
                ->where('tblproducts.id', $productId)
                ->join('tblproductgroups', 'tblproducts.gid', '=', 'tblproductgroups.id')
                ->select('tblproductgroups.name as productGroup', 'tblproducts.id as productId')
                ->first();

            if (!$productData || !isset($config['productGroups'][$productData->productGroup])) {
                logActivity("ServerAllocator Hook: Product Group '{$productData->productGroup}' is not configured.");
                continue;
            }

            // Validate product ID in product group
            if (!in_array($productData->productId, $config['productGroups'][$productData->productGroup]['productIds'])) {
                logActivity("ServerAllocator Hook: Product ID '{$productData->productId}' is not part of Product Group '{$productData->productGroup}'.");
                continue;
            }

            // Fetch configurable option for 'Location'
            $configOption = Capsule::table('tblhostingconfigoptions')
                ->where('relid', $hostingItem->id)
                ->join('tblproductconfigoptions', 'tblhostingconfigoptions.configid', '=', 'tblproductconfigoptions.id')
                ->join('tblproductconfigoptionssub', 'tblhostingconfigoptions.optionid', '=', 'tblproductconfigoptionssub.id')
                ->where('tblproductconfigoptions.optionname', 'Location')
                ->select('tblproductconfigoptionssub.optionname as location')
                ->first();

            if (!$configOption) {
                logActivity("ServerAllocator Hook: No 'Location' configurable option found for Hosting ID {$hostingItem->id}.");
                continue;
            }

            $location = $configOption->location;

            // Check if the location is configured for the product group
            if (!isset($config['productGroups'][$productData->productGroup]['serverIds'][$location])) {
                logActivity("ServerAllocator Hook Error: Location '{$location}' not configured for Product Group '{$productData->productGroup}'.");
                continue;
            }

            $availableServers = $config['productGroups'][$productData->productGroup]['serverIds'][$location];
            if (empty($availableServers)) {
                logActivity("ServerAllocator Hook Error: No servers available for Location '{$location}' in Product Group '{$productData->productGroup}'.");
                continue;
            }

            // Find an available server
            $serverId = Capsule::table('tblservers')
                ->whereIn('id', $availableServers)
                ->where('disabled', 0)
                ->value('id');

            if ($serverId !== null) {
                // Update the hosting record with the selected server ID
                Capsule::table('tblhosting')
                    ->where('id', $hostingItem->id)
                    ->update(['server' => $serverId]);

                logActivity("ServerAllocator Hook: Updated Hosting ID {$hostingItem->id} with Server ID {$serverId} for Location '{$location}' in Product Group '{$productData->productGroup}'.");
            } else {
                logActivity("ServerAllocator Hook Error: No enabled servers available for Location '{$location}' in Product Group '{$productData->productGroup}'.");
            }
        }

    } catch (\Exception $e) {
        logActivity('ServerAllocator Hook Exception: ' . $e->getMessage());
    }
});

 

Config file this also goes into the hooks file server_allocator_config.php

 

<?php

/**
 * Server Allocator Configuration File
 *
 * This configuration file is used by the Server Allocator WHMCS hook to determine which servers
 * should be assigned to specific product groups based on the selected location.
 *
 * How It Works:
 * - Each product group (e.g., "Shared Hosting") is mapped to a set of product IDs.
 * - Each product group has a list of server IDs assigned per location.
 * - When an order is placed, the hook checks the product's group and location.
 * - If a matching **enabled** server is available for the selected location, it updates the order accordingly.
 * - **Disabled servers in WHMCS are automatically skipped**. If no enabled servers are available for a location, an error is logged.
 * - Additional product groups and locations can be added by following the same structure.
 *
 * Location References:
 * - The location keys ('UK', 'USA', etc.) **must exactly match** the values set in WHMCS under 
 *   the configurable option for 'Location'. If they do not match, the hook will not be able 
 *   to assign the correct server.
 * - Locations should be added in **WHMCS ? Setup ? Product/Services ? Configurable Options** 
 *   under an option group containing the location choices.
 * - Ensure the names of the locations in this file are identical to the **option values** 
 *   stored in WHMCS for accurate server assignment.
 */

return [
    'productGroups' => [
        'Shared Hosting' => [
            'productIds' => [1, 2], // List of product IDs in this group. Only include the IDs of those for your default location
            'serverIds' => [
                'UK' => [1], // Server IDs for your default location. Change UK to your default location
                'USA' => [2]  // Server IDs for USA location
            ]
        ],

        /*
        'Reseller Hosting' => [
            'productIds' => [201, 202, 203], // List of product IDs in this group
            'serverIds' => [
                'UK' => [5, 6], // Server IDs for UK location
                'USA' => [7, 8]  // Server IDs for USA location
            ]
        ],
        */

        /*
        // Example: Single Product ID with a Single Server ID per Location
        'Shared Hosting' => [
            'productIds' => [2], // Single product ID
            'serverIds' => [
                'UK' => [1], // Only one server available in the UK
                'USA' => [2]  // Only one server available in the USA
            ]
        ],
        */

        /*
        // Example: Adding Extra Locations
        'Shared Hosting' => [
            'productIds' => [301, 302, 303, 304, 305, 306], // Product IDs for this group
            'serverIds' => [
                'UK' => [21, 22],  // Servers assigned for UK location
                'USA' => [23, 24],  // Servers assigned for USA location
                'Germany' => [25, 26], // New location: Germany
                'France' => [27, 28],  // New location: France
                'Australia' => [29, 30] // New location: Australia
            ]
        ],
        */
    ],
];

 

Run into any problems let me know

Edited by Mytihost
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use & Guidelines and understand your posts will initially be pre-moderated