Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/bin/phpcs-branch.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,19 @@ function run_phpcs( $file, $bin_dir ) {
* Note: This differs from the typical usage of phpcs-changed, which suggests piping in the file contents.
* Here, we create temporary files instead, because piping in the contents causes phpcs-changed to misbehave
* when the file contains special characters (like escape sequences such as '\\').
*
* The temporary file is fed to phpcs on stdin with --stdin-path, so that sniffs which act on the file's
* path (like WordPress.Files.FileName and ruleset exclude-patterns) see the real path, not the temp file.
*/
function run_phpcs_changed( $file, $git, $base_branch, $bin_dir ) {
$name = basename( $file );
exec( "$git diff $base_branch $file > $name.diff" );

exec( "$git show $base_branch:$file > $name.test.php" );
exec( "$bin_dir/phpcs $name.test.php --standard=./phpcs.xml.dist --report=json -snq > $name.orig.phpcs" );
exec( "$bin_dir/phpcs --stdin-path=$file --standard=./phpcs.xml.dist --report=json -snq < $name.test.php > $name.orig.phpcs" );

exec( "cat $file > $name.test.php" );
exec( "$bin_dir/phpcs $name.test.php --standard=./phpcs.xml.dist --report=json -snq > $name.phpcs" );
exec( "$bin_dir/phpcs --stdin-path=$file --standard=./phpcs.xml.dist --report=json -snq < $name.test.php > $name.phpcs" );

$cmd = "$bin_dir/phpcs-changed --diff $name.diff --phpcs-orig $name.orig.phpcs --phpcs-new $name.phpcs";
exec( $cmd, $output, $exec_exit_status );
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ jobs:
wp-env-args: "--config theme-directory/.wp-env.test.json"
container: tests-cli
plugin-name: theme-directory
- name: Translation Events
working-directory: environments
wp-env-args: "--config translate/.wp-env.test.json"
container: tests-cli
plugin-name: wporg-gp-translation-events
steps:
- uses: actions/checkout@v4

Expand Down
6 changes: 6 additions & 0 deletions environments/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ npm run translate:refresh
npm run translate:env -- run cli -- wp <command>
```

**Run tests** (the Translation Events plugin's PHPUnit suite, in a dedicated test environment):

```bash
npm run translate:test
```

**Local overrides:** create `translate/.wp-env.override.json` (git-ignored) to override config values like `WP_HOME` / `WP_SITEURL` for testing behind a custom hostname.

### Handbook (in-plugin)
Expand Down
4 changes: 3 additions & 1 deletion environments/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"browsehappy:env": "wp-env --config browsehappy/.wp-env.json",
"translate:env": "wp-env --config translate/.wp-env.json",
"translate:import": "npm run translate:env -- run cli -- wp eval-file wp-content/env-bin/import-from-wporg.php",
"translate:refresh": "npm run translate:env -- run cli -- wp option delete wporg_translate_env_seeded"
"translate:refresh": "npm run translate:env -- run cli -- wp option delete wporg_translate_env_seeded",
"translate:test:env": "wp-env --config translate/.wp-env.test.json",
"translate:test": "npm run translate:test:env -- start && npm run translate:test:env -- run tests-cli --env-cwd=wp-content/plugins/wporg-gp-translation-events phpunit"
},
"devDependencies": {
"@wordpress/env": "^11"
Expand Down
1 change: 1 addition & 0 deletions environments/translate/.wp-env.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"../wordpress.org/public_html/wp-content/plugins/wporg-gp-contributor-moderation",
"../wordpress.org/public_html/wp-content/plugins/wporg-gp-slack-integrations",
"../wordpress.org/public_html/wp-content/plugins/wporg-gp-profiles",
"../wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events",
"https://downloads.wordpress.org/plugin/logged-out-admin-bar.zip"
],
"themes": [
Expand Down
12 changes: 12 additions & 0 deletions environments/translate/.wp-env.test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"core": "WordPress/WordPress#master",
"phpVersion": "8.4",
"plugins": [
"GlotPress/GlotPress",
"https://downloads.wordpress.org/plugin/sqlite-object-cache.zip",
"../wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events"
],
"lifecycleScripts": {
"afterStart": "bash translate/bin/after-start-test.sh"
}
}
12 changes: 12 additions & 0 deletions environments/translate/bin/after-start-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash
#
# Runs after wp-env start for the test environment.
# Installs PHPUnit 11 and Yoast polyfills in the test container.
#

CONFIG="--config translate/.wp-env.test.json"
RUN="npx wp-env $CONFIG run tests-cli"

echo "Installing PHPUnit 11 and polyfills..."
$RUN composer global require -W phpunit/phpunit:^11.0 2>&1
$RUN composer require --dev yoast/phpunit-polyfills:^4.0 --working-dir=/wordpress-phpunit 2>&1
4 changes: 4 additions & 0 deletions environments/translate/bin/after-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ $WP wp eval '
gp_upgrade_db();
'

# Translation Events also only creates its tables when is_admin() is true.
echo "Ensuring Translation Events schema is up to date..."
$WP wp eval 'Wporg\TranslationEvents\Upgrade::upgrade_if_needed();'

# wporg-gp-custom-stats reads from extra tables (user_translations_count, etc.)
# that production maintains manually — the plugin does not create them.
echo "Creating wporg-gp-custom-stats tables..."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,25 @@
Here we are implementing Translation Events, as discussed in our Polyglots Make P2 Post: [Translation Events Prototype](https://make.wordpress.org/polyglots/2024/02/28/translation-events-prototype/).

## Development environment
First follow [instructions to install `wp-env`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/#prerequisites).

Then install dependencies:
This plugin is part of the translate.wordpress.org development environment in `environments/translate` at the root of this repository, which runs it alongside GlotPress and the other translate.wordpress.org plugins. From the `environments` directory:

```shell
composer install
npm run translate:env start
```

Then you can run a local WordPress instance with the plugin installed:
See `environments/README.md` for details.

```shell
composer dev:start
```

Once the environment is running, you must create the database tables needed by this plugin:

```shell
composer dev:db:schema
```

WordPress is now running at http://localhost:8888, user: `admin`, password: `password`.

### Local environment

If you are not using `wp-env`, you need to add the tables to the database of your local environment. To do this, you can run this command from the plugin folder:

```shell
wp db query < schema.sql
```

### Tests

You can run tests in `wp-env` with the following command:
## Tests

> Note that `wp-env` must be running.
The test suite runs in a dedicated wp-env test environment. From the `environments` directory:

```shell
composer dev:test
npm run translate:test
```

If you want to run only one test, you can use the following command:
If you want to run only one test, start the test environment once and then run PHPUnit directly with a filter:

```shell
composer dev:test -- --filter methods_name
npm run translate:test:env -- run tests-cli --env-cwd=wp-content/plugins/wporg-gp-translation-events phpunit -- --filter method_name
```
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,39 @@

}
);
$( document ).on(
'click',
'.load-more-events-btn',
function ( e ) {
$( this ).text('Loading...').prop('disabled', true);
let eventType = $( this ).data('event-type');
let nextPage = $( this ).data('event-next-page');
const url = `/events/?${encodeURIComponent(eventType)}=${encodeURIComponent(nextPage)}&format=html`;

fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(response => {
const $html = $(response.data.html);
const $listItems = $html.find('li');
if ( 0 === response.data.nextPage ){
$(this).hide();
} else {
$(this).data('event-next-page', response.data.nextPage);
}
$(this).parent().prev('.wp-block-wporg-event-list').find('ul').append($listItems);
$(this).text('Load more').prop('disabled', false);
})
.catch(error => {
console.error('Error fetching next page:', error);
});
}
);


}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,22 @@
require_once __DIR__ . '/includes/attendee/attendee.php';
require_once __DIR__ . '/includes/attendee/attendee-repository.php';
require_once __DIR__ . '/includes/attendee/attendee-adder.php';
require_once __DIR__ . '/includes/event/class-invalid-time-zone.php';
require_once __DIR__ . '/includes/event/class-invalid-start.php';
require_once __DIR__ . '/includes/event/class-invalid-end.php';
require_once __DIR__ . '/includes/event/class-invalid-status.php';
require_once __DIR__ . '/includes/event/event-date.php';
require_once __DIR__ . '/includes/event/class-event-start-date.php';
require_once __DIR__ . '/includes/event/class-event-end-date.php';
require_once __DIR__ . '/includes/event/event.php';
require_once __DIR__ . '/includes/event/event-repository-interface.php';
require_once __DIR__ . '/includes/event/class-events-query-result.php';
require_once __DIR__ . '/includes/event/event-repository.php';
require_once __DIR__ . '/includes/event/event-repository-cached.php';
require_once __DIR__ . '/includes/event/event-form-handler.php';
require_once __DIR__ . '/includes/notifications/notifications-schedule.php';
require_once __DIR__ . '/includes/notifications/notifications-send.php';
require_once __DIR__ . '/includes/event/event-capabilities.php';
require_once __DIR__ . '/includes/stats/class-stats-row.php';
require_once __DIR__ . '/includes/stats/class-event-stats.php';
require_once __DIR__ . '/includes/stats/stats-calculator.php';
require_once __DIR__ . '/includes/stats/stats-listener.php';
require_once __DIR__ . '/includes/project/project-repository.php';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private function import_stats( Event $event, Attendee $attendee ): void {
// phpcs:enable
}

private function check_is_new_contributor( Event $event, int $user_id ): bool {
public function check_is_new_contributor( Event $event, int $user_id ): bool {
global $wpdb, $gp_table_prefix;

// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
namespace Wporg\TranslationEvents\Attendee;

use Exception;
use Wporg\TranslationEvents\Attendee\Attendee_Adder;
use Wporg\TranslationEvents\Event\Event_Repository;
use Wporg\TranslationEvents\Translation_Events;
use DateTimeImmutable;
use DateTimeZone;

class Attendee_Repository {

Expand Down Expand Up @@ -47,8 +52,9 @@ public function update_attendee( Attendee $attendee ): void {
$wpdb->update(
"{$gp_table_prefix}event_attendees",
array(
'is_host' => $attendee->is_host() ? 1 : 0,
'is_remote' => $attendee->is_remote() ? 1 : 0,
'is_host' => $attendee->is_host() ? 1 : 0,
'is_remote' => $attendee->is_remote() ? 1 : 0,
'is_new_contributor' => $attendee->is_new_contributor() ? 1 : 0,
),
array(
'event_id' => $attendee->event_id(),
Expand Down Expand Up @@ -291,4 +297,34 @@ function ( Attendee $attendee ) {
}
);
}

/**
* Check the attendees if they are no longer new contributors and update
*/
public function recheck_new_contributor_status( int $event_id ) {
// Get all attendees marked as new contributors.
$new_contributors = array_filter(
$this->get_attendees( $event_id ),
function ( Attendee $attendee ) {
return $attendee->is_new_contributor();
}
);

if ( empty( $new_contributors ) ) {
return;
}

$now = Translation_Events::now();
$attendee_adder = new Attendee_Adder( $this );
$event = ( new Event_Repository( $now, $this ) )->get_event( $event_id );
if ( ! $event ) {
return;
}
foreach ( $new_contributors as $attendee ) {
if ( ! $attendee_adder->check_is_new_contributor( $event, $attendee->user_id() ) ) {
$attendee->mark_as_active_contributor();
$this->update_attendee( $attendee );
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ public function mark_as_new_contributor(): void {
$this->is_new_contributor = true;
}

public function mark_as_active_contributor(): void {
$this->is_new_contributor = false;
}

public function mark_as_remote_attendee(): void {
$this->is_remote = true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
/**
* The end date of an event.
*
* @package wporg-gp-translation-events
*/

namespace Wporg\TranslationEvents\Event;

use Wporg\TranslationEvents\Translation_Events;

/**
* The date and time at which an event ends.
*/
class Event_End_Date extends Event_Date {
/**
* Prefix a formatted date with a translated "ends" phrase.
*
* @param string $date A formatted date.
* @return string The prefixed date.
*/
public function get_prefixed_date( $date ): string {
if ( $this->is_in_the_past() ) {
// translators: %s: A date.
return sprintf( __( 'ended %s', 'gp-translation-events' ), '<span>' . $date . '</span>' );
}
// translators: %s: A date.
return sprintf( __( 'until %s', 'gp-translation-events' ), '<span>' . $date . '</span>' );
}

/**
* Generate variable text depending on when the event ends.
*
* @return string The date text.
*/
public function get_variable_text(): string {
if ( $this->is_in_the_past() ) {
return $this->get_prefixed_date( $this->format( 'D, F j, Y H:i T' ) );
}

$interval = $this->diff( Translation_Events::now() );
$hours_left = ( $interval->d * 24 ) + $interval->h;
$hours_in_a_day = 24;

if ( 0 === $hours_left ) {
if ( ! $interval->i ) {
return __( 'ends in less than a minute', 'gp-translation-events' );
}
/* translators: %s: Number of minutes left. */
return sprintf( _n( 'ends in %s minute', 'ends in %s minutes', $interval->i, 'gp-translation-events' ), $interval->i );
}

if ( $hours_left <= $hours_in_a_day ) {
/* translators: %s: Number of hours left. */
$out = sprintf( _n( 'ends in %s hour', 'ends in %s hours', $hours_left, 'gp-translation-events' ), $hours_left );
if ( $interval->i ) {
/* translators: %s: Number of minutes left. */
$out .= sprintf( _n( ' and %s minute', ' and %s minutes', $interval->i, 'gp-translation-events' ), $interval->i );
}
return $out;
}

return $this->get_prefixed_date( $this->format( 'D, F j, Y H:i T' ) );
}
}
Loading
Loading