Claude Skill

je-dynamic-visibility-condition

Registers or audits a custom JetEngine Dynamic Visibility condition by extending Conditions\Base and using the conditions/register hook. Covers show/hide polarity, AND/OR behavior, listing-context value resolution, custom controls under condition_settings, groups, module timing,

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download lonsdale201-wp-agent-skills-jet-engine_je-dynamic-visibility-condition-52f6020.zip · 4 KB
Part of lonsdale201/wp-agent-skills — 226 skills

Install

skills CLI npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/jet-engine/je-dynamic-visibility-condition
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart
Git git clone https://github.com/Lonsdale201/wp-agent-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole lonsdale201/wp-agent-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

JetEngine Dynamic Visibility condition

Implement a condition as a deterministic predicate that follows JetEngine's show/hide contract. Do not use visibility as an authorization boundary: hidden markup, REST data, files, and mutations still need server-side access checks.

When to use this skill

  • Add a condition to Dynamic Visibility in a JetEngine companion plugin.
  • Diagnose reversed Show/Hide results or surprising AND/OR combinations.
  • Read a listing object's post, term, user, comment, product, or custom field.
  • Add condition-specific controls or a custom condition group.
  • Audit render-time queries, global-state changes, or context-sensitive output.

Workflow

  1. Confirm JetEngine 3.8.14 and the Dynamic Visibility module are active.
  2. Register only on jet-engine/modules/dynamic-visibility/conditions/register; do not instantiate the base class before JetEngine loads the module.
  3. Give get_id() a stable, vendor-prefixed ID.
  4. Compute the positive match in check(), then return its inverse for hide.
  5. Use get_current_value() when the condition consumes JetEngine's Field UI.
  6. Read custom controls from $args['condition_settings'][<control-key>].
  7. Keep check() pure and cheap. Cache remote/expensive data outside the render loop with a key that includes every relevant user/object/site dimension.
  8. Test show and hide, AND and OR, listing and non-listing context, empty values, logged-in/out users, AJAX/load-more, and repeated calls.

Minimal condition

Load the named class from the callback (or through a guarded autoloader), so its parent exists when PHP parses it.

add_action(
    'jet-engine/modules/dynamic-visibility/conditions/register',
    static function ($manager): void {
        require_once __DIR__ . '/src/class-owned-by-current-user.php';
        $manager->register_condition(new My_Plugin_Owned_By_Current_User());
    }
);
use Jet_Engine\Modules\Dynamic_Visibility\Conditions\Base;

final class My_Plugin_Owned_By_Current_User extends Base {
    public function get_id() {
        return 'my_plugin_owned_by_current_user';
    }

    public function get_name() {
        return __('Owned by current user', 'my-plugin');
    }

    public function get_group() {
        return 'user';
    }

    public function is_for_fields() {
        return false;
    }

    public function need_value_detect() {
        return false;
    }

    public function check($args = array()) {
        $object = jet_engine()->listings->data->get_current_object();
        $match  = $object instanceof WP_Post
            && (int) $object->post_author === get_current_user_id();

        return 'hide' === ($args['type'] ?? 'show') ? ! $match : $match;
    }
}

JetEngine's checker expects each condition to honor type. For a positive predicate M, return M for show and ! M for hide. Do not invert again for AND/OR; the checker combines each returned value.

Field-aware conditions

Base::get_current_value($args) resolves the current listing object:

  • WP_Post and exact WC_Product: post meta;
  • WP_User: user meta;
  • WP_Term: term meta;
  • WP_Comment: comment meta;
  • other listing objects: JetEngine listing-data property;
  • non-listing field context: current post meta;
  • macro/dynamic Field input: JetEngine macro output.

Use adjust_values_type() for JetEngine-compatible numeric, date, datetime, or string comparison. Treat empty, missing, 0, and '0' explicitly; do not use empty() when zero is meaningful.

Custom controls

public function get_custom_controls() {
    return array(
        'my_plugin_roles' => array(
            'label'    => __('Allowed roles', 'my-plugin'),
            'type'     => 'select2',
            'multiple' => true,
            'default'  => array(),
            'options'  => wp_roles()->get_names(),
        ),
    );
}

