From f499d9e657fe79e4413eec9e20ae13d616fac6f5 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Thu, 19 Jan 2023 20:17:55 +0100 Subject: Rename and restructure source files to conform to common namin schemes. - Source files containing a class should only contain _one_ class. - Source files containing a class should be names class-[name of the class].php - Use dashes instead of underscores in file names. - Fix source file comments - Some nitpicking... --- giglogadmin.php | 133 +------ includes/admin/views/giglog_admin_page.php | 2 +- includes/admin/views/giglog_import_gigs.php | 4 +- includes/class-giglogadmin-concert.php | 428 ++++++++++++++++++++ ...class-giglogadmin-duplicateconcertexception.php | 8 + includes/class-giglogadmin-icalexport.php | 95 +++++ includes/class-giglogadmin-plugin.php | 142 +++++++ includes/class-giglogadmin-venue.php | 176 +++++++++ includes/concert.php | 434 --------------------- includes/giglog_visitor_display.php | 13 - includes/giglogadmin-shortcodes.php | 30 ++ includes/ical_export.php | 86 ---- includes/venue.php | 167 -------- tests/VenueTest.php | 2 +- 14 files changed, 885 insertions(+), 835 deletions(-) create mode 100644 includes/class-giglogadmin-concert.php create mode 100644 includes/class-giglogadmin-duplicateconcertexception.php create mode 100644 includes/class-giglogadmin-icalexport.php create mode 100644 includes/class-giglogadmin-plugin.php create mode 100644 includes/class-giglogadmin-venue.php delete mode 100644 includes/concert.php delete mode 100644 includes/giglog_visitor_display.php create mode 100644 includes/giglogadmin-shortcodes.php delete mode 100644 includes/ical_export.php delete mode 100644 includes/venue.php diff --git a/giglogadmin.php b/giglogadmin.php index 2bb751c..2a1cf18 100644 --- a/giglogadmin.php +++ b/giglogadmin.php @@ -24,134 +24,5 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -if ( ! class_exists( 'GiglogAdmin_Plugin' ) ) { - - class GiglogAdmin_Plugin - { - static public function init(): void { - if ( !defined('GIGLOGADMIN_UNIT_TEST') ) { - require_once __DIR__ . '/includes/admin/register_db_tables.php'; - } - - require_once __DIR__ . '/vendor/autoload.php'; - require_once __DIR__ . '/includes/venue.php'; - require_once __DIR__ . '/includes/concert.php'; - require_once __DIR__ . '/includes/view-helpers/select_field.php'; - require_once __DIR__ . '/includes/ical_export.php'; - - if (is_admin()) { - require_once __DIR__ . '/includes/admin/views/giglog_admin_page.php'; - require_once __DIR__ . '/includes/admin/views/giglog_import_gigs.php'; - require_once __DIR__ . '/includes/admin/helpfiles/instrunctions.php'; - require_once __DIR__ . '/includes/admin/helpfiles/instr_reviewers.php'; - require_once __DIR__ . '/includes/admin/helpfiles/instr_photog.php'; - - add_action( 'admin_menu', array( 'GiglogAdmin_Plugin', 'add_admin_pages' )); - add_action( 'admin_menu', array( 'GiglogAdmin_Plugin', 'add_help_pages' )); - - add_filter( 'wp_nav_menu_args', array( 'GiglogAdmin_Plugin', 'nav_menu_args' )); - } - else { - require_once __DIR__ . '/includes/admin/views/_concerts_table.php'; - require_once __DIR__ . '/includes/giglog_visitor_display.php'; - } - } - - static function activate(): void { - } - - static function deactivate(): void { - } - - /** - * Adds the 'Giglog' top level menu to the left side WordPress admin - * menu. Other subpages will come later. - * - * @return void - */ - static function add_admin_pages(): void { - if ( ! current_user_can( 'manage_options' ) ) { - return; - } - $top = add_menu_page( - "Giglog admin", // Page title - "Giglog", // Menu title - "upload_files", // Will show for users with this capability - "giglog", // menu slug - array( 'GiglogAdmin_AdminPage', 'render_html' ), // callable - 'dashicons-tickets-alt', // Icon url - 11); // Position, just below 'Media' - - add_action( 'load-' . $top, array( 'GiglogAdmin_AdminPage', 'update' ) ); - - $import_hook = add_submenu_page( - "giglog", // parent slug - "Import gigs", // page title - "Import gigs", // menu title - "upload_files", // required capability - "giglog_import", // menu slug - array( 'GiglogAdmin_ImportGigsPage', 'render_html' )); // callable - - if ($import_hook !== false) { - add_action( - 'load-' . $import_hook, - array( 'GiglogAdmin_ImportGigsPage', 'submit_form' ) ); - } - - wp_register_style( 'css_style', plugins_url( '/includes/css/main.css', __FILE__ ) ); - wp_enqueue_style('css_style'); - } - - static function add_help_pages(): void { - if ( ! current_user_can( 'manage_options' ) ) { - return; - } - add_menu_page( - "Help for ET users", // Page title - "Help for ET users", // Menu title - "upload_files", // Will show for users with this capability - "helpfiles", // menu slug - array( 'Instructions_Page', 'render_instr_html' ), // callable - 'dashicons-tickets-alt', // Icon url - 10); // Position, just below 'Media' - - add_submenu_page( - "helpfiles", // parent slug - "Reviewer help files", // page title - "Reviewer help files", // menu title - "upload_files", // required capability - "reviewer_help", // menu slug - array( 'Instructions_Reviewers', 'render_instr_rev_html' )); // callable - - add_submenu_page( - "helpfiles", // parent slug - "Photogalleries help files", // page title - "Photogalleries help files", // menu title - "upload_files", // required capability - "photog_help", // menu slug - array( 'Instructions_Photogs', 'render_instr_photo_html' )); // callable - } - - /* - * Show menus based on whether user is logged in or not. - * - * Giglog admin pages should only be visible for logged in users/can eventually - * be customized by role if needed - */ - static function nav_menu_args( array $args = [] ) : array { - if ( is_user_logged_in() ) { - $args['menu'] = 'Loggedusers'; - } else { - $args['menu'] = 'Notloggedusers'; - } - - return $args; - } - - } - - register_activation_hook( __FILE__, array( 'GiglogAdmin_Plugin', 'activate' )); - register_deactivation_hook( __FILE__, array( 'GiglogAdmin_Plugin', 'deactivate' )); - - GiglogAdmin_Plugin::init(); -} +require_once __DIR__ . '/vendor/autoload.php'; +require_once __DIR__ . '/includes/class-giglogadmin-plugin.php'; diff --git a/includes/admin/views/giglog_admin_page.php b/includes/admin/views/giglog_admin_page.php index f3eaa87..acd0172 100644 --- a/includes/admin/views/giglog_admin_page.php +++ b/includes/admin/views/giglog_admin_page.php @@ -6,7 +6,7 @@ // SPDX-License-Identifier: AGPL-3.0-or-later if ( ! class_exists( 'GiglogAdmin_AdminPage' ) ) { - require_once __DIR__ . '/../../venue.php'; + 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'; diff --git a/includes/admin/views/giglog_import_gigs.php b/includes/admin/views/giglog_import_gigs.php index 505e4bd..758981e 100644 --- a/includes/admin/views/giglog_import_gigs.php +++ b/includes/admin/views/giglog_import_gigs.php @@ -6,8 +6,8 @@ // SPDX-License-Identifier: AGPL-3.0-or-later if ( ! class_exists( 'GiglogAdmin_ImportGigsPage' ) ) { - require_once __DIR__ . '/../../concert.php'; - require_once __DIR__ . '/../../venue.php'; + require_once __DIR__ . '/../../class-giglogadmin-concert.php'; + require_once __DIR__ . '/../../class-giglogadmin-venue.php'; class GiglogAdmin_ImportGigsPage { static function render_html(): void { diff --git a/includes/class-giglogadmin-concert.php b/includes/class-giglogadmin-concert.php new file mode 100644 index 0000000..6c7c4da --- /dev/null +++ b/includes/class-giglogadmin-concert.php @@ -0,0 +1,428 @@ + + * SPDX-FileCopyrightText: 2021 Harald Eilertsen + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +if ( ! class_exists( 'GiglogAdmin_Concert' ) ) { + + /** + * Class to hold all information about a given concert. + */ + class GiglogAdmin_Concert { + + // phpcs:disable Squiz.Commenting.VariableComment.Missing + private ?int $id; + private ?string $cname; + private ?GiglogAdmin_Venue $venue; + private ?string $cdate; + private ?string $tickets; + private ?string $eventlink; + private ?int $status; + private array $roles; + private ?DateTimeImmutable $created; + private ?DateTimeImmutable $updated; + // phpcs:enable + + public const STATUS_NONE = 0; + public const STATUS_ACCRED_REQ = 1; + public const STATUS_PHOTO_APPROVED = 2; + public const STATUS_TEXT_APPROVED = 3; + public const STATUS_ALL_APPROVED = 4; + public const STATUS_REJECTED = 5; + + + /** + * Constructs a new concert object from an array of attributes. + * + * The attributes are expected to be named as in the database, + * so this constructor can be used to construct the object + * directly from the database row. + * + * @param object $attrs an object or array with the attributes. + */ + public function __construct( object $attrs ) { + $this->id = isset( $attrs->id ) ? $attrs->id : null; + $this->cname = isset( $attrs->wpgconcert_name ) ? $attrs->wpgconcert_name : null; + $this->cdate = isset( $attrs->wpgconcert_date ) ? $attrs->wpgconcert_date : null; + $this->tickets = isset( $attrs->wpgconcert_tickets ) ? $attrs->wpgconcert_tickets : null; + $this->eventlink = isset( $attrs->wpgconcert_event ) ? $attrs->wpgconcert_event : null; + $this->status = isset( $attrs->wpgconcert_status ) ? $attrs->wpgconcert_status : 0; + $this->roles = isset( $attrs->wpgconcert_roles ) ? json_decode( $attrs->wpgconcert_roles, true ) : array(); + $this->created = isset( $attrs->created ) ? new DateTimeImmutable( $attrs->created ) : null; + $this->updated = isset( $attrs->updated ) ? new DateTimeImmutable( $attrs->updated ) : null; + + if ( isset( $attrs->venue ) ) { + if ( isset( $attrs->wpgvenue_name ) && isset( $attrs->wpgvenue_city ) ) { + $venue_attrs = (object) array( + 'id' => $attrs->venue, + 'wpgvenue_name' => $attrs->wpgvenue_name, + 'wpgvenue_city' => $attrs->wpgvenue_city, + ); + + $this->venue = new GiglogAdmin_Venue( $venue_attrs ); + } else { + $this->venue = GiglogAdmin_Venue::get( $attrs->venue ); + } + } else { + $this->venue = null; + } + } + + /** + * Return the concert with the given id. + * + * @param int $id Database id of the concert to fetch. + * @return null|self + */ + public static function get( int $id ) : ?self { + return self::find_concerts( array( 'id' => $id ) )[0]; + } + + /** + * Create a new concert object. + * + * @param string $name The concert description. + * @param int $venue_id The id of the venue where the concert will be held. + * @param string $date The date of the concert. + * @param string $ticketlink URL where tickets can be bough. + * @param string $eventlink URL for more information about concert. + * + * @throws GiglogAdmin_DuplicateConcertException If concert is a duplicate. + */ + public static function create( string $name, int $venue_id, string $date, string $ticketlink, string $eventlink ): ?self { + $gigs = self::find_concerts( + array( + 'name' => $name, + 'venue_id' => $venue_id, + 'date' => $date, + ) + ); + + if ( ! empty( $gigs ) ) { + throw new GiglogAdmin_DuplicateConcertException( + "Duplicate concert: name: {$name}, venue_id: {$venue_id}, date: {$date}" + ); + } else { + $concert = new GiglogAdmin_Concert( + (object) array( + 'wpgconcert_name' => $name, + 'venue' => $venue_id, + 'wpgconcert_date' => $date, + 'wpgconcert_tickets' => $ticketlink, + 'wpgconcert_event' => $eventlink, + ) + ); + + $concert->save(); + + return self::get( $concert->id() ); + } + } + + + /** + * Update a concert with new content and save to database. + * + * @param object $attrs Object or array of changed attributes. + */ + public function update( object $attrs ) : bool { + $need_update = false; + + if ( isset( $attrs->wpgconcert_name ) && $attrs->wpgconcert_name != $this->cname ) { + $this->cname = $attrs->wpgconcert_name; + $need_update = true; + } + + if ( isset( $attrs->wpgconcert_date ) && $attrs->wpgconcert_date != $this->cdate ) { + $this->cdate = $attrs->wpgconcert_date; + $need_update = true; + } + + if ( isset( $attrs->wpgconcert_tickets ) && $attrs->wpgconcert_tickets != $this->tickets ) { + $this->tickets = $attrs->wpgconcert_tickets; + $need_update = true; + } + + if ( isset( $attrs->wpgconcert_event ) && $attrs->wpgconcert_event != $this->eventlink ) { + $this->eventlink = $attrs->wpgconcert_eventlink; + $need_update = true; + } + + if ( isset( $attrs->wpgconcert_status ) && $attrs->wpgconcert_status != $this->status ) { + $this->status = $attrs->wpgconcert_status; + $need_update = true; + } + + if ( isset( $attrs->wpgconcert_roles ) && $attrs->wpgconcert_roles != $this->roles ) { + $this->roles = $attrs->wpgconcert_roles; + $need_update = true; + } + + if ( isset( $attrs->venue ) && $attrs->venue != $this->venue()->id() ) { + $this->venue = GiglogAdmin_Venue::get( $attrs->venue ); + $need_update = true; + } + + if ( $need_update ) { + $this->save(); + } + + return $need_update; + } + + /** + * Build a query with given filters. + * + * @param array $filter Filters to include in the query. + * @param bool $count Only return count of result if true. + */ + private static function _build_query( array $filter = array(), bool $count = false ) : string { + global $wpdb; + + $ct = "{$wpdb->prefix}giglogadmin_concerts"; + $vt = "{$wpdb->prefix}giglogadmin_venues"; + + if ( $count ) { + $query = "SELECT count({$ct}.id) "; + } else { + $query = "SELECT {$ct}.*, {$vt}.wpgvenue_name, {$vt}.wpgvenue_city "; + } + + $query .= "FROM {$ct} LEFT JOIN {$vt} ON {$ct}.venue = {$vt}.id WHERE wpgconcert_date >= CURRENT_TIMESTAMP"; + + $keymap = array( + 'id' => $wpdb->prefix . 'giglogadmin_concerts.id', + 'name' => 'wpgconcert_name', + 'date' => 'wpgconcert_date', + 'month' => 'MONTH(wpgconcert_date)', + 'venue_id' => $wpdb->prefix . 'giglogadmin_venues.id', + 'venue' => $wpdb->prefix . 'giglogadmin_venues.wpgvenue_name', + 'city' => $wpdb->prefix . 'giglogadmin_venues.wpgvenue_city', + 'currentuser' => 'wpgconcert_roles', + ); + + $where = array(); + $lmt = array(); + foreach ( $filter as $key => $value ) { + switch ( $key ) { + case 'name': + case 'date': + case 'month': + case 'venue': + case 'city': + array_push( $where, $keymap[ $key ] . $wpdb->prepare( '=%s', $value ) ); + break; + + case 'id': + case 'venue_id': + array_push( $where, $keymap[ $key ] . $wpdb->prepare( '=%d', $value ) ); + break; + + case 'currentuser': + array_push( $where, $keymap[ $key ] . $wpdb->prepare( ' like %s', esc_like( $value ) ) ); + break; + + case 'offset': + array_push( $lmt, $value ); + break; + + case 'recperpage': + array_push( $lmt, $value ); + break; + } + } + + if ( ! empty( $where ) ) { + $query .= ' AND ' . implode( ' and ', $where ); + } + + $query .= ' ORDER BY wpgconcert_date'; + + if ( ! empty( $lmt ) ) { + $query .= ' LIMIT ' . implode( ', ', $lmt ); + } + + return $query; + } + + /** + * Return an array of concert objects optionally limited by a specified + * filter. + * + * Valid filters are: + * - 'venue_id' => int : only include concerts at the given venue + * - 'city' => string : only include concerts in the given city + * + * @param array $filter Filter to use for the query. + * @return array + */ + public static function find_concerts( array $filter = array() ) : array { + global $wpdb; + + $query = self::_build_query( $filter, false ); + + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + $results = $wpdb->get_results( $query ); + + return array_map( + function( $c ) { + return new GiglogAdmin_Concert( $c ); + }, + $results + ); + } + + /** + * Return the number of objects matching the given filter. + * + * @param array $filter The filter to use for the query. + * @return int + */ + public static function count( array $filter = array() ) : int { + global $wpdb; + + $query = self::_build_query( $filter, true ); + + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + $count = $wpdb->get_var( $query ); + + return $count ? $count : 0; + } + + /** + * Save concert to database. + */ + public function save() : void { + global $wpdb; + + $columns = array( + 'wpgconcert_name' => $this->cname, + 'venue' => $this->venue->id(), + 'wpgconcert_date' => $this->cdate, + 'wpgconcert_tickets' => $this->tickets, + 'wpgconcert_event' => $this->eventlink, + 'wpgconcert_status' => $this->status, + 'wpgconcert_roles' => wp_json_encode( $this->roles ), + ); + + if ( null !== $this->id ) { + $res = $wpdb->update( $wpdb->prefix . 'giglogadmin_concerts', $columns, array( 'id' => $this->id ) ); + } else { + $res = $wpdb->insert( $wpdb->prefix . 'giglogadmin_concerts', $columns ); + } + + if ( false === $res ) { + $wpdb->print_error( __METHOD__ ); + } elseif ( null === $this->id ) { + $this->id = $wpdb->insert_id; + } + } + + /** + * Return database id for concert. + */ + public function id() : int { + return $this->id ? $this->id : 0; + } + + /** + * Return the concert "name". + */ + public function cname() : string { + return $this->cname ? $this->cname : ''; + } + + /** + * Return the concert venue. + */ + public function venue() { + return $this->venue; + } + + /** + * Return the date of the concert. + */ + public function cdate() { + return $this->cdate ? $this->cdate : ''; + } + + /** + * Return the ticket url for the concert. + */ + public function tickets() { + return $this->tickets ? $this->tickets : ''; + } + + /** + * Return the event link for the concert. + */ + public function eventlink() { + return $this->eventlink ? $this->eventlink : ''; + } + + /** + * Return the status of the concert. + */ + public function status() : int { + return $this->status; + } + + /** + * Set the status of the concert. + * + * @param int $new_status The new status for the concert. + */ + public function set_status( int $new_status ) { + $this->status = $new_status; + } + + /** + * Return the roles defined for this concert. + * + * @return array + */ + public function roles() : array { + return $this->roles ? $this->roles : array(); + } + + /** + * Assign a role for the concert to the given user. + * + * @param string $role The role to assign. + * @param string $username The user to assign the role to. + */ + public function assign_role( string $role, string $username ) : void { + $this->roles[ $role ] = $username; + } + + /** + * Unassign any roles for this concert for the given user. + * + * @param string $username The user to remove from the roles. + */ + public function remove_user_from_roles( string $username ) : void { + $this->roles = array_filter( $this->roles, fn( $u) => $u != $username ); + } + + /** + * Return creation time of the concert object. + */ + public function created() : DateTimeImmutable { + return $this->created; + } + + /** + * Return time of last update to this concert object. + */ + public function updated() : DateTimeImmutable { + return $this->updated; + } + } +} diff --git a/includes/class-giglogadmin-duplicateconcertexception.php b/includes/class-giglogadmin-duplicateconcertexception.php new file mode 100644 index 0000000..3d39f47 --- /dev/null +++ b/includes/class-giglogadmin-duplicateconcertexception.php @@ -0,0 +1,8 @@ + + * SPDX-FileCopyrightText: 2022 Harald Eilertsen + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +use Kigkonsult\Icalcreator\Vcalendar; + +if ( ! class_exists( 'GiglogAdmin_IcalExport' ) ) { + /** + * Class to handle ICAL export of concert data. + */ + class Giglogadmin_IcalExport { + + static function textclean( string $txt ) : string { + $cleantext = preg_replace( '/[^A-Za-z0-9 ]/', '', $txt ); + $cleantext = str_replace( ' ', '_', $cleantext ); + return( $cleantext ); + } + + public static function export_ical() { + $evid = $_GET['evid']; + + $concert = GiglogAdmin_Concert::get( $evid ); + $cfullname = $concert->cname() . ' live at ' . $concert->venue()->name() . ', ' . $concert->venue()->city(); + $cshortname = substr( $cfullname, 0, 20 ); + $fdate = strtotime( $concert->cdate() ); + $newformat = date( 'Ymd', $fdate ); + $filename = 'Concert ' . $concert->venue()->name() . ' ' . $newformat . ' ' . substr( $concert->cname(), 0, 30 ); + $filename = self::textclean( $filename ); + // create a new calendar + $vcalendar = Vcalendar::factory( array( Vcalendar::UNIQUE_ID => 'kigkonsult.se' ) ) + // with calendaring info + ->setMethod( Vcalendar::PUBLISH ) + ->setXprop( + Vcalendar::X_WR_CALNAME, + 'Calendar Sample' + ) + ->setXprop( + Vcalendar::X_WR_CALDESC, + 'Concert ' . $cfullname . '' + ) + ->setXprop( + Vcalendar::X_WR_RELCALID, + '3E26604A-50F4-4449-8B3E-E4F4932D05B5' + ) + ->setXprop( + Vcalendar::X_WR_TIMEZONE, + 'Europe/Oslo' + ); + + // create a new event + $event1 = $vcalendar->newVevent() + ->setTransp( Vcalendar::OPAQUE ) + ->setClass( Vcalendar::P_BLIC ) + ->setSequence( 1 ) + // describe the event + ->setSummary( '' . $cfullname . '' ) + ->setDescription( '' . $cfullname . '' ) + ->setComment( '' . $cfullname . '' ) + // place the event + ->setLocation( '' . $concert->venue()->name() . ', ' . $concert->venue()->city() . '' ) + // set the time + ->setDtstart( + new DateTime( + $newformat . 'T190000', + new DateTimezone( 'Europe/Oslo' ) + ) + ) + ->setDuration( 'PT4H' ); + $vcalendarString = + // apply appropriate Vtimezone with Standard/DayLight components + $vcalendar->vtimezonePopulate() + // and create the (string) calendar + ->createCalendar(); + + header( 'Content-Type: text/calendar' ); + header( 'content-disposition: attachment;filename=' . $filename . '.ics' ); + echo $vcalendarString; + die(); + } + } + + /** @psalm-suppress HookNotFound */ + add_action( 'wp_ajax_nopriv_giglog_export_ical', array( 'GiglogAdmin_IcalExport', 'export_ical' ) ); + + /** @psalm-suppress HookNotFound */ + add_action( 'wp_ajax_giglog_export_ical', array( 'GiglogAdmin_IcalExport', 'export_ical' ) ); +} diff --git a/includes/class-giglogadmin-plugin.php b/includes/class-giglogadmin-plugin.php new file mode 100644 index 0000000..a195ffa --- /dev/null +++ b/includes/class-giglogadmin-plugin.php @@ -0,0 +1,142 @@ + + * SPDX-FileCopyrightText: 2021 Harald Eilertsen + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +if ( ! class_exists( 'GiglogAdmin_Plugin' ) ) { + + class GiglogAdmin_Plugin + { + static public function init(): void { + if ( !defined('GIGLOGADMIN_UNIT_TEST') ) { + require_once __DIR__ . '/admin/register_db_tables.php'; + } + + 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'; + + 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/helpfiles/instrunctions.php'; + require_once __DIR__ . '/admin/helpfiles/instr_reviewers.php'; + require_once __DIR__ . '/admin/helpfiles/instr_photog.php'; + + add_action( 'admin_menu', array( 'GiglogAdmin_Plugin', 'add_admin_pages' )); + add_action( 'admin_menu', array( 'GiglogAdmin_Plugin', 'add_help_pages' )); + + add_filter( 'wp_nav_menu_args', array( 'GiglogAdmin_Plugin', 'nav_menu_args' )); + } + else { + require_once __DIR__ . '/admin/views/_concerts_table.php'; + require_once __DIR__ . '/giglogadmin-shortcodes.php'; + } + } + + static function activate(): void { + } + + static function deactivate(): void { + } + + /** + * Adds the 'Giglog' top level menu to the left side WordPress admin + * menu. Other subpages will come later. + * + * @return void + */ + static function add_admin_pages(): void { + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + $top = add_menu_page( + "Giglog admin", // Page title + "Giglog", // Menu title + "upload_files", // Will show for users with this capability + "giglog", // menu slug + array( 'GiglogAdmin_AdminPage', 'render_html' ), // callable + 'dashicons-tickets-alt', // Icon url + 11); // Position, just below 'Media' + + add_action( 'load-' . $top, array( 'GiglogAdmin_AdminPage', 'update' ) ); + + $import_hook = add_submenu_page( + "giglog", // parent slug + "Import gigs", // page title + "Import gigs", // menu title + "upload_files", // required capability + "giglog_import", // menu slug + array( 'GiglogAdmin_ImportGigsPage', 'render_html' )); // callable + + if ($import_hook !== false) { + add_action( + 'load-' . $import_hook, + array( 'GiglogAdmin_ImportGigsPage', 'submit_form' ) ); + } + + wp_register_style( 'css_style', plugins_url( '/includes/css/main.css', __FILE__ ) ); + wp_enqueue_style('css_style'); + } + + static function add_help_pages(): void { + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + add_menu_page( + "Help for ET users", // Page title + "Help for ET users", // Menu title + "upload_files", // Will show for users with this capability + "helpfiles", // menu slug + array( 'Instructions_Page', 'render_instr_html' ), // callable + 'dashicons-tickets-alt', // Icon url + 10); // Position, just below 'Media' + + add_submenu_page( + "helpfiles", // parent slug + "Reviewer help files", // page title + "Reviewer help files", // menu title + "upload_files", // required capability + "reviewer_help", // menu slug + array( 'Instructions_Reviewers', 'render_instr_rev_html' )); // callable + + add_submenu_page( + "helpfiles", // parent slug + "Photogalleries help files", // page title + "Photogalleries help files", // menu title + "upload_files", // required capability + "photog_help", // menu slug + array( 'Instructions_Photogs', 'render_instr_photo_html' )); // callable + } + + /* + * Show menus based on whether user is logged in or not. + * + * Giglog admin pages should only be visible for logged in users/can eventually + * be customized by role if needed + */ + static function nav_menu_args( array $args = [] ) : array { + if ( is_user_logged_in() ) { + $args['menu'] = 'Loggedusers'; + } else { + $args['menu'] = 'Notloggedusers'; + } + + return $args; + } + + } + + register_activation_hook( __FILE__, array( 'GiglogAdmin_Plugin', 'activate' )); + register_deactivation_hook( __FILE__, array( 'GiglogAdmin_Plugin', 'deactivate' )); + + GiglogAdmin_Plugin::init(); +} + diff --git a/includes/class-giglogadmin-venue.php b/includes/class-giglogadmin-venue.php new file mode 100644 index 0000000..ed148c2 --- /dev/null +++ b/includes/class-giglogadmin-venue.php @@ -0,0 +1,176 @@ + + * SPDX-FileCopyrightText: 2021 Harald Eilertsen + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +if ( ! class_exists( 'GiglogAdmin_Venue' ) ) { + /** + * Class representing venues. + */ + class GiglogAdmin_Venue { + + private ?int $id; + + /** + * @psalm-suppress PropertyNotSetInConstructor + */ + private string $name; + + /** + * @psalm-suppress PropertyNotSetInConstructor + */ + private string $city; + private ?string $address; + private ?string $webpage; + + /* + * Constructs a new venue object from an array of attributes. + * The attributes are expected to be named as in the database, + * so this constructor can be used to construct the object + * directly from the database row. + */ + public function __construct( object $attrs ) { + $this->id = isset( $attrs->id ) ? $attrs->id : null; + + if ( isset( $attrs->wpgvenue_name, $attrs->wpgvenue_city ) ) { + $this->name = $attrs->wpgvenue_name; + $this->city = $attrs->wpgvenue_city; + } else { + error_log( 'Trying to construct a Venue without a name or a city' ); + wp_die(); + } + + $this->address = isset( $attrs->wpgvenue_address ) ? $attrs->wpgvenue_address : null; + $this->webpage = isset( $attrs->wpgvenue_webpage ) ? $attrs->wpgvenue_webpage : null; + } + + /** + * Get venue by given id. + * + * @param int $id + * @return null|self + */ + static function get( int $id ) : ?self { + global $wpdb; + + $query = $wpdb->prepare( "SELECT * from {$wpdb->prefix}giglogadmin_venues WHERE id = %d", $id ); + $results = $wpdb->get_results( $query ); + + return $results ? new GiglogAdmin_Venue( $results[0] ) : null; + } + + static function create( string $name, string $city = 'Oslo' ): self { + $venue = new GiglogAdmin_Venue( + (object) array( + 'wpgvenue_name' => $name, + 'wpgvenue_city' => $city, + ) + ); + $venue->save(); + + return $venue; + } + + static function find_or_create( string $name, string $city = 'Oslo' ): self { + global $wpdb; + $venuesql = "SELECT * FROM {$wpdb->prefix}giglogadmin_venues " + . $wpdb->prepare( 'WHERE upper(wpgvenue_name)=upper(%s) and upper(wpgvenue_city)=upper(%s)', $name, $city ); + + $results = $wpdb->get_results( $venuesql ); + + if ( $results ) { + return new GiglogAdmin_Venue( $results[0] ); + } else { + return self::create( $name, $city ); + } + } + + static function all_cities(): array { + global $wpdb; + $results = $wpdb->get_results( + "select distinct wpgvenue_city from {$wpdb->prefix}giglogadmin_venues" + ); + + return array_map( + function ( $r ) { + return $r->wpgvenue_city; + }, + $results + ); + } + + /** + * @return self[] + * + * @psalm-return array + */ + static function all_venues(): array { + global $wpdb; + + $results = $wpdb->get_results( + "select * from {$wpdb->prefix}giglogadmin_venues ORDER BY wpgvenue_name" + ); + + return array_map( + function ( $r ) { + return new GiglogAdmin_Venue( $r ); + }, + $results + ); + } + + + /** + * @return self[] + * + * @psalm-return array + */ + static function venues_in_city( string $city ): array { + global $wpdb; + $q = $wpdb->prepare( "select * from {$wpdb->prefix}giglogadmin_venues where wpgvenue_city=%s", $city ) + . ' ORDER BY wpgvenue_name'; + $results = $wpdb->get_results( $q ); + + return array_map( + function ( $r ) { + return new GiglogAdmin_Venue( $r ); + }, + $results + ); + } + + public function save(): void { + global $wpdb; + + $wpdb->insert( + $wpdb->prefix . 'giglogadmin_venues', + array( + 'id' => '', + 'wpgvenue_name' => $this->name, + 'wpgvenue_city' => $this->city, + ) + ); + + $this->id = $wpdb->insert_id; + } + + public function id() : int { + return $this->id; + } + + public function name() : string { + return $this->name; + } + + public function city() : string { + return $this->city; + } + } +} diff --git a/includes/concert.php b/includes/concert.php deleted file mode 100644 index 2849dba..0000000 --- a/includes/concert.php +++ /dev/null @@ -1,434 +0,0 @@ - -// SPDX-FileCopyrightText: 2021 Harald Eilertsen -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -require_once __DIR__ . '/venue.php'; - -if ( ! class_exists( 'GiglogAdmin_DuplicateConcertException' ) ) { - // phpcs:ignore Squiz.Commenting.ClassComment.Missing - class GiglogAdmin_DuplicateConcertException extends Exception { - - } -} - -if ( ! class_exists( 'GiglogAdmin_Concert' ) ) { - require_once __DIR__ . '/venue.php'; - - /** - * Class to hold all information about a given concert. - */ - class GiglogAdmin_Concert { - - // phpcs:disable Squiz.Commenting.VariableComment.Missing - private ?int $id; - private ?string $cname; - private ?GiglogAdmin_Venue $venue; - private ?string $cdate; - private ?string $tickets; - private ?string $eventlink; - private ?int $status; - private array $roles; - private ?DateTimeImmutable $created; - private ?DateTimeImmutable $updated; - // phpcs:enable - - public const STATUS_NONE = 0; - public const STATUS_ACCRED_REQ = 1; - public const STATUS_PHOTO_APPROVED = 2; - public const STATUS_TEXT_APPROVED = 3; - public const STATUS_ALL_APPROVED = 4; - public const STATUS_REJECTED = 5; - - - /** - * Constructs a new concert object from an array of attributes. - * - * The attributes are expected to be named as in the database, - * so this constructor can be used to construct the object - * directly from the database row. - * - * @param object $attrs an object or array with the attributes. - */ - public function __construct( object $attrs ) { - $this->id = isset( $attrs->id ) ? $attrs->id : null; - $this->cname = isset( $attrs->wpgconcert_name ) ? $attrs->wpgconcert_name : null; - $this->cdate = isset( $attrs->wpgconcert_date ) ? $attrs->wpgconcert_date : null; - $this->tickets = isset( $attrs->wpgconcert_tickets ) ? $attrs->wpgconcert_tickets : null; - $this->eventlink = isset( $attrs->wpgconcert_event ) ? $attrs->wpgconcert_event : null; - $this->status = isset( $attrs->wpgconcert_status ) ? $attrs->wpgconcert_status : 0; - $this->roles = isset( $attrs->wpgconcert_roles ) ? json_decode( $attrs->wpgconcert_roles, true ) : array(); - $this->created = isset( $attrs->created ) ? new DateTimeImmutable( $attrs->created ) : null; - $this->updated = isset( $attrs->updated ) ? new DateTimeImmutable( $attrs->updated ) : null; - - if ( isset( $attrs->venue ) ) { - if ( isset( $attrs->wpgvenue_name ) && isset( $attrs->wpgvenue_city ) ) { - $venue_attrs = (object) array( - 'id' => $attrs->venue, - 'wpgvenue_name' => $attrs->wpgvenue_name, - 'wpgvenue_city' => $attrs->wpgvenue_city, - ); - - $this->venue = new GiglogAdmin_Venue( $venue_attrs ); - } else { - $this->venue = GiglogAdmin_Venue::get( $attrs->venue ); - } - } else { - $this->venue = null; - } - } - - /** - * Return the concert with the given id. - * - * @param int $id Database id of the concert to fetch. - * @return null|self - */ - public static function get( int $id ) : ?self { - return self::find_concerts( array( 'id' => $id ) )[0]; - } - - /** - * Create a new concert object. - * - * @param string $name The concert description. - * @param int $venue_id The id of the venue where the concert will be held. - * @param string $date The date of the concert. - * @param string $ticketlink URL where tickets can be bough. - * @param string $eventlink URL for more information about concert. - * - * @throws GiglogAdmin_DuplicateConcertException If concert is a duplicate. - */ - public static function create( string $name, int $venue_id, string $date, string $ticketlink, string $eventlink ): ?self { - $gigs = self::find_concerts( - array( - 'name' => $name, - 'venue_id' => $venue_id, - 'date' => $date, - ) - ); - - if ( ! empty( $gigs ) ) { - throw new GiglogAdmin_DuplicateConcertException( - "Duplicate concert: name: {$name}, venue_id: {$venue_id}, date: {$date}" - ); - } else { - $concert = new GiglogAdmin_Concert( - (object) array( - 'wpgconcert_name' => $name, - 'venue' => $venue_id, - 'wpgconcert_date' => $date, - 'wpgconcert_tickets' => $ticketlink, - 'wpgconcert_event' => $eventlink, - ) - ); - - $concert->save(); - - return self::get( $concert->id() ); - } - } - - - /** - * Update a concert with new content and save to database. - * - * @param object $attrs Object or array of changed attributes. - */ - public function update( object $attrs ) : bool { - $need_update = false; - - if ( isset( $attrs->wpgconcert_name ) && $attrs->wpgconcert_name != $this->cname ) { - $this->cname = $attrs->wpgconcert_name; - $need_update = true; - } - - if ( isset( $attrs->wpgconcert_date ) && $attrs->wpgconcert_date != $this->cdate ) { - $this->cdate = $attrs->wpgconcert_date; - $need_update = true; - } - - if ( isset( $attrs->wpgconcert_tickets ) && $attrs->wpgconcert_tickets != $this->tickets ) { - $this->tickets = $attrs->wpgconcert_tickets; - $need_update = true; - } - - if ( isset( $attrs->wpgconcert_event ) && $attrs->wpgconcert_event != $this->eventlink ) { - $this->eventlink = $attrs->wpgconcert_eventlink; - $need_update = true; - } - - if ( isset( $attrs->wpgconcert_status ) && $attrs->wpgconcert_status != $this->status ) { - $this->status = $attrs->wpgconcert_status; - $need_update = true; - } - - if ( isset( $attrs->wpgconcert_roles ) && $attrs->wpgconcert_roles != $this->roles ) { - $this->roles = $attrs->wpgconcert_roles; - $need_update = true; - } - - if ( isset( $attrs->venue ) && $attrs->venue != $this->venue()->id() ) { - $this->venue = GiglogAdmin_Venue::get( $attrs->venue ); - $need_update = true; - } - - if ( $need_update ) { - $this->save(); - } - - return $need_update; - } - - /** - * Build a query with given filters. - * - * @param array $filter Filters to include in the query. - * @param bool $count Only return count of result if true. - */ - private static function _build_query( array $filter = array(), bool $count = false ) : string { - global $wpdb; - - $ct = "{$wpdb->prefix}giglogadmin_concerts"; - $vt = "{$wpdb->prefix}giglogadmin_venues"; - - if ( $count ) { - $query = "SELECT count({$ct}.id) "; - } else { - $query = "SELECT {$ct}.*, {$vt}.wpgvenue_name, {$vt}.wpgvenue_city "; - } - - $query .= "FROM {$ct} LEFT JOIN {$vt} ON {$ct}.venue = {$vt}.id WHERE wpgconcert_date >= CURRENT_TIMESTAMP"; - - $keymap = array( - 'id' => $wpdb->prefix . 'giglogadmin_concerts.id', - 'name' => 'wpgconcert_name', - 'date' => 'wpgconcert_date', - 'month' => 'MONTH(wpgconcert_date)', - 'venue_id' => $wpdb->prefix . 'giglogadmin_venues.id', - 'venue' => $wpdb->prefix . 'giglogadmin_venues.wpgvenue_name', - 'city' => $wpdb->prefix . 'giglogadmin_venues.wpgvenue_city', - 'currentuser' => 'wpgconcert_roles', - ); - - $where = array(); - $lmt = array(); - foreach ( $filter as $key => $value ) { - switch ( $key ) { - case 'name': - case 'date': - case 'month': - case 'venue': - case 'city': - array_push( $where, $keymap[ $key ] . $wpdb->prepare( '=%s', $value ) ); - break; - - case 'id': - case 'venue_id': - array_push( $where, $keymap[ $key ] . $wpdb->prepare( '=%d', $value ) ); - break; - - case 'currentuser': - array_push( $where, $keymap[ $key ] . $wpdb->prepare( ' like %s', esc_like( $value ) ) ); - break; - - case 'offset': - array_push( $lmt, $value ); - break; - - case 'recperpage': - array_push( $lmt, $value ); - break; - } - } - - if ( ! empty( $where ) ) { - $query .= ' AND ' . implode( ' and ', $where ); - } - - $query .= ' ORDER BY wpgconcert_date'; - - if ( ! empty( $lmt ) ) { - $query .= ' LIMIT ' . implode( ', ', $lmt ); - } - - return $query; - } - - /** - * Return an array of concert objects optionally limited by a specified - * filter. - * - * Valid filters are: - * - 'venue_id' => int : only include concerts at the given venue - * - 'city' => string : only include concerts in the given city - * - * @param array $filter Filter to use for the query. - * @return array - */ - public static function find_concerts( array $filter = array() ) : array { - global $wpdb; - - $query = self::_build_query( $filter, false ); - - // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared - $results = $wpdb->get_results( $query ); - - return array_map( - function( $c ) { - return new GiglogAdmin_Concert( $c ); - }, - $results - ); - } - - /** - * Return the number of objects matching the given filter. - * - * @param array $filter The filter to use for the query. - * @return int - */ - public static function count( array $filter = array() ) : int { - global $wpdb; - - $query = self::_build_query( $filter, true ); - - // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared - $count = $wpdb->get_var( $query ); - - return $count ? $count : 0; - } - - /** - * Save concert to database. - */ - public function save() : void { - global $wpdb; - - $columns = array( - 'wpgconcert_name' => $this->cname, - 'venue' => $this->venue->id(), - 'wpgconcert_date' => $this->cdate, - 'wpgconcert_tickets' => $this->tickets, - 'wpgconcert_event' => $this->eventlink, - 'wpgconcert_status' => $this->status, - 'wpgconcert_roles' => wp_json_encode( $this->roles ), - ); - - if ( null !== $this->id ) { - $res = $wpdb->update( $wpdb->prefix . 'giglogadmin_concerts', $columns, array( 'id' => $this->id ) ); - } else { - $res = $wpdb->insert( $wpdb->prefix . 'giglogadmin_concerts', $columns ); - } - - if ( false === $res ) { - $wpdb->print_error( __METHOD__ ); - } elseif ( null === $this->id ) { - $this->id = $wpdb->insert_id; - } - } - - /** - * Return database id for concert. - */ - public function id() : int { - return $this->id ? $this->id : 0; - } - - /** - * Return the concert "name". - */ - public function cname() : string { - return $this->cname ? $this->cname : ''; - } - - /** - * Return the concert venue. - */ - public function venue() { - return $this->venue; - } - - /** - * Return the date of the concert. - */ - public function cdate() { - return $this->cdate ? $this->cdate : ''; - } - - /** - * Return the ticket url for the concert. - */ - public function tickets() { - return $this->tickets ? $this->tickets : ''; - } - - /** - * Return the event link for the concert. - */ - public function eventlink() { - return $this->eventlink ? $this->eventlink : ''; - } - - /** - * Return the status of the concert. - */ - public function status() : int { - return $this->status; - } - - /** - * Set the status of the concert. - * - * @param int $new_status The new status for the concert. - */ - public function set_status( int $new_status ) { - $this->status = $new_status; - } - - /** - * Return the roles defined for this concert. - * - * @return array - */ - public function roles() : array { - return $this->roles ? $this->roles : array(); - } - - /** - * Assign a role for the concert to the given user. - * - * @param string $role The role to assign. - * @param string $username The user to assign the role to. - */ - public function assign_role( string $role, string $username ) : void { - $this->roles[ $role ] = $username; - } - - /** - * Unassign any roles for this concert for the given user. - * - * @param string $username The user to remove from the roles. - */ - public function remove_user_from_roles( string $username ) : void { - $this->roles = array_filter( $this->roles, fn( $u) => $u != $username ); - } - - /** - * Return creation time of the concert object. - */ - public function created() : DateTimeImmutable { - return $this->created; - } - - /** - * Return time of last update to this concert object. - */ - public function updated() : DateTimeImmutable { - return $this->updated; - } - } -} - diff --git a/includes/giglog_visitor_display.php b/includes/giglog_visitor_display.php deleted file mode 100644 index b803bec..0000000 --- a/includes/giglog_visitor_display.php +++ /dev/null @@ -1,13 +0,0 @@ - -// SPDX-FileCopyrightText: 2022 Harald Eilertsen -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -function display_giglog() : string { - $c = new GiglogAdmin_ConcertsTable(); - return $c->render(); -} - -add_shortcode( 'getconcerts', 'display_giglog' ); - diff --git a/includes/giglogadmin-shortcodes.php b/includes/giglogadmin-shortcodes.php new file mode 100644 index 0000000..5070a3e --- /dev/null +++ b/includes/giglogadmin-shortcodes.php @@ -0,0 +1,30 @@ + + * SPDX-FileCopyrightText: 2022 Harald Eilertsen + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +declare(strict_types=1); + +if ( ! function_exists( 'giglogadmin_shortcode_public' ) ) { + + /** + * Shortcode that displays the public concert list. + * + * Usage: `[getconcerts]` + * + * This shortcode does not have any attributes. + */ + function giglogadmin_shortcode_public() : string { + $c = new GiglogAdmin_ConcertsTable(); + return $c->render(); + } + + add_shortcode( 'getconcerts', 'giglogadmin_shortcode_public' ); +} diff --git a/includes/ical_export.php b/includes/ical_export.php deleted file mode 100644 index 627c83b..0000000 --- a/includes/ical_export.php +++ /dev/null @@ -1,86 +0,0 @@ - -// SPDX-FileCopyrightText: 2022 Harald Eilertsen -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -use Kigkonsult\Icalcreator\Vcalendar; - -if ( ! class_exists( 'GiglogAdmin_IcalExport' ) ) { - class Giglogadmin_IcalExport { - - static function textclean( string $txt ) : string { - $cleantext = preg_replace( '/[^A-Za-z0-9 ]/', '', $txt ); - $cleantext = str_replace( ' ', '_', $cleantext ); - return( $cleantext ); - } - public static function export_ical() { - $evid = $_GET['evid']; - - $concert = GiglogAdmin_Concert::get( $evid ); - $cfullname = $concert->cname() . ' live at ' . $concert->venue()->name() . ', ' . $concert->venue()->city(); - $cshortname = substr( $cfullname, 0, 20 ); - $fdate = strtotime( $concert->cdate() ); - $newformat = date( 'Ymd', $fdate ); - $filename = 'Concert ' . $concert->venue()->name() . ' ' . $newformat . ' ' . substr( $concert->cname(), 0, 30 ); - $filename = self::textclean( $filename ); - // create a new calendar - $vcalendar = Vcalendar::factory( array( Vcalendar::UNIQUE_ID => 'kigkonsult.se' ) ) - // with calendaring info - ->setMethod( Vcalendar::PUBLISH ) - ->setXprop( - Vcalendar::X_WR_CALNAME, - 'Calendar Sample' - ) - ->setXprop( - Vcalendar::X_WR_CALDESC, - 'Concert ' . $cfullname . '' - ) - ->setXprop( - Vcalendar::X_WR_RELCALID, - '3E26604A-50F4-4449-8B3E-E4F4932D05B5' - ) - ->setXprop( - Vcalendar::X_WR_TIMEZONE, - 'Europe/Oslo' - ); - - // create a new event - $event1 = $vcalendar->newVevent() - ->setTransp( Vcalendar::OPAQUE ) - ->setClass( Vcalendar::P_BLIC ) - ->setSequence( 1 ) - // describe the event - ->setSummary( '' . $cfullname . '' ) - ->setDescription( '' . $cfullname . '' ) - ->setComment( '' . $cfullname . '' ) - // place the event - ->setLocation( '' . $concert->venue()->name() . ', ' . $concert->venue()->city() . '' ) - // set the time - ->setDtstart( - new DateTime( - $newformat . 'T190000', - new DateTimezone( 'Europe/Oslo' ) - ) - ) - ->setDuration( 'PT4H' ); - $vcalendarString = - // apply appropriate Vtimezone with Standard/DayLight components - $vcalendar->vtimezonePopulate() - // and create the (string) calendar - ->createCalendar(); - - header( 'Content-Type: text/calendar' ); - header( 'content-disposition: attachment;filename=' . $filename . '.ics' ); - echo $vcalendarString; - die(); - } - } - - /** @psalm-suppress HookNotFound */ - add_action( 'wp_ajax_nopriv_giglog_export_ical', array( 'GiglogAdmin_IcalExport', 'export_ical' ) ); - - /** @psalm-suppress HookNotFound */ - add_action( 'wp_ajax_giglog_export_ical', array( 'GiglogAdmin_IcalExport', 'export_ical' ) ); -} diff --git a/includes/venue.php b/includes/venue.php deleted file mode 100644 index a436f91..0000000 --- a/includes/venue.php +++ /dev/null @@ -1,167 +0,0 @@ - -// SPDX-FileCopyrightText: 2021 Harald Eilertsen -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -if ( ! class_exists( 'GiglogAdmin_Venue' ) ) { - class GiglogAdmin_Venue { - - private ?int $id; - - /** - * @psalm-suppress PropertyNotSetInConstructor - */ - private string $name; - - /** - * @psalm-suppress PropertyNotSetInConstructor - */ - private string $city; - private ?string $address; - private ?string $webpage; - - /* - * Constructs a new venue object from an array of attributes. - * The attributes are expected to be named as in the database, - * so this constructor can be used to construct the object - * directly from the database row. - */ - public function __construct( object $attrs ) { - $this->id = isset( $attrs->id ) ? $attrs->id : null; - - if ( isset( $attrs->wpgvenue_name, $attrs->wpgvenue_city ) ) { - $this->name = $attrs->wpgvenue_name; - $this->city = $attrs->wpgvenue_city; - } else { - error_log( 'Trying to construct a Venue without a name or a city' ); - wp_die(); - } - - $this->address = isset( $attrs->wpgvenue_address ) ? $attrs->wpgvenue_address : null; - $this->webpage = isset( $attrs->wpgvenue_webpage ) ? $attrs->wpgvenue_webpage : null; - } - - /** - * Get venue by given id. - * - * @param int $id - * @return null|self - */ - static function get( int $id ) : ?self { - global $wpdb; - - $query = $wpdb->prepare( "SELECT * from {$wpdb->prefix}giglogadmin_venues WHERE id = %d", $id ); - $results = $wpdb->get_results( $query ); - - return $results ? new GiglogAdmin_Venue( $results[0] ) : null; - } - - static function create( string $name, string $city = 'Oslo' ): self { - $venue = new GiglogAdmin_Venue( - (object) array( - 'wpgvenue_name' => $name, - 'wpgvenue_city' => $city, - ) - ); - $venue->save(); - - return $venue; - } - - static function find_or_create( string $name, string $city = 'Oslo' ): self { - global $wpdb; - $venuesql = "SELECT * FROM {$wpdb->prefix}giglogadmin_venues " - . $wpdb->prepare( 'WHERE upper(wpgvenue_name)=upper(%s) and upper(wpgvenue_city)=upper(%s)', $name, $city ); - - $results = $wpdb->get_results( $venuesql ); - - if ( $results ) { - return new GiglogAdmin_Venue( $results[0] ); - } else { - return self::create( $name, $city ); - } - } - - static function all_cities(): array { - global $wpdb; - $results = $wpdb->get_results( - "select distinct wpgvenue_city from {$wpdb->prefix}giglogadmin_venues" - ); - - return array_map( - function ( $r ) { - return $r->wpgvenue_city; - }, - $results - ); - } - - /** - * @return self[] - * - * @psalm-return array - */ - static function all_venues(): array { - global $wpdb; - - $results = $wpdb->get_results( - "select * from {$wpdb->prefix}giglogadmin_venues ORDER BY wpgvenue_name" - ); - - return array_map( - function ( $r ) { - return new GiglogAdmin_Venue( $r ); - }, - $results - ); - } - - - /** - * @return self[] - * - * @psalm-return array - */ - static function venues_in_city( string $city ): array { - global $wpdb; - $q = $wpdb->prepare( "select * from {$wpdb->prefix}giglogadmin_venues where wpgvenue_city=%s", $city ) - . ' ORDER BY wpgvenue_name'; - $results = $wpdb->get_results( $q ); - - return array_map( - function ( $r ) { - return new GiglogAdmin_Venue( $r ); - }, - $results - ); - } - - public function save(): void { - global $wpdb; - - $wpdb->insert( - $wpdb->prefix . 'giglogadmin_venues', - array( - 'id' => '', - 'wpgvenue_name' => $this->name, - 'wpgvenue_city' => $this->city, - ) - ); - - $this->id = $wpdb->insert_id; - } - - public function id() : int { - return $this->id; - } - - public function name() : string { - return $this->name; - } - - public function city() : string { - return $this->city; - } - } -} diff --git a/tests/VenueTest.php b/tests/VenueTest.php index 1fde15e..44040db 100644 --- a/tests/VenueTest.php +++ b/tests/VenueTest.php @@ -6,7 +6,7 @@ declare(strict_types=1); -require __DIR__ . '/../includes/venue.php'; +require __DIR__ . '/../includes/class-giglogadmin-venue.php'; final class VenueTest extends WP_UnitTestCase { -- cgit v1.2.3