From 277fedffc624f55c6ecc8bd80ed8db370134e47e Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Fri, 20 Jan 2023 20:22:06 +0100 Subject: Rename and reorganize more source files. --- .../view-helpers/class-giglogadmin-concertform.php | 142 +++++++ .../class-giglogadmin-concertstable.php | 452 +++++++++++++++++++++ .../view-helpers/class-giglogadmin-venueform.php | 52 +++ includes/view-helpers/select-field-helper.php | 37 ++ includes/view-helpers/select_field.php | 31 -- 5 files changed, 683 insertions(+), 31 deletions(-) create mode 100644 includes/view-helpers/class-giglogadmin-concertform.php create mode 100644 includes/view-helpers/class-giglogadmin-concertstable.php create mode 100644 includes/view-helpers/class-giglogadmin-venueform.php create mode 100644 includes/view-helpers/select-field-helper.php delete mode 100644 includes/view-helpers/select_field.php (limited to 'includes/view-helpers') diff --git a/includes/view-helpers/class-giglogadmin-concertform.php b/includes/view-helpers/class-giglogadmin-concertform.php new file mode 100644 index 0000000..5cc3a47 --- /dev/null +++ b/includes/view-helpers/class-giglogadmin-concertform.php @@ -0,0 +1,142 @@ + + * SPDX-FileCopyrightText: 2021 Harald Eilertsen + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +if ( ! class_exists( 'GiglogAdmin_ConcertForm' ) ) { + class GiglogAdmin_ConcertForm { + + private function get_venue_selector( ?GiglogAdmin_Venue $invenue ): string { + return \EternalTerror\ViewHelpers\select_field( + 'selectvenueadmin', + array_map( fn( $venue) => array( $venue->id(), $venue->name() ), GiglogAdmin_Venue::all_venues() ), + $invenue ? $invenue->id() : null + ); + } + + + private function user_dropdown_for_role( GiglogAdmin_Concert $concert, string $role ): string { + $users = array_map( + fn( $usr): string => $usr->user_login, + get_users( array( 'fields' => array( 'user_login' ) ) ) + ); + + $roles = $concert->roles(); + + $current_user = array_key_exists( $role, $roles ) ? $roles[ $role ] : null; + + return \EternalTerror\ViewHelpers\select_field( + $role, + array_map( fn( $user) => array( $user, $user ), $users ), + $current_user + ); + } + + + + public function render() : string { + $cid = filter_input( INPUT_POST, 'cid' ); + $editing = filter_input( INPUT_POST, 'edit' ) == 'EDIT'; + + if ( $editing && ! empty( $cid ) ) { + $c = GiglogAdmin_Concert::get( $cid ); + if ( ! $c ) { + wp_die( 'Invalid request!', 400 ); + } + } else { + $c = new GiglogAdmin_Concert( (object) array() ); + } + + $content = '
'; + $content .= '
' + . '
CONCERT DETAILS

' + . wp_nonce_field( 'edit-concert', 'nonce' ) + . '' + . '' + . '
' + . '' . $this->get_venue_selector( $c->venue() ) . '
' + // date has to be formatted else it is not red in the date field of html form + . '' + . '
' + . '' + . '
' + . '' + . '
' + . '
'; + + // actions differ if we update or create a concert, hence two buttons needed + if ( $editing ) { + $content .= '

'; + } else { + $content .= '

'; + } + + $content .= '
'; + + $content .= '
ASSIGNMENT DETAILS

' + . '' . $this->user_dropdown_for_role( $c, 'photo1' ) . '
' + . '' . $this->user_dropdown_for_role( $c, 'photo2' ) . '
' + . '' . $this->user_dropdown_for_role( $c, 'rev1' ) . '
' + . '' . $this->user_dropdown_for_role( $c, 'rev2' ) . '
'; + + $content .= '
'; + + return $content; + } + + static function update() : void { + if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'edit-concert' ) ) { + wp_die( 'CSRF validation failed.', 403 ); + } + + if ( isset( $_POST['newconcert'] ) ) { + if ( empty( $_POST['cname'] ) || empty( $_POST['selectvenueadmin'] ) || empty( $_POST['cdate'] ) || empty( $_POST['ticket'] ) || empty( $_POST['eventurl'] ) ) { + echo ''; + } else { + if ( GiglogAdmin_Concert::create( $_POST['cname'], $_POST['selectvenueadmin'], $_POST['cdate'], $_POST['ticket'], $_POST['eventurl'] ) ) { + echo ''; + } else { + echo ''; + } + } + } + + if ( isset( $_POST['editconcert'] ) ) { + $roles = array_reduce( + array( 'photo1', 'photo1', 'rev1', 'rev2' ), + function( $roles, $r ) { + if ( isset( $_POST[ $r ] ) ) { + $roles[ $r ] = sanitize_user( $_POST[ $r ] ); + } + return $roles; + }, + array() + ); + + $attributes = array( + 'wpgconcert_name' => sanitize_text_field( $_POST['cname'] ), + 'venue' => intval( $_POST['selectvenueadmin'] ), + 'wpgconcert_date' => sanitize_text_field( $_POST['cdate'] ), + 'wpgconcert_ticket' => esc_url_raw( $_POST['ticket'] ), + 'wpgconcert_event' => esc_url_raw( $_POST['eventurl'] ), + 'wpgconcert_roles' => $roles, + ); + + $concert = GiglogAdmin_Concert::get( intval( $_POST['pid'] ) ); + if ( $concert && $concert->update( (object) $attributes ) ) { + // let user know the concert was updated. + // Look into admin_notices + } + } + } + } +} diff --git a/includes/view-helpers/class-giglogadmin-concertstable.php b/includes/view-helpers/class-giglogadmin-concertstable.php new file mode 100644 index 0000000..1288cbd --- /dev/null +++ b/includes/view-helpers/class-giglogadmin-concertstable.php @@ -0,0 +1,452 @@ + + * SPDX-FileCopyrightText: 2021 Harald Eilertsen + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +if ( ! class_exists( 'GiglogAdmin_ConcertsTable' ) ) { + class GiglogAdmin_ConcertsTable { + + const STATUS_LABELS = array( + '', + 'Accred Requested', + 'Photo Approved', + 'Text Approved', + 'Photo and Text Approved', + 'Rejected', + ); + + const FILTER_KEYS = array( + 'city', + 'venue', + 'month', + 'only_mine', + ); + + private string $username; + private array $filter; + + private int $page_no = 1; + private int $total_no_of_pages = 1; + private int $previous_page = 0; + private int $next_page = 0; + + private string $nonce; + + public static function update() : void { + // + // Check that we get a nonce, and that it is valid to prevent CSRF attacks. + // + if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'concerts-table' ) ) { + wp_die( 'You are not allowed to do that.', 403 ); + exit(); + } + + if ( isset( $_POST['assignitem'] ) ) { + $concert = GiglogAdmin_Concert::get( intval( $_POST['cid'] ) ); + + if ( $concert ) { + $role = sanitize_text_field( $_POST['pid'] ); + self::assignconcert( $role, $concert ); + } + + return; + } + + if ( isset( $_POST['unassignitem'] ) ) { + $concert = GiglogAdmin_Concert::get( intval( $_POST['cid'] ) ); + + if ( $concert ) { + $role = sanitize_text_field( $_POST['pid'] ); + self::unassignconcert( $role, $concert ); + } + + return; + } + + // handle the status drop down + if ( isset( $_POST['selectstatus'] ) && ! empty( $_POST['selectstatus'] ) && ! empty( $_POST['cid'] ) ) { + if ( $_POST['selectstatus'] > 0 && $_POST['selectstatus'] < count( self::STATUS_LABELS ) ) { + $concert = GiglogAdmin_Concert::get( intval( $_POST['cid'] ) ); + if ( $concert ) { + $concert->set_status( intval( $_POST['selectstatus'] ) ); + $concert->save(); + self::emailuser( $concert, intval( $_POST['selectstatus'] ) ); + } + } + } + } + + static function assignconcert( string $p1, GiglogAdmin_Concert $concert ): void { + $username = wp_get_current_user()->user_login; + $concert->assign_role( $p1, $username ); + $concert->save(); + + $cuser = get_user_by( 'login', 'etadmin' ); + + if ( $cuser ) { + $dest = $cuser->user_email; + $subject = 'WP-GIGLOG ' . $username . ' has taken ' . $p1 . 'for concert ' . $concert->cname(); + $body = 'WP-GIGLOG ' . $username . ' has taken ' . $p1 . 'for concert ' . $concert->cname() . ', concert with ID ' . $concert->id(); + $headers = array( 'Content-Type: text/html; charset=UTF-8' ); + + wp_mail( $dest, $subject, $body ); + } + } + + static function unassignconcert( string $p1, GiglogAdmin_Concert $concert ): void { + $username = wp_get_current_user()->user_login; + $concert->remove_user_from_roles( $username ); + $concert->save(); + + $cuser = get_user_by( 'login', 'etadmin' ); + + if ( $cuser ) { + $dest = $cuser->user_email; + $subject = 'WP-GIGLOG ' . $username . ' has UNASSIGNED ' . $p1 . 'for concert ' . $concert->cname(); + $body = 'WP-GIGLOG ' . $username . ' has UNASSIGNED ' . $p1 . 'for concert ' . $concert->cname() . ', concert with ID ' . $concert->id(); + $headers = array( 'Content-Type: text/html; charset=UTF-8' ); + + wp_mail( $dest, $subject, $body ); + } + } + + static function emailuser( GiglogAdmin_Concert $concert, string $cstatus ): void { + $username = wp_get_current_user()->user_login; + $useremail = 'live@eternal-terror.com'; + $dest = ''; + $roles = $concert->roles(); + $x = ''; + + foreach ( $roles as $role ) { + if ( $role ) { + $cuser = get_user_by( 'login', $role ); + + if ( $cuser ) { + $dest .= $cuser->user_email . ','; + } + } + } + + $subject = 'Message from GIGLOG: Concert ' . $concert->cname() . ' has a new status ' . $cstatus . '.'; + $body = 'You receive this message because you have assigned one of the roles for Concert ' . $concert->cname() . '.'; + $body .= '\r\n This is to inform you that there is a new status for the acreditation ' . $cstatus . '.'; + $body .= '\r\n Should you no longer want to receive updates about this concert, please log in to Giglog and remove yourself from the concert. Thanks!'; + $headers = array( 'Content-Type: text/plain; charset=UTF-8' ); // it is text by default so no need for headers actually + + wp_mail( $dest, $subject, $body ); + } + + public function __construct() { + $this->username = wp_get_current_user()->user_login; + + // Set the nonce we use to check for CSRF attacks. + $this->nonce = wp_create_nonce( 'concerts-table' ); + $this->get_args(); + } + + public function render(): string { + return $this->render_filters() + . $this->render_concerts_table(); + } + + private function render_concert_table_header() : string { + $content = '
'; + $content .= 'Note: the iCal link will download a file with extension .ical which can be used to add the event to your calendar. For convenience, we set all events with start time at 19:00 but please check the actual event for the correct time.'; + + $content .= ''; + $content .= ''; + + if ( ! is_admin() ) { + $content .= ''; + } else { + $content .= ''; + if ( current_user_can( 'administrator' ) ) { + $content .= ''; + } + } + + $content .= ''; + + return $content; + } + + private function get_args() : void { + $this->filter = array(); + + // Use the submitted "city" if any. Otherwise, use the default/static value. + $cty = filter_input( INPUT_GET, 'city', FILTER_SANITIZE_SPECIAL_CHARS ); + if ( $cty ) { + $this->filter['city'] = $cty; + } + + $venue = filter_input( INPUT_GET, 'venue', FILTER_SANITIZE_SPECIAL_CHARS ); + if ( $venue ) { + $this->filter['venue_id'] = $venue; + } + + $smonth = filter_input( INPUT_GET, 'month', FILTER_SANITIZE_SPECIAL_CHARS ); + if ( $smonth ) { + $this->filter['month'] = $smonth; + } + + if ( isset( $_GET['only_mine'] ) && $_GET['only_mone'] == '1' ) { + $this->filter['currentuser'] = $this->username; + } + + if ( isset( $_GET['page_no'] ) && $_GET['page_no'] != '' && is_numeric( $_GET['page_no'] ) && isset( $_GET['page_no'] ) == $this->page_no ) { + $this->page_no = intval( $_GET['page_no'] ); + } else { + $this->page_no = 1; + } + } + + private function get_concerts() : ?array { + $total_records_per_page = 15; + + $total_concerts = GiglogAdmin_Concert::count( $this->filter ); + $this->total_no_of_pages = ceil( $total_concerts / $total_records_per_page ); + + // calculate OFFSET Value and SET other Variables + $offset = ( $this->page_no - 1 ) * $total_records_per_page; + $this->previous_page = $this->page_no - 1; + $this->next_page = $this->page_no + 1; + + if ( $this->page_no > $this->total_no_of_pages ) { + $this->page_no = 1; + } + + $this->filter['offset'] = $offset; + $this->filter['recperpage'] = $total_records_per_page; + + return GiglogAdmin_Concert::find_concerts( $this->filter ); + } + + private function get_filter( string $f ) : ?string { + return isset( $this->filter[ $f ] ) ? $this->filter[ $f ] : null; + } + + private function render_pagination() : string { + $content = + '
' + . ''; + + if ( $this->page_no > 1 ) { + $content .= + '' + . '' + . 'First Page -' + . '' + . '' + . '' + . ' Previous'; + } + + $content .= '' + . '' + . 'Page ' . $this->page_no . ' of ' . $this->total_no_of_pages . '' + . ''; + + $content .= ''; + + if ( $this->page_no < $this->total_no_of_pages ) { + $content .= + '' + . '' + . 'Next - ' + . '' + . '' + . '' + . 'Last Page' + . ''; + } + + $content .= + '' + . '
'; + + return $content; + } + + private function render_concerts_table() : string { + $concerts = $this->get_concerts(); + + $last_city = ''; + + $content = $this->render_concert_table_header(); + + foreach ( $concerts as $concert ) { + $content .= ''; + + $content .= + '' + . '' + . ''; + + if ( is_admin() ) { + $content .= ''; + + foreach ( array( 'photo1', 'photo2', 'rev1', 'rev2' ) as $role ) { + $content .= ''; + } + + $content .= ''; + + if ( current_user_can( 'administrator' ) ) { + $content .= ""; + } + } else { + $content .= ''; + $content .= ''; + } + + $content .= ''; + $content .= ''; + $last_city = $concert->venue()->city(); + } + + $content .= '
CITYDATENAMEVENUEEVENTTICKETSCalendarPHOTO1PHOTO2TEXT1TEXT2STATUSAdminOptions
'; + + if ( $last_city != $concert->venue()->city() ) { + $content .= $concert->venue()->city(); + } + + $content .= '' . date( 'd.M.Y', strtotime( $concert->cdate() ) ) . '' . strtoupper( esc_html( $concert->cname() ) ) . '' . esc_html( $concert->venue()->name() ) . '' . $this->mark_new_concert( $concert ) . '' + . $this->assign_role_for_user_form( $role, $concert ) + . '' . self::STATUS_LABELS[ $concert->status() ] . '{$this->adminactions( $concert )}LinkTicketsiCal
'; + + $content .= $this->render_pagination(); + + // from main form that includes filters + $content .= '
'; + + // return the table + return $content; + } + + private function render_filters() : string { + global $wp_locale; + + $select = '
FILTER DATA: '; + + foreach ( $_GET as $name => $val ) { + if ( in_array( $name, self::FILTER_KEYS ) ) { + continue; + } + + $select .= ''; + } + + $cty = $this->get_filter( 'city' ); + + $select .= \EternalTerror\ViewHelpers\select_field( + 'city', + array_map( fn( $city) => array( $city, $city ), GiglogAdmin_Venue::all_cities() ), + $cty, + 'Select city...' + ); + + if ( ! empty( $cty ) ) { + // second drop down for venue + $select .= \EternalTerror\ViewHelpers\select_field( + 'venue', + array_map( + fn( $venue) => array( $venue->id(), $venue->name() ), + GiglogAdmin_Venue::venues_in_city( $cty ) + ), + $this->get_filter( 'venue_id' ), + 'Select venue...' + ); + } + + $select .= \EternalTerror\ViewHelpers\select_field( + 'month', + array_map( + fn( $m) => array( $m, $wp_locale->get_month( $m ) ), + range( 1, 12 ) + ), + $this->get_filter( 'month' ), + 'Select month...' + ); + + if ( is_admin() ) { + // option to select own concerts only + $select .= 'get_filter( 'current_user' ) ) + . '>'; + + } + // NOTE that I remvoed

and mvoed them up to render_concerts_table function + $select .= ''; + + return $select; + } + + private function adminactions( GiglogAdmin_Concert $concert ) : string { + return '
' + . '' + . '' + . \EternalTerror\ViewHelpers\select_field( + 'selectstatus', + array_map( fn( $i) => array( $i, self::STATUS_LABELS[ $i ] ), range( 1, count( self::STATUS_LABELS ) - 1 ) ), + $concert->status() + ) + . '' + . '' + . '
'; + } + + /** + * Display a mark on the concert if it is new. + * I.e. imported/created within the last ten days. + * + * @return null|string + */ + private function mark_new_concert( GiglogAdmin_Concert $concert ) : string { + $now = new DateTime(); + $new_entry = $now->diff( $concert->created() )->days <= 10; + if ( $new_entry ) { + return 'NEW'; + } else { + return ''; + } + } + + private function assign_role_for_user_form( string $role, GiglogAdmin_Concert $concert ) : ?string { + $roles = $concert->roles(); + $assigned_user = array_key_exists( $role, $roles ) ? $roles[ $role ] : null; + + // first check if current slot is taken by current user + if ( $assigned_user == $this->username ) { + $f = '
' + . ' ' + . ' ' + . ' ' + . ' ' + . '
'; + } elseif ( $assigned_user ) { // check if slot is taken by another user + $f = 'Taken' + . '
Taken by ' . $assigned_user . '
'; + } elseif ( array_search( $this->username, $roles ) ) { + // other slots for this concert are taken by user + $f = '-'; + } else { // not taken by anyone + $f = '
' + . ' ' + . ' ' + . ' ' + . ' ' + . '
'; + } + + return $f; + } + } +} diff --git a/includes/view-helpers/class-giglogadmin-venueform.php b/includes/view-helpers/class-giglogadmin-venueform.php new file mode 100644 index 0000000..f837d73 --- /dev/null +++ b/includes/view-helpers/class-giglogadmin-venueform.php @@ -0,0 +1,52 @@ + + * SPDX-FileCopyrightText: 2021 Harald Eilertsen + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +if ( ! class_exists( 'GiglogAdmin_VenueForm' ) ) { + class GiglogAdmin_VenueForm { + + public function render() : string { + return '
' + . '

VENUE DETAILS

' + . '
' + . '
' + . wp_nonce_field( 'edit-venue', 'nonce' ) + . '
' + . ' ' + . ' ' + . '
' + . '
' + . ' ' + . ' ' + . '
' + . '
' + . ' ' + . '
' + . '
' + . '' + . '
'; + } + + static function update() : void { + if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'edit-venue' ) ) { + header( "{$_SERVER['SERVER_PROTOCOL']} 403 Forbidden" ); + wp_die( 'CSRF validation failed.', 403 ); + } + + if ( empty( $_POST['venuename'] ) || empty( $_POST['venuecity'] ) ) { + echo ''; + } else { + GiglogAdmin_Venue::create( $_POST['venuename'], $_POST['venuecity'] ); + echo ''; + } + } + } +} diff --git a/includes/view-helpers/select-field-helper.php b/includes/view-helpers/select-field-helper.php new file mode 100644 index 0000000..c25244b --- /dev/null +++ b/includes/view-helpers/select-field-helper.php @@ -0,0 +1,37 @@ + + * SPDX-FileCopyrightText: 2021 Harald Eilertsen + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace EternalTerror\ViewHelpers; + +/** + * Return HTML code for a selction box with the given options and preselected value. + * + * @param string $name The name attribute for the selection box + * @param array $opts The options as arrays of [value, label] pairs + * @param mixed|int $selected The value of the preselected option, or null if no + * option is preselected. + * @param string $blank Text to use for "no selection", defaults to "Please + * select..." + * @return string + */ +function select_field( + string $name, + array $opts = array(), + $selected = null, + string $blank = 'Please select...' ) : string { + $body = ""; + foreach ( $opts as $opt ) { + $sel = selected( $selected, $opt[0], false ); + $body .= ""; + } + return ""; +} diff --git a/includes/view-helpers/select_field.php b/includes/view-helpers/select_field.php deleted file mode 100644 index aa156d0..0000000 --- a/includes/view-helpers/select_field.php +++ /dev/null @@ -1,31 +0,0 @@ - -// SPDX-FileCopyrightText: 2021 Harald Eilertsen -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -namespace EternalTerror\ViewHelpers; - -/** - * Return HTML code for a selction box with the given options and preselected value. - * - * @param string $name The name attribute for the selection box - * @param array $opts The options as arrays of [value, label] pairs - * @param mixed|int $selected The value of the preselected option, or null if no - * option is preselected. - * @param string $blank Text to use for "no selection", defaults to "Please - * select..." - * @return string - */ -function select_field( - string $name, - array $opts = array(), - $selected = null, - string $blank = 'Please select...' ) : string { - $body = ""; - foreach ( $opts as $opt ) { - $sel = selected( $selected, $opt[0], false ); - $body .= ""; - } - return ""; -} -- cgit v1.2.3