Skip to content

Commit

Permalink
merge from production branch
Browse files Browse the repository at this point in the history
  • Loading branch information
pkevan committed Dec 18, 2024
2 parents ab35c67 + 5394773 commit 2395f90
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 69 deletions.
14 changes: 3 additions & 11 deletions .docker/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,10 @@ Follow these steps to setup a local WordCamp.org environment using [Docker](http

1. Clone the repo:
```bash
git clone git@github.com:WordPress/wordcamp.org.git wordcamp.test
git clone https://github.com/WordPress/wordcamp.org.git wordcamp.test
cd wordcamp.test
```

If you get an error about "Permission denied (publickey)", you have two options:
- Make sure you have [a working SSH key](https://docs.github.com/en/authentication/troubleshooting-ssh/error-permission-denied-publickey#make-sure-you-have-a-key-that-is-being-used).
- Or use the HTTPS URL:
```bash
git clone https://github.com/WordPress/wordcamp.org.git wordcamp.test
cd wordcamp.test
```

1. Generate and trust the SSL certificates, so you get a green bar and can adequately test service workers.

_Using zsh? You may see `zsh: no matches found: *.wordcamp.test` running the final cert command below. Try prefixing the final command with `noglob`, i.e. `noglob mkcert -cert-file ...`_
Expand All @@ -35,7 +27,7 @@ Follow these steps to setup a local WordCamp.org environment using [Docker](http
cd public_html
git clone git://core.git.wordpress.org/ mu
cd mu
git checkout 6.5
git checkout 6.7
```
1. Install 3rd-party PHP packages used on WordCamp.org. For this, you must have [Composer](https://getcomposer.org/doc/00-intro.md) installed. Once it is, change back to the root directory of the project where the main **composer.json** file is located. (Not the one in .docker/config.)
Expand Down Expand Up @@ -205,7 +197,7 @@ We have separate containers for PHPUnit, a web server & database, to keep the te
docker compose -f docker-compose.phpunit.yml exec phpunit_wp phpunit
```

If you're still in the shell from the previous step, you can run `phpunit` directly.
If you're still in the shell from the previous step, you can run `phpunit` directly. You'll need to be in the `/app` directory to run the tests.
```bash
phpunit
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ public function pre_attendee_timeout( $attendee_id ) {
}

// Uh oh, we've hit timeout on a ticket, but the linked checkout session succeeded.
if ( 'succeeded' === $session['status'] && 'paid' === $session['payment_status'] ) {
if ( 'complete' === $session['status'] && 'paid' === $session['payment_status'] ) {
$camptix->log( 'Stripe checkout timed out, but order succeeded.', $attendee_id, $session );

$transaction_id = $session['payment_intent']['latest_charge'] ?? '';
Expand Down
92 changes: 78 additions & 14 deletions public_html/wp-content/plugins/camptix/addons/require-login.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,26 +71,78 @@ public function block_unauthenticated_actions() {
return;
}

// Temporary: We don't want to block users from editing tickets.
// See: https://github.com/WordPress/wordcamp.org/issues/1393.
if ( ! is_user_logged_in() && ! $this->user_is_editing_ticket() ) {
$args = array();
// If this was a registration, pass through the selected tickets and coupon.
if ( 'attendee_info' === $_REQUEST['tix_action'] && isset( $_REQUEST['tix_tickets_selected'] ) ) {
$args['tix_action'] = $_REQUEST['tix_action'];
$args['tix_tickets_selected'] = $_REQUEST['tix_tickets_selected'];
if ( isset( $_REQUEST['tix_coupon'] ) ) {
$args['tix_coupon'] = $_REQUEST['tix_coupon'];
}
if ( ! is_user_logged_in() ) {

// Temporary: We don't want to block users from editing tickets unless they are unconfirmed.
// See: https://github.com/WordPress/wordcamp.org/issues/1393.
// See: https://github.com/WordPress/wordcamp.org/issues/1420.
if ( $this->user_is_editing_ticket() && ! $this->user_must_confirm_ticket( $_REQUEST['tix_attendee_id'] ?? null ) ) {
return;
}

$args = $this->get_sanitized_tix_parameters( $_REQUEST );
$tickets_url = add_query_arg( $args, $camptix->get_tickets_url() );

wp_safe_redirect( add_query_arg( 'wcname', get_bloginfo( 'name' ), wp_login_url( $tickets_url ) ) );
exit();
}
}

/**
* Get sanitized ticket parameters from request array.
*
* @param array $request_data Array of request data to sanitize.
* @return array Sanitized parameters.
*/
private function get_sanitized_tix_parameters( array $request_data ): array {
$allowed_parameters = array(
'tix_action' => 'text',
'tix_tickets_selected' => 'array_int',
'tix_errors' => 'array_str',
'tix_coupon' => 'text',
'tix_attendee_id' => 'int',
'tix_edit_token' => 'text',
'tix_access_token' => 'text',
'tix_reservation_id' => 'text',
'tix_reservation_token' => 'text',
'tix_single_ticket_purchase' => 'text',
);

$args = array();
foreach ( $allowed_parameters as $key => $type ) {
if ( isset( $request_data[ $key ] ) ) {
switch ( $type ) {
case 'array_int':
if ( is_array( $request_data[ $key ] ) ) {
$args[ $key ] = array_map( 'absint', $request_data[ $key ] );
} else {
$args[ $key ] = array( absint( $request_data[ $key ] ) );
}
break;

case 'array_str':
if ( is_array( $request_data[ $key ] ) ) {
$args[ $key ] = array_map( 'sanitize_text_field', $request_data[ $key ] );
} else {
$args[ $key ] = array( sanitize_text_field( $request_data[ $key ] ) );
}
break;

case 'int':
$args[ $key ] = absint( $request_data[ $key ] );
break;

case 'text':
default:
$args[ $key ] = sanitize_text_field( $request_data[ $key ] );
break;
}
}
}

return $args;
}

/**
* Hide the interactive elements of the Tickets registration form if the user isn't logged in.
*
Expand Down Expand Up @@ -148,7 +200,7 @@ public function ticket_form_message() {
}

// Ask the attendee to confirm their registration
if ( isset( $_REQUEST['tix_action'] ) && 'edit_attendee' == $_REQUEST['tix_action'] && self::UNCONFIRMED_USERNAME == get_post_meta( $_REQUEST['tix_attendee_id'], 'tix_username', true ) ) {
if ( $this->user_is_editing_ticket() && $this->user_must_confirm_ticket( $_REQUEST['tix_attendee_id'] ?? null ) ) {
$tickets_selected = array( get_post_meta( $_REQUEST['tix_attendee_id'], 'tix_ticket_id', true ) => 1 ); // mimic $_REQUEST['tix_tickets_selected']

if ( $this->tickets_have_questions( $tickets_selected ) ) {
Expand Down Expand Up @@ -430,7 +482,7 @@ public function use_custom_email_templates( $template, $attendee ) {

if ( $unknown_attendee_info['email'] == get_post_meta( $attendee->ID, 'tix_email', true ) ) {
$template = 'email_template_multiple_purchase_unknown_attendee';
} elseif ( self::UNCONFIRMED_USERNAME == get_post_meta( $attendee->ID, 'tix_username', true ) ) {
} elseif ( $this->user_must_confirm_ticket( $attendee->ID ) ) {
$template = 'email_template_multiple_purchase_unconfirmed_attendee';
}

Expand Down Expand Up @@ -755,7 +807,7 @@ public function update_attendee_post_meta( $new_ticket_info, $attendee ) {
* @return string
*/
public function rename_save_attendee_info_label( $label, $attendee, $ticket, $questions ) {
if ( self::UNCONFIRMED_USERNAME == get_post_meta( $attendee->ID, 'tix_username', true ) ) {
if ( $this->user_must_confirm_ticket( $attendee->ID ) ) {
$label = __( 'Confirm Registration', 'wordcamporg' );
}

Expand Down Expand Up @@ -841,6 +893,18 @@ public function prevent_unknown_attendees_viewing_private_content( $parameters )
protected function user_is_editing_ticket() {
return isset( $_REQUEST['tix_action'] ) && in_array( $_REQUEST['tix_action'], array( 'access_tickets', 'edit_attendee' ) );
}

/**
* Checks if the user associated with the given attendee ID must confirm their ticket.
* Unconfirmed tickets exist when one user purchases multiple tickets.
*
* @param int $attendee_id The ID of the attendee. If null or invalid, the function returns false.
*
* @return bool True if the attendee must confirm their ticket, false otherwise.
*/
protected function user_must_confirm_ticket( $attendee_id ) {
return isset( $attendee_id ) && self::UNCONFIRMED_USERNAME == get_post_meta( $attendee_id, 'tix_username', true );
}
} // CampTix_Require_Login

camptix_register_addon( 'CampTix_Require_Login' );
1 change: 1 addition & 0 deletions public_html/wp-content/plugins/camptix/camptix.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ function __construct() {

require( dirname( __FILE__ ) . '/inc/class-camptix-addon.php' );
require( dirname( __FILE__ ) . '/inc/class-camptix-payment-method.php' );
require( dirname( __FILE__ ) . '/inc/class-camptix-badges.php' );
require( dirname( __FILE__ ) . '/inc/class-camptix-admin.php' );

if ( defined( 'WP_CLI' ) && WP_CLI ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function admin_menu() {
add_submenu_page( 'edit.php?post_type=tix_ticket', __( 'Tools', 'wordcamporg' ), __( 'Tools', 'wordcamporg' ), $this->caps['manage_tools'], 'camptix_tools', array( $this, 'menu_tools' ) );
add_submenu_page( 'edit.php?post_type=tix_ticket', __( 'Setup', 'wordcamporg' ), __( 'Setup', 'wordcamporg' ), $this->caps['manage_options'], 'camptix_options', array( $this, 'menu_setup' ) );
add_submenu_page( 'edit.php?post_type=tix_ticket', __( 'Badges', 'wordcamporg' ), __( 'Badges', 'wordcamporg' ), $this->caps['manage_options'], 'camptix_badges', array( $this, 'menu_badges' ) );

add_submenu_page( 'edit.php?post_type=tix_ticket', __( 'Profile Badges', 'wordcamporg' ), __( 'Profile Badges', 'wordcamporg' ), $this->caps['manage_options'], 'camptix_badges', 'Camptix\Profile_Badges\menu_badges' );
remove_submenu_page( 'edit.php?post_type=tix_ticket', 'post-new.php?post_type=tix_ticket' );
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace Camptix\Profile_Badges;

use WordPressdotorg\Profiles;

/**
* Process submission and returns appropriate message
*
* @return string
*/
function process_badges() {

if ( ! current_user_can( 'manage_options' ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'badge-submission' ) ) {
return __( 'Invalid request', 'wordcamporg' );
}

$usernames = sanitize_text_field( $_POST['usernames'] );
$operation = sanitize_text_field( $_POST['operation'] );
$badge = sanitize_text_field( $_POST['badge_name'] );

$valid_operations = [ 'add', 'remove' ];
$valid_badges = [ 'wordcamp-volunteer' ];

if ( ! in_array( $operation, $valid_operations ) ) {
return sprintf( __( 'Invalid badge operation used, valid commands are: %s', 'wordcamporg' ), implode( ',', $valid_operations ) );
}

if ( ! in_array( $badge, $valid_badges ) ) {
return __( 'Invalid badge', 'wordcamporg' );
}

if ( empty( $usernames ) ) {
return __( 'You must supply a list of usernames', 'wordcamporg' );
}

$users = explode( "\n", $usernames );

Profiles\badge_api( $operation, $badge, $users );

// Badge_api doesn't return anything apart from a success message, so lets guess how many items were updated.
$count = count( $users );

return sprintf( _n( '%s badge updated', '%s badges updated', $count, 'wordcamporg' ), number_format_i18n( $count ) );
}

/**
* Outputs manage badge admin screen, and allows processing of submit.
*/
function menu_badges() {
if ( isset( $_GET['badge-submit'] ) && ( 1 == $_GET['badge-submit'] ) ) {
$output = process_badges();
wp_admin_notice( $output );
}

// If adding more badges, make sure to add them to the validation check in `process_badges`.
?>
<div class="wrap">
<h1><?php esc_html_e( 'Profile Badge Management', 'wordcamporg' ); ?></h1>
<p><?php esc_html_e( 'This tool allows a limited number of badges to be managed on wordpress.org profiles', 'wordcamporg' ); ?></p>
</div>
<form method="post" action="<?php echo esc_url( add_query_arg( 'badge-submit', '1' ) ); ?>">
<div>
<select name="badge_name">
<option value="wordcamp-volunteer"><?php esc_html_e( 'WordCamp Volunteer', 'wordcamporg' ); ?></option>
</select>
<select name="operation">
<option value="add"><?php esc_html_e( 'Add', 'wordcamporg' ); ?></option>
<option value="remove"><?php esc_html_e( 'Remove', 'wordcamporg' ); ?></option>
</select>
</div>
<div class="wrap">
<textarea name="usernames" cols="50" rows="20" placeholder="<?php esc_attr_e( 'Input usernames, 1 per row', 'wordcamporg' ); ?>"></textarea>
</div>
<input type="hidden" name="action" value="badge_submission" />
<?php wp_nonce_field( 'badge-submission' ); ?>
<div><?php submit_button( __( 'Submit', 'wordcamporg' ) ); ?></div>
</form>
<?php
}
26 changes: 2 additions & 24 deletions public_html/wp-content/themes/wordcamp-central-2012/header.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,6 @@

<body <?php body_class(); ?>>

<?php if ( date_create( 'now' ) <= date_create( '2017-12-04' ) ) : ?>
<section class="regional-camps-promo">
<a href="https://2017.us.wordcamp.org/tickets/">
<picture>
<source
srcset="
https://central.wordcamp.org/files/2017/11/wcc-wcus-2017.png,
https://central.wordcamp.org/files/2017/11/wcc-wcus-2017_2x.png 2x"
media="(min-width: 500px)" />
<source
srcset="https://central.wordcamp.org/files/2017/11/wcc-wcus-2017_mobile.png" />
<img
src="https://central.wordcamp.org/files/2017/11/wcc-wcus-2017.png"
alt="WordCamp US 2017 in Nashville banner" />
</picture>
</a>
</section>
<?php endif; ?>

<div id="header" class="group">
<div id="masthead" class="group">
<?php /* Allow screen readers / text browsers to skip the navigation menu and get right to the good stuff */ ?>
Expand Down Expand Up @@ -87,11 +68,8 @@
<div id="wc-hero-panel">
<div class="wc-hero-wrap group">
<div class="wc-hero-intro">
<h2>WordCamp is a conference that focuses on everything WordPress.</h2>
<p>
WordCamps are informal, community-organized events that are put together by WordPress users like you.
Everyone from casual users to core developers participate, share ideas, and get to know each other.
</p>
<h2>WordPress Events: connect, learn & shape the future of the open web.</h2>
<p>WordCamps and WordPress Events are where innovation meets opportunity. Boost your career by connecting with a diverse community of users, professionals, and entrepreneurs. Together, we’re shaping the future of the open web.</p>
<p class="wc-hero-actions">
<a href="<?php echo esc_url( home_url( '/about/' ) ); ?>" class="wc-hero-learnmore">Learn More</a> or
<a href="<?php echo esc_url( home_url( '/schedule/' ) ); ?>" class="wc-primary-button">Find a WordCamp</a>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<ul class="about-stats clearfix">
<li>
<span class="about-stat-number"><?php echo esc_html( $map_stats['wordcamps'] ); ?></span>
<span class="about-stat-descriptor">WordCamps</span>
<span class="about-stat-descriptor">WordPress Events</span>
</li>

<li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
?>

<div id="primary" class="wc-planned" role="complementary">
<h3>Planned WordCamps</h3>
<h3>Planned WordCamps or WordPress Events</h3>

<p>
These WordCamps are in the early stages of planning, but don't have a date yet. When their dates are confirmed, they'll be added to the schedule of approved WordCamps.
</p>
<p>These WordCamps and WordPress Events are in the early stages of planning and don’t yet have confirmed dates. Once their schedules are finalized, they will be added to our comprehensive list of approved events.</p>

<?php
// Get the upcoming approved (published) WordCamps *with dates*
Expand Down Expand Up @@ -77,11 +75,10 @@

<?php endwhile; // wcpt_wordcamps ?>

<li>
Don&#8217;t see your city on the list, but yearning for a local WordCamp? Check out what it takes to <a href="/become-an-organizer/">become an organizer</a>!
</li>

</ul>
<h3>Looking for a WordCamp or WordPress Event in Your City?</h3>

<p>If you don&#8217;t see your city listed but are excited about the prospect of hosting a local WordCamp or WordPress Event, why not get involved? <a href="https://central.wordcamp.org/become-an-organizer/">Discover what it takes to become an organizer</a> and bring a WordCamp or other WordPress event to your area!</p>

<?php endif; // wcpt_has_wordcamps / function_exists ?>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@

<a href="<?php echo esc_url( home_url( '/schedule/' ) ); ?>" class="wc-schedule-more">
<span class="arrow">&larr;</span>
Upcoming WordCamps
Upcoming WordCamps and WordPress Events
</a>

<?php endif; // wcpt_has_wordcamps ?>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,18 @@

<?php endif; // wcpt_has_wordcamps ?>

<h2>Keeping Track of Upcoming WordCamps</h2>
<h2>Stay Informed About Upcoming Events</h2>

<p>In addition to the list above, there are a few other ways you can keep track of upcoming WordCamps:</p>
<p>There are several ways to keep track of upcoming WordPress Events, including WordCamps, and stay connected with the vibrant WordPress community:</p>

<ul>
<li><strong>RSS Feed</strong> -- Learn <a href="https://central.wordcamp.org/news/2013/12/30/rss-feed-now-available-for-newly-announced-wordcamps/">how to subscribe via RSS</a>.</li>
<li><strong>ICS Calendar</strong> -- Add this URL as a remote calendar in your calendar application to subscribe: <?php echo esc_url( site_url( 'calendar.ics' ) ); ?></li>
<li>
<strong>JSON API</strong> --
This can be used by developers of mobile apps, websites, etc: <?php echo esc_url( get_rest_url( null, 'wp/v2/wordcamps' ) ); ?>.
If you'd like to include meetup events too, then you may want to use <a href="https://codex.wordpress.org/WordPress.org_API#Events">api.wordpress.org/events</a> instead.
<li><strong>Upcoming WordPress Events:</strong> Check out our <a href="https://events.wordpress.org/">landing page with all types of WordPress Events</a> and filter them by format, type, month and country.</li>
<li><strong>RSS Feed:</strong> <a href="https://central.wordcamp.org/news/2013/12/30/rss-feed-now-available-for-newly-announced-wordcamps/">Subscribe to our RSS feed</a> to get updates on new events and schedule changes directly in your feed reader.</li>
<li><strong>ICS Calendar:</strong> Add this URL to your calendar application to keep track of all upcoming events: <a href="https://central.wordcamp.org/calendar.ics"><?php echo esc_url( site_url( 'calendar.ics' ) ); ?></a></li>
<li><strong>JSON API:</strong> Developers can use our <a href="<?php echo esc_url( get_rest_url( null, 'wp/v2/wordcamps' ) ); ?>">JSON API</a> to integrate event information into mobile apps, websites, and more. For Meetup events and other WordPress community gatherings, consider using <a href="https://codex.wordpress.org/WordPress.org_API#Events">api.wordpress.org/events</a>.
</li>
</ul>
<p>Stay tuned and get ready to join us at an upcoming WordPress Event near you!</p>

</div><!-- #content -->
</div><!-- #container -->
Expand Down

0 comments on commit 2395f90

Please sign in to comment.