$npx -y skills add Lonsdale201/wp-agent-skills --skill je-dynamic-visibility-conditionRegister a custom Dynamic Visibility condition for
| 1 | # JetEngine: register a Dynamic Visibility condition |
| 2 | |
| 3 | For developers extending JetEngine's Dynamic Visibility module with custom conditions — "is current page the front page", "is the user past N days since registration", "has the visitor purchased a specific product", "is the LearnDash course completed". The module already ships ~40 built-in conditions; this skill is for the **custom-condition extension contract** that's been stable across JetEngine 3.x. |
| 4 | |
| 5 | ## Misconception this skill corrects |
| 6 | |
| 7 | > "I'll add a `pre_get_posts` filter or a custom shortcode to gate the visibility — same outcome." |
| 8 | |
| 9 | Different layer. JetEngine's Dynamic Visibility runs the condition check INSIDE the rendering pipeline of every JE-aware widget/block (Elementor widgets, Gutenberg blocks, Bricks elements, listing items). A custom condition slots into the SAME UI as the built-in ones — site editors pick it from a dropdown, configure it, and it applies wherever JE Dynamic Visibility is enabled. |
| 10 | |
| 11 | `pre_get_posts` only filters main queries; doesn't help with widget-level visibility. Shortcodes don't get the visibility-condition UI. The verified extension contract is: |
| 12 | |
| 13 | ```php |
| 14 | add_action( 'jet-engine/modules/dynamic-visibility/conditions/register', function ( $manager ) { |
| 15 | $manager->register_condition( new MyCondition() ); |
| 16 | } ); |
| 17 | ``` |
| 18 | |
| 19 | Where `MyCondition` extends `\Jet_Engine\Modules\Dynamic_Visibility\Conditions\Base`. Verified at [wp-content/plugins/jet-engine/includes/modules/dynamic-visibility/inc/conditions/base.php:4](base.php). |
| 20 | |
| 21 | Other AI-prone misconceptions: |
| 22 | |
| 23 | - "`check( $args )` returns true when the visitor SHOULD see the content." Half-true. The semantics is "should the widget be displayed". `$args['type']` carries `'show'` (user wants to show when condition is true) or `'hide'` (user wants to hide when condition is true). Your `check()` MUST invert the result based on `$args['type']` — see the `Equal` built-in at [conditions/equal.php:37-41](equal.php). |
| 24 | - "`is_for_fields()` controls whether the condition is shown in the UI." Wrong — it controls whether the condition is available in the **meta-field** context (where the user is comparing meta values). Conditions like "is front page" don't compare values, so they return `is_for_fields() => false`. |
| 25 | - "I should hardcode `get_post_meta( get_the_ID(), ... )` to read meta." Don't — use `$this->get_current_value( $args )` from the Base class. It handles `current_listing` context automatically (WP_Post / WP_User / WP_Term / WP_Comment / listing-macros). |
| 26 | |
| 27 | ## When to use this skill |
| 28 | |
| 29 | Trigger when ANY of the following is true: |
| 30 | |
| 31 | - The diff calls `register_condition`, hooks `jet-engine/modules/dynamic-visibility/conditions/register`, or extends `\Jet_Engine\Modules\Dynamic_Visibility\Conditions\Base`. |
| 32 | - The user asks "how do I add a custom Dynamic Visibility condition for JetEngine". |
| 33 | - A companion plugin needs role-aware / membership-aware / LMS-progress-aware visibility logic. |
| 34 | - Reviewing PR code that adds a condition class. |
| 35 | |
| 36 | ## The `Base` API surface (verified) |
| 37 | |
| 38 | All methods live on `\Jet_Engine\Modules\Dynamic_Visibility\Conditions\Base` ([base.php:4-212](base.php)): |
| 39 | |
| 40 | | Method | Default | Purpose | |
| 41 | |---|---|---| |
| 42 | | `get_id()` | abstract | Unique slug — used as the form-control key. Pick a stable slug; renaming breaks saved configurations. | |
| 43 | | `get_name()` | abstract | Display label in the editor dropdown. Translatable. | |
| 44 | | `check( $args = [] )` | abstract | The actual gate. Return `true` if the widget should display, `false` to hide. Honor `$args['type']`. | |
| 45 | | `get_group()` | `false` | Optional UI group label. `false` lands the condition in "Other"; otherwise groups con |