Plugin – Sandbox Creation (Part 2) – MultiSite WordPress

Tech Articles | February 14, 2025 | Automation, Blog, Cloudflare, Coding, FlowMattic, GridPane, Hosting, Plugins, SureForms, Wordpress

This is Part 2 of the series, and this is the final part. I was able to condense this into two videos rather than three because I provided an easy-to-manage plugin for the works.

Now, my plan of action is to have a sandbox domain, wpdemo.uk, in my case, and a subdomain for each plugin, which will be its own multisite installation. For this article and for the purpose, the plugin I wanted to offer testing for was Hooksure. This meant I needed to Install, and network activate SureForms and Hooksure, and I set them to automatically update, too. I also installed my emailit mu-plugin to handle email delivery, which is standard on my GridPane installations.

Once this was all done, I had the basis of my multi-site installation, and I went looking for a way to create them with flowmattic and also delete the,m, but I couldn’t find a solution I liked, but I had a feeling this would be the case I wanted Lightweight easy to use and quick so I decided to make my own rest-api points we could use to create and delete a site from a remote Flowmattic instance which will be hosted on another of my gridpane boxes.

So I created a new plugin called multisite-plugin-sandbox, available here on GitHub
https://github.com/stingray82/multisite-plugin-sandbox

Note: This Plugin also has some extra security to prevent uploads and PHP modification once activated, so add this last or disable it network-wide to add a new plugin.

The First thing I did when back on the multisite was disable signup notifications by clicking the checkbox below to uncheck it this is located in wp-admin/network/settings.php

After all the only notifications I want are in Discord, so that disabled those I have since the recording of the videos to this series. I also added an option in the plugin to disable password reset email notifications as I was getting one per site.

Below is what the plugins menu looks like:

I also modified my email it MU plugin so that on multisite installations, it only runs on the main site, on all other sites, it is disabled using an override, but you could adapt your own plugins to do the same if you use a MU email delivery and set up your own variable or put code between the brackets.

if (!is_main_site()) {
    define('td_email_override', true);
}
PHP

So, with these two changes, we now have two new rest API points

  • wp-json/sandbox/v1/create/
  • wp-json/sandbox/v1/delete/

wp-json/sandbox/v1/create/ requires a JSON payload like the one below:

{
    "secret": "your-secure-secret-key",
    "slug": "Yoursites subdomain",
    "title": "My Sandbox Site",
    "email": "[email protected]" 
}
JSON

wp-json/sandbox/v1/delete/ requires the following payload


{
    "secret": "your-secure-secret-key",
    "site_id": 5
}
JSON

We will need that for our automaton, in my case, I will be using flowmatti,c and I also needed a way to generate host names (slug), and I decided I wanted three animals and a random 4 number end in the format of animal1-animal2-animal3-XXXX for my subdomains

To achieve this, I wrote the below function generateRandomAnimalString() with ChatGPT giving me a list of animals I could randomise, this needs to be available on the site running your automation not on the multisite and in my case it was added to WPCodeBox and was called in flowmattic using the PHP function module.

