Skip to content

Create Gutenberg block for the [camptix] shortcode#1683

Open
dd32 wants to merge 22 commits into
WordPress:productionfrom
dd32:create/claude/1675-camptix-block
Open

Create Gutenberg block for the [camptix] shortcode#1683
dd32 wants to merge 22 commits into
WordPress:productionfrom
dd32:create/claude/1675-camptix-block

Conversation

@dd32
Copy link
Copy Markdown
Member

@dd32 dd32 commented Mar 24, 2026

Adds a wordcamp/camptix Gutenberg block that provides a visual editor interface for the CampTix ticket purchase form. This replaces the need to use the [camptix] shortcode directly while offering configurable options that were previously hidden or unavailable.

Features

  • Ticket selection — choose specific tickets to display (or show all)
  • Max tickets per order — limit from 1-10 (default 10)
  • Auto-apply coupon — automatically apply a coupon code on page load
  • Custom messages — customize "No tickets available" and "Event closed" messages
  • Remaining tickets visibility — toggle the "Remaining" column on/off
  • Coupon field visibility — auto (hides when no coupons exist), always show, or always hide
  • Editor preview — static preview table reflecting configured settings

How it works

  • The block uses server-side rendering via the existing shortcode pipeline
  • Block attributes are parsed from post_content during template_redirect() and applied to the CampTix rendering flow
  • The [camptix] shortcode continues to work unchanged for backward compatibility
  • Only one block per page is allowed ("multiple": false), matching the shortcode constraint
  • Adds camptix_have_coupons filter to have_coupons() for coupon field control
  • Currency formatting uses CampTix append_currency() for proper locale support
  • Flips the camptix_hide_empty_tickets filter default to false (show sold-out tickets) so the WordCamp.org behavior is the upstream default, removing the now-redundant __return_false override in camptix-tweaks

Closes #1675

Test plan

  • Insert the "Tickets" block in the editor and verify the ticket preview renders
  • Configure ticket selection, max per order, coupon, and custom messages in the sidebar
  • Toggle "Show remaining tickets" off — verify the Remaining column disappears in preview and frontend
  • Set coupon field to "Always hide" — verify the coupon input is hidden on frontend
  • Set coupon field to "Auto" with no coupons on site — verify the help text warns and field is hidden on frontend
  • Save and view frontend — verify correct tickets shown with configured options
  • Walk through full purchase flow: ticket selection -> attendee info -> checkout
  • Test with the old [camptix] shortcode on a different page — verify unchanged behavior

🤖 Generated with Claude Code

Adds a wordcamp/camptix block that provides a visual editor interface
for the CampTix ticket purchase form with configurable options:

- Select specific tickets to display
- Set max tickets per order (1-10)
- Auto-apply a coupon code on page load
- Customize "No tickets available" and "Event closed" messages

The block uses server-side rendering via the existing shortcode
pipeline. Block attributes are parsed during template_redirect()
and applied to the CampTix rendering flow. The shortcode continues
to work unchanged for backward compatibility.

Closes WordPress#1675

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@dd32 dd32 added [Component] Blocks All custom blocks (Speakers, CrowdCast, Live Schedule, etc) [Component] CampTix Including addons labels Mar 24, 2026
dd32 and others added 5 commits March 24, 2026 14:46
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
form_start() returns HTML via ob_get_contents() internally, it does
not echo directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pass formattedPrice from PHP using CampTix append_currency() which
respects the configured currency and locale settings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
dd32 and others added 3 commits March 24, 2026 15:21
- showRemainingTickets (boolean, default true): toggle the "Remaining"
  column in the ticket table
- showCouponField (auto/show/hide, default auto): control coupon input
  visibility. "auto" hides when no valid coupons exist on the site.
  Adds camptix_have_coupons filter to have_coupons() method.
- showSoldOut (boolean, default false): show sold-out tickets with a
  "Sold out" label instead of hiding them

All three settings are exposed in the block sidebar under Settings,
with live preview updates in the editor.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the two IN (SELECT ...) subqueries with a single LEFT JOIN on
the parent post, making the SQL more readable and efficient.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new wordcamp/camptix Gutenberg block to provide a visual editor interface for the CampTix ticket purchase form, while keeping the existing [camptix] shortcode flow for rendering/purchase.

