Skip to content

Commit

Permalink
Add organizer debrief survey (#1038)
Browse files Browse the repository at this point in the history
* Add plugin: WordCamp Organizer Survey.

* Add cron job.

* Add camptix email.

* Make plugin unable to be network deactivated.

* Embed a token in URL for verifying organizer.

* Fill in data that we already know.

* Fix tix_email stats counting error.
  • Loading branch information
renintw authored Sep 26, 2023
1 parent bb71356 commit 0f1c5fe
Show file tree
Hide file tree
Showing 6 changed files with 526 additions and 8 deletions.
17 changes: 9 additions & 8 deletions .docker/wp-config.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,15 @@
* environments, because generating the keys locally is safer than using the API (and exposing the keys to
* your OS/browser if you copy/paste, etc).
*/
define( 'AUTH_KEY', 'put your unique phrase here' );
define( 'SECURE_AUTH_KEY', 'put your unique phrase here' );
define( 'LOGGED_IN_KEY', 'put your unique phrase here' );
define( 'NONCE_KEY', 'put your unique phrase here' );
define( 'AUTH_SALT', 'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT', 'put your unique phrase here' );
define( 'NONCE_SALT', 'put your unique phrase here' );
define( 'AUTH_KEY', 'put your unique phrase here' );
define( 'SECURE_AUTH_KEY', 'put your unique phrase here' );
define( 'LOGGED_IN_KEY', 'put your unique phrase here' );
define( 'NONCE_KEY', 'put your unique phrase here' );
define( 'AUTH_SALT', 'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT', 'put your unique phrase here' );
define( 'NONCE_SALT', 'put your unique phrase here' );
define( 'ORGANIZER_SURVEY_ACCESS_TOKEN_KEY', 'put your unique phrase here' );


/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ function _get_network_plugin_state_list( $state ) {
} elseif ( EVENTS_NETWORK_ID === $network_id ) {
$network_plugin_state['deactivated'][] = 'tagregator/bootstrap.php';
$network_plugin_state['activated'][] = 'camptix-attendee-survey/camptix-attendee-survey.php';
$network_plugin_state['activated'][] = 'wordcamp-organizer-survey/wordcamp-organizer-survey.php';
}

return $network_plugin_state[ $state ];
Expand Down
3 changes: 3 additions & 0 deletions public_html/wp-content/plugins/camptix/camptix.php
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,9 @@ function manage_columns_email_action( $column, $post_id ) {
break;
case 'tix_total':
$recipients_backup = get_post_meta( $post_id, 'tix_email_recipients_backup', true );
if( empty( $recipients_backup ) ) {
$recipients_backup = [];
}
echo count( $recipients_backup );
break;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<?php

namespace WordCamp\OrganizerSurvey\DebriefSurvey\Cron;

defined( 'WPINC' ) || die();

use CampTix_Plugin;

use function WordCamp\OrganizerSurvey\DebriefSurvey\Email\{
get_email_id,
queue_survey_email,
get_lead_organizer_email,
get_lead_organizer_full_name
};

/**
* Constants.
*/
const DAYS_AFTER_TO_SEND = 2;
const TEMP_ATTENDEE_ID = 'organizer_debrief_survey_temp_attendee';

/**
* Actions & hooks
*/
add_action( 'init', __NAMESPACE__ . '\schedule_jobs' );
add_action( 'wc_organizer_debrief_survey_email', __NAMESPACE__ . '\queue_organizer_survey' );

/**
* Logs a message to the CampTix email log.
*/
function log( $message, $post_id, $data = null ) {
/* @var CampTix_Plugin $camptix */
global $camptix;

$camptix->log( $message, $post_id, $data );
}

/**
* Get Wordcamp attendee ID.
*
* @return int
*/
function get_wordcamp_attendees_id() {
return get_option( TEMP_ATTENDEE_ID );
}

/**
* Add cron jobs to the schedule.
*/
function schedule_jobs() {
if ( ! wp_next_scheduled( 'wc_organizer_debrief_survey_email' ) ) {
wp_schedule_event( time(), 'daily', 'wc_organizer_debrief_survey_email' );
}
}

/**
* Add temporary attendee since email can only be sent to items in attendee tracker.
*/
function add_temp_attendee() {
if ( ! get_wordcamp_attendees_id() ) {
$attendees_id = wp_insert_post( array(
'post_title' => 'Organizer debrief survey',
'post_name' => 'organizer-debrief-survey',
'post_type' => 'tix_attendee',
'post_status' => 'publish',
) );

if ( $attendees_id ) {
update_post_meta( $attendees_id, 'tix_email', get_lead_organizer_email() );
update_post_meta( $attendees_id, 'tix_receipt_email', get_lead_organizer_email() );
update_post_meta( $attendees_id, 'tix_first_name', get_lead_organizer_full_name() );

update_option( TEMP_ATTENDEE_ID, $attendees_id );
log( 'Successfully added attendee:', get_email_id(), $attendees_id );
} else {
log( 'Failed to add attendee:', get_email_id(), $attendees_id );
}
}
}

/**
* Associates attendee to emails.
*/
function associate_attendee_to_email( $email_id ) {
$recipient_id = get_wordcamp_attendees_id();

if ( empty( $recipient_id ) ) {
log( 'No valid recipients', $email_id, null );
return;
}

// Associate attendee to tix_email as a recipient.
$result = add_post_meta( $email_id, 'tix_email_recipient_id', $recipient_id );

if ( ! $result ) {
log( 'Failed to add recipients:', $email_id, $recipient_id );
} else {
update_post_meta( $email_id, 'tix_email_recipients_backup', (array) $recipient_id );
log( 'Successfully added recipients:', $email_id, $recipient_id );
}
}

/**
* Returns true if an emailed will be sent or is queued.
*
* @return bool
*/
function is_email_already_sent_or_queued( $email_id ) {
$email = get_post( $email_id );
return 'publish' === $email->post_status || 'pending' === $email->post_status;
}

/**
* Returns true if it is time to send the email.
*
* @return bool
*/
function is_time_to_send_email( $email_id ) {
$blog_id = get_current_blog_id();
$wordcamp_post = get_wordcamp_post( $blog_id );

if ( ! $wordcamp_post ) {
log( 'Couldn\'t retrieve wordcamp for blog id:', $email_id, $blog_id );
return false;
}

$end_date = $wordcamp_post->meta['End Date (YYYY-mm-dd)'][0];

if ( empty( $end_date ) ) {
// Some sites that are only 1-day events will only have the start date.
$end_date = $wordcamp_post->meta['Start Date (YYYY-mm-dd)'][0];
}

$date = new \DateTime("@$end_date ");
$current_date = new \DateTime();
$interval = $current_date->diff($date);
$days_difference = $interval->days;

return DAYS_AFTER_TO_SEND === $days_difference;
}

/**
* Delete the temporary attendee.
*/
function delete_temp_attendee() {
$attendee_id = get_wordcamp_attendees_id();
wp_delete_post( $attendee_id, true );
delete_option( TEMP_ATTENDEE_ID );
}

/**
* Associates recipients to email and changes its status to be picked up
* by the camptix email cron job `tix_scheduled_every_ten_minutes`.
*/
function queue_organizer_survey() {
$email_id = get_email_id();

if ( empty( $email_id ) ) {
return;
}

// check to make sure we didn't already send an email for this wordcamp.
if ( is_email_already_sent_or_queued( $email_id ) ) {
return;
}

if ( ! is_time_to_send_email( $email_id ) ) {
return;
}

add_temp_attendee();
associate_attendee_to_email( $email_id );

$email_status = queue_survey_email( $email_id );

if ( is_wp_error( $email_status ) ) {
log( 'Failed updating email status', $email_id, $email_status );
} else {
log( 'Email status change to `pending`.', $email_id );
}

// Remove the cron job that queues everything.
wp_clear_scheduled_hook( 'wc_organizer_debrief_survey_email' );
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php
/**
* Creates the Organizer Debrief Survey email in the Camptix email queue.
*/

namespace WordCamp\OrganizerSurvey\DebriefSurvey\Email;

use function WordCamp\Sunrise\get_top_level_domain;

defined( 'WPINC' ) || die();

/**
* Constants.
*/
const EMAIL_KEY_ID = 'organizer_debrief_survey_email';

/**
* Return the email ID.
*
* @return mixed
*/
function get_email_id() {
return get_option( EMAIL_KEY_ID );
}

/**
* Return lead organizer email.
*
* @return string
*/
function get_lead_organizer_email() {
$meta = get_wordcamp_post()->meta;
return $meta['Email Address'][0];
}

/**
* Return lead organizer full name.
*
* @return string
*/
function get_lead_organizer_full_name() {
$meta = get_wordcamp_post()->meta;
return $meta['Organizer Name'][0];
}

/**
* Return WordCamp location.
*
* @return string
*/
function get_wordcamp_location() {
$meta = get_wordcamp_post()->meta;
return $meta['Location'][0];
}


/**
* Return a token to put into the survey URL.
*
* @return string
*/
function get_verification_token() {
$wordcamp_id = get_current_blog_id();
return hash_hmac( 'sha256', $wordcamp_id, ORGANIZER_SURVEY_ACCESS_TOKEN_KEY );
}

/**
* Returns content for the reminder email.
*
* @return string
*/
function get_email_content() {
$wordcamp_name = get_wordcamp_name();
$tld = get_top_level_domain();
$survey_page_url = "https://central.wordcamp.$tld/organizer-survey-event-debrief/?t=" . get_verification_token()
. '&wid=' . get_current_blog_id();

$email = "Howdy [email],\r\n\r\n";
$email .= sprintf( "Congratulations on completing %s! We hope you had a great time, and that you'll soon get some well-deserved rest\r\n\r\n", esc_html( $wordcamp_name ) );

$email .= "We'd love to hear how you feel the event went. What were your proudest moments and your greatest disappointments?\r\n";
$email .= sprintf( "We've created an Organizer Survey, so we can get all the details of how things went with your event. <strong>Please fill it out this form within 10 days:</strong> %s\r\n\r\n", esc_url( $survey_page_url ) );

$email .= "<strong>Event Budget</strong>\r\n";
$email .= 'Please update your working budget on your event dashboard. If you ran your money outside of WordPress Community Support, PBC, please also balance your budget spreadsheet and prepare your Transparency Report.';
$email .= "If there are any issues, please reach out to us at [email protected] to schedule a budget close-out meeting. Please complete these steps within the next two weeks.\r\n\r\n";

$email .= "<strong>Event Recording (if any)</strong>\r\n";
$email .= sprintf( "If you haven't yet done so, please review the submission guidelines before beginning to edit your videos (or before your videographers starts editing): %s\r\n\r\n", esc_url( 'http://blog.wordpress.tv/submission-guidelines/' ) );
$email .= sprintf( "To submit your video for publication to WordPress.tv, just upload them at this page: %s\r\n\r\n", esc_url( 'http://wordpress.tv/submit-video/' ) );
$email .= 'Our intrepid team of video moderators will review the videos and schedule them for publication. ';
$email .= sprintf( "If your content is in a language other than English, please see if you can recruit someone from your community to join the WordPress TV moderators' team and review your videos: %s\r\n\r\n", esc_url( 'http://wordpress.tv/apply-to-be-a-wordpress-tv-moderator/' ) );

$email .= "<strong>Event Recap</strong>\r\n";
$email .= "Finally, if you've published a recap on your site, please let us know, so we can reblog it on the WordCamp Central blog.\r\n\r\n";

$email .= sprintf( "Thanks again for all you've done to grow the WordPress community in %s!\r\n\r\n", get_wordcamp_location() );
$email .= "Best wishes,\r\n";
$email .= 'Your friendly WordCamp Central crew';

return $email;
}

/**
* Adds email to camptix email queue.
*/
function add_email() {
$email_id = get_option( EMAIL_KEY_ID );
if ( $email_id || ! get_wordcamp_post() ) {
return;
}

$email_id = wp_insert_post(
array(
'post_title' => __( 'Organizer Survey (event debrief)', 'wordcamporg' ),
'post_content' => get_email_content(),
'post_status' => 'draft',
'post_type' => 'tix_email',
)
);

if ( $email_id > 0 ) {
update_option( EMAIL_KEY_ID, $email_id );
}
}

/**
* Turns on the email by changing its status to 'pending'.
*
* The Camptix email queue will send the email.
*
* @return int|WP_Error
*/
function queue_survey_email( $email_id ) {
return wp_update_post( array(
'ID' => $email_id,
'post_status' => 'pending',
) );
}

/**
* Delete the email and associated meta data.
*/
function delete_email() {
$email_id = get_email_id();
// Clean up any associated attendees to the email.
delete_post_meta( $email_id, 'tix_email_recipient_id' );
delete_post_meta( $email_id, 'tix_email_recipients_backup' );
wp_delete_post( $email_id, true );
delete_option( EMAIL_KEY_ID );
}
Loading

0 comments on commit 0f1c5fe

Please sign in to comment.