Jump to content

Hook that executes shell script and passes variable based on product's service ID


hosthuski

Recommended Posts

Hello all. I am hoping you can help me do what I think should be simple for people who have dealt with hooks already.

I want to do this:

IF a product's ID = x (I imagine this involves getting the product ID from a variable and doing an IF statement in PHP)

THEN 

get the service_domain field (built-in field, not custom field),

run a shell script while passing the domain field as a bash variable to be used within the script's execution.

Why do I want to do this?

This will allow me to begin the process of provisioning maintenance coverage via WP CLI for customers who order a maintenance plan from us.

I'll create an additional 2 hooks -- three total so one for each maintenance plan. If I can get the first hook, i can make the others and likely merge them together. I just need a "template" to follow from someone who understands PHP more than on the surface like I do. This ultimately will chain 3 of my servers together. WHMCS server, our cPanel server, and the maintenance server.

Any help is appreciated. Would anyone be willing to paste in an effective code sample that I can use?

Link to comment
Share on other sites

When do you want the hook to fire?   Let's say after the server modules does the create:

<?php
add_hook('AfterModuleCreate', 1, function($vars) {
    if (isset($vars['domain']) and !empty($vars['domain']))
    {
        if (function_exists("exec"))
        {
            exec("/path/to/script/shell.sh ".$vars['domain'], $Output, $result_code);
          	// Shell scripts should return "0" when successful and any other number when failed
            if ($result_code === 0)
            {
                // Yay, we are successful, now process output if really wanted
                foreach($Output as $line)
                {
                    if ($line === "some output")
                    {
                        // Run more processing
                    }
                }
            }
            else
            {
                throw new Exception("Uh oh batman, the joker got away");
            }
        }
        else
            throw new Exception("Dude, the security here is nice but we can't do anything");
    }
    else
        throw new Exception("Uh oh, domain isn't given and it should be but it isn't but it reallly should have been!!!");
});

Just note shell_exec, exec, and the other such functions can be disabled for security and so that is the case you would need to have that removed for this to be possible. 

Link to comment
Share on other sites

Whenever exec or shell\_\exec is used, it should be absolutely ensured that the user input is validated, otherwise this can end problematically. I don't see a big problem with the "domain" parameter, since WHMCS should already validate this value, but it's definitely not wrong to validate the parameters again, just in case. 

In addition to validation, I recommend escaping the arguments via the standard PHP function escapeshellarg.

PS: I had to obfuscate shell\_\exec as otherwise the WHMCS server does block my post.

Link to comment
Share on other sites

Thank you so much everyone. This is a huge help to get started.

3 hours ago, steven99 said:

When do you want the hook to fire?   Let's say after the server modules does the create:

That would be great but I don't have a module for this. So I'm hoping to avoid using a module by using a hook instead. In this case, the hook would read what the ID of the product is (to match a product in my products list) and check if it = X.

This way when someone buys a specific product (ie: Maintenance) I can run the hook to provision the maintenance. And if it doesn't match a product we want to match, it does nothing.

Link to comment
Share on other sites

  • 1 month later...
<?php
add_hook('AcceptOrder', 1, function($vars) {
    $serviceid = $vars['serviceid'];
    if (isset($vars['domain']) and !empty($vars['domain']) and isset($vars['serviceid']) and in_array($serviceid, ['10','11','12'], true )  )
    {
        if (function_exists("exec"))
        {
            exec("path/to/bash.sh ".$vars['domain'], $Output, $result_code);
          	// Shell scripts should return "0" when successful and any other number when failed
            if ($result_code === 0)
            {
            exit;
            }
            else
            {
                throw new Exception("Maintenance plan failed to provision automatically. Manual setup required.");
            }
        }
    }
});

Thanks everyone for your help. I've come up with this for my hook code. Does this look like it will be sufficient?

Link to comment
Share on other sites

15 minutes ago, steven99 said:

You'll want to do a "return true" or "return 'success'" or nothing instead of just "exit" as that will quit WHMCS processes . 

Thanks! Fixed it.

<?php
add_hook('AcceptOrder', 1, function($vars) {
    $serviceid = $vars['serviceid'];
    if (isset($vars['domain']) and !empty($vars['domain']) and isset($vars['serviceid']) and in_array($serviceid, ['10','11','12'], true )  )
    {
        if (function_exists("exec"))
        {
            exec("/path/to/bash.sh ".$vars['domain'], $Output, $result_code);
          	// Shell scripts should return "0" when successful and any other number when failed
            if ($result_code === 0)
            {
            exit;
            }
            return true
            {
                throw new Exception("Maintenance plan failed to provision automatically. Manual setup required.");
            }
        }
    }
});

 

Link to comment
Share on other sites

oops! I accidentally erased "else" thinking it was "exit." don't worry. you were perfectly clear. it's fixed now. that's embarassing.

<?php
add_hook('AcceptOrder', 1, function($vars) {
    $serviceid = $vars['serviceid'];
    if (isset($vars['domain']) and !empty($vars['domain']) and isset($vars['serviceid']) and in_array($serviceid, ['10','11','12'], true )  )
    {
        if (function_exists("exec"))
        {
            exec("/path/to/bash.sh ".$vars['domain'], $Output, $result_code);
          	// Shell scripts should return "0" when successful and any other number when failed
            if ($result_code === 0)
            {
            return true
            }
            else
            {
                throw new Exception("Maintenance plan failed to provision automatically. Manual setup required.");
            }
        }
    }
});

 

Edited by hosthuski
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.

×
×
  • 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