Changes:

  • Integrates block attribute parsing into CampTix’s template_redirect() flow and applies attributes to ticket/coupon/visibility behavior.
  • Registers a new wordcamp/camptix block (metadata + controller) and editor UI (Inspector controls + preview styles).
  • Adds PHPUnit coverage for key block behaviors (attribute parsing, messages, max quantity, coupon injection).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
public_html/wp-content/plugins/camptix/camptix.php Adds block attribute support in template_redirect()/form_start() and introduces camptix_have_coupons filter.
public_html/wp-content/plugins/camptix/tests/test-camptix-block.php New tests covering block-related behavior and some compatibility checks.
public_html/wp-content/mu-plugins/blocks/blocks.php Loads the new Camptix block controller when CampTix is available.
public_html/wp-content/mu-plugins/blocks/source/blocks/index.js Registers the new Camptix block module in the JS bundle.
public_html/wp-content/mu-plugins/blocks/source/blocks/camptix/index.js Block module entry exporting NAME/SETTINGS.
public_html/wp-content/mu-plugins/blocks/source/blocks/camptix/edit.js Editor UI controls and a static preview table for configured settings.
public_html/wp-content/mu-plugins/blocks/source/blocks/camptix/edit.scss Editor-only styling for the preview table and coupon notice.
public_html/wp-content/mu-plugins/blocks/source/blocks/camptix/controller.php Registers the dynamic block, renders via shortcode pipeline, and injects editor script data (tickets + coupon existence).
public_html/wp-content/mu-plugins/blocks/source/blocks/camptix/block.json Block metadata and attribute schema (including supports.multiple=false).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread public_html/wp-content/plugins/camptix/camptix.php
Comment thread public_html/wp-content/plugins/camptix/camptix.php
Comment thread public_html/wp-content/plugins/camptix/tests/test-camptix-block.php Outdated
Comment thread public_html/wp-content/plugins/camptix/tests/test-camptix-block.php Outdated
Comment thread public_html/wp-content/plugins/camptix/camptix.php Outdated
Comment thread public_html/wp-content/plugins/camptix/camptix.php Outdated
Copilot AI review requested due to automatic review settings April 28, 2026 04:09
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread public_html/wp-content/plugins/camptix/camptix.php Outdated
Comment thread public_html/wp-content/plugins/camptix/camptix.php Outdated
Comment thread public_html/wp-content/plugins/camptix/tests/test-camptix-block.php
Copilot AI review requested due to automatic review settings April 28, 2026 05:59
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread public_html/wp-content/mu-plugins/blocks/source/blocks/camptix/controller.php Outdated
Comment thread public_html/wp-content/plugins/camptix/camptix.php Outdated
Comment thread public_html/wp-content/plugins/camptix/tests/test-camptix-block.php Outdated
- Drop the dead-code optimization in the block render() that reached for
  $camptix->shortcode_contents (protected — empty() returned true silently,
  so the cache-skip branch never fired and the shortcode ran twice).
  do_shortcode( '[camptix]' ) already returns the cached contents via
  shortcode_callback(), so the optimization was redundant.
- Rewrite test_auto_coupon_injection and test_manual_coupon_overrides_auto_coupon
  so they actually exercise CampTix_Plugin::template_redirect() against a page
  containing the block, instead of re-implementing the auto-coupon logic
  inline (which left the production code path untested).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dd32
Copy link
Copy Markdown
Member Author

dd32 commented May 12, 2026

Addressed the rest of the review feedback in af193d28 (on top of fixes already landed in prior commits):

This commit

  • Drop the dead $camptix->shortcode_contents check in the block render callback. The property is protected, so empty() silently returned true from outside the class — the cache-skip branch never fired and the shortcode ran twice. do_shortcode( "[camptix]" ) already returns the cached contents via shortcode_callback(), so the optimization was redundant. Comments #3151417333 and #3151907777.
  • Rewrite test_auto_coupon_injection and test_manual_coupon_overrides_auto_coupon to exercise CampTix_Plugin::template_redirect() against a page containing the block, rather than re-implementing the auto-coupon logic in the test. Comment #3151907837.

