mirror of
https://github.com/WordPress/five-for-the-future.git
synced 2025-04-22 11:03:43 +03:00
Add a Contributor custom post type (#42)
Contributors associated with pledges have a state: they can be confirmed or unconfirmed. They also have some important meta data, namely when they were confirmed. Thus, managing contributor data for pledges is more robust if we treat them as their own post type instead of as a multidimensional array of post meta data. This also reorganizes some of the functions related to pledges so that things are more consistent between the pledge CPT and the contributior CPT. Fixes #11
This commit is contained in:
parent
2927532544
commit
266ba447b4
177
plugins/wporg-5ftf/includes/contributor.php
Normal file
177
plugins/wporg-5ftf/includes/contributor.php
Normal file
|
@ -0,0 +1,177 @@
|
|||
<?php
|
||||
namespace WordPressDotOrg\FiveForTheFuture\Contributor;
|
||||
|
||||
use WordPressDotOrg\FiveForTheFuture;
|
||||
use WordPressDotOrg\FiveForTheFuture\Pledge;
|
||||
use WP_Error, WP_Post;
|
||||
|
||||
defined( 'WPINC' ) || die();
|
||||
|
||||
const SLUG = 'contributor';
|
||||
const SLUG_PL = 'contributors';
|
||||
const CPT_ID = FiveForTheFuture\PREFIX . '_' . SLUG;
|
||||
|
||||
add_action( 'init', __NAMESPACE__ . '\register_custom_post_type', 0 );
|
||||
add_filter( 'manage_edit-' . CPT_ID . '_columns', __NAMESPACE__ . '\add_list_table_columns' );
|
||||
add_action( 'manage_' . CPT_ID . '_posts_custom_column', __NAMESPACE__ . '\populate_list_table_columns', 10, 2 );
|
||||
|
||||
/**
|
||||
* Register the post type(s).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function register_custom_post_type() {
|
||||
$labels = array(
|
||||
'name' => _x( 'Contributors', 'Pledges General Name', 'wporg' ),
|
||||
'singular_name' => _x( 'Contributor', 'Pledge Singular Name', 'wporg' ),
|
||||
'menu_name' => __( 'Five for the Future', 'wporg' ),
|
||||
'archives' => __( 'Contributor Archives', 'wporg' ),
|
||||
'attributes' => __( 'Contributor Attributes', 'wporg' ),
|
||||
'parent_item_colon' => __( 'Parent Contributor:', 'wporg' ),
|
||||
'all_items' => __( 'Contributors', 'wporg' ),
|
||||
'add_new_item' => __( 'Add New Contributor', 'wporg' ),
|
||||
'add_new' => __( 'Add New', 'wporg' ),
|
||||
'new_item' => __( 'New Contributor', 'wporg' ),
|
||||
'edit_item' => __( 'Edit Contributor', 'wporg' ),
|
||||
'update_item' => __( 'Update Contributor', 'wporg' ),
|
||||
'view_item' => __( 'View Contributor', 'wporg' ),
|
||||
'view_items' => __( 'View Contributors', 'wporg' ),
|
||||
'search_items' => __( 'Search Contributors', 'wporg' ),
|
||||
'not_found' => __( 'Not found', 'wporg' ),
|
||||
'not_found_in_trash' => __( 'Not found in Trash', 'wporg' ),
|
||||
'insert_into_item' => __( 'Insert into contributor', 'wporg' ),
|
||||
'uploaded_to_this_item' => __( 'Uploaded to this contributor', 'wporg' ),
|
||||
'items_list' => __( 'Contributors list', 'wporg' ),
|
||||
'items_list_navigation' => __( 'Contributors list navigation', 'wporg' ),
|
||||
'filter_items_list' => __( 'Filter contributors list', 'wporg' ),
|
||||
);
|
||||
|
||||
$args = array(
|
||||
'labels' => $labels,
|
||||
'supports' => array( 'title' ),
|
||||
'hierarchical' => false,
|
||||
'public' => false,
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => 'edit.php?post_type=' . Pledge\CPT_ID,
|
||||
'menu_position' => 25,
|
||||
'show_in_admin_bar' => false,
|
||||
'show_in_nav_menus' => false,
|
||||
'can_export' => false,
|
||||
'taxonomies' => array(),
|
||||
'has_archive' => false,
|
||||
'exclude_from_search' => true,
|
||||
'publicly_queryable' => false,
|
||||
'capability_type' => 'page',
|
||||
'show_in_rest' => false, // todo Maybe turn this on later.
|
||||
);
|
||||
|
||||
register_post_type( CPT_ID, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add columns to the Contributors list table.
|
||||
*
|
||||
* @param array $columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function add_list_table_columns( $columns ) {
|
||||
$first = array_slice( $columns, 0, 2, true );
|
||||
$last = array_slice( $columns, 2, null, true );
|
||||
|
||||
$new_columns = array(
|
||||
'pledge' => __( 'Pledge', 'wporg' ),
|
||||
);
|
||||
|
||||
return array_merge( $first, $new_columns, $last );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render content in the custom columns added to the Contributors list table.
|
||||
*
|
||||
* @param string $column
|
||||
* @param int $post_id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function populate_list_table_columns( $column, $post_id ) {
|
||||
switch ( $column ) {
|
||||
case 'pledge':
|
||||
$contributor = get_post( $post_id );
|
||||
$pledge = get_post( $contributor->post_parent );
|
||||
|
||||
$pledge_name = get_the_title( $pledge );
|
||||
|
||||
if ( current_user_can( 'edit_post', $pledge->ID ) ) {
|
||||
$pledge_name = sprintf(
|
||||
'<a href="%1$s">%2$s</a>',
|
||||
get_edit_post_link( $pledge ),
|
||||
$pledge_name
|
||||
);
|
||||
}
|
||||
|
||||
echo $pledge_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a contributor post as a child of a pledge post.
|
||||
*
|
||||
* @param string $wporg_username
|
||||
* @param int $pledge_id
|
||||
*
|
||||
* @return int|WP_Error Post ID on success. Otherwise WP_Error.
|
||||
*/
|
||||
function create_new_contributor( $wporg_username, $pledge_id ) {
|
||||
$args = array(
|
||||
'post_type' => CPT_ID,
|
||||
'post_title' => sanitize_user( $wporg_username ),
|
||||
'post_parent' => $pledge_id,
|
||||
'post_status' => 'pending',
|
||||
);
|
||||
|
||||
return wp_insert_post( $args, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contributor posts associated with a particular pledge post.
|
||||
*
|
||||
* @param int $pledge_id The post ID of the pledge.
|
||||
* @param string $status Optional. 'all', 'pending', or 'publish'.
|
||||
*
|
||||
* @return array An array of contributor posts. If $status is set to 'all', will be
|
||||
* a multidimensional array with keys for each status.
|
||||
*/
|
||||
function get_pledge_contributors( $pledge_id, $status = 'publish' ) {
|
||||
$args = array(
|
||||
'post_type' => CPT_ID,
|
||||
'post_parent' => $pledge_id,
|
||||
'numberposts' => -1,
|
||||
'orderby' => 'title',
|
||||
'order' => 'asc',
|
||||
);
|
||||
|
||||
if ( 'all' === $status ) {
|
||||
$args['post_status'] = array( 'pending', 'publish' );
|
||||
} else {
|
||||
$args['post_status'] = sanitize_key( $status );
|
||||
}
|
||||
|
||||
$posts = get_posts( $args );
|
||||
|
||||
if ( 'all' === $status && ! empty( $posts ) ) {
|
||||
$initial = array(
|
||||
'publish' => array(),
|
||||
'pending' => array(),
|
||||
);
|
||||
|
||||
$posts = array_reduce( $posts, function( $carry, WP_Post $item ) {
|
||||
$carry[ $item->post_status ][] = $item;
|
||||
|
||||
return $carry;
|
||||
}, $initial );
|
||||
}
|
||||
|
||||
return $posts;
|
||||
}
|
|
@ -8,6 +8,7 @@ namespace WordPressDotOrg\FiveForTheFuture\PledgeForm;
|
|||
use WordPressDotOrg\FiveForTheFuture;
|
||||
use WordPressDotOrg\FiveForTheFuture\Pledge;
|
||||
use WordPressDotOrg\FiveForTheFuture\PledgeMeta;
|
||||
use WordPressDotOrg\FiveForTheFuture\Contributor;
|
||||
use WP_Error, WP_Post, WP_User;
|
||||
|
||||
defined( 'WPINC' ) || die();
|
||||
|
@ -81,7 +82,7 @@ function process_form_new() {
|
|||
);
|
||||
}
|
||||
|
||||
$contributors = parse_contributors( $submission['org-pledge-contributors'] );
|
||||
$contributors = parse_contributors( $submission['pledge-contributors'] );
|
||||
|
||||
if ( is_wp_error( $contributors ) ) {
|
||||
return $contributors;
|
||||
|
@ -94,10 +95,14 @@ function process_form_new() {
|
|||
Pledge\CPT_ID
|
||||
);
|
||||
|
||||
$created = create_new_pledge( $name );
|
||||
$new_pledge_id = Pledge\create_new_pledge( $name );
|
||||
|
||||
if ( is_wp_error( $created ) ) {
|
||||
return $created;
|
||||
if ( is_wp_error( $new_pledge_id ) ) {
|
||||
return $new_pledge_id;
|
||||
}
|
||||
|
||||
foreach ( $contributors as $wporg_username ) {
|
||||
Contributor\create_new_contributor( $wporg_username, $new_pledge_id );
|
||||
}
|
||||
|
||||
return 'success';
|
||||
|
@ -184,7 +189,7 @@ function get_form_submission() {
|
|||
wp_list_pluck( PledgeMeta\get_pledge_meta_config( 'user_input' ), 'php_filter' ),
|
||||
// Inputs with no corresponding meta value.
|
||||
array(
|
||||
'org-pledge-contributors' => FILTER_SANITIZE_STRING,
|
||||
'pledge-contributors' => FILTER_SANITIZE_STRING,
|
||||
'pledge-agreement' => FILTER_VALIDATE_BOOLEAN,
|
||||
)
|
||||
);
|
||||
|
@ -235,40 +240,6 @@ function has_existing_pledge( $key, $key_type, int $current_pledge_id = 0 ) {
|
|||
return ! empty( $matching_pledge );
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO Move this to the contributor cpt include file.
|
||||
*
|
||||
* @param int $pledge_id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function get_pledge_contributors( $pledge_id = 0 ) {
|
||||
$contributors = array();
|
||||
|
||||
// Get POST'd submission, if it exists.
|
||||
$submission = filter_input( INPUT_POST, 'org-pledge-contributors', FILTER_SANITIZE_STRING );
|
||||
|
||||
// Get existing pledge, if it exists.
|
||||
$pledge = get_post( $pledge_id );
|
||||
|
||||
if ( ! empty( $submission ) ) {
|
||||
$contributors = array_map( 'sanitize_user', explode( ',', $submission ) );
|
||||
} elseif ( $pledge instanceof WP_Post ) {
|
||||
// TODO the Contributor post type is being introduced in a separate PR. These details may change.
|
||||
|
||||
$contributor_posts = get_posts( array(
|
||||
'post_type' => '',
|
||||
'post_status' => array( 'pending', 'publish' ),
|
||||
'post_parent' => $pledge_id,
|
||||
'numberposts' => -1,
|
||||
) );
|
||||
|
||||
$contributors = wp_list_pluck( $contributor_posts, 'post_title' );
|
||||
}
|
||||
|
||||
return $contributors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure each item in a list of usernames is valid and corresponds to a user.
|
||||
*
|
||||
|
@ -318,20 +289,3 @@ function parse_contributors( $contributors ) {
|
|||
|
||||
return $sanitized_contributors;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $name The name of the company to use as the post title.
|
||||
*
|
||||
* @return int|WP_Error Post ID on success. Otherwise WP_Error.
|
||||
*/
|
||||
function create_new_pledge( $name ) {
|
||||
$args = [
|
||||
'post_type' => Pledge\CPT_ID,
|
||||
'post_title' => $name,
|
||||
'post_status' => 'draft',
|
||||
];
|
||||
|
||||
return wp_insert_post( $args, true );
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace WordPressDotOrg\FiveForTheFuture\PledgeMeta;
|
|||
use WordPressDotOrg\FiveForTheFuture;
|
||||
use WordPressDotOrg\FiveForTheFuture\Pledge;
|
||||
use WordPressDotOrg\FiveForTheFuture\PledgeForm;
|
||||
use WordPressDotOrg\FiveForTheFuture\Contributor;
|
||||
use WP_Post, WP_Error;
|
||||
|
||||
defined( 'WPINC' ) || die();
|
||||
|
@ -60,12 +61,6 @@ function get_pledge_meta_config( $context = '' ) {
|
|||
'show_in_rest' => false,
|
||||
'php_filter' => FILTER_VALIDATE_INT,
|
||||
),
|
||||
'org-pledge-contributors' => array(
|
||||
'single' => true,
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
'show_in_rest' => false,
|
||||
'php_filter' => FILTER_SANITIZE_STRING,
|
||||
),
|
||||
);
|
||||
|
||||
$generated = array(
|
||||
|
@ -153,12 +148,14 @@ function add_meta_boxes() {
|
|||
*/
|
||||
function render_meta_boxes( $pledge, $box ) {
|
||||
$readonly = ! current_user_can( 'edit_page', $pledge->ID );
|
||||
$data = array();
|
||||
|
||||
$data = array();
|
||||
foreach ( get_pledge_meta_config() as $key => $config ) {
|
||||
$data[ $key ] = get_post_meta( $pledge->ID, META_PREFIX . $key, $config['single'] );
|
||||
}
|
||||
|
||||
$contributors = Contributor\get_pledge_contributors( $pledge->ID, 'all' );
|
||||
|
||||
echo '<div class="pledge-form">';
|
||||
|
||||
switch ( $box['id'] ) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
namespace WordPressDotOrg\FiveForTheFuture\Pledge;
|
||||
|
||||
use WordPressDotOrg\FiveForTheFuture;
|
||||
use WP_Error;
|
||||
|
||||
defined( 'WPINC' ) || die();
|
||||
|
||||
|
@ -15,6 +16,7 @@ const SLUG_PL = 'pledges';
|
|||
const CPT_ID = FiveForTheFuture\PREFIX . '_' . SLUG;
|
||||
|
||||
add_action( 'init', __NAMESPACE__ . '\register', 0 );
|
||||
add_action( 'admin_menu', __NAMESPACE__ . '\admin_menu' );
|
||||
|
||||
/**
|
||||
* Register all the things.
|
||||
|
@ -26,6 +28,15 @@ function register() {
|
|||
register_custom_post_status();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjustments to the Five for the Future admin menu.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function admin_menu() {
|
||||
remove_submenu_page( 'edit.php?post_type=' . CPT_ID, 'post-new.php?post_type=' . CPT_ID );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the post type(s).
|
||||
*
|
||||
|
@ -39,7 +50,7 @@ function register_custom_post_type() {
|
|||
'archives' => __( 'Pledge Archives', 'wporg' ),
|
||||
'attributes' => __( 'Pledge Attributes', 'wporg' ),
|
||||
'parent_item_colon' => __( 'Parent Pledge:', 'wporg' ),
|
||||
'all_items' => __( 'All Pledges', 'wporg' ),
|
||||
'all_items' => __( 'Pledges', 'wporg' ),
|
||||
'add_new_item' => __( 'Add New Pledge', 'wporg' ),
|
||||
'add_new' => __( 'Add New', 'wporg' ),
|
||||
'new_item' => __( 'New Pledge', 'wporg' ),
|
||||
|
@ -100,3 +111,20 @@ function register_custom_post_status() {
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pledge post.
|
||||
*
|
||||
* @param string $name The name of the company to use as the post title.
|
||||
*
|
||||
* @return int|WP_Error Post ID on success. Otherwise WP_Error.
|
||||
*/
|
||||
function create_new_pledge( $name ) {
|
||||
$args = array(
|
||||
'post_type' => CPT_ID,
|
||||
'post_title' => $name,
|
||||
'post_status' => 'draft',
|
||||
);
|
||||
|
||||
return wp_insert_post( $args, true );
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ add_action( 'plugins_loaded', __NAMESPACE__ . '\load' );
|
|||
*
|
||||
*/
|
||||
function load() {
|
||||
require_once get_includes_path() . 'contributor.php';
|
||||
require_once get_includes_path() . 'pledge.php';
|
||||
require_once get_includes_path() . 'pledge-meta.php';
|
||||
require_once get_includes_path() . 'pledge-form.php';
|
||||
|
|
|
@ -15,8 +15,8 @@ namespace WordPressDotOrg\FiveForTheFuture\View;
|
|||
<input
|
||||
type="text"
|
||||
id="5ftf-pledge-contributors"
|
||||
name="org-pledge-contributors"
|
||||
value="<?php echo esc_attr( $data['org-pledge-contributors'] ); ?>"
|
||||
name="pledge-contributors"
|
||||
value="<?php echo esc_attr( $data['pledge-contributors'] ); ?>"
|
||||
required
|
||||
aria-describedby="5ftf-pledge-contributors-help"
|
||||
/>
|
||||
|
@ -28,7 +28,49 @@ namespace WordPressDotOrg\FiveForTheFuture\View;
|
|||
<?php else : ?>
|
||||
|
||||
<div class="5ftf-contributors">
|
||||
<?php foreach ( $contributors as $status => $group ) : ?>
|
||||
<?php if ( ! empty( $group ) ) : ?>
|
||||
<h3 class="contributor-list-heading">
|
||||
<?php
|
||||
switch ( $status ) {
|
||||
case 'pending':
|
||||
esc_html_e( 'Unconfirmed', 'wporg' );
|
||||
break;
|
||||
case 'publish':
|
||||
esc_html_e( 'Confirmed', 'wporg' );
|
||||
break;
|
||||
}
|
||||
?>
|
||||
</h3>
|
||||
|
||||
<ul class="contributor-list <?php echo esc_attr( $status ); ?>">
|
||||
<?php foreach ( $group as $contributor_post ) :
|
||||
$contributor = get_user_by( 'login', $contributor_post->post_title );
|
||||
?>
|
||||
<li>
|
||||
<?php echo get_avatar( $contributor->user_email, 32 ); ?>
|
||||
<?php echo $contributor_post->post_title; ?>
|
||||
<!-- TODO These buttons don't do anything yet.
|
||||
<button class="button-primary" data-action="remove" data-contributor-post="<?php echo esc_attr( $contributor_post->ID ); ?>">
|
||||
<?php esc_html_e( 'Remove', 'wporg' ); ?>
|
||||
</button>
|
||||
<?php if ( 'pending' === $contributor_post->post_status ) : ?>
|
||||
<button class="button-secondary" data-action="resend-confirmation" data-contributor-post="<?php echo esc_attr( $contributor_post->ID ); ?>">
|
||||
<?php esc_html_e( 'Resend confirmation', 'wporg' ); ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
-->
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<!-- TODO This button doesn't do anything yet.
|
||||
<button class="button-primary" data-action="add-contributor">
|
||||
<?php esc_html_e( 'Add new contributor', 'wporg' ); ?>
|
||||
</button>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
|
|
Loading…
Reference in a new issue