namespace, '/search', array( array( 'methods' => 'GET', 'callback' => array( $this, 'search' ), 'permission_callback' => array( $this, 'can_read' ), 'args' => array( 'q' => array( 'type' => 'string' ), ), ), ) ); } /** * @param WP_REST_Request $request The request. */ public function search( WP_REST_Request $request ): WP_REST_Response { $term = trim( sanitize_text_field( (string) ( $request->get_param( 'q' ) ?? '' ) ) ); if ( mb_strlen( $term ) < self::MIN_LENGTH ) { return $this->ok( array() ); } /** * Register a global-search provider. * * Each entry is: * 'label' => string Plural, shown as the group heading. * 'route' => string Client route; "{id}" is replaced with the result's id. * 'order' => int Where the group sits. * 'search' => callable (string $term, int $limit): array * * @param array> $providers Keyed by entity slug. */ $providers = (array) apply_filters( 'plugixa_crm_search_providers', array() ); uasort( $providers, static fn( array $a, array $b ): int => ( $a['order'] ?? 100 ) <=> ( $b['order'] ?? 100 ) ); $groups = array(); foreach ( $providers as $slug => $provider ) { if ( ! isset( $provider['search'] ) || ! is_callable( $provider['search'] ) ) { continue; } $hits = (array) call_user_func( $provider['search'], $term, self::PER_PROVIDER ); if ( array() === $hits ) { continue; } $groups[] = array( 'entity' => $slug, 'label' => (string) ( $provider['label'] ?? $slug ), 'route' => (string) ( $provider['route'] ?? '' ), 'results' => array_values( $hits ), ); } return $this->ok( $groups ); } }