Skip to content
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 new capabilty to make a form field editable #269

Merged
merged 23 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e0a3b05
Add new capabilty to make a form field editable
trymebytes May 10, 2024
fa1f2e2
Add new capability for each form field
trymebytes May 15, 2024
0c9340b
Add tests for the different cases
trymebytes May 15, 2024
4b16414
Add new capabilities to phpcs
trymebytes May 15, 2024
3d23dbb
Fix typo in text
trymebytes May 16, 2024
8747533
Add capability check to form fields
trymebytes May 16, 2024
2784a4d
Implement edit form field capabilites
trymebytes May 16, 2024
f8393f8
Fix lint errors
trymebytes May 16, 2024
ff48cd8
Modify edit form capability to allow access to edit form
trymebytes May 16, 2024
4f9ea89
Modify form handler to allow saving past events
trymebytes May 16, 2024
21595f6
Check form field capability for edit form only
trymebytes May 16, 2024
433bc04
Decouple set_times to set_start and set_end
trymebytes May 16, 2024
2838ad9
Check that user can edit form field before updating an event
trymebytes May 16, 2024
4f039ee
Move function to another line
trymebytes May 17, 2024
29d3d16
Update tests
trymebytes May 17, 2024
1075b34
Replace readonly with disabled for select dropdown
trymebytes May 17, 2024
8f2323d
Use is_active method
trymebytes May 20, 2024
4dff95c
Rename to has_edit_field
trymebytes May 20, 2024
d93cb9e
Use event->start() directly
trymebytes May 21, 2024
20635ff
Remove happening_now variable
trymebytes May 21, 2024
ae95af0
Fix timezone error
trymebytes May 23, 2024
2cd5b45
Remove whitespace
trymebytes May 23, 2024
71a10df
Pass value of $now as argument
trymebytes May 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 64 additions & 15 deletions includes/event/event-capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,25 @@
use Exception;
use GP;
use WP_User;
use DateTimeImmutable;
use DateTimeZone;
use Wporg\TranslationEvents\Attendee\Attendee;
use Wporg\TranslationEvents\Attendee\Attendee_Repository;
use Wporg\TranslationEvents\Stats\Stats_Calculator;