public function check($args = array()) {
    $settings = $args['condition_settings'] ?? array();
    $roles    = isset($settings['my_plugin_roles'])
        ? (array) $settings['my_plugin_roles']
        : array();
    $match    = (bool) array_intersect($roles, wp_get_current_user()->roles);

    return 'hide' === ($args['type'] ?? 'show') ? ! $match : $match;
}

Control keys are not copied to the top-level $args. Prefix them to avoid collisions. Use a built-in group slug (general, jet-engine, user, posts, date_time, listing) or add a label through jet-engine/modules/dynamic-visibility/conditions/groups.

Security and reliability invariants

  • Never grant access because an element is hidden or visible.
  • Never change the current listing object, query globals, locale, or user from check() without restoring state in finally.
  • Never emit output, redirect, mutate data, or call an unstable remote service.
  • Avoid one database query per card in a Listing Grid; prefetch or cache.
  • Do not bypass jet-engine/modules/dynamic-visibility/condition/prevent-check. JetEngine 3.8.14 uses it while silently preloading listing assets.
  • Return a boolean on every path and choose a safe failure result deliberately.

Verification

Assert all four polarity/composition cases and run the same condition twice:

show + match       => render
show + no match    => suppress
hide + match       => suppress
hide + no match    => render

Also verify a Listing Grid with load more and a builder preview. Check query counts when the rule can appear on many cards.

Deeper implementation reference

Read implementation-reference.md when implementing field comparisons, custom groups, context handling, or tests.

References