<?php 
function generateRandomAnimalString() {
    $animals = [
        "Aardvark", "Albatross", "Alligator", "Alpaca", "Anaconda", "Ant", "Anteater", "Antelope",
        "Armadillo", "Axolotl", "Baboon", "Badger", "Barracuda", "Bat", "Beaver", "Bee", "Bison",
        "Blackbird", "Boa", "Boar", "Bobcat", "Bonobo", "Buffalo", "Butterfly", "Camel", "Capybara",
        "Caracal", "Caribou", "Cassowary", "Cat", "Caterpillar", "Cheetah", "Chicken", "Chimpanzee",
        "Chinchilla", "Clam", "Clownfish", "Cobra", "Cockatoo", "Cockroach", "Cod", "Condor", "Coral",
        "Cougar", "Cow", "Coyote", "Crab", "Crane", "Crawfish", "Crocodile", "Crow", "Cuttlefish",
        "Dachshund", "Deer", "Dhole", "Dingo", "Dodo", "Dog", "Dolphin", "Donkey", "Dormouse",
        "Dragonfly", "Duck", "Dugong", "Dunlin", "Eagle", "Echidna", "Eel", "Egret", "Elephant",
        "Elk", "Emu", "Falcon", "Ferret", "Finch", "Firefly", "Fish", "Flamingo", "Flea", "Fly",
        "FlyingSquirrel", "Fossa", "Fox", "Frigatebird", "Frog", "Gannet", "Gar", "Gazelle", "Gecko",
        "Gerbil", "Gharial", "Gibbon", "Giraffe", "Goat", "Goldfish", "Goose", "Gorilla",
        "Grasshopper", "Grouper", "Grouse", "Guanaco", "GuineaPig", "Gull", "Hamster", "Hare", "Hawk",
        "Hedgehog", "Heron", "Herring", "Hippopotamus", "Hornet", "Horse", "Human", "Hummingbird",
        "Husky", "Hyena", "Ibex", "Ibis", "Iguana", "IndianStarTortoise", "Jackal", "Jaguar",
        "Jellyfish", "Kangaroo", "Kingfisher", "Kiwi", "Koala", "Koi", "KomodoDragon", "Krill",
        "Ladybird", "Lamprey", "Lark", "Leech", "Lemur", "Leopard", "Lion", "Lizard", "Llama",
        "Lobster", "Locust", "Loris", "Lynx", "Macaw", "Magpie", "Mallard", "Manatee", "Mandrill",
        "MantaRay", "Mantis", "Meerkat", "Mink", "Mole", "Mongoose", "Mongrel", "Monkey", "Moose",
        "Moth", "Mouse", "Mule", "Narwhal", "Nautilus", "Newt", "Nightingale", "Numbat", "Ocelot",
        "Octopus", "Okapi", "Olm", "Opossum", "Orangutan", "Orca", "Osprey", "Ostrich", "Otter",
        "Owl", "Ox", "Oyster", "Pademelon", "Panda", "Panther", "Parrot", "Peacock", "Pelican",
        "Penguin", "Pheasant", "Pig", "Pigeon", "Pike", "Platypus", "PolarBear", "Pony", "Porcupine",
        "Porpoise", "Possum", "PrairieDog", "Prawn", "Pronghorn", "Puffin", "Puma", "Quail",
        "Quelea", "Quokka", "Quoll", "Rabbit", "Raccoon", "Ram", "Rat", "Rattlesnake", "Raven",
        "RedPanda", "Reindeer", "Rhinoceros", "Roadrunner", "Robin", "Rooster", "Salamander",
        "Salmon", "Sandpiper", "Saola", "Scorpion", "Seahorse", "Seal", "Shark", "Sheep", "Shrimp",
        "Skunk", "Sloth", "Snail", "Snake", "SnowLeopard", "SnowyOwl", "Spider", "Sponge", "Squid",
        "Squirrel", "Starfish", "Stingray", "Stork", "SugarGlider", "Swan", "Swordfish", "Tamarin",
        "Tapir", "Tarsier", "TasmanianDevil", "Termite", "Tetra", "Tiger", "Toad", "Tortoise",
        "Toucan", "Tuna", "Turkey", "Turtle", "VampireBat", "Viper", "Vulture", "Wallaby",
        "Walrus", "Warthog", "Wasp", "Weasel", "Whale", "Whippet", "WhiteRhino", "WildBoar",
        "Wolf", "Wolverine", "Wombat", "Woodpecker", "Wren", "Xerus", "Yak", "YellowfinTuna",
        "Zebra", "Zebu", "Zorilla"
    ];

    // Shuffle the array and select 3 unique animals
    shuffle($animals);
    $selectedAnimals = array_slice($animals, 0, 3);

    // Generate a random 4-digit number
    $randomNumber = rand(1000, 9999);

    // Return formatted string
    return implode("-", $selectedAnimals) . "-" . $randomNumber;
}
PHP

Now we begin automation.

I now went to my site and built a basic page. Do you want to create a sandbox page for Hooksure. I did this with bricks and SureForms. You can see that page below and I had this installed on the site I also had flowmattic on so was able to use the SureForms trigger as I wasn’t returning anything and I wasn’t on a different site.

This would then allow me to build out the following workflow in FlowMattic, its actually not all that complex I will explain it below

This may seem like a complex setup but actually, the workflow is minimal and simple thanks to the use of the API module and knowing what the api’s require

Step 1:

We Trigger using Sureforms native integration in flowmattic

Step 2:

We generate our random subdomain using generateRandomAnimalString()

Step 3:

We then use /wp-json/sandbox/v1/create/ with our payload consisting of a) our secret key b) our Step2 subdomain c) HookSure Sandbox, and d) the email that triggered the workflow we get back some data for this one, including the site_id we will need this later for step 6

Step 4:

We then take the details of the name of the subdomain and send it to Discord as a notification that someone has tried a sandbox; we are only sending a simple message, so we don’t use the native integration. We just send it directly to the webhook.

Step 5:

We now wait 2 hours using the delay options

Step 6:

We use the site_id from step three and our secret key to delete the site after the delay has ended.

I then tested the flow, and all worked as intended. Our site is created, we get the emails, and we don’t get passwords or new site creation emails.

Note: Since this article was written and the videos recorded, I have added a step between 4 and 5 that sends the following email to the email address from the SureForms trigger. I didn’t like the fact it wasn’t clear what your site was without one and thought this was the easiest way to rectify it, I could also return the site details via Response for SureForms, but I thought this was better on this occasion.

Support the Author

buy me a coffee
Really Useful Plugin Logo
Appoligies for any spelling and grammer issue. As a dyslexic i need to rely on tools for this they like me are not perfect but I do try my best