class Event_Capabilities {
private const MANAGE = 'manage_translation_events';
private const CREATE = 'create_translation_event';
private const VIEW = 'view_translation_event';
private const EDIT = 'edit_translation_event';
private const TRASH = 'trash_translation_event';
private const DELETE = 'delete_translation_event';
private const EDIT_ATTENDEES = 'edit_translation_event_attendees';
private const MANAGE = 'manage_translation_events';
private const CREATE = 'create_translation_event';
private const VIEW = 'view_translation_event';
private const EDIT = 'edit_translation_event';
private const TRASH = 'trash_translation_event';
private const DELETE = 'delete_translation_event';
private const EDIT_ATTENDEES = 'edit_translation_event_attendees';
psrpinto marked this conversation as resolved.
Show resolved Hide resolved
private const EDIT_TITLE = 'edit_translation_event_title';
private const EDIT_DESCRIPTION = 'edit_translation_event_description';
private const EDIT_START = 'edit_translation_event_start';
private const EDIT_END = 'edit_translation_event_end';
private const EDIT_TIMEZONE = 'edit_translation_event_timezone';

/**
* All the capabilities that concern Events.
Expand All @@ -29,6 +36,11 @@ class Event_Capabilities {
self::TRASH,
self::DELETE,
self::EDIT_ATTENDEES,
self::EDIT_TITLE,
self::EDIT_DESCRIPTION,
self::EDIT_START,
self::EDIT_END,
self::EDIT_TIMEZONE,
);

private Event_Repository_Interface $event_repository;
Expand Down Expand Up @@ -64,6 +76,11 @@ private function has_cap( string $cap, array $args, WP_User $user ): bool {
case self::TRASH:
case self::DELETE:
case self::EDIT_ATTENDEES:
case self::EDIT_TITLE:
case self::EDIT_DESCRIPTION:
case self::EDIT_START:
case self::EDIT_END:
case self::EDIT_TIMEZONE:
if ( ! isset( $args[2] ) || ! is_numeric( $args[2] ) ) {
return false;
}
Expand All @@ -87,6 +104,9 @@ private function has_cap( string $cap, array $args, WP_User $user ): bool {
if ( self::EDIT_ATTENDEES === $cap ) {
return $this->has_edit_attendees( $user, $event );
}
if ( self::EDIT_TITLE === $cap || self::EDIT_DESCRIPTION === $cap || self::EDIT_START === $cap || self::EDIT_END === $cap || self::EDIT_TIMEZONE === $cap ) {
return $this->has_edit_field( $user, $event, $cap );
}
break;
}

Expand Down Expand Up @@ -136,14 +156,6 @@ private function has_view( WP_User $user, Event $event ): bool {
* @return bool
*/
private function has_edit( WP_User $user, Event $event ): bool {
if ( $event->end()->is_in_the_past() ) {
return false;
}

if ( $this->stats_calculator->event_has_stats( $event->id() ) ) {
return false;
}

if ( $event->author_id() === $user->ID ) {
return true;
}
Expand Down Expand Up @@ -240,6 +252,43 @@ private function has_edit_attendees( WP_User $user, Event $event ): bool {
return false;
}

/**
* Evaluate whether a user can edit event title for a specific event.
*
* @param WP_User $user User for which we're evaluating the capability.
* @param Event $event Event for which we're evaluating the capability.
* @return bool
*/
private function has_edit_field( WP_User $user, Event $event, $cap ): bool {
$now = new DateTimeImmutable( 'now', new DateTimeZone( 'UTC' ) );
$event_end_plus_1_hr = $event->end()->modify( '+1 hour' );

if ( self::EDIT_DESCRIPTION === $cap ) {
return true;
}

if ( $event->start() > $now ) {
return true;
}

if ( $event->is_active() && ! $this->stats_calculator->event_has_stats( $event->id() ) ) {
return true;
}

if ( $event->is_active() && $this->stats_calculator->event_has_stats( $event->id() ) ) {
return ( self::EDIT_TITLE === $cap || self::EDIT_END === $cap );
}

if ( $event->end()->is_in_the_past() && $now < $event_end_plus_1_hr ) {
return ( self::EDIT_TITLE === $cap || self::EDIT_END === $cap );
psrpinto marked this conversation as resolved.
Show resolved Hide resolved
}
if ( $event->end()->is_in_the_past() && $now > $event_end_plus_1_hr ) {
return ( self::EDIT_DESCRIPTION === $cap );
}

return false;
}

public function register_hooks(): void {
add_action(
'user_has_cap',
Expand Down
39 changes: 27 additions & 12 deletions includes/event/event-form-handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public function handle( array $form_data ): void {
wp_send_json_error( esc_html__( 'Invalid form name.', 'gp-translation-events' ), 403 );
}

$event_id = isset( $form_data['event_id'] ) ? sanitize_text_field( wp_unslash( $form_data['event_id'] ) ) : 0;
$event_id = isset( $form_data['event_id'] ) ? intval( sanitize_text_field( wp_unslash( $form_data['event_id'] ) ) ) : 0;
$event = null;

if ( 'create_event' === $action && ( ! current_user_can( 'create_translation_event' ) ) ) {
wp_send_json_error( esc_html__( 'You do not have permissions to create events.', 'gp-translation-events' ), 403 );
Expand All @@ -54,10 +55,12 @@ public function handle( array $form_data ): void {
}

$response_message = '';
if ( $event_id ) {
$event = $this->event_repository->get_event( $event_id );
}

if ( 'trash_event' === $action ) {
// Trash event.
$event_id = intval( sanitize_text_field( wp_unslash( $form_data['event_id'] ) ) );
$event = $this->event_repository->get_event( $event_id );
if ( ! $event ) {
wp_send_json_error( esc_html__( 'Event does not exist.', 'gp-translation-events' ), 404 );
}
Expand All @@ -84,6 +87,9 @@ public function handle( array $form_data ): void {
// Create or update event.

try {
if ( 'edit_event' === $action && $event ) {
$form_data['event_timezone'] = $event->timezone()->getName();
}
$new_event = $this->parse_form_data( $form_data );
} catch ( InvalidTimeZone $e ) {
wp_send_json_error( esc_html__( 'Invalid time zone.', 'gp-translation-events' ), 422 );
Expand All @@ -104,11 +110,6 @@ public function handle( array $form_data ): void {
return;
}

if ( $new_event->end() < new DateTime( 'now', new DateTimeZone( 'UTC' ) ) ) {
wp_send_json_error( esc_html__( 'Past events cannot be created or edited.', 'gp-translation-events' ), 422 );
return;
}

// This is a list of slugs that are not allowed, as they conflict with the event URLs.
$invalid_slugs = array( 'new', 'edit', 'attend', 'my-events' );
if ( in_array( sanitize_title( $new_event->title() ), $invalid_slugs, true ) ) {
Expand All @@ -132,10 +133,24 @@ public function handle( array $form_data ): void {

try {
$event->set_status( $new_event->status() );
$event->set_title( $new_event->title() );
$event->set_description( $new_event->description() );
$event->set_timezone( $new_event->timezone() );
$event->set_times( $new_event->start(), $new_event->end() );
if ( current_user_can( 'edit_translation_event_title', $event->id() ) ) {
$event->set_title( $new_event->title() );
}
if ( current_user_can( 'edit_translation_event_description', $event->id() ) ) {
$event->set_description( $new_event->description() );
}
if ( current_user_can( 'edit_translation_event_timezone', $event->id() ) ) {
$event->set_timezone( $new_event->timezone() );
}

$event->validate_times( $new_event->start(), $new_event->end() );

if ( current_user_can( 'edit_translation_event_start', $event->id() ) ) {
$event->set_start( $new_event->start() );
}
if ( current_user_can( 'edit_translation_event_end', $event->id() ) ) {
$event->set_end( $new_event->end() );
}
} catch ( Exception $e ) {
wp_send_json_error( esc_html__( 'Failed to update event.', 'gp-translation-events' ), 422 );
return;
Expand Down
17 changes: 9 additions & 8 deletions includes/event/event.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ public function __construct(
string $description
) {
$this->author_id = $author_id;
$this->set_times( $start, $end );
$this->validate_times( $start, $end );
$this->set_start( $start );
$this->set_end( $end );
$this->set_timezone( $timezone );
$this->set_status( $status );
$this->set_title( $title );
Expand Down Expand Up @@ -129,13 +131,12 @@ public function set_slug( string $slug ): void {
$this->slug = $slug;
}

/**
* @throws InvalidStart|InvalidEnd
*/
public function set_times( Event_Start_Date $start, Event_End_Date $end ): void {
$this->validate_times( $start, $end );
public function set_start( Event_Start_Date $start ): void {
$this->start = $start;
$this->end = $end;
}

public function set_end( Event_End_Date $end ): void {
$this->end = $end;
}

public function set_timezone( DateTimeZone $timezone ): void {
Expand Down Expand Up @@ -164,7 +165,7 @@ public function set_description( string $description ): void {
* @throws InvalidStart
* @throws InvalidEnd
*/
private function validate_times( Event_Start_Date $start, Event_End_Date $end ) {
public function validate_times( Event_Start_Date $start, Event_End_Date $end ) {
if ( $end <= $start ) {
throw new InvalidEnd();
}
Expand Down
2 changes: 1 addition & 1 deletion phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<rule ref="WordPress">
<properties>
<property name="custom_capabilities[]" value="manage_translation_events,create_translation_event,view_translation_event,edit_translation_event,trash_translation_event,delete_translation_event,edit_translation_event_attendees"/>
<property name="custom_capabilities[]" value="manage_translation_events,create_translation_event,view_translation_event,edit_translation_event,trash_translation_event,delete_translation_event,edit_translation_event_attendees,edit_translation_event_title,edit_translation_event_description,edit_translation_event_start,edit_translation_event_end,edit_translation_event_timezone"/>
</properties>
<exclude name="Squiz.Commenting.FileComment.SpacingAfterOpen"/>
<exclude name="Squiz.Commenting.FileComment.SpacingAfterComment"/>
Expand Down
10 changes: 5 additions & 5 deletions templates/events-form.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<input type="hidden" id="event-form-action" name="event_form_action">
<div>
<label for="event-title"><?php esc_html_e( 'Event Title', 'gp-translation-events' ); ?></label>
<input type="text" id="event-title" name="event_title" value="<?php echo esc_html( $event->title() ); ?>" required size="42">
<input type="text" id="event-title" name="event_title" value="<?php echo esc_html( $event->title() ); ?>" <?php echo esc_html( $is_create_form || current_user_can( 'edit_translation_event_title', $event->id() ) ?: 'readonly' ); ?> required size="42">
</div>
<?php $event_url_class = $is_create_form ? 'hide-event-url' : ''; ?>
<?php $event_url = $is_create_form ? '' : Urls::event_details_absolute( $event->id() ); ?>
Expand All @@ -46,7 +46,7 @@
</div>
<div>
<label for="event-description"><?php esc_html_e( 'Event Description', 'gp-translation-events' ); ?></label>
<textarea id="event-description" name="event_description" rows="4" cols="40" required><?php echo esc_html( $event->description() ); ?></textarea>
<textarea id="event-description" name="event_description" rows="4" cols="40" required <?php echo esc_html( $is_create_form || current_user_can( 'edit_translation_event_description', $event->id() ) ?: 'readonly' ); ?>><?php echo esc_html( $event->description() ); ?></textarea>
<?php
echo wp_kses(
Event_Text_Snippet::get_snippet_links(),
Expand All @@ -63,15 +63,15 @@
?>
<div>
<label for="event-start"><?php esc_html_e( 'Start Date', 'gp-translation-events' ); ?></label>
<input type="datetime-local" id="event-start" name="event_start" value="<?php echo esc_attr( $event->start()->format( 'Y-m-d H:i' ) ); ?>" required>
<input type="datetime-local" id="event-start" name="event_start" value="<?php echo esc_attr( $event->start()->format( 'Y-m-d H:i' ) ); ?>" required <?php echo esc_html( $is_create_form || current_user_can( 'edit_translation_event_start', $event->id() ) ?: 'readonly' ); ?> >
</div>
<div>
<label for="event-end"><?php esc_html_e( 'End Date', 'gp-translation-events' ); ?></label>
<input type="datetime-local" id="event-end" name="event_end" value="<?php echo esc_attr( $event->end()->format( 'Y-m-d H:i' ) ); ?>" required>
<input type="datetime-local" id="event-end" name="event_end" value="<?php echo esc_attr( $event->end()->format( 'Y-m-d H:i' ) ); ?>" required <?php echo esc_html( $is_create_form || current_user_can( 'edit_translation_event_end', $event->id() ) ?: 'readonly' ); ?>>
</div>
<div>
<label for="event-timezone"><?php esc_html_e( 'Event Timezone', 'gp-translation-events' ); ?></label>
<select id="event-timezone" name="event_timezone" required>
<select id="event-timezone" name="event_timezone" required <?php echo esc_html( $is_create_form || current_user_can( 'edit_translation_event_timezone', $event->id() ) ?: 'disabled' ); ?> >
<?php
echo wp_kses(
wp_timezone_choice( $is_create_form ? null : $event->timezone()->getName(), get_user_locale() ),
Expand Down
Loading
Loading