Files (wp-agent-skills)
  • agents
    • openai.yaml 277 B
      interface:
        display_name: "JetEngine Visibility Condition"
        short_description: "Build safe JetEngine visibility conditions"
        default_prompt: "Use $je-dynamic-visibility-condition to implement or audit this JetEngine Dynamic Visibility condition and its show/hide behavior."
      
  • references
    • implementation-reference.md 3.2 KB
      # Dynamic Visibility implementation reference
      
      Load this reference when the condition needs JetEngine field semantics, custom
      controls, a custom group, or a concrete regression matrix.
      
      ## Base contract
      
      Required methods:
      
      ```php
      abstract public function get_id();
      abstract public function get_name();
      abstract public function check($args = array());
      ```
      
      Optional defaults:
      
      ```text
      get_group()          false
      is_for_fields()      true
      need_value_detect()  true
      need_type_detect()   false
      get_custom_controls() false
      ```
      
      Use `is_for_fields() === false` for request/user/date conditions that do not
      need the Field selector. Use `need_value_detect() === false` when no comparison
      value is required. Return `true` from `need_type_detect()` only when the UI must
      offer numeric/date/string coercion.
      
      ## Checker argument shape
      
      The checker prepares these top-level keys:
      
      ```php
      array(
          'type'               => 'show',
          'condition'          => 'my_plugin_condition',
          'user_role'          => null,
          'user_id'            => null,
          'field'              => null,
          'field_raw'          => null,
          'value'              => null,
          'data_type'          => null,
          'context'            => null,
          'condition_settings' => array(/* complete saved repeater row */),
      )
      ```
      
      The filter `jet-engine/modules/dynamic-visibility/condition/args` can adjust the
      shape before `check()`. Do not make a condition depend on an undocumented key
      without a default.
      
      ## Comparison pattern
      
      ```php
      public function check($args = array()) {
          $current = $this->get_current_value($args);
          $wanted  = $args['value'] ?? null;
          $type    = $args['data_type'] ?? 'chars';
          $values  = $this->adjust_values_type($current, $wanted, $type);
          $match   = $values['current'] === $values['compare'];
      
          return 'hide' === ($args['type'] ?? 'show') ? ! $match : $match;
      }
      ```
      
      Choose strict or loose comparison intentionally. JetEngine's built-in Equal
      uses loose equality after type adjustment; a custom condition can be stricter
      when its saved-data contract permits it.
      
      ## Custom group
      
      ```php
      add_filter(
          'jet-engine/modules/dynamic-visibility/conditions/groups',
          static function(array $groups): array {
              $groups['my_plugin'] = array(
                  'label'   => __('My Plugin', 'my-plugin'),
                  'options' => array(),
              );
              return $groups;
          }
      );
      ```
      
      Return `my_plugin` from `get_group()`. If an unknown slug is returned without a
      filter, JetEngine currently creates a group whose displayed label is the raw
      slug; do not rely on that as polished UI.
      
      ## Regression matrix
      
      Test at least:
      
      | Dimension | Cases |
      |---|---|
      | Intent | show, hide |
      | Relation | one condition, AND, OR |
      | Match | true, false, missing value, zero value |
      | Object | post, user/term/comment/custom object where supported |
      | Context | current listing, current post, macro field |
      | Request | normal page, builder preview, AJAX/load more |
      | State | logged out, allowed user, disallowed user |
      | Repeatability | two calls with identical inputs produce identical output |
      
      For expensive conditions, compare database query counts for one card and a
      multi-card listing. A request cache must include object ID, user ID, blog ID,
      locale, and any setting that changes the result.
      
  • SKILL.md 7.1 KB
    ---
    name: je-dynamic-visibility-condition
    description: >-
      Registers or audits a custom JetEngine Dynamic Visibility condition by
      extending Conditions\Base and using the conditions/register hook. Covers
      show/hide polarity, AND/OR behavior, listing-context value resolution,
      custom controls under condition_settings, groups, module timing, pure checks,
      and 3.8.14 silent listing-asset preload behavior. Use when a companion plugin
      adds visibility rules, a condition appears but evaluates backwards, custom UI
      values are missing, or listing/admin/AJAX rendering differs.
    metadata:
      wp-skills-author: "Soczó Kristóf"
      wp-skills-contact: "mailto:lonsdale201@hotmail.com"
      wp-skills-plugin: "jet-engine"
      wp-skills-plugin-version-tested: "3.8.14"
      wp-skills-wp-version-tested: "7.0.4"
      wp-skills-php-min: "7.4"
      wp-skills-last-updated: "2026-08-17"
    ---
    
    # JetEngine Dynamic Visibility condition
    
    Implement a condition as a deterministic predicate that follows JetEngine's
    show/hide contract. Do not use visibility as an authorization boundary: hidden
    markup, REST data, files, and mutations still need server-side access checks.
    
    ## When to use this skill
    
    - Add a condition to Dynamic Visibility in a JetEngine companion plugin.
    - Diagnose reversed Show/Hide results or surprising AND/OR combinations.
    - Read a listing object's post, term, user, comment, product, or custom field.
    - Add condition-specific controls or a custom condition group.
    - Audit render-time queries, global-state changes, or context-sensitive output.
    
    ## Workflow
    
    1. Confirm JetEngine 3.8.14 and the Dynamic Visibility module are active.
    2. Register only on
       `jet-engine/modules/dynamic-visibility/conditions/register`; do not instantiate
       the base class before JetEngine loads the module.
    3. Give `get_id()` a stable, vendor-prefixed ID.
    4. Compute the positive match in `check()`, then return its inverse for `hide`.
    5. Use `get_current_value()` when the condition consumes JetEngine's Field UI.
    6. Read custom controls from `$args['condition_settings'][<control-key>]`.
    7. Keep `check()` pure and cheap. Cache remote/expensive data outside the render
       loop with a key that includes every relevant user/object/site dimension.
    8. Test show and hide, AND and OR, listing and non-listing context, empty values,
       logged-in/out users, AJAX/load-more, and repeated calls.
    
    ## Minimal condition
    
    Load the named class from the callback (or through a guarded autoloader), so its
    parent exists when PHP parses it.
    
    ```php
    add_action(
        'jet-engine/modules/dynamic-visibility/conditions/register',
        static function ($manager): void {
            require_once __DIR__ . '/src/class-owned-by-current-user.php';
            $manager->register_condition(new My_Plugin_Owned_By_Current_User());
        }
    );
    ```
    
    ```php
    use Jet_Engine\Modules\Dynamic_Visibility\Conditions\Base;
    
    final class My_Plugin_Owned_By_Current_User extends Base {
        public function get_id() {
            return 'my_plugin_owned_by_current_user';
        }
    
        public function get_name() {
            return __('Owned by current user', 'my-plugin');
        }
    
        public function get_group() {
            return 'user';
        }
    
        public function is_for_fields() {
            return false;
        }
    
        public function need_value_detect() {
            return false;
        }
    
        public function check($args = array()) {
            $object = jet_engine()->listings->data->get_current_object();
            $match  = $object instanceof WP_Post
                && (int) $object->post_author === get_current_user_id();
    
            return 'hide' === ($args['type'] ?? 'show') ? ! $match : $match;
        }
    }
    ```
    
    JetEngine's checker expects each condition to honor `type`. For a positive
    predicate `M`, return `M` for `show` and `! M` for `hide`. Do not invert again
    for AND/OR; the checker combines each returned value.
    
    ## Field-aware conditions
    
    `Base::get_current_value($args)` resolves the current listing object:
    
    - `WP_Post` and exact `WC_Product`: post meta;
    - `WP_User`: user meta;
    - `WP_Term`: term meta;
    - `WP_Comment`: comment meta;
    - other listing objects: JetEngine listing-data property;
    - non-listing field context: current post meta;
    - macro/dynamic Field input: JetEngine macro output.
    
    Use `adjust_values_type()` for JetEngine-compatible `numeric`, `date`,
    `datetime`, or string comparison. Treat empty, missing, `0`, and `'0'`
    explicitly; do not use `empty()` when zero is meaningful.
    
    ## Custom controls
    
    ```php
    public function get_custom_controls() {
        return array(
            'my_plugin_roles' => array(
                'label'    => __('Allowed roles', 'my-plugin'),
                'type'     => 'select2',
                'multiple' => true,
                'default'  => array(),
                'options'  => wp_roles()->get_names(),
            ),
        );
    }
    
    public function check($args = array()) {
        $settings = $args['condition_settings'] ?? array();
        $roles    = isset($settings['my_plugin_roles'])
            ? (array) $settings['my_plugin_roles']
            : array();
        $match    = (bool) array_intersect($roles, wp_get_current_user()->roles);
    
        return 'hide' === ($args['type'] ?? 'show') ? ! $match : $match;
    }
    ```
    
    Control keys are not copied to the top-level `$args`. Prefix them to avoid
    collisions. Use a built-in group slug (`general`, `jet-engine`, `user`, `posts`,
    `date_time`, `listing`) or add a label through
    `jet-engine/modules/dynamic-visibility/conditions/groups`.
    
    ## Security and reliability invariants
    
    - Never grant access because an element is hidden or visible.
    - Never change the current listing object, query globals, locale, or user from
      `check()` without restoring state in `finally`.
    - Never emit output, redirect, mutate data, or call an unstable remote service.
    - Avoid one database query per card in a Listing Grid; prefetch or cache.
    - Do not bypass
      `jet-engine/modules/dynamic-visibility/condition/prevent-check`. JetEngine
      3.8.14 uses it while silently preloading listing assets.
    - Return a boolean on every path and choose a safe failure result deliberately.
    
    ## Verification
    
    Assert all four polarity/composition cases and run the same condition twice:
    
    ```text
    show + match       => render
    show + no match    => suppress
    hide + match       => suppress
    hide + no match    => render
    ```
    
    Also verify a Listing Grid with load more and a builder preview. Check query
    counts when the rule can appear on many cards.
    
    ## Deeper implementation reference
    
    Read [implementation-reference.md](references/implementation-reference.md) when
    implementing field comparisons, custom groups, context handling, or tests.
    
    ## References
    
    - Official documentation: <https://crocoblock.com/knowledge-base/plugins/jetengine/>
    - Crocoblock developer documentation: <https://github.com/Crocoblock/developer-documentation/tree/main/01-jet-engine>
    - Verified source paths:
      - `wp-content/plugins/jet-engine/includes/modules/dynamic-visibility/inc/conditions/base.php`
      - `wp-content/plugins/jet-engine/includes/modules/dynamic-visibility/inc/conditions/manager.php`
      - `wp-content/plugins/jet-engine/includes/modules/dynamic-visibility/inc/conditions-checker.php`
      - `wp-content/plugins/jet-engine/includes/modules/dynamic-visibility/inc/conditions/week-days.php`
      - `wp-content/plugins/jet-engine/includes/components/listings/frontend.php`
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related