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. --- includes/admin/register_db_tables.php | 55 --- includes/admin/views/_concerts_table.php | 448 -------------------- includes/admin/views/_edit_concert_form.php | 138 ------- includes/admin/views/_new_venue_form.php | 46 --- .../admin/views/class-giglogadmin-adminpage.php | 96 +++++ .../views/class-giglogadmin-importgigspage.php | 138 +++++++ includes/admin/views/giglog_admin_page.php | 91 ----- includes/admin/views/giglog_import_gigs.php | 133 ------ includes/class-giglogadmin-plugin.php | 13 +- includes/giglogadmin-register-db-tables.php | 62 +++ .../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 -- 15 files changed, 986 insertions(+), 948 deletions(-) delete mode 100644 includes/admin/register_db_tables.php delete mode 100644 includes/admin/views/_concerts_table.php delete mode 100644 includes/admin/views/_edit_concert_form.php delete mode 100644 includes/admin/views/_new_venue_form.php create mode 100644 includes/admin/views/class-giglogadmin-adminpage.php create mode 100644 includes/admin/views/class-giglogadmin-importgigspage.php delete mode 100644 includes/admin/views/giglog_admin_page.php delete mode 100644 includes/admin/views/giglog_import_gigs.php create mode 100644 includes/giglogadmin-register-db-tables.php 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 diff --git a/includes/admin/register_db_tables.php b/includes/admin/register_db_tables.php deleted file mode 100644 index 5f83e25..0000000 --- a/includes/admin/register_db_tables.php +++ /dev/null @@ -1,55 +0,0 @@ - -// SPDX-FileCopyrightText: 2021 Harald Eilertsen -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -if ( ! function_exists( 'giglog_register_db_tables' ) ) { - /** - * Registers the tables used by the GiglogAdmin plugin - */ - function giglog_register_db_tables() : void { - global $wpdb; - - $tables = array(); - $tables[] = - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}giglogadmin_venues` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `wpgvenue_name` VARCHAR(500) NOT NULL, - `wpgvenue_city` VARCHAR(250) DEFAULT NULL, - `wpgvenue_address` VARCHAR(2000) DEFAULT NULL, - `wpgvenue_webpage` VARCHAR(200) DEFAULT NULL, - `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - `updated` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"; - - $tables[] = - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}giglogadmin_concerts` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `wpgconcert_name` VARCHAR(2000) NOT NULL, - `venue` int(11) NOT NULL, - `wpgconcert_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - `wpgconcert_tickets` VARCHAR(2000) DEFAULT NULL, - `wpgconcert_event` VARCHAR(2000) DEFAULT NULL, - `wpgconcert_type` INT NOT NULL DEFAULT '1' COMMENT '1 concert, 2 festival', - `wpgconcert_status` INT DEFAULT 1, - `wpgconcert_roles` JSON CHECK (JSON_VALID(wpgconcert_roles)), - `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - `updated` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - CONSTRAINT `wpgconcert_venue` - FOREIGN KEY (`venue`) - REFERENCES `{$wpdb->prefix}giglogadmin_venues` (`id`) ON DELETE NO ACTION - ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"; - - foreach ( $tables as $tabledef ) { - $result = $wpdb->query( $tabledef ); - if ( $result === false ) { - error_log( 'Registering table failed.' ); - } - } - } - - giglog_register_db_tables(); -} diff --git a/includes/admin/views/_concerts_table.php b/includes/admin/views/_concerts_table.php deleted file mode 100644 index 4f9b3c9..0000000 --- a/includes/admin/views/_concerts_table.php +++ /dev/null @@ -1,448 +0,0 @@ - -// SPDX-FileCopyrightText: 2021 Harald Eilertsen -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -require_once __DIR__ . '/../../view-helpers/select_field.php'; - -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/admin/views/_edit_concert_form.php b/includes/admin/views/_edit_concert_form.php deleted file mode 100644 index 1a2e5a6..0000000 --- a/includes/admin/views/_edit_concert_form.php +++ /dev/null @@ -1,138 +0,0 @@ - -// SPDX-FileCopyrightText: 2021 Harald Eilertsen -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -require_once __DIR__ . '/../../view-helpers/select_field.php'; - -if ( ! class_exists( 'GiglogAdmin_EditConcertForm' ) ) { - class GiglogAdmin_EditConcertForm { - - 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/admin/views/_new_venue_form.php b/includes/admin/views/_new_venue_form.php deleted file mode 100644 index 39eb1b2..0000000 --- a/includes/admin/views/_new_venue_form.php +++ /dev/null @@ -1,46 +0,0 @@ - -// SPDX-FileCopyrightText: 2021 Harald Eilertsen -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -if ( ! class_exists( 'GiglogAdmin_NewVenueForm' ) ) { - class GiglogAdmin_NewVenueForm { - - 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/admin/views/class-giglogadmin-adminpage.php b/includes/admin/views/class-giglogadmin-adminpage.php new file mode 100644 index 0000000..23a0a85 --- /dev/null +++ b/includes/admin/views/class-giglogadmin-adminpage.php @@ -0,0 +1,96 @@ + + * SPDX-FileCopyrightText: 2021 Harald Eilertsen + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +if ( ! class_exists( 'GiglogAdmin_AdminPage' ) ) { + require_once __DIR__ . '/../../class-giglogadmin-venue.php'; + require_once __DIR__ . '/../../view-helpers/class-giglogadmin-concertstable.php'; + require_once __DIR__ . '/../../view-helpers/class-giglogadmin-concertform.php'; + require_once __DIR__ . '/../../view-helpers/class-giglogadmin-venueform.php'; + + class GiglogAdmin_AdminPage { + + const STATUS_LABELS = array( + '', + 'Accred Requested', + 'Photo Approved', + 'Text Approved', + 'Photo and Text Approved', + 'Rejected', + ); + + public static function render_html() : void { + $page = new self(); + $page->render_page(); + } + + private function render_page() : void { + $concerts = new GiglogAdmin_ConcertsTable(); + ?> +
+

