-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add attendee survey to wordcamps. #997
Changes from 54 commits
151c60f
31d02ae
b7e00c0
88eeabd
e789546
6853dfb
1b1e716
eb59992
a13748d
5d1213d
548cd90
dbdef69
fa9d8ac
7a34c49
bcf5e97
4969c09
2e145e0
0788ba1
0035826
30bb11f
5332304
17bfa43
256f437
d85b5d5
d78ede5
6c6adbe
a83f53c
6fa71ee
aee4a02
bae6c80
1bf4814
bfc7ee0
9a42483
6557822
cf75cad
338a921
ea3c714
093d557
dab7600
3b44be1
0a1fdd4
f086b8c
5acdee8
d19de33
af29c86
b444446
ef2ea8f
01ed96f
1578442
fe22789
20f2751
f72f387
f446ba2
8d4df83
1c312e1
6d9a3d3
8306d9e
b567296
57073be
78c0a7a
11c757a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
<?php | ||
/** | ||
* Plugin Name: CampTix Attendee Survey | ||
* Plugin URI: https://wordcamp.org | ||
* Description: Send survey to WordCamp attendees. | ||
* Author: WordCamp.org | ||
* Author URI: https://wordcamp.org | ||
* Version: 1 | ||
* | ||
* @package CampTix\AttendeeSurvey | ||
*/ | ||
|
||
namespace CampTix\AttendeeSurvey; | ||
|
||
use function CampTix\AttendeeSurvey\Email\{add_email, delete_email}; | ||
use function CampTix\AttendeeSurvey\Page\{add_page, delete_page}; | ||
|
||
defined( 'WPINC' ) || die(); | ||
|
||
/** | ||
* Local dependencies. | ||
*/ | ||
require_once get_includes_path() . 'email.php'; | ||
require_once get_includes_path() . 'page.php'; | ||
|
||
/** | ||
* Plugin activation and deactivation hooks. | ||
*/ | ||
register_deactivation_hook( __FILE__, __NAMESPACE__ . '\deactivate' ); | ||
|
||
/** | ||
* Actions & hooks | ||
*/ | ||
add_action( 'plugins_loaded', __NAMESPACE__ . '\load' ); | ||
|
||
/** | ||
* Get the ID of the survey feature. | ||
*/ | ||
function get_feature_id() { | ||
return 'attendee_survey'; | ||
} | ||
|
||
/** | ||
* Check dependencies for loading the plugin. | ||
* | ||
* @return bool | ||
*/ | ||
function can_load() { | ||
$skip_feature = wcorg_skip_feature( get_feature_id() ); | ||
|
||
return ! $skip_feature; | ||
} | ||
|
||
/** | ||
* Include the rest of the plugin. | ||
* | ||
* @return void | ||
*/ | ||
function load() { | ||
if ( ! can_load() ) { | ||
return; | ||
} | ||
|
||
// We only want to admin panel on central, nothing else. | ||
if ( WORDCAMP_ROOT_BLOG_ID === get_current_blog_id() ) { | ||
require_once get_includes_path() . 'admin-page.php'; | ||
} | ||
|
||
if ( is_wordcamp_type( 'next-gen' ) ) { | ||
require_once get_includes_path() . 'cron.php'; | ||
add_action( 'init', __NAMESPACE__ . '\activate_on_current_site' ); | ||
} | ||
} | ||
|
||
/** | ||
* The activation routine for a single site. | ||
* | ||
* @return void | ||
*/ | ||
function activate_on_current_site() { | ||
add_page(); | ||
add_email(); | ||
|
||
// Flushing the rewrite rules is buggy in the context of `switch_to_blog`. | ||
// The rules will automatically get recreated on the next request to the site. | ||
delete_option( 'rewrite_rules' ); | ||
} | ||
|
||
/** | ||
* Remove the survey page. | ||
* | ||
* @param bool $is_network True if deactivating network-wide. | ||
* | ||
* @return void | ||
*/ | ||
function deactivate( $is_network = false ) { | ||
if ( $is_network ) { | ||
deactivate_on_network(); | ||
} else { | ||
deactivate_on_current_site(); | ||
} | ||
} | ||
|
||
/** | ||
* Run the deactivation routine on all valid sites in the network. | ||
* | ||
* @return void | ||
*/ | ||
function deactivate_on_network() { | ||
$valid_sites = get_site_ids_without_skip_flag(); | ||
|
||
foreach ( $valid_sites as $blog_id ) { | ||
switch_to_blog( $blog_id ); | ||
deactivate_on_current_site(); | ||
restore_current_blog(); | ||
} | ||
} | ||
|
||
/** | ||
* The deactivation routine for a single site. | ||
* | ||
* @return void | ||
*/ | ||
function deactivate_on_current_site() { | ||
delete_page(); | ||
delete_email(); | ||
} | ||
|
||
/** | ||
* Get the IDs of sites that do not have the FEATURE_ID skip feature flag. | ||
* | ||
* @return array | ||
*/ | ||
function get_site_ids_without_skip_flag() { | ||
global $wpdb; | ||
|
||
$blog_ids = $wpdb->get_col( | ||
$wpdb->prepare(" | ||
SELECT b.blog_id | ||
FROM $wpdb->blogs AS b | ||
LEFT OUTER JOIN $wpdb->blogmeta AS m | ||
ON b.blog_id = m.blog_id AND m.meta_key = 'wordcamp_skip_feature' AND m.meta_value = %s | ||
WHERE m.meta_value IS NULL | ||
", | ||
get_feature_id() | ||
) | ||
); | ||
|
||
return array_map( 'absint', $blog_ids ); | ||
} | ||
|
||
/** | ||
* Shortcut to the includes directory. | ||
* | ||
* @return string | ||
*/ | ||
function get_includes_path() { | ||
return plugin_dir_path( __FILE__ ) . 'includes/'; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
<?php | ||
/** | ||
* Adds a page to the central admin. | ||
*/ | ||
|
||
namespace CampTix\AttendeeSurvey\AdminPage; | ||
|
||
defined( 'WPINC' ) || die(); | ||
|
||
use CampTix_Plugin; | ||
|
||
use function CampTix\AttendeeSurvey\{get_feature_id}; | ||
use function CampTix\AttendeeSurvey\Email\{get_email_id}; | ||
use function CampTix\AttendeeSurvey\Page\{get_page_id}; | ||
use function CampTix\AttendeeSurvey\Cron\{get_wordcamp_attendees_id}; | ||
|
||
add_action( 'init', __NAMESPACE__ . '\init' ); | ||
|
||
/** | ||
* Registered the appropriate filters and actions. | ||
*/ | ||
function init() { | ||
add_action( 'admin_menu', __NAMESPACE__ . '\admin_menu' ); | ||
} | ||
|
||
/** | ||
* Add a menu item. | ||
*/ | ||
function admin_menu() { | ||
add_menu_page( | ||
__( 'WordCamp Attendee Survey', 'wordcamporg' ), | ||
__( 'Attendee Survey', 'wordcamporg' ), | ||
'manage_options', | ||
get_feature_id(), | ||
__NAMESPACE__ . '\render_menu_page', | ||
'dashicons-feedback', | ||
58 | ||
); | ||
} | ||
|
||
/** | ||
* Get stats for each feedback for all sites. | ||
* | ||
* @return array[] An array of custom elements. | ||
* Each element has the following structure: | ||
* [ | ||
* 'title' => string, | ||
* 'sent' => string, | ||
* 'responses' => string, | ||
* 'rate' => string, | ||
* ] | ||
*/ | ||
function get_feedback_details() { | ||
/* @var CampTix_Plugin $camptix */ | ||
global $camptix; | ||
|
||
$wordcamps = get_posts( array( | ||
'post_type' => WCPT_POST_TYPE_ID, | ||
'post_status' => 'wcpt-closed', | ||
'posts_per_page' => -1, | ||
) ); | ||
|
||
$feedback_details = array(); | ||
|
||
foreach ( $wordcamps as $camp ) { | ||
$site_id = get_post_meta( $camp->ID, '_site_id', true ); | ||
|
||
switch_to_blog( $site_id ); | ||
|
||
$blog_details = get_blog_details( $site_id ); | ||
|
||
// TODO: This should be tested elsewhere. | ||
if ( 'events.wordpress.test' !== $blog_details->domain ) { | ||
continue; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this'll need to be updated to work on production. You could use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep. Makes sense. |
||
|
||
$query = new \WP_Query( array( | ||
'post_type' => 'feedback', | ||
'post_parent' => get_page_id(), | ||
'posts_per_page' => -1, | ||
) ); | ||
|
||
$sent = (int) $camptix->get_sent_email_count( get_email_id() ); | ||
$responses = (int) $query->found_posts; | ||
|
||
$feedback_details[] = array( | ||
'title' => $blog_details->blogname, | ||
'admin_url' => admin_url(), | ||
'email_url' => get_edit_post_link( get_email_id() ), | ||
'responses_url' => admin_url( sprintf( 'edit.php?post_type=feedback&jetpack_form_parent_id=%s', get_page_id() ) ), | ||
'sent' => $sent, | ||
'responses' => $responses, | ||
'rate' => 0 !== $sent ? ( $responses / $sent ) * 100 . '%' : '', | ||
); | ||
|
||
// Restore the original site context. | ||
restore_current_blog(); | ||
} | ||
|
||
// Reset the global post object. | ||
wp_reset_postdata(); | ||
|
||
return $feedback_details; | ||
} | ||
|
||
/** | ||
* Render the menu page. | ||
*/ | ||
function render_menu_page() { | ||
?> | ||
<div class="wrap"> | ||
<h1><?php echo esc_html__( 'Attendee Survey', 'wordcamporg' ); ?></h1> | ||
|
||
<table class="wp-list-table widefat fixed striped table-view-list"> | ||
<thead> | ||
<tr> | ||
<td><?php esc_html_e( 'Event', 'wordcamporg' ); ?></td> | ||
<td><?php esc_html_e( 'Total Sent', 'wordcamporg' ); ?></td> | ||
<td><?php esc_html_e( 'Total Responses', 'wordcamporg' ); ?></td> | ||
<td><?php esc_html_e( 'Response rate', 'wordcamporg' ); ?></td> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<?php | ||
$feedback_details = get_feedback_details(); | ||
|
||
foreach ( $feedback_details as $feedback_detail ) { | ||
echo '<tr>'; | ||
echo '<td><a href="'. esc_url( $feedback_detail['admin_url'] ) . '">' . esc_html( $feedback_detail['title'] ) . '</a></td>'; | ||
echo '<td><a href="'. esc_url( $feedback_detail['email_url'] ) . '">' . esc_html( $feedback_detail['sent'] ) . '</a></td>'; | ||
echo '<td><a href="'. esc_url( $feedback_detail['responses_url'] ) . '">' . esc_html( $feedback_detail['responses'] ) . '</a></td>'; | ||
echo '<td>' . esc_html( $feedback_detail['rate'] ) . '</td>'; | ||
echo '</tr>'; | ||
} | ||
|
||
if ( empty( $feedback_details ) ) { | ||
echo '<tr><td colspan="4">' . esc_html__( 'Nothing to report', 'wordcamporg' ) . '</td></tr>'; | ||
} | ||
|
||
?> | ||
</tbody> | ||
</table> | ||
</div> | ||
<?php | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we've needed this here and in the Speaker Feedback plugin, I think it makes sense to extract it into a generic function in
mu-plugins/wp-cli-commands/miscellaneous.php
, next toset_skip_feature_flag()
.That way any plugin can use it, rather than duplicating it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also wondered about just removing it since we're limiting it to events and this survey will probably apply across the board.
I think I'll remove it. Yep.