Skip to content

Instantly share code, notes, and snippets.

@Pirenko
Last active July 21, 2022 10:56
Show Gist options
  • Save Pirenko/6c51ddcd9a54ecf5da3266e6ffa81030 to your computer and use it in GitHub Desktop.
Save Pirenko/6c51ddcd9a54ecf5da3266e6ffa81030 to your computer and use it in GitHub Desktop.
<?php
/*
Copyright 2018 - Pirenko Studio
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
What is this script for?
This script clones WordPress installs from a WordPress multisite. In this example what triggers the event is a form from the Contact Form 7 plugin.
You can see a live example at https://www.pirenko.com/sandbox/
Requirements:
1) WordPress Multisite Install
2) Blog copier plugin https://wordpress.org/plugins/blog-copier/
3) In this example the Blog Copier plugin was adjusted so that the function "copy_blog" returns the copied blog ID. You can grab the tweaked version of the plugin here https://www.dropbox.com/s/f6693p5u2aj0zb1/blog-copier.zip
4) If the idea is to clone installs make sure also that you create at least one. You will also need to have the install(s) ID's to use in the "switch" statement located inside the "wpcf7_create_sandbox" function
Installation:
1) The content of this file can be added to the theme functions.php file. You can also create a plugin or simply include this file on your theme
2) You will need to create a trigger that will kickstart the clone process. In this example it is a contact form and, once again, you can see an example at https://www.pirenko.com/sandbox/
Any feedback or improvement suggestions are welcome. Also if there's something that is not clear, please reach me using this email: [email protected]
*/
//EXIT IF ACCESSED DIRECTLY
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
//MAKE SURE THAT ALL THE MULTISITE REQUIRED FUNCTIONS ARE INCLUDED
require_once( ABSPATH . '/wp-admin/includes/ms.php');
//GENERATE A RANDOM PASSWORD - THE USER WILL ALSO RECEIVE AN EMAIL WHERE HE CAN CHANGE IT
//AS SEEN HERE https://stackoverflow.com/questions/6101956/generating-a-random-password-in-php
function randomPassword() {
$alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
$pass = array();
$alphaLength = strlen($alphabet) - 1;
for ($i = 0; $i < 8; $i++) {
$n = rand(0, $alphaLength);
$pass[] = $alphabet[$n];
}
return implode($pass);
}
//GENERATE RANDOM PRONOUNCEABLE WORDS - THIS FUNCTION IS USED TO GENERATE A RANDOM URL FOR EACH INSTALLATION
//AS SEEN HERE http://planetozh.com/blog/2012/10/generate-random-pronouceable-words/
function random_pronounceable_word( $length = 6 ) {
//consonant sounds
$cons = array(
//single consonants. Beware of Q, it's often awkward in words
'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'z',
//possible combinations excluding those which cannot start a word
'pt', 'gl', 'gr', 'ch', 'ph', 'ps', 'sh', 'st', 'th', 'wh',
);
//consonant combinations that cannot start a word
$cons_cant_start = array(
'ck', 'cm',
'dr', 'ds',
'ft',
'gh', 'gn',
'kr', 'ks',
'ls', 'lt', 'lr',
'mp', 'mt', 'ms',
'ng', 'ns',
'rd', 'rg', 'rs', 'rt',
'ss',
'ts', 'tch',
);
//wovels
$vows = array(
//single vowels
'a', 'e', 'i', 'o', 'u', 'y',
//vowel combinations your language allows
'ee', 'oa', 'oo',
);
//start by vowel or consonant ?
$current = ( mt_rand( 0, 1 ) == '0' ? 'cons' : 'vows' );
$word = '';
while( strlen( $word ) < $length ) {
// After first letter, use all consonant combos
if( strlen( $word ) == 2 )
$cons = array_merge( $cons, $cons_cant_start );
// random sign from either $cons or $vows
$rnd = ${$current}[ mt_rand( 0, count( ${$current} ) -1 ) ];
// check if random sign fits in word length
if( strlen( $word . $rnd ) <= $length ) {
$word .= $rnd;
// alternate sounds
$current = ( $current == 'cons' ? 'vows' : 'cons' );
}
}
return $word;
}
//IN THIS EXAMPLE IT IS A CONTACT FORM THAT TRIGGERS THE INSTALLATION CLONE PROCESS
//THE ACTION THAT TRIGGERS THE PROCESS IS A SPECIFIC ACTION OF THE CONTACT FORM 7 PLUGIN. IF YOU ARE USING ANOTHER PLUGIN OR TRIGGER MAKE SURE THAT YOU ADJUST THE 'wpcf7_before_send_mail' PARAMETER
add_action( 'wpcf7_before_send_mail', 'wpcf7_create_sandbox',1 );
//CLONE AN EXISTING WORDPRESS INSTALLATION
function wpcf7_create_sandbox($contact_form) {
$submission = WPCF7_Submission::get_instance();
//CHECK SUBMISSION
if ( $submission ) {
//GET THE FORM FIELDS
$posted_data = $submission->get_posted_data();
$user_name = $posted_data['your-name'];
$user_email = strtolower($posted_data['your-email']);
$theme_name = strtolower($posted_data['menu-448']);
//GET THE ID OF THE INSTALLATION THAT WILL BE COPIED
//THE CONTACT FORM SEND THE THEME SLUG AND NOW WE NEED TO GET THE INSTALLATION ID
switch ($theme_name) {
case "theme-a":
$copy_id=1;
break;
case "theme-b":
$copy_id=2;
break;
case "theme-c":
$copy_id=3;
break;
default:
exit;
}
/*
* Copy the blog function syntax - this function belongs to the blog copier plugin
*
* @param string $domain url of the new blog
* @param string $title title of the new blog
* @param int $from_blog_id ID of the blog being copied from.
* @param bool $copy_files true if files should be copied
* @return new blog ID or error message
*/
$BlogCopier_sand = new BlogCopier();
$appender=$theme_name.'-'.random_pronounceable_word();
$sand_url='sandbox/'.$appender.'/';
$sandbox_result=$BlogCopier_sand->copy_blog($sand_url,'Pirenko Themes Sandbox',$copy_id,true);
//ADD NEW USER
$sand_user=wp_create_user( $user_email, randomPassword() , $user_email );
//CHECK IF USER ALREADY EXISTS
if ( is_wp_error( $sand_user ) ) {
$sand_user=get_user_by('email',$user_email);
if ( is_wp_error( $sand_user ) ) {
//CAN'T FIND THIS USER - GIVE UP
//TODO: SEND MESSAGE TO ADMIN AND USER
exit;
}
else {
//IN THIS CASE WE NEED TO GET THE USER ID FROM THE OBJECT
$sand_user=$sand_user->ID;
}
}
else {
//SEND EMAIL WITH THE NEW USER NOTIFICATION
wp_new_user_notification($sand_user,'','both');
}
//REMOVE USER FROM THE MAIN INSTALLATION - NOT SURE WHY, BUT THE USER IS SOMETIMES ADDED TO THE FIRST/DEFAULT INSTALLATION
remove_user_from_blog($sand_user,'1');
//ADD USER TO HIS BRAND NEW INSTALLATION
add_user_to_blog( $sandbox_result , $sand_user, 'administrator' );
//GET NEW INSTALLATION URL
$sand_url="https://www.pirenko.com/".$sand_url;
//ADJUST THE WEBSITE URL
switch_to_blog($sandbox_result);
update_site_option('siteurl',$sand_url);
update_site_option('home',$sand_url);
restore_current_blog();
//BUILD WELCOME EMAIL
$to = $user_email;
$subject = 'Good news! Your '.$posted_data['menu-448'].' WordPress Theme tryout is ready.';
$message = 'Hi '.$user_name.',<br />';
$message.= "Some awesome message goes here.";
$headers = array('Content-Type: text/html; charset=UTF-8','From: Someone <[email protected]>','Bcc: [email protected]','Reply-To: Someone <[email protected]>');
//SEND WELCOME EMAIL
$sent_message = wp_mail( $to, $subject, $message, $headers );
//TODO: SEND MESSAGE TO ADMIN IF THE EMAIL IS NOT SENT FOR SOME REASON
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment