Skip to content

Add OnManagerSearch event to allow extending quick search#16915

Open
biz87 wants to merge 3 commits intomodxcms:3.xfrom
biz87:feature/on-manager-search-event
Open

Add OnManagerSearch event to allow extending quick search#16915
biz87 wants to merge 3 commits intomodxcms:3.xfrom
biz87:feature/on-manager-search-event

Conversation

@biz87
Copy link

@biz87 biz87 commented Mar 3, 2026

Summary

Closes #16912

Adds the OnManagerSearch system event that fires during manager quick search (uberbar) processing. Plugins can register custom search providers through declarative configuration arrays — the processor builds and executes xPDO queries from these configs.

Key changes:

  • New OnManagerSearch event (service=2, group=System) fired in Search/Search processor after built-in searches
  • New searchProvider() method handles provider configs: builds xPDO queries with optional joins, custom search fields, permission checks, and custom icons/labels
  • ArrayObject is used for the $providers parameter so that object identity is preserved through array_merge/extract in the event dispatch chain — all plugins share the same instance
  • Upgrade script for existing installations
  • No JS changes needed — the frontend already checks for label and icon fields before falling back to built-in mappings

Plugin usage example:

// Plugin on OnManagerSearch event
// $query, $providers, $maxResults, $searchInContent are available via extract()

$providers[] = [
    'class'            => 'MyExtra\Model\Product',
    'type'             => 'products',
    'label'            => 'Products',
    'icon'             => 'shopping-cart',
    'permission'       => 'myextra_view',
    'nameField'        => 'name',
    'descriptionField' => 'sku',
    'contentField'     => 'description',
    'idField'          => 'id',
    'action'           => 'myextra/product/update&id=',
    'joins'            => [
        [
            'class' => 'MyExtra\Model\Category',
            'alias' => 'Category',
            'on'    => 'Product.category_id = Category.id',
            'type'  => 'left',
        ],
    ],
    'searchFields' => ['Category.name'],
];

Provider config keys:

Key Required Description
class yes xPDO model class (validated via getTableName)
type yes Result group identifier
nameField yes Primary search/display field
action yes URL pattern (record ID is appended)
descriptionField no Secondary search/display field
contentField no Content field (respects quick_search_in_content)
label no Display label for group header
icon no FontAwesome icon name
permission no Permission to check before searching
idField no Primary key field name (default: id)
joins no Array of xPDO join configs (class, alias, on, type)
searchFields no Additional fields to search (e.g. from joins)

Test plan

  • Verify built-in search (resources, elements, users) still works as before
  • Create a test plugin on OnManagerSearch that registers a provider for an existing model (e.g. modCategory) and verify results appear in the search bar
  • Verify permission check prevents results when user lacks the specified permission
  • Verify label and icon display correctly in the search dropdown
  • Verify joins and searchFields allow searching related model fields
  • Verify malformed provider configs (missing required keys) are silently skipped
  • Verify invalid xPDO class in provider config doesn't break the search
  • Run upgrade on an existing 3.2.0 installation and verify the OnManagerSearch event is created

biz87 added 2 commits March 4, 2026 01:14
)

Add a system event that fires during manager quick search processing,
allowing plugins to register custom search providers via declarative
configuration arrays. The processor builds and executes xPDO queries
from these configs, supporting joins, custom icons/labels, and
permission checks. No JS changes needed — the frontend already
supports custom result types.
- Fix sortby with prefixed nameField (e.g. Product.name)
- Add select() for main class when joins are used to prevent column conflicts
- Validate xPDO class via getTableName() before querying
- Add optional idField config key (default: id) for custom primary keys
- Validate searchFields elements are non-empty strings
@biz87 biz87 requested review from Mark-H and opengeek as code owners March 3, 2026 20:15
@Ibochkarev Ibochkarev added the feature Request about implementing a brand new function or possibility. label Mar 4, 2026
Comment on lines +323 to +325
'name' => $record->get($nameField),
'description' => !empty($descriptionField) ? $record->get($descriptionField) : '',
'_action' => $config['action'] . $record->get($idField),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Potential regression for prefixed fields (Alias.field).

This method now supports dotted nameField in sorting, but the result mapping still reads:

  • $record->get($nameField)
  • $record->get($idField)

If config uses Product.name / Product.id, get() may not resolve these keys, which can produce empty name/id and broken _action URLs.

Please normalize field names before get() (strip alias), or select aliased columns and read those aliases.

Select dotted fields from joined tables and strip alias prefix
before xPDO get() calls to correctly resolve values.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Request about implementing a brand new function or possibility.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add OnManagerSearch event to allow extending quick search (uberbar)

2 participants