Making WordPress.org

Changeset 13529


Ignore:
Timestamp:
04/15/2024 01:37:55 PM (2 years ago)
Author:
amieiro
Message:

Translate: Sync "Translation Events" from GitHub

Location:
sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events
Files:
14 added
2 deleted
16 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/assets/css/translation-events.css

    r13299 r13529  
    44        vertical-align: top;
    55}
     6
    67.translation-event-form #event-title,
    78.translation-event-form #event-description {
    89        width: 30%;
    910}
     11
    1012.translation-event-form input[type="text"],
    1113.translation-event-form input[type="date"] {
    1214        width: 13%;
    1315}
     16
    1417.translation-event-form div {
    1518        margin-top: 1em;
    1619}
     20
    1721.translation-event-form #submit-event {
    1822        margin-left: 10%;
    … …  
    2125        display: block;
    2226}
    23 .event-page-title {
    24         border-bottom: #d9d8d8 thin solid;
    25         padding-bottom: .5em;
    26 }
     27
    2728.event-details-page {
    2829        border-bottom: #cfd4d4 thin solid;
    … …  
    3031        margin: 0 auto;
    3132}
     33
    3234.event-details-left {
    3335        width: 77%;
    … …  
    3739        padding-right: 1em;
    3840}
     41
    3942.event-details-right {
    4043        width: 22%;
    … …  
    4245        padding-top: 1em;
    4346}
     47
    4448.event-details-stats {
    4549        clear: both;
    46         margin: 1em;
     50        margin: 0;
     51}
     52
     53.event-details-stats table {
     54        margin: 1rem;
    4755}
    4856.event-details-stats table {
    … …  
    5058        table-layout: fixed;
    5159}
    52 .event-details-stats table th, .event-details-stats table td {
     60
     61.event-details-stats table th,
     62.event-details-stats table td {
    5363        padding: 1em;
    5464        text-align: center;
    5565}
     66
    5667.event-details-stats table td:first-child {
    5768        text-align: left;
    5869        word-break: break-all;
    5970}
     71
    6072.event-details-stats table tr {
    6173        border-bottom: thin solid #f0f0f0;
    6274}
     75
    6376.event-details-stats table th {
    6477        background-color: #e9e9e9;
    … …  
    6679        word-break: break-all;
    6780}
     81
    6882.event-details-stats-totals td {
    6983        font-weight: bold;
    7084}
    71 .event-contributors li {
     85
     86.event-contributors li, .event-attendees li {
    7287        display: inline-block;
    7388        list-style-type: none;
    … …  
    7691        width: 15em;
    7792}
    78 .event-contributors li .avatar {
     93
     94.event-contributors li .avatar, .event-attendees li .avatar {
    7995        border-radius: 50%;
    8096        vertical-align: middle;
    8197}
     98
     99.event-attendees h2 {
     100        margin-bottom: 0;
     101}
     102
     103span.event-creator, span.event-you {
     104        display: block;
     105        margin-left: 55px;
     106        margin-top: 1em;
     107        font-size: smaller;
     108}
    82109.hide-event-url {
    83110        display: none;
    84111}
     112
    85113.translation-event-form button.save-draft {
    86114        background: #fff;
    87115        color: var(--gp-color-btn-primary-bg);
    88116}
     117
    89118#event-url span {
    90119        width: 10%;
    91120        display: inline-block;
    92121}
     122
    93123span.event-list-date {
    94124        display: block;
    … …  
    97127        font-weight: normal;
    98128}
     129
    99130span.event-list-date.events-i-am-attending {
    100131        font-size: .8em;
    101132        font-weight: normal;
    102133}
    103 .event-list-item a{
     134
     135.event-list-item a {
    104136        font-weight: bold;
    105137        font-size: 1.2em;
    106138}
     139
    107140li.event-list-item {
    108141        list-style-type: none;
    109 }
     142        margin-bottom: .5em;
     143}
     144
    110145li.event-list-item p {
    111146        margin-top: 0;
    … …  
    113148        font-size: .95em;
    114149}
     150
    115151h2.event_page_title {
    116152        border-bottom: #e0e0e0 thin solid;
    … …  
    118154        font-weight: bold;
    119155}
     156
    120157.event-list-top-bar {
    121         display: block;
    122158        width: 80%;
    123159        margin: 0 auto;
    124         text-align: right;
    125 }
     160        display: grid;
     161        grid-template-columns: 1fr auto;
     162        align-items: center;
     163        border-bottom: #d9d8d8 thin solid;
     164        padding-bottom: .5em;
     165}
     166
    126167.event-list-nav li {
    127168        display: inline;
    128169        margin: 0 0.1rem;
    129170}
     171
    130172.event-list-nav li a {
    131173        text-decoration: none;
    132174        font-weight: bold;
    133175}
     176
    134177.event-list-nav li:not(:first-child):not(:last-child):before {
    135178        content: " | ";
    136179}
     180
    137181.event-left-col {
    138182        width: 75%;
    … …  
    140184        border-right: var(--gp-color-secondary-400) thin solid;
    141185}
     186
    142187.event-right-col {
    143188        width: 25%;
    … …  
    145190        padding-left: 1em;
    146191}
     192
    147193.event-attending-list {
    148194        list-style-type: none;
    149195        padding: 0;
    150196}
     197
    151198.event-attending-list li {
    152199        margin-bottom: 1em;
    153200}
     201
    154202.event-list-nav li a.button {
    155203        background-color: var(--gp-color-btn-primary-bg) !important;
    156204        color: #fff !important;
    157205}
     206
    158207a.event-link-draft {
    159         color:#80807f;
    160 }
    161 span.event-label-draft, span.event-details-join-expired, span.active-events-before-translation-table {
     208        color: #80807f;
     209}
     210
     211span.event-label-draft,
     212span.event-details-join-expired,
     213span.active-events-before-translation-table {
    162214        font-weight: 500;
    163         color: var( --gp-color-bubble-inactive-project-text );
    164         border: 1px solid var( --gp-color-bubble-inactive-project-text );
     215        color: var(--gp-color-bubble-inactive-project-text);
     216        border: 1px solid var(--gp-color-bubble-inactive-project-text);
    165217        font-size: .7em;
    166218        margin-right: 0.3em;
    … …  
    171223        text-transform: capitalize;
    172224}
     225
    173226span.active-events-before-translation-table a {
    174         color: var( --gp-color-bubble-inactive-project-text );
    175         text-decoration: none;
    176 }
     227        color: var(--gp-color-bubble-inactive-project-text);
     228        text-decoration: none;
     229}
     230
    177231.active-events-before-translation-table {
    178232        width: 100%;
    179         border: 1px solid var( --gp-color-border-default );
    180         background: var( --gp-color-status-waiting-subtle );
     233        border: 1px solid var(--gp-color-border-default);
     234        background: var(--gp-color-status-waiting-subtle);
    181235        margin: 1rem 0;
    182236        padding: 0.3rem 0.8rem;
    183237}
     238
    184239.event-page-wrapper {
    185240        margin: 0 auto;
    186241        width: 80%;
    187242}
     243
    188244.event-list {
    189245        margin: 0;
    190246        padding: 0;
    191247}
    192 .event-details-head {
    193         border-bottom: var(--gp-color-secondary-400) thin solid;
    194 }
     248
     249input[type="submit"].remove-as-host, input[type="submit"].convert-to-host {
     250        text-align: center;
     251        display: inline;
     252        margin-top: 1em;
     253        font-weight: bold;
     254}
     255
    195256input[type="submit"].attend-btn {
    196257        width: 100%;
    … …  
    200261        font-weight: bold;
    201262}
    202 input[type="submit"].attending-btn, a.button.is-primary.attend-btn {
     263
     264input[type="submit"].attending-btn,
     265a.button.is-primary.attend-btn {
    203266        width: 100%;
    204267        text-align: center;
    … …  
    206269        margin-top: 1em;
    207270}
     271
    208272.event-details-date {
    209273        background: #f4f4f4;
    210274        color: #606161;
    211         padding: .5em;
     275        padding: 0.1em .5em;
    212276        font-size: .9em;
    213277        line-height: 1.8em;
    214278        font-weight: 500;
    215 }
     279        margin-bottom: 1em;
     280}
     281
    216282.event-page-edit-link {
    217283        float: right;
    218284        text-decoration: none;
    219 }
     285        justify-self: end;
     286        grid-column: 2;
     287}
     288
    220289.event-stats-summary {
    221290        margin-top: 1em;
    222291}
     292
    223293.event-stats-summary summary {
    224294        background: #f8f8f8;
    … …  
    229299        font-size: .9em;
    230300}
     301
    231302.event-stats-summary p.event-stats-text {
    232303        margin: 0;
    … …  
    236307        border-top: thin solid #e0e0e0;
    237308}
    238 time.event-utc-time {
    239         display: block;
     309
     310.event-details-date time {
    240311        font-size: .95em;
    241 }
    242 .event-utc-time:first-of-type{
     312        font-weight: normal;
     313}
     314
     315.event-details-date time:last-child {
     316        margin-bottom: 0;
     317}
     318
     319.event-details-date time.full-time {
     320        display: block;
    243321        border-bottom: #cdcdcd thin solid;
    244322        padding-bottom: 0.5em;
    245323        margin-bottom: 0.5em;
    246324}
     325
    247326span.event-details-date-label {
    248327        font-weight: bold;
    249328        color: #5a5a5a;
    250329        display: block;
     330}
     331
     332.event-host {
     333        display: flex;
     334        grid-column: 1;
     335}
     336
     337p.event-sub-head {
     338        grid-column: 1 / -1;
     339        margin-top: 0;
     340}
     341
     342a.event-page-edit-link {
     343        font-size: .9em;
     344        text-decoration: none;
     345}
     346
     347a.event-page-edit-link:hover {
     348        border-bottom: var(--gp-color-btn-primary-bg) thin solid;
     349        text-decoration: none;
     350}
     351ul.text-snippets {
     352        padding: 0;
     353        margin-left: 160px;
     354}
     355.first-time-contributor-tada::after {
     356        content: ' 🎉';
    251357}
    252358
    253359/* show the event-details-right below instead of on the right on mobile */
    254360@media (max-width: 768px) {
    255         .event-page-wrapper, .event-details-right, .event-details-left {
     361
     362        .event-page-wrapper,
     363        .event-details-right,
     364        .event-details-left {
    256365                width: 100%;
    257366                float: none;
    258367        }
     368
    259369        .event-details-left {
    260370                border-right: none;
    … …  
    262372                padding: 0;
    263373        }
    264 
    265         .event-details-stats {
    266                 margin: 0;
    267         }
    268 }
     374}
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/assets/js/translation-events.js

    r13268 r13529  
    1010                                validateEventDates();
    1111                                convertToUserLocalTime();
     12                                setInterval( convertToUserLocalTime, 10000 );
    1213
    1314                                $( '.submit-event' ).on(
    … …  
    2829                                        }
    2930                                );
     31
     32                                $( '.text-snippet' ).on(
     33                                        'click',
     34                                        function ( e ) {
     35                                                e.preventDefault();
     36                                                var textArea        = $( this ).closest( 'div' ).find( 'textarea' );
     37                                                var textAreaContent = textArea.val();
     38                                                textArea.val( textAreaContent + $( this ).data( 'snippet' ) );
     39                                        }
     40                                );
    3041                        }
    3142                );
    … …  
    3849                 */
    3950                function handleSubmit( eventStatus, isDraft ) {
     51                        const $form = $( '.translation-event-form' );
     52                        if ( ! $form[0].reportValidity() ) {
     53                                return;
     54                        }
     55
     56                        if ( '' === $( '#event-title' ).val() ) {
     57                                $gp.notices.error( 'Event title must be set.' );
     58                                return;
     59                        }
    4060                        if ( '' === $( '#event-start' ).val() ) {
    4161                                $gp.notices.error( 'Event start date and time must be set.' );
    … …  
    5777                        }
    5878                        $( '#event-form-action' ).val( eventStatus );
    59                         const $form        = $( '.translation-event-form' );
    6079                        const $is_creation = $( '#form-name' ).val() === 'create_event';
    6180
    … …  
    149168                        timeElements.forEach(
    150169                                function ( timeEl ) {
    151                                         const eventDateObj         = new Date( timeEl.getAttribute( 'datetime' ) );
     170                                        const datetime = timeEl.getAttribute( 'datetime' );
     171                                        if ( ! datetime ) {
     172                                                return;
     173                                        }
     174                                        const eventDateObj = new Date( datetime );
     175                                        timeEl.title       = eventDateObj.toUTCString();
     176
    152177                                        const userTimezoneOffset   = new Date().getTimezoneOffset();
    153178                                        const userTimezoneOffsetMs = userTimezoneOffset * 60 * 1000;
    154179                                        const userLocalDateTime    = new Date( eventDateObj.getTime() - userTimezoneOffsetMs );
    155180
    156                                         const options      = {
     181                                        if ( timeEl.classList.contains( 'relative' ) ) {
     182                                                // Display the relative time.
     183                                                const now    = new Date();
     184                                                let diff     = userLocalDateTime - now;
     185                                                let in_text  = 'in ';
     186                                                let ago_text = '';
     187                                                if ( diff < 0 ) {
     188                                                        if ( timeEl.classList.contains( 'future' ) ) {
     189                                                                // If an event transitions from future to past, reload the page to move it from active to past events and vice versa.
     190                                                                location.reload();
     191                                                        }
     192                                                        in_text  = '';
     193                                                        ago_text = ' ago';
     194                                                        diff     = - diff;
     195                                                }
     196
     197                                                const seconds    = Math.floor( diff / 1000 );
     198                                                const minutes    = Math.floor( seconds / 60 );
     199                                                const hours      = Math.floor( minutes / 60 );
     200                                                const days       = Math.floor( hours / 24 );
     201                                                const weeks      = Math.floor( days / 7 );
     202                                                const months     = Math.floor( days / 30 );
     203                                                const years      = Math.floor( days / 365.25 );
     204                                                let relativeTime = '';
     205                                                if ( years > 1 ) {
     206                                                        if ( ! timeEl.classList.contains( 'hide-if-too-far' ) ) {
     207                                                                relativeTime = years + ' year' + ( years > 1 ? 's' : '' );
     208                                                        } else {
     209                                                                in_text = '';
     210                                                        }
     211                                                } else if ( months > 1 ) {
     212                                                        if ( ! timeEl.classList.contains( 'hide-if-too-far' ) ) {
     213                                                                relativeTime = months + ' month' + ( months > 1 ? 's' : '' );
     214                                                        } else {
     215                                                                in_text = '';
     216                                                        }
     217                                                } else if ( weeks > 1 ) {
     218                                                        if ( ! timeEl.classList.contains( 'hide-if-too-far' ) || weeks < 3 ) {
     219                                                                relativeTime = weeks + ' week' + ( weeks > 1 ? 's' : '' );
     220                                                        } else {
     221                                                                in_text = '';
     222                                                        }
     223                                                } else if ( days > 0 ) {
     224                                                        relativeTime = days + ' day' + ( days > 1 ? 's' : '' );
     225                                                } else if ( hours > 0 ) {
     226                                                        relativeTime = hours + ' hour' + ( hours > 1 ? 's' : '' );
     227                                                } else if ( minutes > 0 ) {
     228                                                        relativeTime = minutes + ' minute' + ( minutes > 1 ? 's' : '' );
     229                                                } else {
     230                                                        relativeTime = 'less than a minute';
     231                                                }
     232                                                timeEl.textContent = in_text + relativeTime + ago_text;
     233                                                return;
     234                                        }
     235
     236                                        const options = {
    157237                                                weekday: 'short',
    158238                                                year: 'numeric',
    … …  
    163243                                                timeZoneName: 'short'
    164244                                        };
     245                                        if ( timeEl.dataset.format ) {
     246                                                if ( timeEl.dataset.format.includes( 'l' ) ) {
     247                                                        options.weekday = 'long';
     248                                                } else if ( ! timeEl.dataset.format.includes( 'D' ) ) {
     249                                                        delete options.weekday;
     250                                                }
     251                                                if ( timeEl.dataset.format.includes( 'F' ) ) {
     252                                                        options.month = 'long';
     253                                                } else if ( timeEl.dataset.format.includes( 'm' ) || timeEl.dataset.format.includes( 'n' ) ) {
     254                                                        options.month = 'numeric';
     255                                                }
     256                                        }
    165257                                        timeEl.textContent = userLocalDateTime.toLocaleTimeString( navigator.language, options );
    166258                                }
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/routes/event/create.php

    r13298 r13529  
    33namespace Wporg\TranslationEvents\Routes\Event;
    44
     5use Wporg\TranslationEvents\Event\Event_End_Date;
     6use Wporg\TranslationEvents\Event\Event_Start_Date;
    57use Wporg\TranslationEvents\Routes\Route;
    68
    … …  
    1517                        exit;
    1618                }
    17                 $event_form_title         = 'Create Event';
     19                $event_page_title         = 'Create Event';
    1820                $event_form_name          = 'create_event';
    1921                $css_show_url             = 'hide-event-url';
    … …  
    2123                $event_title              = '';
    2224                $event_description        = '';
    23                 $event_timezone           = '';
    24                 $event_start              = '';
    25                 $event_end                = '';
    2625                $event_url                = '';
    2726                $create_delete_button     = true;
    2827                $visibility_delete_button = 'none';
     28                $event_timezone           = null;
     29                $event_start              = new Event_Start_Date( date_i18n( 'Y - m - d H:i' ) );
     30                $event_end                = new Event_End_Date( date_i18n( 'Y - m - d H:i' ) );
    2931
    3032                $this->tmpl( 'events-form', get_defined_vars() );
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/routes/event/details.php

    r13298 r13529  
    55use Exception;
    66use GP;
     7use Wporg\TranslationEvents\Attendee\Attendee;
     8use Wporg\TranslationEvents\Attendee\Attendee_Repository;
     9use Wporg\TranslationEvents\Event\Event_Repository_Interface;
    710use Wporg\TranslationEvents\Routes\Route;
    811use Wporg\TranslationEvents\Stats_Calculator;
    … …  
    1316 */
    1417class Details_Route extends Route {
     18        private Event_Repository_Interface $event_repository;
     19        private Attendee_Repository $attendee_repository;
     20
     21        public function __construct() {
     22                parent::__construct();
     23                $this->event_repository    = Translation_Events::get_event_repository();
     24                $this->attendee_repository = Translation_Events::get_attendee_repository();
     25        }
     26
    1527        public function handle( string $event_slug ): void {
    1628                $user  = wp_get_current_user();
    1729                $event = get_page_by_path( $event_slug, OBJECT, Translation_Events::CPT );
     30                if ( ! $event ) {
     31                        $this->die_with_404();
     32                }
     33                $event = $this->event_repository->get_event( $event->ID );
    1834                if ( ! $event ) {
    1935                        $this->die_with_404();
    … …  
    2642                 */
    2743                $can_crud_event = apply_filters( 'gp_translation_events_can_crud_event', GP::$permission->current_user_can( 'admin' ) );
    28                 if ( 'publish' !== $event->post_status && ! $can_crud_event ) {
     44                if ( 'publish' !== $event->status() && ! $can_crud_event ) {
    2945                        $this->die_with_error( esc_html__( 'You are not authorized to view this page.', 'gp-translation-events' ), 403 );
    3046                }
    3147
    32                 $event_id            = $event->ID;
    33                 $event_title         = $event->post_title;
    34                 $event_description   = $event->post_content;
    35                 $event_start         = get_post_meta( $event->ID, '_event_start', true ) ?: '';
    36                 $event_end           = get_post_meta( $event->ID, '_event_end', true ) ?: '';
    37                 $attending_event_ids = get_user_meta( $user->ID, Translation_Events::USER_META_KEY_ATTENDING, true ) ?: array();
    38                 $user_is_attending   = isset( $attending_event_ids[ $event_id ] );
     48                $event_id          = $event->id();
     49                $event_title       = $event->title();
     50                $event_description = $event->description();
     51                $event_start       = $event->start();
     52                $event_end         = $event->end();
     53
     54                $attendee          = $this->attendee_repository->get_attendee( $event->id(), $user->ID );
     55                $user_is_attending = $attendee instanceof Attendee;
    3956
    4057                $stats_calculator = new Stats_Calculator();
    4158                try {
    42                         $event_stats  = $stats_calculator->for_event( $event );
    43                         $contributors = $stats_calculator->get_contributors( $event );
     59                        $event_stats   = $stats_calculator->for_event( $event->id() );
     60                        $contributors  = $stats_calculator->get_contributors( $event->id() );
     61                        $attendees     = $stats_calculator->get_attendees_not_contributing( $event->id() );
     62                        $attendee_repo = $this->attendee_repository;
     63                        $hosts         = $this->attendee_repository->get_hosts( $event->id() );
     64                        $projects      = $stats_calculator->get_projects( $event->id() );
    4465                } catch ( Exception $e ) {
    4566                        // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
    … …  
    4869                }
    4970
     71                $is_editable_event = true;
     72                if ( $event_end->is_in_the_past() || $stats_calculator->event_has_stats( $event->id() ) ) {
     73                        $is_editable_event = false;
     74                }
     75
    5076                $this->tmpl( 'event', get_defined_vars() );
    5177        }
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/routes/event/edit.php

    r13298 r13529  
    33namespace Wporg\TranslationEvents\Routes\Event;
    44
    5 use DateTime;
    6 use DateTimeZone;
    7 use Exception;
     5use Wporg\TranslationEvents\Attendee\Attendee;
     6use Wporg\TranslationEvents\Attendee\Attendee_Repository;
     7use Wporg\TranslationEvents\Event\Event_Repository_Interface;
    88use Wporg\TranslationEvents\Routes\Route;
    99use Wporg\TranslationEvents\Stats_Calculator;
    … …  
    1414 */
    1515class Edit_Route extends Route {
     16        private Event_Repository_Interface $event_repository;
     17        private Attendee_Repository $attendee_repository;
     18
     19        public function __construct() {
     20                parent::__construct();
     21                $this->event_repository    = Translation_Events::get_event_repository();
     22                $this->attendee_repository = Translation_Events::get_attendee_repository();
     23        }
     24
    1625        public function handle( int $event_id ): void {
    1726                global $wp;
    … …  
    2029                        exit;
    2130                }
    22                 $event = get_post( $event_id );
    23                 if ( ! $event || Translation_Events::CPT !== $event->post_type || ! ( current_user_can( 'edit_post', $event->ID ) || intval( $event->post_author ) === get_current_user_id() ) ) {
     31                $event    = $this->event_repository->get_event( $event_id );
     32                $attendee = $this->attendee_repository->get_attendee( $event->id(), get_current_user_id() );
     33
     34                if ( ! $event || ! ( ( $attendee instanceof Attendee && $attendee->is_host() ) || current_user_can( 'edit_post', $event->id() ) || $event->author_id() === get_current_user_id() ) ) {
    2435                        $this->die_with_error( esc_html__( 'Event does not exist, or you do not have permission to edit it.', 'gp-translation-events' ), 403 );
    2536                }
    26                 if ( 'trash' === $event->post_status ) {
     37                if ( 'trash' === $event->status() ) {
    2738                        $this->die_with_error( esc_html__( 'You cannot edit a trashed event', 'gp-translation-events' ), 403 );
    2839                }
    2940
    3041                include ABSPATH . 'wp-admin/includes/post.php';
    31                 $event_form_title              = 'Edit Event';
     42                $event_page_title              = 'Edit Event';
    3243                $event_form_name               = 'edit_event';
    3344                $css_show_url                  = '';
    34                 $event_title                   = $event->post_title;
    35                 $event_description             = $event->post_content;
    36                 $event_status                  = $event->post_status;
    37                 list( $permalink, $post_name ) = get_sample_permalink( $event_id );
     45                $event_title                   = $event->title();
     46                $event_description             = $event->description();
     47                $event_status                  = $event->status();
     48                list( $permalink, $post_name ) = get_sample_permalink( $event->id() );
    3849                $permalink                     = str_replace( '%pagename%', $post_name, $permalink );
    3950                $event_url                     = get_site_url() . gp_url( wp_make_link_relative( $permalink ) );
    40                 $event_timezone                = get_post_meta( $event_id, '_event_timezone', true ) ?: '';
     51                $event_timezone                = $event->timezone();
     52                $event_start                   = $event->start();
     53                $event_end                     = $event->end();
    4154                $create_delete_button          = false;
    4255                $visibility_delete_button      = 'inline-flex';
    4356
     57                if ( $event->end()->is_in_the_past() ) {
     58                        $this->die_with_error( esc_html__( 'You cannot edit a past event.', 'gp-translation-events' ), 403 );
     59                }
     60
    4461                $stats_calculator = new Stats_Calculator();
    45                 if ( ! $stats_calculator->event_has_stats( $event ) ) {
     62
     63                if ( $stats_calculator->event_has_stats( $event->id() ) ) {
     64                        $this->die_with_error( esc_html__( 'You cannot edit an event with translations.', 'gp-translation-events' ), 403 );
     65                }
     66
     67                if ( ! $stats_calculator->event_has_stats( $event->id() ) ) {
    4668                        $current_user = wp_get_current_user();
    47                         if ( $current_user->ID === $event->post_author || current_user_can( 'manage_options' ) ) {
     69                        if ( ( $current_user->ID === $event->author_id() || ( $attendee instanceof Attendee && $attendee->is_host() ) || current_user_can( 'manage_options' ) ) && ! $event->end()->is_in_the_past() ) {
    4870                                $create_delete_button = true;
    4971                        }
    5072                }
    5173
    52                 try {
    53                         $event_start = self::convertToTimezone( get_post_meta( $event_id, '_event_start', true ), $event_timezone );
    54                         $event_end   = self::convertToTimezone( get_post_meta( $event_id, '_event_end', true ), $event_timezone );
    55                 } catch ( Exception $e ) {
    56                         // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
    57                         error_log( $e );
    58                         $this->die_with_error( esc_html__( 'Something is wrong.', 'gp-translation-events' ) );
    59                 }
    60 
    6174                $this->tmpl( 'events-form', get_defined_vars() );
    6275        }
    63 
    64         /**
    65          * Convert date time stored in UTC to a date time in a time zone.
    66          *
    67          * @param string $date_time The date time in UTC.
    68          * @param string $time_zone The time zone.
    69          *
    70          * @return string The date time in the time zone.
    71          * @throws Exception When date is invalid.
    72          */
    73         private static function convertToTimezone( string $date_time, string $time_zone ): string {
    74                 return ( new DateTime( $date_time, new DateTimeZone( 'UTC' ) ) )->setTimezone( new DateTimeZone( $time_zone ) )->format( 'Y-m-d H:i:s' );
    75         }
    7676}
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/routes/event/list.php

    r13298 r13529  
    77use Exception;
    88use WP_Query;
     9use Wporg\TranslationEvents\Event\Event_Repository_Interface;
    910use Wporg\TranslationEvents\Routes\Route;
    1011use Wporg\TranslationEvents\Translation_Events;
    … …  
    1415 */
    1516class List_Route extends Route {
     17        private Event_Repository_Interface $event_repository;
     18
     19        public function __construct() {
     20                parent::__construct();
     21                $this->event_repository = Translation_Events::get_event_repository();
     22        }
     23
    1624        public function handle(): void {
    1725                $current_datetime_utc = null;
    … …  
    5664                // phpcs:enable
    5765
    58                 $current_events_args  = array(
    59                         'post_type'      => Translation_Events::CPT,
    60                         'posts_per_page' => 10,
    61                         'paged'          => $_current_events_paged,
    62                         'post_status'    => 'publish',
    63                         // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
    64                         'meta_query'     => array(
    65                                 array(
    66                                         'key'     => '_event_start',
    67                                         'value'   => $current_datetime_utc,
    68                                         'compare' => '<=',
    69                                         'type'    => 'DATETIME',
    70                                 ),
    71                                 array(
    72                                         'key'     => '_event_end',
    73                                         'value'   => $current_datetime_utc,
    74                                         'compare' => '>=',
    75                                         'type'    => 'DATETIME',
    76                                 ),
    77                         ),
    78                         'orderby'        => 'meta_value',
    79                         'order'          => 'ASC',
    80                 );
    81                 $current_events_query = new WP_Query( $current_events_args );
    82 
    83                 $upcoming_events_args  = array(
    84                         'post_type'      => Translation_Events::CPT,
    85                         'posts_per_page' => 10,
    86                         'paged'          => $_upcoming_events_paged,
    87                         'post_status'    => 'publish',
    88                         // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
    89                         'meta_query'     => array(
    90                                 array(
    91                                         'key'     => '_event_start',
    92                                         'value'   => $current_datetime_utc,
    93                                         'compare' => '>=',
    94                                         'type'    => 'DATETIME',
    95                                 ),
    96                         ),
    97                         'orderby'        => 'meta_value',
    98                         'order'          => 'ASC',
    99                 );
    100                 $upcoming_events_query = new WP_Query( $upcoming_events_args );
    101 
    102                 $past_events_args  = array(
    103                         'post_type'      => Translation_Events::CPT,
    104                         'posts_per_page' => 10,
    105                         'paged'          => $_past_events_paged,
    106                         'post_status'    => 'publish',
    107                         // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
    108                         'meta_query'     => array(
    109                                 array(
    110                                         'key'     => '_event_end',
    111                                         'value'   => $current_datetime_utc,
    112                                         'compare' => '<',
    113                                         'type'    => 'DATETIME',
    114                                 ),
    115                         ),
    116                         'orderby'        => 'meta_value',
    117                         'order'          => 'ASC',
    118                 );
    119                 $past_events_query = new WP_Query( $past_events_args );
    120 
    121                 $user_attending_events      = get_user_meta( get_current_user_id(), Translation_Events::USER_META_KEY_ATTENDING, true ) ?: array( 0 );
    122                 $user_attending_events_args = array(
    123                         'post_type'      => Translation_Events::CPT,
    124                         'post__in'       => array_keys( $user_attending_events ),
    125                         'posts_per_page' => 10,
    126                         'paged'          => $_user_attending_events_paged,
    127                         'post_status'    => 'publish',
    128                         // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
    129                         'meta_query'     => array(
    130                                 array(
    131                                         'key'     => '_event_end',
    132                                         'value'   => $current_datetime_utc,
    133                                         'compare' => '>',
    134                                         'type'    => 'DATETIME',
    135                                 ),
    136                         ),
    137                         // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
    138                         'meta_key'       => '_event_start',
    139                         'orderby'        => 'meta_value',
    140                         'order'          => 'ASC',
    141                 );
    142                 $user_attending_events_query = new WP_Query( $user_attending_events_args );
     66                $current_events_query        = $this->event_repository->get_current_events( $_current_events_paged, 10 );
     67                $upcoming_events_query       = $this->event_repository->get_upcoming_events( $_upcoming_events_paged, 10 );
     68                $past_events_query           = $this->event_repository->get_past_events( $_past_events_paged, 10 );
     69                $user_attending_events_query = $this->event_repository->get_current_and_upcoming_events_for_user( get_current_user_id(), $_user_attending_events_paged, 10 );
    14370
    14471                $this->tmpl( 'events-list', get_defined_vars() );
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/routes/user/attend-event.php

    r13298 r13529  
    33namespace Wporg\TranslationEvents\Routes\User;
    44
     5use Wporg\TranslationEvents\Attendee\Attendee;
     6use Wporg\TranslationEvents\Attendee\Attendee_Repository;
     7use Wporg\TranslationEvents\Event\Event_Repository_Interface;
    58use Wporg\TranslationEvents\Routes\Route;
    69use Wporg\TranslationEvents\Translation_Events;
    … …  
    1215 */
    1316class Attend_Event_Route extends Route {
     17        private Event_Repository_Interface $event_repository;
     18        private Attendee_Repository $attendee_repository;
     19
     20        public function __construct() {
     21                parent::__construct();
     22                $this->event_repository    = Translation_Events::get_event_repository();
     23                $this->attendee_repository = Translation_Events::get_attendee_repository();
     24        }
     25
    1426        public function handle( int $event_id ): void {
    1527                $user = wp_get_current_user();
    … …  
    1830                }
    1931
    20                 $event = get_post( $event_id );
    21 
     32                $event = $this->event_repository->get_event( $event_id );
    2233                if ( ! $event ) {
    2334                        $this->die_with_404();
    2435                }
    2536
    26                 $event_ids = get_user_meta( $user->ID, Translation_Events::USER_META_KEY_ATTENDING, true ) ?? array();
    27                 if ( ! $event_ids ) {
    28                         $event_ids = array();
     37                $attendee = $this->attendee_repository->get_attendee( $event->id(), $user->ID );
     38                if ( $attendee instanceof Attendee && $attendee->is_host() && ( 1 === count( $this->attendee_repository->get_hosts( $event_id ) ) ) ) {
     39                        $this->die_with_error( esc_html__( 'The event needs a host. Add a new host before stopping to attend the event.', 'gp-translation-events' ), 403 );
     40                }
     41                if ( $attendee instanceof Attendee ) {
     42                        $this->attendee_repository->remove_attendee( $event->id(), $user->ID );
     43                } else {
     44                        $attendee = new Attendee( $event->id(), $user->ID );
     45                        $this->attendee_repository->insert_attendee( $attendee );
    2946                }
    3047
    31                 if ( ! isset( $event_ids[ $event_id ] ) ) {
    32                         // Not yet attending, mark as attending.
    33                         $event_ids[ $event_id ] = true;
    34                 } else {
    35                         // Currently attending, mark as not attending.
    36                         unset( $event_ids[ $event_id ] );
    37                 }
    38 
    39                 update_user_meta( $user->ID, Translation_Events::USER_META_KEY_ATTENDING, $event_ids );
    40 
    41                 wp_safe_redirect( gp_url( "/events/$event->post_name" ) );
     48                wp_safe_redirect( gp_url( "/events/{$event->slug()}" ) );
    4249                exit;
    4350        }
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/routes/user/my-events.php

    r13298 r13529  
    33namespace Wporg\TranslationEvents\Routes\User;
    44
    5 use DateTime;
    6 use DateTimeZone;
    7 use WP_Query;
     5use Wporg\TranslationEvents\Event\Event_Repository_Interface;
    86use Wporg\TranslationEvents\Routes\Route;
    97use Wporg\TranslationEvents\Translation_Events;
    … …  
    1311 */
    1412class My_Events_Route extends Route {
     13        private Event_Repository_Interface $event_repository;
     14
     15        public function __construct() {
     16                parent::__construct();
     17                $this->event_repository = Translation_Events::get_event_repository();
     18        }
     19
    1520        public function handle(): void {
    1621                global $wp;
    … …  
    2227
    2328                $_events_i_created_paged  = 1;
     29                $_events_i_hosted_paged   = 1;
    2430                $_events_i_attended_paged = 1;
    2531
    … …  
    2935                        if ( is_numeric( $value ) ) {
    3036                                $_events_i_created_paged = (int) $value;
     37                        }
     38                }
     39                if ( isset( $_GET['events_i_hosted_paged'] ) ) {
     40                        $value = sanitize_text_field( wp_unslash( $_GET['events_i_hosted_paged'] ) );
     41                        if ( is_numeric( $value ) ) {
     42                                $_events_i_hosted_paged = (int) $value;
    3143                        }
    3244                }
    … …  
    3951                // phpcs:enable
    4052
    41                 $user_id              = get_current_user_id();
    42                 $events               = get_user_meta( $user_id, Translation_Events::USER_META_KEY_ATTENDING, true ) ?: array();
    43                 $events               = array_keys( $events );
    44                 $current_datetime_utc = ( new DateTime( 'now', new DateTimeZone( 'UTC' ) ) )->format( 'Y-m-d H:i:s' );
    45                 $args                 = array(
    46                         'post_type'              => Translation_Events::CPT,
    47                         'posts_per_page'         => 10,
    48                         'events_i_created_paged' => $_events_i_created_paged,
    49                         'paged'                  => $_events_i_created_paged,
    50                         'post_status'            => array( 'publish', 'draft' ),
    51                         'author'                 => $user_id,
    52                         // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
    53                         'meta_key'               => '_event_start',
    54                         'orderby'                => 'meta_value',
    55                         'order'                  => 'DESC',
    56                 );
    57                 $events_i_created_query = new WP_Query( $args );
    58 
    59                 $args = array(
    60                         'post_type'               => Translation_Events::CPT,
    61                         'posts_per_page'          => 10,
    62                         'events_i_attended_paged' => $_events_i_attended_paged,
    63                         'paged'                   => $_events_i_attended_paged,
    64                         'post_status'             => 'publish',
    65                         'post__in'                => $events,
    66                         // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
    67                         'meta_query'              => array(
    68                                 array(
    69                                         'key'     => '_event_end',
    70                                         'value'   => $current_datetime_utc,
    71                                         'compare' => '<',
    72                                         'type'    => 'DATETIME',
    73                                 ),
    74                         ),
    75                         // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
    76                         'meta_key'                => '_event_end',
    77                         'orderby'                 => 'meta_value',
    78                         'order'                   => 'DESC',
    79                 );
    80                 $events_i_attended_query = new WP_Query( $args );
     53                $events_i_created_query  = $this->event_repository->get_events_created_by_user( get_current_user_id(), $_events_i_created_paged, 10 );
     54                $events_i_host_query     = $this->event_repository->get_events_hosted_by_user( get_current_user_id(), $_events_i_hosted_paged, 10 );
     55                $events_i_attended_query = $this->event_repository->get_past_events_for_user( get_current_user_id(), $_events_i_attended_paged, 10 );
    8156
    8257                $this->tmpl( 'events-my-events', get_defined_vars() );
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/stats-calculator.php

    r13298 r13529  
    66use WP_Post;
    77use WP_User;
     8use GP;
    89use GP_Locale;
    910use GP_Locales;
     11use DateTimeImmutable;
     12use DateTimeZone;
    1013
    1114class Stats_Row {
    … …  
    8689         * @throws Exception When stats calculation failed.
    8790         */
    88         public function for_event( WP_Post $event ): Event_Stats {
     91        public function for_event( int $event_id ): Event_Stats {
    8992                $stats = new Event_Stats();
    9093                global $wpdb, $gp_table_prefix;
    … …  
    99102                                "
    100103                                select locale,
    101                                            sum(action = 'create') as created,
    102                                            count(*) as total,
    103                                            count(distinct user_id) as users
     104                                        sum(action = 'create') as created,
     105                                        count(*) as total,
     106                                        count(distinct user_id) as users
    104107                                from {$gp_table_prefix}event_actions
    105108                                where event_id = %d
    … …  
    107110                        ",
    108111                                array(
    109                                         $event->ID,
     112                                        $event_id,
    110113                                )
    111114                        )
    … …  
    148151         * Get contributors for an event.
    149152         */
    150         public function get_contributors( WP_Post $event ): array {
     153        public function get_contributors( int $event_id ): array {
    151154                global $wpdb, $gp_table_prefix;
    152155
    … …  
    165168                        ",
    166169                                array(
    167                                         $event->ID,
     170                                        $event_id,
    168171                                )
    169172                        )
    … …  
    189192
    190193        /**
     194         * Get attendees without contributions for an event.
     195         */
     196        public function get_attendees_not_contributing( int $event_id ): array {
     197                global $wpdb, $gp_table_prefix;
     198
     199                // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     200                // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
     201                // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching
     202                $all_attendees_ids = $wpdb->get_col(
     203                        $wpdb->prepare(
     204                                "
     205                                select distinct user_id
     206                                from {$gp_table_prefix}event_attendees
     207                                where event_id = %d
     208                        ",
     209                                array(
     210                                        $event_id,
     211                                )
     212                        ),
     213                );
     214
     215                $contributing_ids = $wpdb->get_col(
     216                        $wpdb->prepare(
     217                                "
     218                                select distinct user_id
     219                                from {$gp_table_prefix}event_actions
     220                                where event_id = %d
     221                        ",
     222                                array(
     223                                        $event_id,
     224                                )
     225                        )
     226                );
     227
     228                $attendees_not_contributing_ids = array_diff( $all_attendees_ids, $contributing_ids );
     229
     230                $attendees_not_contributing = array();
     231                foreach ( $attendees_not_contributing_ids as $user_id ) {
     232                        $attendees_not_contributing[] = new WP_User( $user_id );
     233                }
     234
     235                return $attendees_not_contributing;
     236        }
     237
     238        /**
     239         * Get projects for an event.
     240         */
     241        public function get_projects( int $event_id ): array {
     242                global $wpdb, $gp_table_prefix;
     243
     244                // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     245                // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
     246                // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching
     247                // phpcs thinks we're doing a schema change but we aren't.
     248                // phpcs:disable WordPress.DB.DirectDatabaseQuery.SchemaChange
     249                $rows = $wpdb->get_results(
     250                        $wpdb->prepare(
     251                                "
     252                                select
     253                                        o.project_id as project,
     254                                        group_concat( distinct e.locale ) as locales,
     255                                        sum(action = 'create') as created,
     256                                        count(*) as total,
     257                                        count(distinct user_id) as users
     258                                from {$gp_table_prefix}event_actions e, {$gp_table_prefix}originals o
     259                                where e.event_id = %d and e.original_id = o.id
     260                                group by o.project_id
     261                        ",
     262                                array(
     263                                        $event_id,
     264                                )
     265                        )
     266                );
     267                // phpcs:enable
     268
     269                $projects = array();
     270                foreach ( $rows as $row ) {
     271                        $row->project      = GP::$project->get( $row->project );
     272                        $project_name      = $row->project->name;
     273                        $parent_project_id = $row->project->parent_project_id;
     274                        while ( $parent_project_id ) {
     275                                $parent_project    = GP::$project->get( $parent_project_id );
     276                                $parent_project_id = $parent_project->parent_project_id;
     277                                $project_name      = substr( htmlspecialchars_decode( $parent_project->name ), 0, 35 ) . ' - ' . $project_name;
     278                        }
     279                        $projects[ $project_name ] = $row;
     280                }
     281
     282                ksort( $projects );
     283
     284                return $projects;
     285        }
     286
     287        /**
    191288         * Check if an event has stats.
    192289         *
    193          * @param WP_Post $event The event to check.
     290         * @param int $event_id The id of the event to check.
    194291         *
    195292         * @return bool True if the event has stats, false otherwise.
    196293         */
    197         public function event_has_stats( WP_Post $event ): bool {
     294        public function event_has_stats( int $event_id ): bool {
    198295                try {
    199                         $stats = $this->for_event( $event );
     296                        $stats = $this->for_event( $event_id );
    200297                } catch ( Exception $e ) {
    201298                        return false;
    … …  
    204301                return ! empty( $stats->rows() );
    205302        }
     303
     304        /**
     305         * Check if a user is a first time contributor.
     306         *
     307         * @param Event_Start_Date $event_start The event start date.
     308         * @param int              $user_id      The user ID.
     309         *
     310         * @return bool True if the user is a first time contributor, false otherwise.
     311         */
     312        public function is_first_time_contributor( $event_start, $user_id ) {
     313                global $wpdb, $gp_table_prefix;
     314
     315                // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     316                // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
     317                // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching
     318                // phpcs:disable WordPress.DB.DirectDatabaseQuery.SchemaChange
     319                $users_first_translation_date = $wpdb->get_var(
     320                        $wpdb->prepare(
     321                                "
     322                        select min(date_added) from {$gp_table_prefix}translations where user_id = %d
     323                ",
     324                                array(
     325                                        $user_id,
     326                                )
     327                        )
     328                );
     329
     330                if ( get_userdata( $user_id ) && ! $users_first_translation_date ) {
     331                        return true;
     332                }
     333                $event_start_date_time  = new DateTimeImmutable( $event_start->__toString(), new DateTimeZone( 'UTC' ) );
     334                $first_translation_date = new DateTimeImmutable( $users_first_translation_date, new DateTimeZone( 'UTC' ) );
     335                // A first time contributor is someone whose first translation was made not earlier than 24 hours before the event.
     336                $event_start_date_time = $event_start_date_time->modify( '-1 day' );
     337                return $event_start_date_time <= $first_translation_date;
     338        }
    206339}
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/stats-listener.php

    r13298 r13529  
    88use GP_Translation;
    99use GP_Translation_Set;
     10use Wporg\TranslationEvents\Attendee\Attendee_Repository;
     11use Wporg\TranslationEvents\Event\Event;
     12use Wporg\TranslationEvents\Event\Event_Repository_Interface;
    1013
    1114class Stats_Listener {
    … …  
    1518        const ACTION_REQUEST_CHANGES = 'request_changes';
    1619
    17         private Active_Events_Cache $active_events_cache;
     20        private Attendee_Repository $attendee_repository;
     21        private Event_Repository_Interface $event_repository;
    1822
    19         public function __construct( Active_Events_Cache $active_events_cache ) {
    20                 $this->active_events_cache = $active_events_cache;
     23        public function __construct(
     24                Event_Repository_Interface $event_repository,
     25                Attendee_Repository $attendee_repository
     26        ) {
     27                $this->event_repository    = $event_repository;
     28                $this->attendee_repository = $attendee_repository;
    2129        }
    2230
    … …  
    7078                try {
    7179                        // Get events that are active when the action happened, for which the user is registered for.
    72                         $active_events = $this->get_active_events( $happened_at );
    73                         $events        = $this->select_events_user_is_registered_for( $active_events, $user_id );
     80                        $active_events = $this->event_repository->get_current_events();
     81                        $events        = $this->select_events_user_is_registered_for( $active_events->events, $user_id );
    7482
    7583                        // phpcs:ignore Generic.Commenting.DocComment.MissingShort
    … …  
    108116
    109117        /**
    110          * Get active events at a given time.
    111          *
    112          * @return Event[]
    113          * @throws Exception When it fails to get active events.
    114          */
    115         private function get_active_events( DateTimeImmutable $at ): array {
    116                 $events = $this->active_events_cache->get();
    117                 if ( null === $events ) {
    118                         $cache_duration = Active_Events_Cache::CACHE_DURATION;
    119                         $boundary_start = $at;
    120                         $boundary_end   = $at->modify( "+$cache_duration seconds" );
    121 
    122                         // Get events for which start is before $boundary_end AND end is after $boundary_start.
    123                         $event_ids = get_posts(
    124                                 array(
    125                                         'post_type'      => Translation_Events::CPT,
    126                                         'post_status'    => 'publish',
    127                                         'posts_per_page' => - 1,
    128                                         'fields'         => 'ids',
    129                                         'meta_query'     => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
    130                                                 array(
    131                                                         'key'     => '_event_start',
    132                                                         'value'   => $boundary_end->format( 'Y-m-d H:i:s' ),
    133                                                         'compare' => '<',
    134                                                         'type'    => 'DATETIME',
    135                                                 ),
    136                                                 array(
    137                                                         'key'     => '_event_end',
    138                                                         'value'   => $boundary_start->format( 'Y-m-d H:i:s' ),
    139                                                         'compare' => '>',
    140                                                         'type'    => 'DATETIME',
    141                                                 ),
    142                                         ),
    143                                 ),
    144                         );
    145 
    146                         $events = array();
    147                         foreach ( $event_ids as $event_id ) {
    148                                 $meta     = get_post_meta( $event_id );
    149                                 $events[] = Event::from_post_meta( $event_id, $meta );
    150                         }
    151 
    152                         $this->active_events_cache->cache( $events );
    153                 }
    154 
    155                 // Filter out events that aren't actually active at $at.
    156                 return array_filter(
    157                         $events,
    158                         function ( $event ) use ( $at ) {
    159                                 return $event->start() <= $at && $at <= $event->end();
    160                         }
    161                 );
    162         }
    163 
    164         /**
    165118         * Filter an array of events so that it only includes events the given user is attending.
    166119         *
    … …  
    172125        // phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.Found
    173126        private function select_events_user_is_registered_for( array $events, int $user_id ): array {
    174                 $attending_event_ids = get_user_meta( $user_id, Translation_Events::USER_META_KEY_ATTENDING, true );
     127                $attending_event_ids = $this->attendee_repository->get_events_for_user( $user_id );
    175128                return array_filter(
    176129                        $events,
    177130                        function ( Event $event ) use ( $attending_event_ids ) {
    178                                 return isset( $attending_event_ids[ $event->id() ] );
     131                                return in_array( $event->id(), $attending_event_ids, true );
    179132                        }
    180133                );
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/templates/event.php

    r13298 r13529  
    66namespace Wporg\TranslationEvents;
    77
    8 use WP_Post;
    9 
    10 /** @var WP_Post $event */
     8use WP_User;
     9use Wporg\TranslationEvents\Attendee\Attendee;
     10use Wporg\TranslationEvents\Attendee\Attendee_Repository;
     11use Wporg\TranslationEvents\Event\Event;
     12use Wporg\TranslationEvents\Event\Event_End_Date;
     13use Wporg\TranslationEvents\Event\Event_Start_Date;
     14
     15/** @var Attendee_Repository $attendee_repo */
     16/** @var Attendee $attendee */
     17/** @var Event $event */
    1118/** @var int $event_id */
    1219/** @var string $event_title */
    1320/** @var string $event_description */
    14 /** @var string $event_start */
    15 /** @var string $event_end */
    16 /** @var bool $user_is_attending */
     21/** @var Event_Start_Date $event_start */
     22/** @var Event_End_Date $event_end */
    1723/** @var Event_Stats $event_stats */
     24/** @var array $projects */
     25/** @var WP_User $user */
    1826
    1927/* translators: %s: Event title. */
    … …  
    2129gp_breadcrumb_translation_events( array( esc_html( $event_title ) ) );
    2230gp_tmpl_header();
     31$event_page_title = $event_title;
    2332gp_tmpl_load( 'events-header', get_defined_vars(), __DIR__ );
    2433?>
    2534
    2635<div class="event-page-wrapper">
    27         <div class="event-details-head">
    28                 <h1>
    29                         <?php echo esc_html( $event_title ); ?>
    30                         <?php if ( 'draft' === $event->post_status ) : ?>
    31                                 <span class="event-label-draft"><?php echo esc_html( $event->post_status ); ?></span>
    32                         <?php endif; ?>
    33                 </h1>
    34                 <p>
    35                         Host: <a href="<?php echo esc_attr( get_author_posts_url( $event->post_author ) ); ?>"><?php echo esc_html( get_the_author_meta( 'display_name', $event->post_author ) ); ?></a>
    36                         <?php if ( current_user_can( 'edit_post', $event_id ) ) : ?>
    37                                 <a class="event-page-edit-link button" href="<?php echo esc_url( gp_url( 'events/edit/' . $event_id ) ); ?>"><span class="dashicons dashicons-edit"></span>Edit event</a>
    38                         <?php endif ?>
    39                 </p>
    40         </div>
    4136        <div class="event-details-left">
    4237                <div class="event-page-content">
    … …  
    4540                        ?>
    4641                </div>
     42                <?php if ( ! empty( $contributors ) ) : ?>
     43                        <div class="event-contributors">
     44                                <h2><?php esc_html_e( 'Contributors', 'gp-translation-events' ); ?></h2>
     45                                <ul>
     46                                        <?php foreach ( $contributors as $contributor ) : ?>
     47                                                <li class="event-contributor" title="<?php echo esc_html( implode( ', ', $contributor->locales ) ); ?>">
     48                                                        <a href="<?php echo esc_url( get_author_posts_url( $contributor->ID ) ); ?>"><?php echo get_avatar( $contributor->ID, 48 ); ?></a>
     49                                                        <a href="<?php echo esc_url( get_author_posts_url( $contributor->ID ) ); ?>"><?php echo esc_html( get_the_author_meta( 'display_name', $contributor->ID ) ); ?></a>
     50                                                        <?php if ( $stats_calculator->is_first_time_contributor( $event_start, $contributor->ID ) ) : ?>
     51                                                                <span class="first-time-contributor-tada"></span>
     52                                                        <?php endif; ?>
     53                                                        <?php
     54                                                        if ( ! $event->end()->is_in_the_past() ) :
     55                                                                if ( ( $attendee instanceof Attendee && $attendee->is_host() ) || current_user_can( 'manage_options' ) ) :
     56                                                                        if ( $user->ID !== $contributor->ID ) :
     57                                                                                $_attendee = $attendee_repo->get_attendee( $event_id, $contributor->ID );
     58                                                                                if ( $_attendee instanceof Attendee ) :
     59                                                                                        echo '<form class="add-remove-user-as-host" method="post" action="' . esc_url( gp_url( "/events/host/$event_id/$contributor->ID" ) ) . '">';
     60                                                                                        if ( $_attendee->is_host() ) :
     61                                                                                                if ( 1 === count( $attendee_repo->get_hosts( $event_id ) ) ) :
     62                                                                                                        echo '<input type="submit" class="button is-primary remove-as-host" disabled value="Remove as host"/>';
     63                                                                                                else :
     64                                                                                                        echo '<input type="submit" class="button is-primary remove-as-host" value="Remove as host"/>';
     65                                                                                                endif;
     66                                                                                        else :
     67                                                                                                echo '<input type="submit" class="button is-secondary convert-to-host" value="Make co-host"/>';
     68                                                                                        endif;
     69                                                                                        echo '</form>';
     70                                                                                endif;
     71                                                                        elseif ( ( $attendee instanceof Attendee && $attendee->is_host() ) ) :
     72                                                                                        echo '<span class="event-you">' . esc_html__( 'You (host)', 'gp-translation-events' ) . '</span>';
     73                                                                                else :
     74                                                                                        echo '<span class="event-you">' . esc_html__( 'You (event creator)', 'gp-translation-events' ) . '</span>';
     75                                                                        endif;
     76                                                                endif;
     77                                                        endif;
     78                                                        ?>
     79                                                </li>
     80                                        <?php endforeach; ?>
     81                                </ul>
     82                        </div>
     83                <?php endif; ?>
     84                <?php if ( ! empty( $attendees ) && ( ! $event->end()->is_in_the_past() || ( ( $attendee instanceof Attendee && $attendee->is_host() ) || current_user_can( 'manage_options' ) ) ) ) : ?>
     85                        <div class="event-attendees">
     86                                <h2><?php esc_html_e( 'Attendees', 'gp-translation-events' ); ?></h2>
     87                                <ul>
     88                                        <?php foreach ( $attendees as $_user ) : ?>
     89                                                <li class="event-attendee">
     90                                                        <a href="<?php echo esc_url( get_author_posts_url( $_user->ID ) ); ?>"><?php echo get_avatar( $_user->ID, 48 ); ?></a>
     91                                                        <a href="<?php echo esc_url( get_author_posts_url( $_user->ID ) ); ?>"><?php echo esc_html( get_the_author_meta( 'display_name', $_user->ID ) ); ?></a>
     92                                                        <?php if ( $stats_calculator->is_first_time_contributor( $event_start, $_user->ID ) ) : ?>
     93                                                                <span class="first-time-contributor-tada"></span>
     94                                                        <?php endif; ?>
     95                                                        <?php
     96                                                        if ( ! $event->end()->is_in_the_past() ) :
     97                                                                if ( ( $attendee instanceof Attendee && $attendee->is_host() ) || current_user_can( 'manage_options' ) ) :
     98                                                                        if ( $user->ID !== $_user->ID ) :
     99                                                                                $_attendee = $attendee_repo->get_attendee( $event_id, $_user->ID );
     100                                                                                if ( $_attendee instanceof Attendee ) :
     101                                                                                        echo '<form class="add-remove-user-as-host" method="post" action="' . esc_url( gp_url( "/events/host/$event_id/$_user->ID" ) ) . '">';
     102                                                                                        if ( $_attendee->is_host() ) :
     103                                                                                                if ( 1 === count( $attendee_repo->get_hosts( $event_id ) ) ) :
     104                                                                                                        echo '<input type="submit" class="button is-primary remove-as-host" disabled value="Remove as host"/>';
     105                                                                                                else :
     106                                                                                                        echo '<input type="submit" class="button is-primary remove-as-host" value="Remove as host"/>';
     107                                                                                                endif;
     108                                                                                        else :
     109                                                                                                echo '<input type="submit" class="button is-secondary convert-to-host" value="Make co-host"/>';
     110                                                                                        endif;
     111                                                                                        echo '</form>';
     112                                                                                endif;
     113                                                                        elseif ( ( $attendee instanceof Attendee && $attendee->is_host() ) ) :
     114                                                                                        echo '<span class="event-you">' . esc_html__( 'You (host)', 'gp-translation-events' ) . '</span>';
     115                                                                                else :
     116                                                                                        echo '<span class="event-you">' . esc_html__( 'You (event creator)', 'gp-translation-events' ) . '</span>';
     117                                                                        endif;
     118                                                                endif;
     119                                                        endif;
     120                                                        ?>
     121                                                </li>
     122                                        <?php endforeach; ?>
     123                                </ul>
     124                        </div>
     125                <?php endif; ?>
    47126                <?php if ( ! empty( $event_stats->rows() ) ) : ?>
    48         <div class="event-details-stats">
    49                 <h2><?php esc_html_e( 'Stats', 'gp-translation-events' ); ?></h2>
    50                 <table>
    51                         <thead>
    52                         <tr>
    53                                 <th scope="col">Locale</th>
    54                                 <th scope="col">Translations created</th>
    55                                 <th scope="col">Translations reviewed</th>
    56                                 <th scope="col">Contributors</th>
    57                         </tr>
    58                         </thead>
    59                         <tbody>
    60                         <?php /** @var $row Stats_Row */ ?>
    61                         <?php foreach ( $event_stats->rows() as $_locale => $row ) : ?>
    62                         <tr>
    63                                 <td title="<?php echo esc_html( $_locale ); ?> "><a href="<?php echo esc_url( gp_url_join( gp_url( '/languages' ), $row->language->slug ) ); ?>"><?php echo esc_html( $row->language->english_name ); ?></a></td>
    64                                 <td><?php echo esc_html( $row->created ); ?></td>
    65                                 <td><?php echo esc_html( $row->reviewed ); ?></td>
    66                                 <td><?php echo esc_html( $row->users ); ?></td>
    67                         </tr>
    68                 <?php endforeach ?>
    69                         <tr class="event-details-stats-totals">
    70                                 <td>Total</td>
    71                                 <td><?php echo esc_html( $event_stats->totals()->created ); ?></td>
    72                                 <td><?php echo esc_html( $event_stats->totals()->reviewed ); ?></td>
    73                                 <td><?php echo esc_html( $event_stats->totals()->users ); ?></td>
    74                         </tr>
    75                         </tbody>
    76                 </table>
    77         </div>
    78         <div class="event-contributors">
    79                 <h2><?php esc_html_e( 'Contributors', 'gp-translation-events' ); ?></h2>
    80                 <ul>
    81                         <?php foreach ( $contributors as $contributor ) : ?>
    82                         <li class="event-contributor" title="<?php echo esc_html( implode( ', ', $contributor->locales ) ); ?>"
    83                                 <a href="<?php echo esc_url( get_author_posts_url( $contributor->ID ) ); ?>"><?php echo get_avatar( $contributor->ID, 48 ); ?></a>
    84                                 <a href="<?php echo esc_url( get_author_posts_url( $contributor->ID ) ); ?>"><?php echo esc_html( get_the_author_meta( 'display_name', $contributor->ID ) ); ?></a>
    85                         </li>
    86                 <?php endforeach; ?>
    87                 </ul>
    88         </div>
    89         <details class="event-stats-summary">
    90                 <summary>View stats summary in text </summary>
    91                 <p class="event-stats-text">
    92                         <?php
    93                         echo wp_kses(
    94                                 sprintf(
    95                                         // translators: %1$s: Event title, %2$d: Number of contributors, %3$d: Number of languages, %4$s: List of languages, %5$d: Number of strings translated, %6$d: Number of strings reviewed.
    96                                         __( 'At the <strong>%1$s</strong> event, %2$d people contributed in %3$d languages (%4$s), translated %5$d strings and reviewed %6$d strings.', 'gp-translation-events' ),
    97                                         esc_html( $event_title ),
    98                                         esc_html( $event_stats->totals()->users ),
    99                                         count( $event_stats->rows() ),
    100                                         esc_html(
    101                                                 implode(
    102                                                         ', ',
    103                                                         array_map(
    104                                                                 function ( $row ) {
    105                                                                         return $row->language->english_name;
    106                                                                 },
    107                                                                 $event_stats->rows()
     127                        <div class="event-details-stats">
     128                                <h2><?php esc_html_e( 'Stats', 'gp-translation-events' ); ?></h2>
     129                                <table>
     130                                        <thead>
     131                                        <tr>
     132                                                <th scope="col">Locale</th>
     133                                                <th scope="col">Translations created</th>
     134                                                <th scope="col">Translations reviewed</th>
     135                                                <th scope="col">Contributors</th>
     136                                        </tr>
     137                                        </thead>
     138                                        <tbody>
     139                                        <?php /** @var $row Stats_Row */ ?>
     140                                        <?php foreach ( $event_stats->rows() as $_locale => $row ) : ?>
     141                                        <tr>
     142                                                <td title="<?php echo esc_html( $_locale ); ?> "><a href="<?php echo esc_url( gp_url_join( gp_url( '/languages' ), $row->language->slug ) ); ?>"><?php echo esc_html( $row->language->english_name ); ?></a></td>
     143                                                <td><?php echo esc_html( $row->created ); ?></td>
     144                                                <td><?php echo esc_html( $row->reviewed ); ?></td>
     145                                                <td><?php echo esc_html( $row->users ); ?></td>
     146                                        </tr>
     147                                <?php endforeach ?>
     148                                        <tr class="event-details-stats-totals">
     149                                                <td>Total</td>
     150                                                <td><?php echo esc_html( $event_stats->totals()->created ); ?></td>
     151                                                <td><?php echo esc_html( $event_stats->totals()->reviewed ); ?></td>
     152                                                <td><?php echo esc_html( $event_stats->totals()->users ); ?></td>
     153                                        </tr>
     154                                        </tbody>
     155                                </table>
     156                        </div>
     157                        <div class="event-projects">
     158                                <h2><?php esc_html_e( 'Projects', 'gp-translation-events' ); ?></h2>
     159                                <ul>
     160                                        <?php foreach ( $projects as $project_name => $row ) : ?>
     161                                        <li class="event-project" title="<?php echo esc_html( str_replace( ',', ', ', $row->locales ) ); ?>">
     162                                                <a href="<?php echo esc_url( gp_url_project( $row->project ) ); ?>"><?php echo esc_html( $project_name ); ?></a> <small> to
     163                                                <?php
     164                                                foreach ( explode( ',', $row->locales ) as $_locale ) {
     165                                                        $_locale = \GP_Locales::by_slug( $_locale );
     166                                                        ?>
     167                                                        <a href="<?php echo esc_url( gp_url_project_locale( $row->project, $_locale, 'default' ) ); ?>"><?php echo esc_html( $_locale->english_name ); ?></a>
     168                                                        <?php
     169                                                }
     170                                                // translators: %d: Number of contributors.
     171                                                echo esc_html( sprintf( _n( 'by %d contributor', 'by %d contributors', $row->users, 'gp-translation-events' ), $row->users ) );
     172                                                ?>
     173                                                </small>
     174                                        </li>
     175                                <?php endforeach; ?>
     176                                </ul>
     177                        </div>
     178                        <details class="event-stats-summary">
     179                                <summary>View stats summary in text </summary>
     180                                <p class="event-stats-text">
     181                                        <?php
     182                                        echo wp_kses(
     183                                                sprintf(
     184                                                        // translators: %1$s: Event title, %2$d: Number of contributors, %3$d: Number of languages, %4$s: List of languages, %5$d: Number of strings translated, %6$d: Number of strings reviewed.
     185                                                        __( 'At the <strong>%1$s</strong> event, %2$d people contributed in %3$d languages (%4$s), translated %5$d strings and reviewed %6$d strings.', 'gp-translation-events' ),
     186                                                        esc_html( $event_title ),
     187                                                        esc_html( $event_stats->totals()->users ),
     188                                                        count( $event_stats->rows() ),
     189                                                        esc_html(
     190                                                                implode(
     191                                                                        ', ',
     192                                                                        array_map(
     193                                                                                function ( $row ) {
     194                                                                                        return $row->language->english_name;
     195                                                                                },
     196                                                                                $event_stats->rows()
     197                                                                        )
     198                                                                )
     199                                                        ),
     200                                                        esc_html( $event_stats->totals()->created ),
     201                                                        esc_html( $event_stats->totals()->reviewed )
     202                                                ),
     203                                                array(
     204                                                        'strong' => array(),
     205                                                )
     206                                        );
     207                                        ?>
     208                                        <?php
     209                                        echo wp_kses(
     210                                                sprintf(
     211                                                // translators: %s the contributors.
     212                                                        esc_html__( 'Contributors were %s.', 'gp-translation-events' ),
     213                                                        implode(
     214                                                                ', ',
     215                                                                array_map(
     216                                                                        function ( $contributor ) use ( $stats_calculator, $event_start ) {
     217                                                                                $append_tada = $stats_calculator->is_first_time_contributor( $event_start, $contributor->ID ) ? '<span class="first-time-contributor-tada"></span>' : '';
     218                                                                                return '@' . $contributor->user_login . $append_tada;
     219                                                                        },
     220                                                                        $contributors
     221                                                                )
    108222                                                        )
     223                                                ),
     224                                                array(
     225                                                        'span' => array(
     226                                                                'class' => array(),
     227                                                        ),
    109228                                                )
    110                                         ),
    111                                         esc_html( $event_stats->totals()->created ),
    112                                         esc_html( $event_stats->totals()->reviewed )
    113                                 ),
    114                                 array(
    115                                         'strong' => array(),
    116                                 )
    117                         );
    118                         ?>
    119                         <?php
    120                         echo esc_html(
    121                                 sprintf(
    122                                         // translators: %s the contributors.
    123                                         __( 'Contributors were %s.', 'gp-translation-events' ),
    124                                         esc_html(
    125                                                 implode(
    126                                                         ', ',
    127                                                         array_map(
    128                                                                 function ( $contributor ) {
    129                                                                         return '@' . $contributor->user_login;
    130                                                                 },
    131                                                                 $contributors
    132                                                         )
    133                                                 )
    134                                         )
    135                                 )
    136                         );
    137                         ?>
     229                                        );
     230                                        ?>
    138231                        </p>
    139232        </details>
    140 
    141         <?php endif; ?>
     233                <?php endif; ?>
    142234        </div>
    143235        <div class="event-details-right">
    144236                <div class="event-details-date">
    145237                        <p>
    146                                 <span class="event-details-date-label">Starts:</span> <time class="event-utc-time" datetime="<?php echo esc_attr( $event_start ); ?>"></time>
    147                                 <span class="event-details-date-label">Ends:</span><time class="event-utc-time" datetime="<?php echo esc_attr( $event_end ); ?>"></time>
     238                                <span class="event-details-date-label">
     239                                        <?php echo esc_html( $event_start->is_in_the_past() ? __( 'Started', 'gp-translation-events' ) : __( 'Starts', 'gp-translation-events' ) ); ?>:
     240                                        <?php $event_start->print_relative_time_html(); ?>
     241                                </span>
     242                                <?php $event_start->print_time_html(); ?>
     243                                <span class="event-details-date-label">
     244                                        <?php echo esc_html( $event_end->is_in_the_past() ? __( 'Ended', 'gp-translation-events' ) : __( 'Ends', 'gp-translation-events' ) ); ?>:
     245                                        <?php $event_end->print_relative_time_html(); ?>
     246
     247                                </span>
     248                                <?php $event_end->print_time_html(); ?>
    148249                        </p>
    149250                </div>
    150251                <?php if ( is_user_logged_in() ) : ?>
    151252                <div class="event-details-join">
    152                         <?php
    153                         $current_time = gmdate( 'Y-m-d H:i:s' );
    154                         if ( strtotime( $current_time ) > strtotime( $event_end ) ) :
    155                                 ?>
    156                                 <?php if ( $user_is_attending ) : ?>
    157                                         <span class="event-details-join-expired"><?php esc_html_e( 'You attended', 'gp-translation-events' ); ?></span>
    158                                 <?php endif ?>
     253                        <?php if ( $event_end->is_in_the_past() ) : ?>
     254                                <?php if ( $attendee instanceof Attendee ) : ?>
     255                                        <button disabled="disabled" class="button is-primary attend-btn"><?php esc_html_e( 'You attended', 'gp-translation-events' ); ?></button>
     256                                <?php endif; ?>
    159257                        <?php else : ?>
    160258                                <form class="event-details-attend" method="post" action="<?php echo esc_url( gp_url( "/events/attend/$event_id" ) ); ?>">
    161                                         <?php if ( ! $user_is_attending ) : ?>
     259                                        <?php if ( $attendee instanceof Attendee ) : ?>
     260                                                <?php if ( $attendee->is_host() && ( 1 === count( $attendee_repo->get_hosts( $event_id ) ) ) ) : ?>
     261                                                        <input type="submit" class="button is-secondary attending-btn" disabled value="You're attending" />
     262                                                <?php else : ?>
     263                                                        <input type="submit" class="button is-secondary attending-btn" value="You're attending" />
     264                                                <?php endif; ?>
     265                                        <?php else : ?>
    162266                                                <input type="submit" class="button is-primary attend-btn" value="Attend Event"/>
    163                                         <?php else : ?>
    164                                                 <input type="submit" class="button is-secondary attending-btn" value="You're attending"/>
    165                                         <?php endif ?>
     267                                        <?php endif; ?>
    166268                                </form>
    167                         <?php endif ?>
     269                        <?php endif; ?>
    168270                </div>
    169271                <?php else : ?>
    170272                <div class="event-details-join">
    171273                        <p>
    172                                 <?php global $wp; ?>
    173                                 <a href="<?php echo esc_url( wp_login_url( home_url( $wp->request ) ) ); ?>" class="button is-primary attend-btn"><?php esc_html_e( 'Login to attend', 'gp-translation-events' ); ?></a>
     274                                <?php if ( ! $event_end->is_in_the_past() ) : ?>
     275                                        <a href="<?php echo esc_url( wp_login_url() ); ?>" class="button is-primary attend-btn"><?php esc_html_e( 'Login to attend', 'gp-translation-events' ); ?></a>
     276                                <?php else : ?>
     277                                        <button disabled="disabled" class="button is-primary attend-btn"><?php esc_html_e( 'Event is over', 'gp-translation-events' ); ?></button>
     278                                <?php endif; ?>
    174279                        </p>
    175280                </div>
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/templates/events-form.php

    r13268 r13529  
    66namespace Wporg\TranslationEvents;
    77
    8 /** @var string $event_form_title */
     8use DateTimeZone;
     9use Wporg\TranslationEvents\Event\Event_End_Date;
     10use Wporg\TranslationEvents\Event\Event_Start_Date;
     11
     12/** @var string $event_page_title */
    913/** @var string $event_form_name */
    10 /** @var int $event_id */
     14/** @var int    $event_id */
    1115/** @var string $event_title */
    1216/** @var string $event_description */
    13 /** @var string $event_start */
    14 /** @var string $event_end */
    15 /** @var string $event_timezone */
     17/** @var Event_Start_Date $event_start */
     18/** @var Event_End_Date $event_end */
     19/** @var DateTimeZone|null $event_timezone */
    1620/** @var string $event_url */
    1721/** @var string $css_show_url */
    1822
    19 gp_title( __( 'Translation Events' ) . ' - ' . esc_html( $event_form_title . ' - ' . $event_title ) );
    20 gp_breadcrumb_translation_events( array( esc_html( $event_form_title ) ) );
     23gp_title( __( 'Translation Events' ) . ' - ' . esc_html( $event_page_title . ' - ' . $event_title ) );
     24gp_breadcrumb_translation_events( array( esc_html( $event_page_title ) ) );
    2125gp_tmpl_header();
    2226gp_tmpl_load( 'events-header', get_defined_vars(), __DIR__ );
    2327?>
    2428<div class="event-page-wrapper">
    25 <h2 class="event-page-title"><?php echo esc_html( $event_form_title ); ?></h2>
    2629<form class="translation-event-form" action="" method="post">
    2730        <?php wp_nonce_field( '_event_nonce', '_event_nonce' ); ?>
    … …  
    4144                <label for="event-description">Event Description</label>
    4245                <textarea id="event-description" name="event_description" rows="4" required><?php echo esc_html( $event_description ); ?></textarea>
    43         </div>
    44         <div>
     46                <?php
     47                echo wp_kses(
     48                        Event_Text_Snippet::get_snippet_links(),
     49                        array(
     50                                'a'  => array(
     51                                        'href'         => array(),
     52                                        'data-snippet' => array(),
     53                                        'class'        => array(),
     54                                ),
     55                                'ul' => array( 'class' => array() ),
     56                                'li' => array(),
     57                        )
     58                );
     59                ?>
     60                        <div>
    4561                <label for="event-start">Start Date</label>
    46                 <input type="datetime-local" id="event-start" name="event_start" value="<?php echo esc_attr( $event_start ); ?>" required>
     62                <input type="datetime-local" id="event-start" name="event_start" value="<?php echo esc_attr( $event_start->format( 'Y-m-d H:i' ) ); ?>" required>
    4763        </div>
    4864        <div>
    4965                <label for="event-end">End Date</label>
    50                 <input type="datetime-local" id="event-end" name="event_end" value="<?php echo esc_attr( $event_end ); ?>" required>
     66                <input type="datetime-local" id="event-end" name="event_end" value="<?php echo esc_attr( $event_end->format( 'Y-m-d H:i' ) ); ?>" required>
    5167        </div>
    5268        <div>
    5369                <label for="event-timezone">Event Timezone</label>
    54                 <select id="event-timezone" name="event_timezone"  required>
     70                <select id="event-timezone" name="event_timezone" required>
    5571                        <?php
    5672                        echo wp_kses(
    57                                 wp_timezone_choice( $event_timezone, get_user_locale() ),
     73                                wp_timezone_choice( $event_timezone ? $event_timezone->getName() : null, get_user_locale() ),
    5874                                array(
    5975                                        'optgroup' => array( 'label' => array() ),
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/templates/events-header.php

    r13268 r13529  
    11<?php
     2
    23namespace Wporg\TranslationEvents;
    34
    45use GP;
     6use Wporg\TranslationEvents\Attendee\Attendee;
     7use Wporg\TranslationEvents\Event\Event;
     8
     9/** @var Attendee $attendee */
     10/** @var Event  $event */
     11/** @var string $event_page_title */
     12/** @var bool   $is_editable_event */
    513?>
    614
    715<div class="event-list-top-bar">
     16<h2 class="event-page-title">
     17        <?php echo esc_html( $event_page_title ); ?>
     18        <?php if ( isset( $event ) && 'draft' === $event->status() ) : ?>
     19                                <span class="event-label-draft"><?php echo esc_html( $event->status() ); ?></span>
     20                        <?php endif; ?>
     21</h2>
    822        <ul class="event-list-nav">
    923                <?php if ( is_user_logged_in() ) : ?>
    … …  
    2236                <?php endif; ?>
    2337        </ul>
     38        <?php if ( isset( $event ) && ! isset( $event_form_name ) ) : ?>
     39        <p class="event-sub-head">
     40                        <span class="event-host">
     41                                <?php
     42                                if ( 1 === count( $hosts ) ) :
     43                                        esc_html_e( 'Host:', 'gp-translation-events' );
     44                                else :
     45                                        esc_html_e( 'Hosts:', 'gp-translation-events' );
     46                                endif;
     47                                ?>
     48                                <?php foreach ( $hosts as $host ) : ?>
     49                                        <?php $user = get_userdata( $host->user_id() ); ?>
     50                                        &nbsp;<a href="<?php echo esc_attr( get_author_posts_url( $user->ID ) ); ?>"><?php echo esc_html( get_the_author_meta( 'display_name', $user->ID ) ); ?></a>
     51                                        <?php if ( end( $hosts ) !== $host ) : ?>
     52                                                ,
     53                                        <?php endif; ?>
     54                                <?php endforeach; ?>
     55                        .</span>
     56                        <?php $show_edit_button = ( ( $attendee instanceof Attendee && $attendee->is_host() ) || current_user_can( 'edit_post', $event->id() ) ) && $is_editable_event; ?>
     57                        <?php if ( $show_edit_button ) : ?>
     58                                <a class="event-page-edit-link" href="<?php echo esc_url( gp_url( 'events/edit/' . $event->id() ) ); ?>"><span class="dashicons dashicons-edit"></span><?php esc_html_e( 'Edit event', 'gp-translation-events' ); ?></a>
     59                        <?php endif ?>
     60                </p>
     61                <?php endif; ?>
     62
    2463</div>
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/templates/events-list.php

    r13268 r13529  
    88use DateTime;
    99use WP_Query;
     10use Wporg\TranslationEvents\Event\Event;
     11use Wporg\TranslationEvents\Event\Events_Query_Result;
    1012
    11 /** @var WP_Query $current_events_query */
    12 /** @var WP_Query $upcoming_events_query */
    13 /** @var WP_Query $past_events_query */
     13/** @var Events_Query_Result $current_events_query */
     14/** @var Events_Query_Result $upcoming_events_query */
     15/** @var Events_Query_Result $past_events_query */
     16/** @var Events_Query_Result $user_attending_events_query */
    1417
    1518gp_title( __( 'Translation Events', 'gp-translation-events' ) );
    1619gp_breadcrumb_translation_events();
    1720gp_tmpl_header();
     21$event_page_title = __( 'Translation Events', 'gp-translation-events' );
    1822gp_tmpl_load( 'events-header', get_defined_vars(), __DIR__ );
    1923?>
    2024
    2125<div class="event-page-wrapper">
    22         <h1 class="event_page_title"><?php esc_html_e( 'Translation Events', 'gp-translation-events' ); ?></h1>
    2326<div class="event-left-col">
    2427<?php
    25 if ( $current_events_query->have_posts() ) :
     28if ( ! empty( $current_events_query->events ) ) :
    2629        ?>
    2730        <h2><?php esc_html_e( 'Current events', 'gp-translation-events' ); ?></h2>
    2831        <ul class="event-list">
    2932                <?php
    30                 while ( $current_events_query->have_posts() ) :
    31                         $current_events_query->the_post();
    32                         $event_end = Event::get_end_date_text( get_post_meta( get_the_ID(), '_event_end', true ) );
    33                         $event_url = gp_url( wp_make_link_relative( get_the_permalink() ) );
     33                foreach ( $current_events_query->events as $event ) :
     34                        $event_url = gp_url( wp_make_link_relative( get_the_permalink( $event->id() ) ) );
    3435                        ?>
    3536                        <li class="event-list-item">
    36                                 <a href="<?php echo esc_url( $event_url ); ?>"><?php the_title(); ?></a>
    37                                 <span class="event-list-date"><?php echo esc_html( $event_end ); ?></span>
    38                                 <?php the_excerpt(); ?>
     37                                <a href="<?php echo esc_url( $event_url ); ?>"><?php echo esc_html( $event->title() ); ?></a>
     38                                <span class="event-list-date">ends <?php $event->end()->print_relative_time_html(); ?></time></span>
     39                                <?php echo esc_html( get_the_excerpt( $event->id() ) ); ?>
    3940                        </li>
    4041                        <?php
    41                 endwhile;
     42                endforeach;
    4243                ?>
    4344        </ul>
    … …  
    4748                paginate_links(
    4849                        array(
    49                                 'total'     => $current_events_query->max_num_pages,
    50                                 'current'   => max( 1, $current_events_query->query_vars['paged'] ),
     50                                'total'     => $current_events_query->page_count,
     51                                'current'   => $current_events_query->current_page,
    5152                                'format'    => '?current_events_paged=%#%',
    5253                                'prev_text' => '&laquo; Previous',
    … …  
    5859        wp_reset_postdata();
    5960endif;
    60 if ( $upcoming_events_query->have_posts() ) :
     61
     62if ( ! empty( $upcoming_events_query->events ) ) :
    6163        ?>
    6264        <h2><?php esc_html_e( 'Upcoming events', 'gp-translation-events' ); ?></h2>
    6365        <ul class="event-list">
    6466                <?php
    65                 while ( $upcoming_events_query->have_posts() ) :
    66                         $upcoming_events_query->the_post();
    67                         $event_start = ( new DateTime( get_post_meta( get_the_ID(), '_event_start', true ) ) )->format( 'l, F j, Y' );
     67                foreach ( $upcoming_events_query->events as $event ) :
     68                        $event_url = gp_url( wp_make_link_relative( get_the_permalink( $event->id() ) ) );
    6869                        ?>
    6970                        <li class="event-list-item">
    70                                 <a href="<?php echo esc_url( gp_url( wp_make_link_relative( get_the_permalink() ) ) ); ?>"><?php the_title(); ?></a>
    71                                 <span class="event-list-date"><?php echo esc_html( $event_start ); ?></span>
    72                                 <?php the_excerpt(); ?>
     71                                <a href="<?php echo esc_url( $event_url ); ?>"><?php echo esc_html( $event->title() ); ?></a>
     72                                <span class="event-list-date">starts <?php $event->start()->print_relative_time_html(); ?></span>
     73                                <?php echo esc_html( get_the_excerpt( $event->id() ) ); ?>
    7374                        </li>
    7475                        <?php
    75                 endwhile;
     76                endforeach;
    7677                ?>
    7778        </ul>
    … …  
    8182                paginate_links(
    8283                        array(
    83                                 'total'     => $upcoming_events_query->max_num_pages,
    84                                 'current'   => max( 1, $upcoming_events_query->query_vars['paged'] ),
     84                                'total'     => $upcoming_events_query->page_count,
     85                                'current'   => $upcoming_events_query->current_page,
    8586                                'format'    => '?upcoming_events_paged=%#%',
    8687                                'prev_text' => '&laquo; Previous',
    … …  
    9293        wp_reset_postdata();
    9394endif;
    94 if ( $past_events_query->have_posts() ) :
     95if ( ! empty( $past_events_query->events ) ) :
    9596        ?>
    9697        <h2><?php esc_html_e( 'Past events', 'gp-translation-events' ); ?></h2>
    9798        <ul class="event-list">
    9899                <?php
    99                 while ( $past_events_query->have_posts() ) :
    100                         $past_events_query->the_post();
    101                         $event_start = ( new DateTime( get_post_meta( get_the_ID(), '_event_start', true ) ) )->format( 'M j, Y' );
    102                         $event_end   = ( new DateTime( get_post_meta( get_the_ID(), '_event_end', true ) ) )->format( 'M j, Y' );
     100                foreach ( $past_events_query->events as $event ) :
     101                        $event_url = gp_url( wp_make_link_relative( get_the_permalink( $event->id() ) ) );
    103102                        ?>
    104103                        <li class="event-list-item">
    105                                 <a href="<?php echo esc_url( gp_url( wp_make_link_relative( get_the_permalink() ) ) ); ?>"><?php the_title(); ?></a>
    106                                 <?php if ( $event_start === $event_end ) : ?>
    107                                         <span class="event-list-date"><?php echo esc_html( $event_start ); ?></span>
    108                                 <?php else : ?>
    109                                         <span class="event-list-date"><?php echo esc_html( $event_start ); ?> - <?php echo esc_html( $event_end ); ?></span>
    110                                 <?php endif; ?>
    111                                 <?php the_excerpt(); ?>
     104                                <a href="<?php echo esc_url( $event_url ); ?>"><?php echo esc_html( $event->title() ); ?></a>
     105                                <span class="event-list-date">ended <?php $event->end()->print_relative_time_html( 'F j, Y H:i T' ); ?></span>
     106                                <?php esc_html( get_the_excerpt( $event->id() ) ); ?>
    112107                        </li>
    113108                        <?php
    114                 endwhile;
     109                endforeach;
    115110                ?>
    116111        </ul>
    … …  
    120115                paginate_links(
    121116                        array(
    122                                 'total'     => $past_events_query->max_num_pages,
    123                                 'current'   => max( 1, $past_events_query->query_vars['paged'] ),
     117                                'total'     => $past_events_query->page_count,
     118                                'current'   => $past_events_query->current_page,
    124119                                'format'    => '?past_events_paged=%#%',
    125120                                'prev_text' => '&laquo; Previous',
    … …  
    132127endif;
    133128
    134 if ( 0 === $current_events_query->post_count && 0 === $upcoming_events_query->post_count && 0 === $past_events_query->post_count ) :
     129if ( empty( $current_events_query->events ) && empty( $upcoming_events_query->events ) && empty( $past_events_query->post_count ) ) :
    135130        esc_html_e( 'No events found.', 'gp-translation-events' );
    136131endif;
    … …  
    139134<?php if ( is_user_logged_in() ) : ?>
    140135        <div class="event-right-col">
    141                 <h3 class="">Events I'm Attending</h3>
    142                 <?php if ( ! $user_attending_events_query->have_posts() ) : ?>
     136                <h2>Events I'm Attending</h2>
     137                <?php if ( empty( $user_attending_events_query->events ) ) : ?>
    143138                        <p>You don't have any events to attend.</p>
    144139                <?php else : ?>
    145140                        <ul class="event-attending-list">
    146141                                <?php
    147                                 while ( $user_attending_events_query->have_posts() ) :
    148                                         $user_attending_events_query->the_post();
    149                                         $event_start = ( new DateTime( get_post_meta( get_the_ID(), '_event_start', true ) ) )->format( 'M j, Y' );
    150                                         $event_end   = ( new DateTime( get_post_meta( get_the_ID(), '_event_end', true ) ) )->format( 'M j, Y' );
     142                                foreach ( $user_attending_events_query->events as $event ) :
     143                                        $event_url = gp_url( wp_make_link_relative( get_the_permalink( $event->id() ) ) );
    151144                                        ?>
    152145                                        <li class="event-list-item">
    153                                                 <a href="<?php echo esc_url( gp_url( wp_make_link_relative( get_the_permalink() ) ) ); ?>"><?php the_title(); ?></a>
    154                                                 <?php if ( $event_start === $event_end ) : ?>
    155                                                         <span class="event-list-date events-i-am-attending"><?php echo esc_html( $event_start ); ?></span>
     146                                                <a href="<?php echo esc_url( $event_url ); ?>"><?php echo esc_html( $event->title() ); ?></a>
     147                                                <?php if ( $event->start() === $event->end() ) : ?>
     148                                                        <span class="event-list-date events-i-am-attending"><?php $event->start()->print_time_html( 'F j, Y H:i T' ); ?></span>
    156149                                                <?php else : ?>
    157                                                         <span class="event-list-date events-i-am-attending"><?php echo esc_html( $event_start ); ?> - <?php echo esc_html( $event_end ); ?></span>
     150                                                        <span class="event-list-date events-i-am-attending"><?php $event->start()->print_time_html( 'F j, Y H:i T' ); ?> - <?php $event->end()->print_time_html( 'F j, Y H:i T' ); ?></span>
    158151                                                <?php endif; ?>
    159152                                        </li>
    160153                                        <?php
    161                                 endwhile;
     154                                endforeach;
    162155                                ?>
    163156                        </ul>
    … …  
    166159                                        paginate_links(
    167160                                                array(
    168                                                         'total'     => $user_attending_events_query->max_num_pages,
    169                                                         'current'   => max( 1, $user_attending_events_query->query_vars['paged'] ),
     161                                                        'total'     => $user_attending_events_query->page_count,
     162                                                        'current'   => $user_attending_events_query->current_page,
    170163                                                        'format'    => '?user_attending_events_paged=%#%',
    171164                                                        'prev_text' => '&laquo; Previous',
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/templates/events-my-events.php

    r13268 r13529  
    66namespace Wporg\TranslationEvents;
    77
    8 use DateTime;
    9 use WP_Query;
     8use Wporg\TranslationEvents\Event\Events_Query_Result;
    109
    11 /** @var WP_Query $events_i_created_query */
    12 /** @var WP_Query $events_i_attended_query */
     10/** @var Events_Query_Result $events_i_created_query */
     11/** @var Events_Query_Result $events_i_host_query */
     12/** @var Events_Query_Result $events_i_attended_query */
    1313
    1414gp_title( esc_html__( 'Translation Events', 'gp-translation-events' ) . ' - ' . esc_html__( 'My Events', 'gp-translation-events' ) );
    1515gp_breadcrumb_translation_events( array( esc_html__( 'My Events', 'gp-translation-events' ) ) );
    1616gp_tmpl_header();
     17$event_page_title = __( 'My Events', 'gp-translation-events' );
    1718gp_tmpl_load( 'events-header', get_defined_vars(), __DIR__ );
    1819?>
    1920
    2021<div class="event-page-wrapper">
    21         <h1 class="event_page_title"><?php esc_html_e( 'My Events', 'gp-translation-events' ); ?> </h1>
    22         <h2 class="event_page_title"><?php esc_html_e( 'Events I have created', 'gp-translation-events' ); ?> </h2>
    23         <?php if ( $events_i_created_query->have_posts() ) : ?>
     22        <?php if ( ! empty( $events_i_host_query->events ) ) : ?>
     23                <h2><?php esc_html_e( 'Events I host', 'gp-translation-events' ); ?> </h2>
    2424                <ul>
    2525                <?php
    26                 while ( $events_i_created_query->have_posts() ) :
    27                         $events_i_created_query->the_post();
    28                         $event_id                      = get_the_ID();
    29                         $event_start                   = get_post_meta( $event_id, '_event_start', true );
    30                         list( $permalink, $post_name ) = get_sample_permalink( $event_id );
     26                foreach ( $events_i_host_query->events as $event ) :
     27                        list( $permalink, $post_name ) = get_sample_permalink( $event->id() );
    3128                        $permalink                     = str_replace( '%pagename%', $post_name, $permalink );
    3229                        $event_url                     = gp_url( wp_make_link_relative( $permalink ) );
    33                         $event_edit_url                = gp_url( 'events/edit/' . $event_id );
    34                         $event_status                  = get_post_status( $event_id );
    35                         $event_start                   = ( new DateTime( get_post_meta( get_the_ID(), '_event_start', true ) ) )->format( 'M j, Y' );
    36                         $event_end                     = ( new DateTime( get_post_meta( get_the_ID(), '_event_end', true ) ) )->format( 'M j, Y' );
     30                        $event_edit_url                = gp_url( 'events/edit/' . $event->id() );
     31                        $stats_calculator              = new Stats_Calculator();
     32                        $has_stats                     = $stats_calculator->event_has_stats( $event->id() );
    3733                        ?>
    3834                        <li class="event-list-item">
    39                                 <a class="event-link-<?php echo esc_attr( $event_status ); ?>" href="<?php echo esc_url( $event_url ); ?>"><?php the_title(); ?></a>
    40                                 <a href="<?php echo esc_url( $event_edit_url ); ?>" class="button is-small action edit">Edit</a>
    41                                 <?php if ( 'draft' === $event_status ) : ?>
    42                                         <span class="event-label-<?php echo esc_attr( $event_status ); ?>"><?php echo esc_html( $event_status ); ?></span>
     35                                <a class="event-link-<?php echo esc_attr( $event->status() ); ?>" href="<?php echo esc_url( $event_url ); ?>"><?php echo esc_html( $event->title() ); ?></a>
     36                                <?php if ( ! $event->end()->is_in_the_past() && ! $has_stats ) : ?>
     37                                        <a href="<?php echo esc_url( $event_edit_url ); ?>" class="button is-small action edit">Edit</a>
    4338                                <?php endif; ?>
    44                                 <?php if ( $event_start === $event_end ) : ?>
    45                                         <span class="event-list-date events-i-am-attending"><?php echo esc_html( $event_start ); ?></span>
     39                                <?php if ( 'draft' === $event->status() ) : ?>
     40                                        <span class="event-label-<?php echo esc_attr( $event->status() ); ?>"><?php echo esc_html( $event->status() ); ?></span>
     41                                <?php endif; ?>
     42                                <?php if ( $event->start()->format( 'Y-m-d' ) === $event->end()->format( 'Y-m-d' ) ) : ?>
     43                                        <span class="event-list-date events-i-am-attending"><?php $event->start()->print_time_html(); ?></span>
    4644                                <?php else : ?>
    47                                         <span class="event-list-date events-i-am-attending"><?php echo esc_html( $event_start ); ?> - <?php echo esc_html( $event_end ); ?></span>
     45                                        <span class="event-list-date events-i-am-attending"><?php $event->start()->print_time_html(); ?> - <?php $event->end()->print_time_html(); ?></span>
    4846                                <?php endif; ?>
    49                                 <p><?php the_excerpt(); ?></p>
     47                                <p><?php echo esc_html( get_the_excerpt( $event->id() ) ); ?></p>
    5048                        </li>
    51                 <?php endwhile; ?>
     49                <?php endforeach; ?>
    5250                </ul>
    5351
    … …  
    5654                        paginate_links(
    5755                                array(
    58                                         'total'     => $events_i_created_query->max_num_pages,
    59                                         'current'   => max( 1, $events_i_created_query->query_vars['events_i_created_paged'] ),
     56                                        'total'     => $events_i_host_query->page_count,
     57                                        'current'   => $events_i_host_query->current_page,
     58                                        'format'    => '?events_i_hosted_paged=%#%',
     59                                        'prev_text' => '&laquo; Previous',
     60                                        'next_text' => 'Next &raquo;',
     61                                )
     62                        ) ?? ''
     63                );
     64
     65                wp_reset_postdata();
     66        endif;
     67        ?>
     68
     69        <?php if ( ! empty( $events_i_created_query->events ) ) : ?>
     70                <h2><?php esc_html_e( 'Events I have created', 'gp-translation-events' ); ?> </h2>
     71                <ul>
     72                        <?php
     73                        foreach ( $events_i_created_query->events as $event ) :
     74                                list( $permalink, $post_name ) = get_sample_permalink( $event->id() );
     75                                $permalink                     = str_replace( '%pagename%', $post_name, $permalink );
     76                                $event_url                     = gp_url( wp_make_link_relative( $permalink ) );
     77                                $event_edit_url                = gp_url( 'events/edit/' . $event->id() );
     78                                $stats_calculator              = new Stats_Calculator();
     79                                $has_stats                     = $stats_calculator->event_has_stats( $event->id() );
     80                                ?>
     81                                <li class="event-list-item">
     82                                        <a class="event-link-<?php echo esc_attr( $event->status() ); ?>" href="<?php echo esc_url( $event_url ); ?>"><?php echo esc_html( $event->title() ); ?></a>
     83                                        <?php if ( ! $event->end()->is_in_the_past() && ! $has_stats ) : ?>
     84                                                <a href="<?php echo esc_url( $event_edit_url ); ?>" class="button is-small action edit">Edit</a>
     85                                        <?php endif; ?>
     86                                        <?php if ( 'draft' === $event->status() ) : ?>
     87                                                <span class="event-label-<?php echo esc_attr( $event->status() ); ?>"><?php echo esc_html( $event->status() ); ?></span>
     88                                        <?php endif; ?>
     89                                        <?php if ( $event->start()->format( 'Y-m-d' ) === $event->end()->format( 'Y-m-d' ) ) : ?>
     90                                                <span class="event-list-date events-i-am-attending"><?php $event->start()->print_time_html(); ?></span>
     91                                        <?php else : ?>
     92                                                <span class="event-list-date events-i-am-attending"><?php $event->start()->print_time_html(); ?> - <?php $event->end()->print_time_html(); ?></span>
     93                                        <?php endif; ?>
     94                                        <p><?php echo esc_html( get_the_excerpt( $event->id() ) ); ?></p>
     95                                </li>
     96                        <?php endforeach; ?>
     97                </ul>
     98
     99                <?php
     100                echo wp_kses_post(
     101                        paginate_links(
     102                                array(
     103                                        'total'     => $events_i_created_query->page_count,
     104                                        'current'   => $events_i_created_query->current_page,
    60105                                        'format'    => '?events_i_created_paged=%#%',
    61106                                        'prev_text' => '&laquo; Previous',
    … …  
    66111
    67112                wp_reset_postdata();
    68         else :
    69                 echo 'No events found.';
    70113        endif;
    71114        ?>
    72115
    73         <h2 class="event_page_title"><?php esc_html_e( 'Events I attended', 'gp-translation-events' ); ?> </h2>
    74         <?php if ( $events_i_attended_query->have_posts() ) : ?>
     116        <h2><?php esc_html_e( 'Events I attended', 'gp-translation-events' ); ?> </h2>
     117        <?php if ( ! empty( $events_i_attended_query->events ) ) : ?>
    75118                <ul>
    76119                <?php
    77                 while ( $events_i_attended_query->have_posts() ) :
    78                         $events_i_attended_query->the_post();
    79                         $event_id                      = get_the_ID();
    80                         $event_start                   = get_post_meta( $event_id, '_event_start', true );
    81                         list( $permalink, $post_name ) = get_sample_permalink( $event_id );
     120                foreach ( $events_i_attended_query->events as $event ) :
     121                        list( $permalink, $post_name ) = get_sample_permalink( $event->id() );
    82122                        $permalink                     = str_replace( '%pagename%', $post_name, $permalink );
    83123                        $event_url                     = gp_url( wp_make_link_relative( $permalink ) );
    84                         $event_edit_url                = gp_url( 'events/edit/' . $event_id );
    85                         $event_status                  = get_post_status( $event_id );
    86                         $event_start                   = ( new DateTime( get_post_meta( get_the_ID(), '_event_start', true ) ) )->format( 'M j, Y' );
    87                         $event_end                     = ( new DateTime( get_post_meta( get_the_ID(), '_event_end', true ) ) )->format( 'M j, Y' );
    88124                        ?>
    89125                        <li class="event-list-item">
    90                                 <a class="event-link-<?php echo esc_attr( $event_status ); ?>" href="<?php echo esc_url( $event_url ); ?>"><?php the_title(); ?></a>
    91                                 <?php if ( $event_start === $event_end ) : ?>
    92                                         <span class="event-list-date events-i-am-attending"><?php echo esc_html( $event_start ); ?></span>
     126                                <a class="event-link-<?php echo esc_attr( $event->status() ); ?>" href="<?php echo esc_url( $event_url ); ?>"><?php echo esc_html( $event->title() ); ?></a>
     127                                <?php if ( $event->start() === $event->end() ) : ?>
     128                                        <span class="event-list-date events-i-am-attending"><?php $event->start()->print_time_html(); ?></span>
    93129                                <?php else : ?>
    94                                         <span class="event-list-date events-i-am-attending"><?php echo esc_html( $event_start ); ?> - <?php echo esc_html( $event_end ); ?></span>
     130                                        <span class="event-list-date events-i-am-attending"><?php $event->start()->print_time_html(); ?> - <?php $event->end()->print_time_html(); ?></span>
    95131                                <?php endif; ?>
    96                                 <p><?php the_excerpt(); ?></p>
     132                                <p><?php echo esc_html( get_the_excerpt( $event->id() ) ); ?></p>
    97133                        </li>
    98                 <?php endwhile; ?>
     134                <?php endforeach; ?>
    99135                </ul>
    100136
    … …  
    103139                        paginate_links(
    104140                                array(
    105                                         'total'     => $events_i_attended_query->max_num_pages,
    106                                         'current'   => max( 1, $events_i_attended_query->query_vars['events_i_attended_paged'] ),
     141                                        'total'     => $events_i_attended_query->page_count,
     142                                        'current'   => $events_i_attended_query->current_page,
    107143                                        'format'    => '?events_i_attended_paged=%#%',
    108144                                        'prev_text' => '&laquo; Previous',
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/wporg-gp-translation-events.php

    r13298 r13529  
    2525use WP_Post;
    2626use WP_Query;
     27use Wporg\TranslationEvents\Attendee\Attendee;
     28use Wporg\TranslationEvents\Attendee\Attendee_Repository;
     29use Wporg\TranslationEvents\Event\Event_Form_Handler;
     30use Wporg\TranslationEvents\Event\Event_Repository_Cached;
     31use Wporg\TranslationEvents\Event\Event_Repository_Interface;
    2732
    2833class Translation_Events {
    29         public const CPT                     = 'translation_event';
    30         public const USER_META_KEY_ATTENDING = 'translation-events-attending';
    31 
    32         public static function get_instance() {
     34        public const CPT = 'translation_event';
     35
     36        public static function get_instance(): Translation_Events {
    3337                static $instance = null;
    3438                if ( null === $instance ) {
     39                        require_once __DIR__ . '/autoload.php';
    3540                        $instance = new self();
    3641                }
    … …  
    3843        }
    3944
     45        public static function get_event_repository(): Event_Repository_Interface {
     46                static $event_repository = null;
     47                if ( null === $event_repository ) {
     48                        $event_repository = new Event_Repository_Cached( self::get_attendee_repository() );
     49                }
     50                return $event_repository;
     51        }
     52
     53        public static function get_attendee_repository(): Attendee_Repository {
     54                static $attendee_repository = null;
     55                if ( null === $attendee_repository ) {
     56                        $attendee_repository = new Attendee_Repository();
     57                }
     58                return $attendee_repository;
     59        }
     60
    4061        public function __construct() {
    41                 \add_action( 'wp_ajax_submit_event_ajax', array( $this, 'submit_event_ajax' ) );
    42                 \add_action( 'wp_ajax_nopriv_submit_event_ajax', array( $this, 'submit_event_ajax' ) );
    43                 \add_action( 'wp_enqueue_scripts', array( $this, 'register_translation_event_js' ) );
    44                 \add_action( 'init', array( $this, 'register_event_post_type' ) );
    45                 \add_action( 'add_meta_boxes', array( $this, 'event_meta_boxes' ) );
    46                 \add_action( 'save_post', array( $this, 'save_event_meta_boxes' ) );
    47                 \add_action( 'transition_post_status', array( $this, 'event_status_transition' ), 10, 3 );
    48                 \add_filter( 'gp_nav_menu_items', array( $this, 'gp_event_nav_menu_items' ), 10, 2 );
    49                 \add_filter( 'wp_insert_post_data', array( $this, 'generate_event_slug' ), 10, 2 );
    50                 \add_action( 'gp_init', array( $this, 'gp_init' ) );
    51                 \add_action( 'gp_before_translation_table', array( $this, 'add_active_events_current_user' ) );
    52                 \register_activation_hook( __FILE__, array( $this, 'activate' ) );
     62                add_action( 'wp_ajax_submit_event_ajax', array( $this, 'submit_event_ajax' ) );
     63                add_action( 'wp_ajax_nopriv_submit_event_ajax', array( $this, 'submit_event_ajax' ) );
     64                add_action( 'wp_enqueue_scripts', array( $this, 'register_translation_event_js' ) );
     65                add_action( 'init', array( $this, 'register_event_post_type' ) );
     66                add_action( 'add_meta_boxes', array( $this, 'event_meta_boxes' ) );
     67                add_action( 'save_post', array( $this, 'save_event_meta_boxes' ) );
     68                add_action( 'transition_post_status', array( $this, 'event_status_transition' ), 10, 3 );
     69                add_filter( 'gp_nav_menu_items', array( $this, 'gp_event_nav_menu_items' ), 10, 2 );
     70                add_filter( 'wp_insert_post_data', array( $this, 'generate_event_slug' ), 10, 2 );
     71                add_action( 'gp_init', array( $this, 'gp_init' ) );
     72                add_action( 'gp_before_translation_table', array( $this, 'add_active_events_current_user' ) );
     73
     74                if ( is_admin() ) {
     75                        Upgrade::upgrade_if_needed();
     76                }
    5377        }
    5478
    5579        public function gp_init() {
    56                 require_once __DIR__ . '/templates/helper-functions.php';
    57                 require_once __DIR__ . '/includes/active-events-cache.php';
    58                 require_once __DIR__ . '/includes/event.php';
    59                 require_once __DIR__ . '/includes/routes/route.php';
    60                 require_once __DIR__ . '/includes/routes/event/create.php';
    61                 require_once __DIR__ . '/includes/routes/event/details.php';
    62                 require_once __DIR__ . '/includes/routes/event/edit.php';
    63                 require_once __DIR__ . '/includes/routes/event/list.php';
    64                 require_once __DIR__ . '/includes/routes/user/attend-event.php';
    65                 require_once __DIR__ . '/includes/routes/user/my-events.php';
    66                 require_once __DIR__ . '/includes/stats-calculator.php';
    67                 require_once __DIR__ . '/includes/stats-listener.php';
    68 
    6980                GP::$router->add( '/events?', array( 'Wporg\TranslationEvents\Routes\Event\List_Route', 'handle' ) );
    7081                GP::$router->add( '/events/new', array( 'Wporg\TranslationEvents\Routes\Event\Create_Route', 'handle' ) );
    7182                GP::$router->add( '/events/edit/(\d+)', array( 'Wporg\TranslationEvents\Routes\Event\Edit_Route', 'handle' ) );
    7283                GP::$router->add( '/events/attend/(\d+)', array( 'Wporg\TranslationEvents\Routes\User\Attend_Event_Route', 'handle' ), 'post' );
     84                GP::$router->add( '/events/host/(\d+)/(\d+)', array( 'Wporg\TranslationEvents\Routes\User\Host_Event_Route', 'handle' ), 'post' );
    7385                GP::$router->add( '/events/my-events', array( 'Wporg\TranslationEvents\Routes\User\My_Events_Route', 'handle' ) );
    7486                GP::$router->add( '/events/([a-z0-9_-]+)', array( 'Wporg\TranslationEvents\Routes\Event\Details_Route', 'handle' ) );
    7587
    76                 $active_events_cache = new Active_Events_Cache();
    77                 $stats_listener      = new Stats_Listener( $active_events_cache );
     88                $stats_listener = new Stats_Listener(
     89                        self::get_event_repository(),
     90                        self::get_attendee_repository(),
     91                );
    7892                $stats_listener->start();
    79         }
    80 
    81         public function activate() {
    82                 global $gp_table_prefix;
    83                 $create_table = "
    84                 CREATE TABLE `{$gp_table_prefix}event_actions` (
    85                         `translate_event_actions_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    86                         `event_id` int(10) NOT NULL COMMENT 'Post_ID of the translation_event post in the wp_posts table',
    87                         `original_id` int(10) NOT NULL COMMENT 'ID of the translation',
    88                         `user_id` int(10) NOT NULL COMMENT 'ID of the user who made the action',
    89                         `action` enum('approve','create','reject','request_changes') NOT NULL COMMENT 'The action that the user made (create, reject, etc)',
    90                         `locale` varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL COMMENT 'Locale of the translation',
    91                         `happened_at` datetime NOT NULL COMMENT 'When the action happened, in UTC',
    92                 PRIMARY KEY (`translate_event_actions_id`),
    93                 UNIQUE KEY `event_per_translated_original_per_user` (`event_id`,`locale`,`original_id`,`user_id`)
    94                 ) COMMENT='Tracks translation actions that happened during a translation event'";
    95                 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    96                 dbDelta( $create_table );
    9793        }
    9894
    … …  
    131127         */
    132128        public function event_meta_boxes() {
    133                 \add_meta_box( 'event_dates', 'Event Dates', array( $this, 'event_dates_meta_box' ), self::CPT, 'normal', 'high' );
     129                add_meta_box( 'event_dates', 'Event Dates', array( $this, 'event_dates_meta_box' ), self::CPT, 'normal', 'high' );
    134130        }
    135131
    … …  
    176172
    177173        /**
    178          * Validate the event dates.
    179          *
    180          * @param string $event_start The event start date.
    181          * @param string $event_end The event end date.
    182          * @return bool Whether the event dates are valid.
    183          * @throws Exception When dates are invalid.
    184          */
    185         public function validate_event_dates( string $event_start, string $event_end ): bool {
    186                 if ( ! $event_start || ! $event_end ) {
    187                         return false;
    188                 }
    189                 $event_start = new DateTime( $event_start );
    190                 $event_end   = new DateTime( $event_end );
    191                 if ( $event_start < $event_end ) {
    192                         return true;
    193                 }
    194                 return false;
    195         }
    196 
    197         /**
    198174         * Handle the event form submission for the creation, editing, and deletion of events. This function is called via AJAX.
    199175         */
    200176        public function submit_event_ajax() {
    201                 if ( ! is_user_logged_in() ) {
    202                         wp_send_json_error( esc_html__( 'The user must be logged in.', 'gp-translation-events' ), 403 );
    203                 }
    204                 $action           = isset( $_POST['form_name'] ) ? sanitize_text_field( wp_unslash( $_POST['form_name'] ) ) : '';
    205                 $event_id         = null;
    206                 $event            = null;
    207                 $response_message = '';
    208                 $form_actions     = array( 'draft', 'publish', 'delete' );
    209                 $is_nonce_valid   = false;
    210                 $nonce_name       = '_event_nonce';
    211                 if ( ! in_array( $action, array( 'create_event', 'edit_event', 'delete_event' ), true ) ) {
    212                         wp_send_json_error( esc_html__( 'Invalid form name.', 'gp-translation-events' ), 403 );
    213                 }
    214                 /**
    215                  * Filter the ability to create, edit, or delete an event.
    216                  *
    217                  * @param bool $can_crud_event Whether the user can create, edit, or delete an event.
    218                  */
    219                 $can_crud_event = apply_filters( 'gp_translation_events_can_crud_event', GP::$permission->current_user_can( 'admin' ) );
    220                 if ( 'create_event' === $action && ( ! $can_crud_event ) ) {
    221                         wp_send_json_error( esc_html__( 'The user does not have permission to create an event.', 'gp-translation-events' ), 403 );
    222                 }
    223                 if ( 'edit_event' === $action ) {
    224                         $event_id = isset( $_POST['event_id'] ) ? sanitize_text_field( wp_unslash( $_POST['event_id'] ) ) : '';
    225                         $event    = get_post( $event_id );
    226                         if ( ! ( $can_crud_event || current_user_can( 'edit_post', $event_id ) || intval( $event->post_author ) === get_current_user_id() ) ) {
    227                                 wp_send_json_error( esc_html__( 'The user does not have permission to edit or delete the event.', 'gp-translation-events' ), 403 );
    228                         }
    229                 }
    230                 if ( 'delete_event' === $action ) {
    231                         $event_id = isset( $_POST['event_id'] ) ? sanitize_text_field( wp_unslash( $_POST['event_id'] ) ) : '';
    232                         $event    = get_post( $event_id );
    233                         if ( ! ( $can_crud_event || current_user_can( 'delete_post', $event->ID ) || get_current_user_id() === $event->post_author ) ) {
    234                                 wp_send_json_error( esc_html__( 'You do not have permission to delete this event.', 'gp-translation-events' ), 403 );
    235                         }
    236                 }
    237                 if ( isset( $_POST[ $nonce_name ] ) ) {
    238                         $nonce_value = sanitize_text_field( wp_unslash( $_POST[ $nonce_name ] ) );
    239                         if ( wp_verify_nonce( $nonce_value, $nonce_name ) ) {
    240                                 $is_nonce_valid = true;
    241                         }
    242                 }
    243                 if ( ! $is_nonce_valid ) {
    244                         wp_send_json_error( esc_html__( 'Nonce verification failed.', 'gp-translation-events' ), 403 );
    245                 }
    246                 // This is a list of slugs that are not allowed, as they conflict with the event URLs.
    247                 $invalid_slugs = array( 'new', 'edit', 'attend', 'my-events' );
    248                 $title         = isset( $_POST['event_title'] ) ? sanitize_text_field( wp_unslash( $_POST['event_title'] ) ) : '';
    249                 // This will be sanitized by santitize_post which is called in wp_insert_post.
    250                 $description    = isset( $_POST['event_description'] ) ? force_balance_tags( wp_unslash( $_POST['event_description'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
    251                 $event_start    = isset( $_POST['event_start'] ) ? sanitize_text_field( wp_unslash( $_POST['event_start'] ) ) : '';
    252                 $event_end      = isset( $_POST['event_end'] ) ? sanitize_text_field( wp_unslash( $_POST['event_end'] ) ) : '';
    253                 $event_timezone = isset( $_POST['event_timezone'] ) ? sanitize_text_field( wp_unslash( $_POST['event_timezone'] ) ) : '';
    254                 if ( isset( $title ) && in_array( sanitize_title( $title ), $invalid_slugs, true ) ) {
    255                         wp_send_json_error( esc_html__( 'Invalid slug.', 'gp-translation-events' ), 422 );
    256                 }
    257 
    258                 $is_valid_event_date = false;
    259                 try {
    260                         $is_valid_event_date = $this->validate_event_dates( $event_start, $event_end );
    261                 } catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
    262                         // Deliberately ignored, handled below.
    263                 }
    264                 if ( ! $is_valid_event_date ) {
    265                         wp_send_json_error( esc_html__( 'Invalid event dates.', 'gp-translation-events' ), 422 );
    266                 }
    267 
    268                 $event_status = '';
    269                 if ( isset( $_POST['event_form_action'] ) && in_array( $_POST['event_form_action'], $form_actions, true ) ) {
    270                         $event_status = sanitize_text_field( wp_unslash( $_POST['event_form_action'] ) );
    271                 }
    272 
    273                 if ( ! isset( $_POST['form_name'] ) ) {
    274                         wp_send_json_error( esc_html__( 'Form name must be set.', 'gp-translation-events' ), 422 );
    275                 }
    276 
    277                 if ( 'create_event' === $action ) {
    278                         $event_id         = wp_insert_post(
    279                                 array(
    280                                         'post_type'    => self::CPT,
    281                                         'post_title'   => $title,
    282                                         'post_content' => $description,
    283                                         'post_status'  => $event_status,
    284                                 )
    285                         );
    286                         $response_message = esc_html__( 'Event created successfully!', 'gp-translation-events' );
    287                 }
    288                 if ( 'edit_event' === $action ) {
    289                         if ( ! isset( $_POST['event_id'] ) ) {
    290                                 wp_send_json_error( esc_html__( 'Event id is required.', 'gp-translation-events' ), 422 );
    291                         }
    292                         $event_id = sanitize_text_field( wp_unslash( $_POST['event_id'] ) );
    293                         $event    = get_post( $event_id );
    294                         if ( ! $event || self::CPT !== $event->post_type || ! ( current_user_can( 'edit_post', $event->ID ) || intval( $event->post_author ) === get_current_user_id() ) ) {
    295                                 wp_send_json_error( esc_html__( 'Event does not exist.', 'gp-translation-events' ), 404 );
    296                         }
    297                         wp_update_post(
    298                                 array(
    299                                         'ID'           => $event_id,
    300                                         'post_title'   => $title,
    301                                         'post_content' => $description,
    302                                         'post_status'  => $event_status,
    303                                 )
    304                         );
    305                         $response_message = esc_html__( 'Event updated successfully!', 'gp-translation-events' );
    306                 }
    307                 if ( 'delete_event' === $action ) {
    308                         $event_id = sanitize_text_field( wp_unslash( $_POST['event_id'] ) );
    309                         $event    = get_post( $event_id );
    310                         if ( ! $event || self::CPT !== $event->post_type ) {
    311                                 wp_send_json_error( esc_html__( 'Event does not exist.', 'gp-translation-events' ), 404 );
    312                         }
    313                         if ( ! ( current_user_can( 'delete_post', $event->ID ) || get_current_user_id() === $event->post_author ) ) {
    314                                 wp_send_json_error( 'You do not have permission to delete this event' );
    315                         }
    316                         $stats_calculator = new Stats_Calculator();
    317                         try {
    318                                 $event_stats = $stats_calculator->for_event( $event );
    319                         } catch ( Exception $e ) {
    320                                 wp_send_json_error( esc_html__( 'Failed to calculate event stats.', 'gp-translation-events' ), 500 );
    321                         }
    322                         if ( ! empty( $event_stats->rows() ) ) {
    323                                 wp_send_json_error( esc_html__( 'Event has translations and cannot be deleted.', 'gp-translation-events' ), 422 );
    324                         }
    325                         wp_trash_post( $event_id );
    326                         $response_message = esc_html__( 'Event deleted successfully!', 'gp-translation-events' );
    327                 }
    328                 if ( ! $event_id ) {
    329                         wp_send_json_error( esc_html__( 'Event could not be created or updated.', 'gp-translation-events' ), 422 );
    330                 }
    331                 if ( 'delete_event' !== $_POST['form_name'] ) {
    332                         try {
    333                                 update_post_meta( $event_id, '_event_start', $this->convert_to_utc( $event_start, $event_timezone ) );
    334                                 update_post_meta( $event_id, '_event_end', $this->convert_to_utc( $event_end, $event_timezone ) );
    335                         } catch ( Exception $e ) {
    336                                 wp_send_json_error( esc_html__( 'Invalid start or end', 'gp-translation-events' ), 422 );
    337                         }
    338 
    339                         update_post_meta( $event_id, '_event_timezone', $event_timezone );
    340                 }
    341                 try {
    342                         Active_Events_Cache::invalidate();
    343                 } catch ( Exception $e ) {
    344                         // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
    345                         error_log( $e );
    346                 }
    347 
    348                 list( $permalink, $post_name ) = get_sample_permalink( $event_id );
    349                 $permalink                     = str_replace( '%pagename%', $post_name, $permalink );
    350                 wp_send_json_success(
    351                         array(
    352                                 'message'        => $response_message,
    353                                 'eventId'        => $event_id,
    354                                 'eventUrl'       => str_replace( '%pagename%', $post_name, $permalink ),
    355                                 'eventStatus'    => $event_status,
    356                                 'eventEditUrl'   => esc_url( gp_url( '/events/edit/' . $event_id ) ),
    357                                 'eventDeleteUrl' => esc_url( gp_url( '/events/my-events/' ) ),
    358                         )
    359                 );
    360         }
    361 
    362 
    363 
    364 
    365         /**
    366          * Convert a date time in a time zone to UTC.
    367          *
    368          * @param string $date_time The date time in the time zone.
    369          * @param string $time_zone The time zone.
    370          * @return string The date time in UTC.
    371          * @throws Exception When dates are invalid.
    372          */
    373         public function convert_to_utc( string $date_time, string $time_zone ): string {
    374                 $date_time = new DateTime( $date_time, new DateTimeZone( $time_zone ) );
    375                 $date_time->setTimezone( new DateTimeZone( 'UTC' ) );
    376                 return $date_time->format( 'Y-m-d H:i:s' );
     177                $form_handler = new Event_Form_Handler( self::get_event_repository(), self::get_attendee_repository() );
     178                // Nonce verification is done by the form handler.
     179                // phpcs:ignore WordPress.Security.NonceVerification.Missing
     180                $form_handler->handle( $_POST );
    377181        }
    378182
    … …  
    400204         * @param string  $old_status The old post status.
    401205         * @param WP_Post $post       The post object.
     206         *
     207         * @throws Exception
    402208         */
    403209        public function event_status_transition( string $new_status, string $old_status, WP_Post $post ): void {
    … …  
    406212                }
    407213                if ( 'publish' === $new_status && ( 'new' === $old_status || 'draft' === $old_status ) ) {
    408                         $current_user_id         = get_current_user_id();
    409                         $user_attending_events   = get_user_meta( $current_user_id, self::USER_META_KEY_ATTENDING, true ) ?: array();
    410                         $is_user_attending_event = in_array( $post->ID, $user_attending_events, true );
    411                         if ( ! $is_user_attending_event ) {
    412                                 $new_user_attending_events              = $user_attending_events;
    413                                 $new_user_attending_events[ $post->ID ] = true;
    414                                 update_user_meta( $current_user_id, self::USER_META_KEY_ATTENDING, $new_user_attending_events, $user_attending_events );
     214                        $event_id            = $post->ID;
     215                        $user_id             = $post->post_author;
     216                        $attendee_repository = self::get_attendee_repository();
     217                        $attendee            = $attendee_repository->get_attendee( $event_id, $user_id );
     218
     219                        if ( null === $attendee ) {
     220                                $attendee = new Attendee( $event_id, $user_id );
     221                                $attendee->mark_as_host();
     222                                $attendee_repository->insert_attendee( $attendee );
    415223                        }
    416224                }
    … …  
    466274         * Add the active events for the current user before the translation table.
    467275         *
    468          * @return void
     276         * @throws Exception
    469277         */
    470278        public function add_active_events_current_user(): void {
    471                 $user_attending_events = get_user_meta( get_current_user_id(), self::USER_META_KEY_ATTENDING, true ) ?: array();
    472                 if ( empty( $user_attending_events ) ) {
     279                $attendee_repository      = new Attendee_Repository();
     280                $user_attending_event_ids = $attendee_repository->get_events_for_user( get_current_user_id() );
     281                if ( empty( $user_attending_event_ids ) ) {
    473282                        return;
    474283                }
    … …  
    477286                $user_attending_events_args = array(
    478287                        'post_type'   => self::CPT,
    479                         'post__in'    => array_keys( $user_attending_events ),
     288                        'post__in'    => $user_attending_event_ids,
    480289                        'post_status' => 'publish',
    481290                        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
    … …  
    499308                        'order'       => 'ASC',
    500309                );
     310
    501311                $user_attending_events_query = new WP_Query( $user_attending_events_args );
    502312                $number_of_events            = $user_attending_events_query->post_count;
Note: See TracChangeset for help on using the changeset viewer.