I've got a handful of sites I need to hit via Cron. I didn't want to create 20 cron jobs, so I created one that hits a single PHP script on my development server. It looks like this:
<?php //This script will send out directives to send [some] emails to [people]
//Start new init with $ch1, $ch2, $ch3 etc
$ch1 = curl_init();
$ch2 = curl_init();
$ch3 = curl_init();
$ch4 = curl_init();
$ch5 = curl_init();
$ch6 = curl_init();
$ch7 = curl_init();
$ch8 = curl_init();
$ch9 = curl_init();
$ch10 = curl_init();
$ch11 = curl_init();
$ch12 = curl_init();
$ch13 = curl_init();
$ch14 = curl_init();
$ch15 = curl_init();
$ch16 = curl_init();
$ch17 = curl_init();
$ch18 = curl_init();
$ch19 = curl_init();
//Set URL and options
curl_setopt($ch1, CURLOPT_URL, 'http://site1.com/?key=mykey');
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch2, CURLOPT_URL, 'http://site2.com/?key=mykey');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch3, CURLOPT_URL, 'http://site3.com/?key=mykey');
curl_setopt($ch3, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch4, CURLOPT_URL, 'http://site4.com/?key=mykey');
curl_setopt($ch4, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch5, CURLOPT_URL, 'http://site5.com/?key=mykey');
curl_setopt($ch5, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch6, CURLOPT_URL, 'http://site6.com/?key=mykey');
curl_setopt($ch6, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch7, CURLOPT_URL, 'http://site7.com/?key=mykey');
curl_setopt($ch7, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch8, CURLOPT_URL, 'http://site8.com/?key=mykey');
curl_setopt($ch8, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch9, CURLOPT_URL, 'http://site9.com/?key=mykey');
curl_setopt($ch9, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch10, CURLOPT_URL, 'http://site10.com/?key=mykey');
curl_setopt($ch10, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch11, CURLOPT_URL, 'http://site11.com/?key=mykey');
curl_setopt($ch11, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch12, CURLOPT_URL, 'http://site12.com/?key=mykey');
curl_setopt($ch12, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch13, CURLOPT_URL, 'http://site13.com/?key=mykey');
curl_setopt($ch13, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch14, CURLOPT_URL, 'http://site14.com/?key=mykey');
curl_setopt($ch14, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch15, CURLOPT_URL, 'http://site15.com/?key=mykey');
curl_setopt($ch15, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch16, CURLOPT_URL, 'http://site16.com/?key=mykey');
curl_setopt($ch16, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch17, CURLOPT_URL, 'http://site17.com/?key=mykey');
curl_setopt($ch17, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch18, CURLOPT_URL, 'http://site18.com/?key=mykey');
curl_setopt($ch18, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch19, CURLOPT_URL, 'http://site19.com/?key=mykey');
curl_setopt($ch19, CURLOPT_RETURNTRANSFER, 1);
//Create multiple cURL handlers
$mh = curl_multi_init();
//Add the handles
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);
curl_multi_add_handle($mh, $ch3);
curl_multi_add_handle($mh, $ch4);
curl_multi_add_handle($mh, $ch5);
curl_multi_add_handle($mh, $ch6);
curl_multi_add_handle($mh, $ch7);
curl_multi_add_handle($mh, $ch8);
curl_multi_add_handle($mh, $ch9);
curl_multi_add_handle($mh, $ch10);
curl_multi_add_handle($mh, $ch11);
curl_multi_add_handle($mh, $ch12);
curl_multi_add_handle($mh, $ch13);
curl_multi_add_handle($mh, $ch14);
curl_multi_add_handle($mh, $ch15);
curl_multi_add_handle($mh, $ch16);
curl_multi_add_handle($mh, $ch17);
curl_multi_add_handle($mh, $ch18);
curl_multi_add_handle($mh, $ch19);
$active = null;
//Execute handles
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
//Error Report
echo 'Errors for <strong>site1.com</strong>: '.curl_error($ch1).'<br />';
echo 'Error Count for site1.com: <strong>'.curl_errno($ch1).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site2.com</strong>: '.curl_error($ch2).'<br />';
echo 'Error Count for site2.com: <strong>'.curl_errno($ch2).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site3.com</strong>: '.curl_error($ch3).'<br />';
echo 'Error Count for site3.com: <strong>'.curl_errno($ch3).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site4.com</strong>: '.curl_error($ch4).'<br />';
echo 'Error Count for site4.com: <strong>'.curl_errno($ch4).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site5.com</strong>: '.curl_error($ch5).'<br />';
echo 'Error Count for site5.com: <strong>'.curl_errno($ch5).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site6.com</strong>: '.curl_error($ch6).'<br />';
echo 'Error Count for site6.com: <strong>'.curl_errno($ch6).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site7.com</strong>: '.curl_error($ch7).'<br />';
echo 'Error Count for site7.com: <strong>'.curl_errno($ch7).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site8.com</strong>: '.curl_error($ch8).'<br />';
echo 'Error Count for site8.com: <strong>'.curl_errno($ch8).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site9.com</strong>: '.curl_error($ch9).'<br />';
echo 'Error Count for site9.com: <strong>'.curl_errno($ch9).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site10.com</strong>: '.curl_error($ch10).'<br />';
echo 'Error Count for site10.com: <strong>'.curl_errno($ch10).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site11.com</strong>: '.curl_error($ch11).'<br />';
echo 'Error Count for site11.com: <strong>'.curl_errno($ch11).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site12.com.au</strong>: '.curl_error($ch12).'<br />';
echo 'Error Count for site12.com.au: <strong>'.curl_errno($ch12).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site13.com</strong>: '.curl_error($ch13).'<br />';
echo 'Error Count for site13.com: <strong>'.curl_errno($ch13).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site14.com</strong>: '.curl_error($ch14).'<br />';
echo 'Error Count for site14.com: <strong>'.curl_errno($ch14).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site15.com</strong>: '.curl_error($ch15).'<br />';
echo 'Error Count for site15.com: <strong>'.curl_errno($ch15).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site16.com</strong>: '.curl_error($ch16).'<br />';
echo 'Error Count for site16.com: <strong>'.curl_errno($ch16).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site17.com</strong>: '.curl_error($ch17).'<br />';
echo 'Error Count for site17.com: <strong>'.curl_errno($ch17).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site18.com</strong>: '.curl_error($ch18).'<br />';
echo 'Error Count for site18.com: <strong>'.curl_errno($ch18).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site19.com</strong>: '.curl_error($ch19).'<br />';
echo 'Error Count for site19.com: <strong>'.curl_errno($ch19).'</strong><br /><br />';
//Close handles
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_remove_handle($mh, $ch3);
curl_multi_remove_handle($mh, $ch4);
curl_multi_remove_handle($mh, $ch5);
curl_multi_remove_handle($mh, $ch6);
curl_multi_remove_handle($mh, $ch7);
curl_multi_remove_handle($mh, $ch8);
curl_multi_remove_handle($mh, $ch9);
curl_multi_remove_handle($mh, $ch10);
curl_multi_remove_handle($mh, $ch11);
curl_multi_remove_handle($mh, $ch12);
curl_multi_remove_handle($mh, $ch13);
curl_multi_remove_handle($mh, $ch14);
curl_multi_remove_handle($mh, $ch15);
curl_multi_remove_handle($mh, $ch16);
curl_multi_remove_handle($mh, $ch17);
curl_multi_remove_handle($mh, $ch18);
curl_multi_remove_handle($mh, $ch19);
curl_multi_close($mh);
echo 'Script Executed Successfully!'; // Just shows me the file is actually loading to completion
?>
Each of these sites is WordPress that's built to handle the query string.
<?php
if( $_GET['key'] == 'mykey'){
$network_array = wp_get_sites();
foreach( $network_array as $site ){
$temp = file_get_contents('http://'.$site['domain'].'/page-with-mail-script/?runkey=AnotherKey');
$temp = '';
}
}
?>
At this point, the idea is to use the wp_get_sites()
function to get an array of all of the sites on that particular network (these are all wordpress multisite). I use file_get_contents()
to visit the site with a query string to run the script on that page.
That page template runs a wp_query for a list of emails to send, and one for a list of "contacts" to send them to, using Mandrill by MailChimp. This is that file:
get_header();
do_action( 'genesis_before_content_sidebar_wrap' );
?>
<div id="content-sidebar-wrap">
<?php do_action( 'genesis_before_content' ); ?>
<div id="content" class="hfeed">
<?php
if($_GET['key'] == 'AnotherKey'){
#Start up contact query
$contact_query = new WP_Query(array('post_type' => 'contacts', 'posts_per_page' => '-1'));
$invite_query = new WP_Query(array('post_type' => 'invites', 'posts_per_page' => '-1'));
#Let's use the get_posts method for a foreach loop option
$contacts = $contact_query->get_posts();
$invites = $invite_query->get_posts();
#Loop through the contacts
foreach( $contacts as $contact ){
$email_status = 'skipped.';
#Initiate the custom fields
$contact_custom = get_post_custom($contact->ID);
#Return custom fields as variables
$email_address = $contact_custom['email_address'][0]; //Where do we reach them?
$email_number = $contact_custom['email_number'][0]; //Which email do they need?
$last_email_date = $contact_custom['last_email_date'][0]; //When did they last get one?
//$phone_number = $contact_custom['phone_number']; // Phone Number (NOT USED 9-23-14)
#Let's get some other variables we need
$today = time();
$remove_me_link = '<a href="'.site_url().'/remove-me?email='.urlencode($email_address).'" target="_blank">Get Removed From This List</a>';
#If EMAIL_NUMBER is GREATER than zero, continue, otherwise skip (this is set to a negative value to remove them from the list)
if( $email_number > 0 ){
#We need to find the email to send them.
foreach( $invites as $invite ){
#Initiate the custom fields
$invite_custom = get_post_custom($invite->ID);
#Return custom fields as variables
$invite_number = $invite_custom['invite_number'][0]; //Which email is this?
$invite_delay = $invite_custom['invite_delay'][0]; //How long should we wait to send this one?
$forgiving_delay = $invite_delay * 86400; //Ex. 1, or 7 times a unix day
$forgiving_delay = $forgiving_delay - 28800; // Remove 8 hours from the timeframe, this allows some leway in server time discrepancies
$publish_date = get_the_time('U', $contact->ID); //Convert publish date to unix
#See if the invite number matches their required email number
if( $invite_number == $email_number ){
#It does! Now see if the proper delay has been met
if( empty($last_email_date) || $last_email_date == '' || $last_email_date < 9999 ){ //This means they're new. We need to wait until the delay after the PUBLISH date for this.
if($today - $publish_date > $forgiving_delay){
$to = $email_address;
$subject = $invite->post_title;
$message = '
<html>
<head>
<title>'.$invite->post_title.'</title>
</head>
<body>
<p>'.$invite->post_content.'</p>
<br />
<br />
<p style="font-size: 10px;">This email was sent to you on behalf of <strong>'.$gv->organization.'</strong>, <strong>'.$gv->address.', '.$gv->city.' '.$gv->state.' '.$gv->zip_code.'</strong><br />If you have any questions, please send an email to <strong>'.$gv->author_email.'</strong> or call <strong>'.$gv->phone.'</strong>.</p>
<p style="font-size: 10px;">Don\'t want to see this? '.$remove_me_link.'</p>
</body>
</html>';
$message = str_replace('{contact_name}', $contact->post_title, $message);
$message = str_replace('{contact_email}', $email_address, $message);
$message = str_replace('{review_engine_url}', str_replace(array('http://', 'https://'), '', site_url()), $message);
$message = str_replace('{google_url}', $gv->google_plus, $message);
$message = str_replace('{yelp_url}', $gv->yelp, $message);
$message = str_replace('{facebook_url}', $gv->like_box, $message);
$message = str_replace('{review_site_one_url}', $gv->review_site_one_url, $message);
$message = str_replace('{review_site_two_url}', $gv->review_site_two_url, $message);
$message = str_replace('{review_site_three_url}', $gv->review_site_three_url, $message);
$message = str_replace('{review_site_four_url}', $gv->review_site_four_url, $message);
$message = str_replace('{superpages_url}', $gv->super_pages, $message);
$message = nl2br($message);
//$from = 'mailer@'.str_replace(array('http://', 'https://'), '', site_url());
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
//$headers .= 'From: '.$from;
$mail = wpMandrill::mail($to, $subject, $message, $headers);
#If it succeeded, let's update post data in the contact
if( $mail ){
update_post_meta($contact->ID, 'email_number', $email_number + 1);
update_post_meta($contact->ID, 'last_email_date', $today);
$email_status = 'Good!';
} else {
$email_status = 'Bad.';
}
echo $contact->post_title.': <strong>'.$email_status.'</strong><br />';
}
} else {
if($today - $last_email_date > $forgiving_delay){ // This means they've gotten emails before, proceed as normal
//trm_send_invite_email(); //WHAT DID THIS DO?
$to = $email_address;
$subject = $invite->post_title;
$message = '
<html>
<head>
<title>'.$invite->post_title.'</title>
</head>
<body>
<p>'.$invite->post_content.'</p>
<br />
<br />
<p style="font-size: 10px;">This email was sent to you on behalf of <strong>'.$gv->organization.'</strong>: <strong>'.$gv->address.', '.$gv->city.' '.$gv->state.' '.$gv->zip_code.'</strong><br />If you have any questions, please send an email to <strong>'.$gv->author_email.'</strong> or call <strong>'.$gv->phone.'</strong>.</p>
<p style="font-size: 10px;">Don\'t want to see this? '.$remove_me_link.'</p>
</body>
</html>';
$message = str_replace('{contact_name}', $contact->post_title, $message);
$message = str_replace('{contact_email}', $email_address, $message);
$message = str_replace('{review_engine_url}', str_replace(array('http://', 'https://'), '', site_url()), $message);
$message = str_replace('{google_url}', $gv->google_plus, $message);
$message = str_replace('{yelp_url}', $gv->yelp, $message);
$message = str_replace('{facebook_url}', $gv->like_box, $message);
$message = str_replace('{review_site_one_url}', $gv->review_site_one_url, $message);
$message = str_replace('{review_site_two_url}', $gv->review_site_two_url, $message);
$message = str_replace('{review_site_three_url}', $gv->review_site_three_url, $message);
$message = str_replace('{review_site_four_url}', $gv->review_site_four_url, $message);
$message = str_replace('{superpages_url}', $gv->super_pages, $message);
$message = nl2br($message);
//$from = $gv->organization.'@'.str_replace(array('http://', 'http:s//'), '', site_url());
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
//$headers .= 'From: '.$from;
$mail = wpMandrill::mail($to, $subject, $message, $headers);
#If it succeeded, let's update post data in the contact
if( $mail ){
update_post_meta($contact->ID, 'email_number', $email_number + 1);
update_post_meta($contact->ID, 'last_email_date', $today);
} else {
$email_status = 'Bad.';
}
}
echo $contact->post_title.': <strong>'.$email_status.'</strong><br />';
}
}
} //End Invite Loop
}
} //End Contact loop
} else {
echo '<h1 class="entry-title">Hold on, partner!</h1>';
echo '<p>You\'re not supposed to be here!</p>';
} ?>
</div><!-- end #content -->
<?php do_action( 'genesis_after_content' ); ?>
<div style="clear:both;"></div>
</div><!-- end #content-sidebar-wrap -->
<?php
do_action( 'genesis_after_content_sidebar_wrap' );
get_footer();
I get a notification from the Cron Daemon saying that the script executed, by showing the "Script Executed Succesfully" echo in the first file that gets hit by the cron.
The problem is, the emails seem to get sent on the first couple sites, but then the rest remain untouched, as shown by a custom field in the "contact" post type.
Is the script timing out? Getting killed? Should I instead of going to each site in one file, go to each separately? Or should I used curl_init()
, curl_setopt
, and then remove the cURL before going to the next one?