Giglog Admin

+ +

The available slots are marked with the green checkbox. + If you click on it, it will be assigned to you and if you no longer + wish to cover that concert, click on the red icon and you will be + unassigned. A mail should be sent to the admin when this happens, + but in order for the accreditation request to be sent, you have to + mail live@eternal-terror.com with the template containing concert + information. There might be some exceptions, but those are discussed + case by case. So whenever you want a concert, assign yourself and send + the template no later than 3 weeks before the concert.

+ +

Admin will try to keep the concert status updated so that you know + what the accreditation status is. You will get personal message if this + is really close to the concert date.

+ +

render(); ?>

+
+ +
+

Form to create/edit concerts and venues

+
+
+ render() . $venue_form->render(); ?> +
+ + * SPDX-FileCopyrightText: 2021 Harald Eilertsen + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +if ( ! class_exists( 'GiglogAdmin_ImportGigsPage' ) ) { + require_once __DIR__ . '/../../class-giglogadmin-concert.php'; + require_once __DIR__ . '/../../class-giglogadmin-venue.php'; + + class GiglogAdmin_ImportGigsPage { + static function render_html(): void { + ?> +
+

Import gigs

+

Import gig data from a tab separated data file.

+
+ + + + +
+
+ $file + */ + static function process_upload( array $file ): void { + $fo = new SplFileObject( $file['tmp_name'] ); + $importerrors = array(); + $rid = 0; + + foreach ( $fo as $line ) { + $rid++; + $line = trim( $line ); + if ( ! empty( $line ) ) { + try { + self::process_line( $line ); + } catch ( Exception $e ) { + $importerrors[] = "Error importing line {$rid}: {$e->getMessage()}"; + } + } + } + + if ( ! empty( $importerrors ) ) { + echo implode( '
', $importerrors ); + } else { + echo ( 'All rows imported ok' ); + } + } + + static function process_line( string $line ) : void { + $resultArray = explode( "\t", $line ); + + // unsure if this is needed, considering we are also checking if + // each individual important field is missing. But if they are not + // replaced by tabs, then everything gets shifted so probably best + // to check if a value is empty and NOT replaced by tab + + if ( count( $resultArray ) < 6 ) { + throw new Exception( 'missing a field' ); + } + + if ( ! preg_match( '/\d{4}\-\d{2}-\d{2}/', $resultArray[3] ) ) { + throw new Exception( 'invalid date: ' . esc_html( $resultArray[3] ) ); + } + + if ( empty( trim( $resultArray[0] ) ) ) { + throw new Exception( 'missing concert name' ); + } + + if ( empty( trim( $resultArray[1] ) ) ) { + throw new Exception( 'missing venue' ); + } + + if ( empty( trim( $resultArray[2] ) ) ) { + throw new Exception( 'missing city' ); + } + + $condate = date( 'Y-m-d', strtotime( $resultArray[3] ) ); + + if ( $condate < date( 'Y-m-d' ) ) { + throw new Exception( 'has date in the past: ' . esc_html( $resultArray[3] ) ); + } + + $cname = trim( $resultArray[0] ); + $venue = trim( $resultArray[1] ); + + if ( is_numeric( $venue ) ) { + $venue = GiglogAdmin_Venue::get( intval( $venue ) ); + if ( ! $venue ) { + throw new Exception( "invalid venue id: {$venue}" ); + } + } else { + $venue = GiglogAdmin_Venue::find_or_create( $venue, trim( $resultArray[2] ) ); + } + + $ticketlink = trim( $resultArray[4] ); + $eventlink = trim( $resultArray[5] ); + + GiglogAdmin_Concert::create( $cname, $venue->id(), $condate, $ticketlink, $eventlink ); + } + } +} diff --git a/includes/admin/views/giglog_admin_page.php b/includes/admin/views/giglog_admin_page.php deleted file mode 100644 index acd0172..0000000 --- a/includes/admin/views/giglog_admin_page.php +++ /dev/null @@ -1,91 +0,0 @@ - -// SPDX-FileCopyrightText: 2021 Harald Eilertsen -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -if ( ! class_exists( 'GiglogAdmin_AdminPage' ) ) { - require_once __DIR__ . '/../../class-giglogadmin-venue.php'; - require_once __DIR__ . '/_concerts_table.php'; - require_once __DIR__ . '/_edit_concert_form.php'; - require_once __DIR__ . '/_new_venue_form.php'; - - class GiglogAdmin_AdminPage { - - const STATUS_LABELS = array( - '', - 'Accred Requested', - 'Photo Approved', - 'Text Approved', - 'Photo and Text Approved', - 'Rejected', - ); - - public static function render_html() : void { - $page = new self(); - $page->render_page(); - } - - private function render_page() : void { - $concerts = new GiglogAdmin_ConcertsTable(); - ?> -
-

Giglog Admin

- -

The available slots are marked with the green checkbox. - If you click on it, it will be assigned to you and if you no longer - wish to cover that concert, click on the red icon and you will be - unassigned. A mail should be sent to the admin when this happens, - but in order for the accreditation request to be sent, you have to - mail live@eternal-terror.com with the template containing concert - information. There might be some exceptions, but those are discussed - case by case. So whenever you want a concert, assign yourself and send - the template no later than 3 weeks before the concert.

- -

Admin will try to keep the concert status updated so that you know - what the accreditation status is. You will get personal message if this - is really close to the concert date.

- -

render(); ?>

-
- -
-

Form to create/edit concerts and venues

-
-
- render() . $venue_form->render(); ?> -
- -// SPDX-FileCopyrightText: 2021 Harald Eilertsen -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -if ( ! class_exists( 'GiglogAdmin_ImportGigsPage' ) ) { - require_once __DIR__ . '/../../class-giglogadmin-concert.php'; - require_once __DIR__ . '/../../class-giglogadmin-venue.php'; - - class GiglogAdmin_ImportGigsPage { - static function render_html(): void { - ?> -
-

Import gigs

-

Import gig data from a tab separated data file.

-
- - - - -
-
- $file - */ - static function process_upload( array $file ): void { - $fo = new SplFileObject( $file['tmp_name'] ); - $importerrors = array(); - $rid = 0; - - foreach ( $fo as $line ) { - $rid++; - $line = trim( $line ); - if ( ! empty( $line ) ) { - try { - self::process_line( $line ); - } catch ( Exception $e ) { - $importerrors[] = "Error importing line {$rid}: {$e->getMessage()}"; - } - } - } - - if ( ! empty( $importerrors ) ) { - echo implode( '
', $importerrors ); - } else { - echo ( 'All rows imported ok' ); - } - } - - static function process_line( string $line ) : void { - $resultArray = explode( "\t", $line ); - - // unsure if this is needed, considering we are also checking if - // each individual important field is missing. But if they are not - // replaced by tabs, then everything gets shifted so probably best - // to check if a value is empty and NOT replaced by tab - - if ( count( $resultArray ) < 6 ) { - throw new Exception( 'missing a field' ); - } - - if ( ! preg_match( '/\d{4}\-\d{2}-\d{2}/', $resultArray[3] ) ) { - throw new Exception( 'invalid date: ' . esc_html( $resultArray[3] ) ); - } - - if ( empty( trim( $resultArray[0] ) ) ) { - throw new Exception( 'missing concert name' ); - } - - if ( empty( trim( $resultArray[1] ) ) ) { - throw new Exception( 'missing venue' ); - } - - if ( empty( trim( $resultArray[2] ) ) ) { - throw new Exception( 'missing city' ); - } - - $condate = date( 'Y-m-d', strtotime( $resultArray[3] ) ); - - if ( $condate < date( 'Y-m-d' ) ) { - throw new Exception( 'has date in the past: ' . esc_html( $resultArray[3] ) ); - } - - $cname = trim( $resultArray[0] ); - $venue = trim( $resultArray[1] ); - - if ( is_numeric( $venue ) ) { - $venue = GiglogAdmin_Venue::get( intval( $venue ) ); - if ( ! $venue ) { - throw new Exception( "invalid venue id: {$venue}" ); - } - } else { - $venue = GiglogAdmin_Venue::find_or_create( $venue, trim( $resultArray[2] ) ); - } - - $ticketlink = trim( $resultArray[4] ); - $eventlink = trim( $resultArray[5] ); - - GiglogAdmin_Concert::create( $cname, $venue->id(), $condate, $ticketlink, $eventlink ); - } - } -} diff --git a/includes/class-giglogadmin-plugin.php b/includes/class-giglogadmin-plugin.php index a195ffa..6236f60 100644 --- a/includes/class-giglogadmin-plugin.php +++ b/includes/class-giglogadmin-plugin.php @@ -15,17 +15,18 @@ if ( ! class_exists( 'GiglogAdmin_Plugin' ) ) { { static public function init(): void { if ( !defined('GIGLOGADMIN_UNIT_TEST') ) { - require_once __DIR__ . '/admin/register_db_tables.php'; + require_once __DIR__ . '/giglogadmin-register-db-tables.php'; + giglog_register_db_tables(); } require_once __DIR__ . '/class-giglogadmin-venue.php'; require_once __DIR__ . '/class-giglogadmin-concert.php'; require_once __DIR__ . '/class-giglogadmin-icalexport.php'; - require_once __DIR__ . '/view-helpers/select_field.php'; + require_once __DIR__ . '/view-helpers/select-field-helper.php'; if (is_admin()) { - require_once __DIR__ . '/admin/views/giglog_admin_page.php'; - require_once __DIR__ . '/admin/views/giglog_import_gigs.php'; + require_once __DIR__ . '/admin/views/class-giglogadmin-adminpage.php'; + require_once __DIR__ . '/admin/views/class-giglogadmin-importgigspage.php'; require_once __DIR__ . '/admin/helpfiles/instrunctions.php'; require_once __DIR__ . '/admin/helpfiles/instr_reviewers.php'; require_once __DIR__ . '/admin/helpfiles/instr_photog.php'; @@ -36,7 +37,7 @@ if ( ! class_exists( 'GiglogAdmin_Plugin' ) ) { add_filter( 'wp_nav_menu_args', array( 'GiglogAdmin_Plugin', 'nav_menu_args' )); } else { - require_once __DIR__ . '/admin/views/_concerts_table.php'; + require_once __DIR__ . '/view-helpers/class-giglogadmin-concertstable.php'; require_once __DIR__ . '/giglogadmin-shortcodes.php'; } } @@ -82,7 +83,7 @@ if ( ! class_exists( 'GiglogAdmin_Plugin' ) ) { array( 'GiglogAdmin_ImportGigsPage', 'submit_form' ) ); } - wp_register_style( 'css_style', plugins_url( '/includes/css/main.css', __FILE__ ) ); + wp_register_style( 'css_style', plugins_url( '/css/main.css', __FILE__ ) ); wp_enqueue_style('css_style'); } diff --git a/includes/giglogadmin-register-db-tables.php b/includes/giglogadmin-register-db-tables.php new file mode 100644 index 0000000..84df6e8 --- /dev/null +++ b/includes/giglogadmin-register-db-tables.php @@ -0,0 +1,62 @@ + + * SPDX-FileCopyrightText: 2021 Harald Eilertsen + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +if ( ! function_exists( 'giglog_register_db_tables' ) ) { + /** + * Registers the tables used by the GiglogAdmin plugin + */ + function giglog_register_db_tables() : void { + global $wpdb; + + $tables = array(); + $tables[] = + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}giglogadmin_venues` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `wpgvenue_name` VARCHAR(500) NOT NULL, + `wpgvenue_city` VARCHAR(250) DEFAULT NULL, + `wpgvenue_address` VARCHAR(2000) DEFAULT NULL, + `wpgvenue_webpage` VARCHAR(200) DEFAULT NULL, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `updated` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"; + + $tables[] = + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}giglogadmin_concerts` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `wpgconcert_name` VARCHAR(2000) NOT NULL, + `venue` int(11) NOT NULL, + `wpgconcert_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `wpgconcert_tickets` VARCHAR(2000) DEFAULT NULL, + `wpgconcert_event` VARCHAR(2000) DEFAULT NULL, + `wpgconcert_type` INT NOT NULL DEFAULT '1' COMMENT '1 concert, 2 festival', + `wpgconcert_status` INT DEFAULT 1, + `wpgconcert_roles` JSON CHECK (JSON_VALID(wpgconcert_roles)), + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `updated` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + CONSTRAINT `wpgconcert_venue` + FOREIGN KEY (`venue`) + REFERENCES `{$wpdb->prefix}giglogadmin_venues` (`id`) ON DELETE NO ACTION + ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"; + + foreach ( $tables as $tabledef ) { + // This use of the `query` nethod is safe + // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared + $result = $wpdb->query( $tabledef ); + + if ( $result === false ) { + error_log( 'Registering table failed.' ); + } + } + } +} 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