Already addressed in earlier commits on this branch

  • ticketIds is now sanitized with array_map( "absint", array_filter(..., "is_scalar") ) + array_unique before array_flip/array_intersect_key (#3151417311, #3151521724).
  • The coupon-row colspan now matches the showRemainingTickets filter (4 columns / 3 columns) (#3151417324).
  • add_script_data() short-circuits when not in the block editor (! is_admin() or ! wp_should_load_block_editor_scripts_and_styles()), so it no longer queries on every front-end request (#3151417333, #3151521707).
  • block.json now declares "postTypes": [ "page" ] so the block matches the is_page() gate in template_redirect() (#3151417347).
  • get_camptix_block() uses has_block( "wordcamp/camptix", $content ) and find_camptix_block() walks innerBlocks recursively, so nested blocks are detected too (#3151417382). There is a test_nested_block_detection_sets_block_attributes covering this.
  • maxTicketsPerOrder is clamped with max( 1, min( 10, (int) ... ) ) before the filter, matching the block UI bounds (#3151417395). Tests for the lower and upper limits are included.
  • showSoldOut: false now explicitly registers add_filter( "camptix_hide_empty_tickets", "__return_true" ) to override the WordCamp-wide __return_false set by camptix-tweaks (#3151521732).
  • test_block_detection_sets_block_attributes and test_ticket_filtering_by_ids now call the real template_redirect() via run_template_redirect_for_page() and assert against $camptix->block_attributes / $camptix->tickets (#3151417373, #3151521740).
  • The ticket-quantity option-value test now assertSame( 1, preg_match(...) ) and assertNotEmpty( $option_matches[1] ) so it cannot silently pass when the markup changes (#3151417359).

Deliberate non-change

  • #3151907820: when ticketIds is provided but every value sanitizes to 0/invalid, the code falls back to showing all tickets rather than none. Kept as a graceful fallback — if a referenced ticket gets deleted, the page should still sell the remaining tickets rather than going blank. Open to revisiting if that is the wrong call.

Calling template_redirect() in the coupon tests reaches the
get_coupon_by_code() path which still uses get_page_by_title()
(deprecated in WP 6.2). Match the existing pattern in
test-camptix-admin.php and declare the expected deprecation on these
tests so the WP test framework no longer treats it as an unexpected
notice.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 12, 2026 06:16
When the editor opted into a specific ticket selection, an "all values
invalid" outcome (e.g. every referenced ticket has been deleted) now
narrows the tickets list to zero rather than silently falling back to
showing every ticket. Less surprising than appearing to recover.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Comment thread public_html/wp-content/mu-plugins/blocks/source/blocks/camptix/block.json Outdated
Comment thread public_html/wp-content/plugins/camptix/camptix.php
dd32 and others added 2 commits May 12, 2026 16:34
… it.

The filter used to default to `true` (hide sold-out), which forced every
WordCamp site to register a `__return_false` override in camptix-tweaks
just to get the project-wide "show sold-out tickets" behavior. The Tickets
block then had to opt back in with another `__return_false` and out with
`__return_true`, and the block UI default (showSoldOut: false) silently
disagreed with the actual frontend default.

Flip the input passed to apply_filters() so the new default is `false`
(show sold-out), drop the redundant `__return_false` override in
camptix-tweaks, and switch the block default to `showSoldOut: true`. The
block now only needs to register a single `__return_true` when the editor
opts in to hiding sold-out tickets.

Tests cover both "no attribute, filter stays at default false" and
"showSoldOut: false flips it to true".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Now that camptix_hide_empty_tickets defaults to false (show sold-out
tickets) and there are no project-wide overrides, the block does not
need its own per-instance toggle. Remove the attribute from block.json,
the toggle and destructured variable from edit.js, the filter wiring
in template_redirect(), and the showSoldOut-specific tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 12, 2026 06:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Comment thread public_html/wp-content/plugins/camptix/camptix.php Outdated
The shortcode search returns a numerically-indexed array from
get_posts(). Assigning the block search results back into it with
`$posts[ $post->ID ] = $post` could overwrite real entries when a
block page ID happened to match a low numeric index (any of 0-49,
since posts_per_page is 50). Build the merged set as an ID-keyed
array from both result lists so neither side can clobber the other.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

if (
apply_filters( 'camptix_hide_empty_tickets', true ) &&
apply_filters( 'camptix_hide_empty_tickets', false ) &&
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional; A filter on WordCamp was forcing this to false, this PR has removed that filter and set this to false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Component] Blocks All custom blocks (Speakers, CrowdCast, Live Schedule, etc) [Component] CampTix Including addons

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tickets: Create a [camptix] block

2 participants