Enable Manage Form functionality

This commit is contained in:
Kelly Dwan 2019-11-21 18:36:54 -05:00
parent 60fd0d2fb3
commit 8b4d55782d
No known key found for this signature in database
GPG key ID: 8BA5575F3D11575D
4 changed files with 152 additions and 63 deletions

View file

@ -65,7 +65,7 @@ function render_form_new() {
*/ */
function process_form_new() { function process_form_new() {
$submission = get_form_submission(); $submission = get_form_submission();
$has_error = check_invalid_submission( $submission ); $has_error = check_invalid_submission( $submission, 'create' );
if ( $has_error ) { if ( $has_error ) {
return $has_error; return $has_error;
} }
@ -149,56 +149,100 @@ function process_pledge_confirmation_email( $pledge_id, $action, $unverified_tok
* @return false|string * @return false|string
*/ */
function render_form_manage() { function render_form_manage() {
$action = filter_input( INPUT_POST, 'action' ); /*
$messages = []; * Prevent Gutenberg from executing this on the Edit Post screen.
$updated = false; * See https://github.com/WordPress/gutenberg/issues/18394
*/
if ( is_admin() ) {
return '';
}
// @todo Get pledge ID from somewhere. $messages = [];
$data = PledgeMeta\get_pledge_meta(); $errors = [];
$is_manage = true;
$action = sanitize_text_field( $_REQUEST['action'] ?? '' );
$pledge_id = absint( $_REQUEST['pledge_id'] ?? 0 );
$auth_token = sanitize_text_field( $_REQUEST['auth_token'] ?? '' );
$can_view_form = Auth\can_manage_pledge( $pledge_id, $auth_token );
if ( is_wp_error( $can_view_form ) ) {
// Can't manage pledge, only show errors.
$errors = array( $can_view_form->get_error_message() );
ob_start();
require FiveForTheFuture\PATH . 'views/partial-result-messages.php';
return ob_get_clean();
}
$contributors = Contributor\get_pledge_contributors( $pledge_id, $status = 'all' );
if ( 'Update Pledge' === $action ) { if ( 'Update Pledge' === $action ) {
$processed = process_form_manage(); $results = process_form_manage( $pledge_id, $auth_token );
if ( is_wp_error( $processed ) ) { if ( is_wp_error( $results ) ) {
$messages = array_merge( $messages, $processed->get_error_messages() ); $can_view_form = false;
} elseif ( 'success' === $processed ) { $errors = $results->get_error_messages();
$updated = true; } else {
$messages = array( __( 'Your pledge has been updated.', 'wporg-5ftf' ) );
} }
} }
$data = PledgeMeta\get_pledge_meta( $pledge_id );
ob_start(); ob_start();
$readonly = false; $readonly = false;
$is_manage = true;
require FiveForTheFuture\PATH . 'views/form-pledge-manage.php'; require FiveForTheFuture\PATH . 'views/form-pledge-manage.php';
return ob_get_clean(); return ob_get_clean();
} }
/** /**
* Process a submission from the Manage Existing Pledge form. * Process a submission from the Manage Pledge form.
* *
* TODO This doesn't actually update any data yet when the form is submitted. * @return WP_Error|true An error if the pledge could not be saved. Otherwise true.
*
* @return string|WP_Error String "success" if the form processed correctly. Otherwise WP_Error.
*/ */
function process_form_manage() { function process_form_manage( $pledge_id, $auth_token ) {
$errors = array();
$nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
$nonce_action = 'manage_pledge_' . $pledge_id;
$has_valid_nonce = wp_verify_nonce( $nonce, $nonce_action );
/*
* This should be redundant, since it's also called by `render_form_manage()`, but it's good to also do it here
* just in case other code changes in the future, or this gets called by another flow, etc.
*/
$can_view_form = Auth\can_manage_pledge( $pledge_id, $auth_token );
if ( ! $has_valid_nonce || ! $can_view_form ) {
return new WP_Error(
'invalid_token',
sprintf(
__( 'Your link has expired, please <a href="%s">obtain a new one</a>.', 'wporg-5ftf' ),
get_permalink( $pledge_id )
)
);
}
$submission = get_form_submission(); $submission = get_form_submission();
$has_error = check_invalid_submission( $submission ); $has_error = check_invalid_submission( $submission, 'update' );
if ( $has_error ) { if ( $has_error ) {
return $has_error; return $has_error;
} }
// todo email any new contributors for confirmation PledgeMeta\save_pledge_meta( $pledge_id, $submission );
// notify any removed contributors?
// ask them to update their profiles? // @todo Upload & attach logo.
// automatically update contributor profiles? // @todo Save contributors.
// anything else?
// If we made it to here, we've successfully saved the pledge.
return true;
} }
/** /**
* Get and sanitize $_POST values from a form submission. * Get and sanitize $_POST values from a form submission.
* *
* @return array|bool * @return array
*/ */
function get_form_submission() { function get_form_submission() {
$input_filters = array_merge( $input_filters = array_merge(
@ -222,10 +266,13 @@ function get_form_submission() {
/** /**
* Check the submission for valid data. * Check the submission for valid data.
* *
* @param array $submission The user input.
* @param string $context Whether this is a new pledge (`create`) or an edit to an existing one (`update`).
*
* @return false|WP_Error Return any errors in the submission, or false if no errors. * @return false|WP_Error Return any errors in the submission, or false if no errors.
*/ */
function check_invalid_submission( $submission ) { function check_invalid_submission( $submission, $context ) {
$has_required = PledgeMeta\has_required_pledge_meta( $submission ); $has_required = PledgeMeta\has_required_pledge_meta( $submission, $context );
if ( is_wp_error( $has_required ) ) { if ( is_wp_error( $has_required ) ) {
return $has_required; return $has_required;
} }
@ -237,20 +284,22 @@ function check_invalid_submission( $submission ) {
Pledge\CPT_ID Pledge\CPT_ID
); );
if ( Pledge\has_existing_pledge( $email, 'email' ) ) { if ( 'create' === $context ) {
return new WP_Error( if ( Pledge\has_existing_pledge( $email, 'email' ) ) {
'existing_pledge_email', return new WP_Error(
__( 'This email address is already connected to an existing pledge.', 'wporg-5ftf' ) 'existing_pledge_email',
); __( 'This email address is already connected to an existing pledge.', 'wporg-5ftf' )
} );
}
$domain = PledgeMeta\get_normalized_domain_from_url( $submission['org-url'] ); $domain = PledgeMeta\get_normalized_domain_from_url( $submission['org-url'] );
if ( Pledge\has_existing_pledge( $domain, 'domain' ) ) { if ( Pledge\has_existing_pledge( $domain, 'domain' ) ) {
return new WP_Error( return new WP_Error(
'existing_pledge_domain', 'existing_pledge_domain',
__( 'A pledge already exists for this domain.', 'wporg-5ftf' ) __( 'A pledge already exists for this domain.', 'wporg-5ftf' )
); );
}
} }
return false; return false;

View file

@ -38,24 +38,28 @@ function get_pledge_meta_config( $subset = 'all' ) {
'single' => true, 'single' => true,
'sanitize_callback' => __NAMESPACE__ . '\sanitize_description', 'sanitize_callback' => __NAMESPACE__ . '\sanitize_description',
'show_in_rest' => true, 'show_in_rest' => true,
'context' => array( 'create', 'update' ),
'php_filter' => FILTER_UNSAFE_RAW, 'php_filter' => FILTER_UNSAFE_RAW,
), ),
'org-name' => array( 'org-name' => array(
'single' => true, 'single' => true,
'sanitize_callback' => 'sanitize_text_field', 'sanitize_callback' => 'sanitize_text_field',
'show_in_rest' => true, 'show_in_rest' => true,
'context' => array( 'create', 'update' ),
'php_filter' => FILTER_SANITIZE_STRING, 'php_filter' => FILTER_SANITIZE_STRING,
), ),
'org-url' => array( 'org-url' => array(
'single' => true, 'single' => true,
'sanitize_callback' => 'esc_url_raw', 'sanitize_callback' => 'esc_url_raw',
'show_in_rest' => true, 'show_in_rest' => true,
'context' => array( 'create', 'update' ),
'php_filter' => FILTER_VALIDATE_URL, 'php_filter' => FILTER_VALIDATE_URL,
), ),
'org-pledge-email' => array( 'org-pledge-email' => array(
'single' => true, 'single' => true,
'sanitize_callback' => 'sanitize_email', 'sanitize_callback' => 'sanitize_email',
'show_in_rest' => false, 'show_in_rest' => false,
'context' => array( 'create' ),
'php_filter' => FILTER_VALIDATE_EMAIL, 'php_filter' => FILTER_VALIDATE_EMAIL,
), ),
); );
@ -243,12 +247,13 @@ function save_pledge( $pledge_id, $pledge ) {
$get_action = filter_input( INPUT_GET, 'action' ); $get_action = filter_input( INPUT_GET, 'action' );
$post_action = filter_input( INPUT_POST, 'action' ); $post_action = filter_input( INPUT_POST, 'action' );
$ignored_actions = array( 'trash', 'untrash', 'restore' ); $ignored_actions = array( 'trash', 'untrash', 'restore' );
$context = ( 'editpost' === $post_action ) ? 'update' : 'create';
/* /*
* This is only intended to run when the front end form and wp-admin forms are submitted, not when posts are * This is only intended to run when the front end form and wp-admin forms are submitted, not when posts are
* programmatically updated. * programmatically updated.
*/ */
if ( 'Submit Pledge' !== $post_action && 'editpost' !== $post_action ) { if ( ! in_array( $post_action, [ 'Submit Pledge', 'editpost' ], true ) ) {
return; return;
} }
@ -268,7 +273,7 @@ function save_pledge( $pledge_id, $pledge ) {
$submitted_meta = PledgeForm\get_form_submission(); $submitted_meta = PledgeForm\get_form_submission();
if ( is_wp_error( has_required_pledge_meta( $submitted_meta ) ) ) { if ( is_wp_error( has_required_pledge_meta( $submitted_meta, $context ) ) ) {
return; return;
} }
@ -294,6 +299,10 @@ function save_pledge_meta( $pledge_id, $new_values ) {
$config = get_pledge_meta_config(); $config = get_pledge_meta_config();
foreach ( $new_values as $key => $value ) { foreach ( $new_values as $key => $value ) {
// A null value can happen if the submission form did not have a given field.
if ( is_null( $value ) ) {
continue;
}
if ( array_key_exists( $key, $config ) ) { if ( array_key_exists( $key, $config ) ) {
$meta_key = META_PREFIX . $key; $meta_key = META_PREFIX . $key;
@ -391,14 +400,22 @@ function update_single_cached_pledge_data( $pledge_id ) {
/** /**
* Check that an array contains values for all required keys. * Check that an array contains values for all required keys.
* *
* @return bool|WP_Error True if all required values are present. Otherwise WP_Error. * @param array $submission Form submission data.
* @param string $context Whether this is a new pledge (`create`) or an edit to an existing one (`update`).
*
* @return true|WP_Error True if all required values are present. Otherwise WP_Error.
*/ */
function has_required_pledge_meta( array $submission ) { function has_required_pledge_meta( array $submission, $context ) {
$error = new WP_Error(); $error = new WP_Error();
$required = array_keys( get_pledge_meta_config( 'user_input' ) ); $meta_config = get_pledge_meta_config( 'user_input' );
$required = array_keys( $meta_config );
foreach ( $required as $key ) { foreach ( $required as $key ) {
if ( ! in_array( $context, $meta_config[ $key ]['context'] ) ) {
continue;
}
if ( ! isset( $submission[ $key ] ) || is_null( $submission[ $key ] ) ) { if ( ! isset( $submission[ $key ] ) || is_null( $submission[ $key ] ) ) {
$error->add( $error->add(
'required_field_empty', 'required_field_empty',

View file

@ -1,25 +1,38 @@
<?php <?php
namespace WordPressDotOrg\FiveForTheFuture\View;
namespace WordPressDotOrg\FiveForTheFuture\View;
use function WordPressDotOrg\FiveForTheFuture\get_views_path; use function WordPressDotOrg\FiveForTheFuture\get_views_path;
/** @var array $messages */ /**
/** @var bool $updated */ * @var bool $can_view_form
* @var int $pledge_id
* @var string $auth_token
*/
require __DIR__ . '/partial-result-messages.php';
?> ?>
<form class="pledge-form" id="5ftf-form-pledge-manage" action="" method="post" enctype="multipart/form-data"> <?php if ( true === $can_view_form ) : ?>
<?php
require get_views_path() . 'inputs-pledge-org-info.php';
require get_views_path() . 'manage-contributors.php';
require get_views_path() . 'inputs-pledge-org-email.php';
?>
<div> <form class="pledge-form" id="5ftf-form-pledge-manage" action="" method="post" enctype="multipart/form-data">
<input <input type="hidden" name="pledge_id" value="<?php echo absint( $pledge_id ); ?>" />
type="submit" <input type="hidden" name="auth_token" value="<?php echo esc_attr( $auth_token ); ?>" />
id="5ftf-pledge-submit"
name="action" <?php
value="<?php esc_attr_e( 'Update Pledge', 'wporg-5ftf' ); ?>" wp_nonce_field( 'manage_pledge_' . $pledge_id );
/>
</div> require get_views_path() . 'inputs-pledge-org-info.php';
</form> ?>
<div>
<input
type="submit"
id="5ftf-pledge-submit"
name="action"
value="<?php esc_attr_e( 'Update Pledge', 'wporg-5ftf' ); ?>"
/>
</div>
</form>
<?php endif; ?>

View file

@ -1,8 +1,13 @@
<?php <?php
namespace WordPressDotOrg\FiveForTheFuture\View; namespace WordPressDotOrg\FiveForTheFuture\View;
/** @var array $data */ /**
/** @var bool $readonly */ * @var array $data
* @var int $pledge_id
* @var bool $readonly
*/
?> ?>
<div class="form-field"> <div class="form-field">
@ -20,6 +25,11 @@ namespace WordPressDotOrg\FiveForTheFuture\View;
</div> </div>
<?php if ( ! is_admin() ) : ?> <?php if ( ! is_admin() ) : ?>
<?php if ( has_post_thumbnail( $pledge_id ) ) : ?>
<div class="form-field form-field__logo-display">
<?php echo get_the_post_thumbnail( $pledge_id, 'pledge-logo' ); ?>
</div>
<?php endif; ?>
<div class="form-field form-field__logo"> <div class="form-field form-field__logo">
<label for="5ftf-org-logo"> <label for="5ftf-org-logo">
<?php esc_html_e( 'Logo', 'wporg-5ftf' ); ?> <?php esc_html_e( 'Logo', 'wporg-5ftf' ); ?>