Sindbad~EG File Manager
<?php
/**
* Object Search REST API Controller
*
* @copyright (c) 2024, Code Atlantic LLC.
* @package PopupMaker\RestAPI
*/
namespace PopupMaker\RestAPI;
defined( 'ABSPATH' ) || exit;
use WP_REST_Controller;
use WP_REST_Server;
use WP_REST_Response;
use WP_Error;
use WP_REST_Request;
/**
* Object Search REST API Controller
*
* Provides REST API equivalent of the AJAX object search functionality.
* Supports post types, taxonomies, users, and custom object types via filters.
*/
class ObjectSearch extends WP_REST_Controller {
/**
* API namespace.
*
* @var string
*/
protected $namespace = 'popup-maker/v2';
/**
* REST base.
*
* @var string
*/
protected $rest_base = 'object-search';
/**
* Register routes.
*/
public function register_routes() {
register_rest_route(
$this->namespace,
'/' . $this->rest_base,
[
[
'methods' => WP_REST_Server::READABLE,
'callback' => [ $this, 'search_objects' ],
'permission_callback' => [ $this, 'permissions_check' ],
'args' => $this->get_search_args(),
],
]
);
}
/**
* Check if user has permission to search objects.
*
* @return bool|WP_Error True if the request has permission; WP_Error object otherwise.
*/
public function permissions_check() {
if ( ! current_user_can( 'edit_posts' ) ) {
return new WP_Error(
'rest_forbidden',
__( 'You do not have permission to search objects.', 'popup-maker' ),
[ 'status' => 403 ]
);
}
return true;
}
/**
* Search objects (posts, taxonomies, users, custom types).
*
* @param WP_REST_Request $request Full data about the request.
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function search_objects( $request ) {
$results = [
'items' => [],
'total_count' => 0,
];
$object_type = $request->get_param( 'object_type' );
$included = $request->get_param( 'include' ) ?: [];
$excluded = $request->get_param( 'exclude' ) ?: [];
if ( ! empty( $included ) ) {
$excluded = array_merge( $included, $excluded );
}
/**
* Filter object search results for unknown or custom object types.
*
* Allows plugins to handle custom object types that aren't natively supported.
*
* @param array{items:array,total_count:int}|null $results Current search results with 'items' and 'total_count'.
* @param string $object_type The object type being searched.
* @param array $request The full request parameters.
*
* @return array{items:array,total_count:int}|null $results
*/
$pre_results = apply_filters( 'popup_maker/pre_object_search', null, $object_type, $request->get_params() );
if ( null !== $pre_results ) {
$results = $pre_results;
} else {
switch ( $object_type ) {
case 'post_type':
$post_type = $request->get_param( 'object_key' ) ?: 'post';
$results = $this->search_post_type( $post_type, $request, $included, $excluded );
break;
case 'taxonomy':
$taxonomy = $request->get_param( 'object_key' ) ?: 'category';
$results = $this->search_taxonomy( $taxonomy, $request, $included, $excluded );
break;
case 'user':
if ( ! current_user_can( 'list_users' ) ) {
return new WP_Error(
'rest_forbidden',
__( 'You do not have permission to search users.', 'popup-maker' ),
[ 'status' => 403 ]
);
}
$user_role = $request->get_param( 'object_key' );
$results = $this->search_users( $user_role, $request, $included, $excluded );
break;
case 'custom_entity':
// Custom entities are handled by the popup_maker/object_search filter below.
// Leave results empty so filter handlers can populate them.
break;
}
}
/**
* Filter object search results for unknown or custom object types.
*
* Allows plugins to handle custom object types that aren't natively supported.
* This filter runs for both REST and AJAX requests - use popup_maker_object_search_unified() helper.
*
* @param array $results Current search results with 'items' and 'total_count'.
* @param string $object_type The object type being searched.
* @param array $request The full request parameters.
*/
$results = apply_filters( 'popup_maker/object_search', $results, $object_type, $request->get_params() );
// Take out keys which were only used to deduplicate.
$results['items'] = array_values( $results['items'] );
return new WP_REST_Response( $results, 200 );
}
/**
* Search post type objects.
*
* @param string $post_type Post type to search.
* @param WP_REST_Request $request Request object.
* @param array $included IDs to include.
* @param array $excluded IDs to exclude.
* @return array Search results.
*/
private function search_post_type( $post_type, $request, $included, $excluded ) {
$results = [
'items' => [],
'total_count' => 0,
];
if ( ! empty( $included ) ) {
$included_query = \PUM_Helpers::post_type_selectlist_query(
$post_type,
[
'post__in' => $included,
'posts_per_page' => -1,
],
true
);
foreach ( $included_query['items'] as $id => $name ) {
$results['items'][] = [
'id' => $id,
'text' => "$name (ID: $id)",
];
}
$results['total_count'] += (int) $included_query['total_count'];
}
$query = \PUM_Helpers::post_type_selectlist_query(
$post_type,
[
's' => $request->get_param( 's' ),
'paged' => $request->get_param( 'paged' ),
'post__not_in' => $excluded,
'posts_per_page' => 10,
],
true
);
foreach ( $query['items'] as $id => $name ) {
$results['items'][] = [
'id' => $id,
'text' => "$name (ID: $id)",
];
}
$results['total_count'] += (int) $query['total_count'];
return $results;
}
/**
* Search taxonomy objects.
*
* @param string $taxonomy Taxonomy to search.
* @param WP_REST_Request $request Request object.
* @param array $included IDs to include.
* @param array $excluded IDs to exclude.
* @return array Search results.
*/
private function search_taxonomy( $taxonomy, $request, $included, $excluded ) {
$results = [
'items' => [],
'total_count' => 0,
];
if ( ! empty( $included ) ) {
$included_query = \PUM_Helpers::taxonomy_selectlist_query(
$taxonomy,
[
'include' => $included,
'number' => 0,
],
true
);
foreach ( $included_query['items'] as $id => $name ) {
$results['items'][] = [
'id' => $id,
'text' => "$name (ID: $id)",
];
}
$results['total_count'] += (int) $included_query['total_count'];
}
$query = \PUM_Helpers::taxonomy_selectlist_query(
$taxonomy,
[
'search' => $request->get_param( 's' ),
'paged' => $request->get_param( 'paged' ),
'exclude' => $excluded,
'number' => 10,
],
true
);
foreach ( $query['items'] as $id => $name ) {
$results['items'][] = [
'id' => $id,
'text' => "$name (ID: $id)",
];
}
$results['total_count'] += (int) $query['total_count'];
return $results;
}
/**
* Search user objects.
*
* @param string|null $user_role User role to filter by.
* @param WP_REST_Request $request Request object.
* @param array $included IDs to include.
* @param array $excluded IDs to exclude.
* @return array Search results.
*/
private function search_users( $user_role, $request, $included, $excluded ) {
$results = [
'items' => [],
'total_count' => 0,
];
if ( ! empty( $included ) ) {
$included_query = \PUM_Helpers::user_selectlist_query(
[
'role' => $user_role,
'include' => $included,
'number' => -1,
],
true
);
foreach ( $included_query['items'] as $id => $name ) {
$results['items'][] = [
'id' => $id,
'text' => "$name (ID: $id)",
];
}
$results['total_count'] += (int) $included_query['total_count'];
}
$search = $request->get_param( 's' );
$query = \PUM_Helpers::user_selectlist_query(
[
'role' => $user_role,
'search' => $search ? '*' . $search . '*' : null,
'paged' => $request->get_param( 'paged' ),
'exclude' => $excluded,
'number' => 10,
],
true
);
foreach ( $query['items'] as $id => $name ) {
$results['items'][] = [
'id' => $id,
'text' => "$name (ID: $id)",
];
}
$results['total_count'] += (int) $query['total_count'];
return $results;
}
/**
* Get arguments for search endpoint.
*
* @return array Endpoint arguments.
*/
protected function get_search_args() {
return [
'object_type' => [
'type' => 'string',
'description' => __( 'Type of object to search (post_type, taxonomy, user, custom_entity)', 'popup-maker' ),
'required' => true,
'enum' => [ 'post_type', 'taxonomy', 'user', 'custom_entity' ],
],
'object_key' => [
'type' => 'string',
'description' => __( 'Specific object key (post type name, taxonomy name, user role)', 'popup-maker' ),
'required' => false,
],
's' => [
'type' => 'string',
'description' => __( 'Search term', 'popup-maker' ),
'required' => false,
],
'include' => [
'type' => 'array',
'description' => __( 'IDs to include in results (integers for standard objects, strings for custom entities)', 'popup-maker' ),
'required' => false,
'items' => [
'type' => [ 'integer', 'string' ],
],
],
'exclude' => [
'type' => 'array',
'description' => __( 'IDs to exclude from results (integers for standard objects, strings for custom entities)', 'popup-maker' ),
'required' => false,
'items' => [
'type' => [ 'integer', 'string' ],
],
],
'paged' => [
'type' => 'integer',
'description' => __( 'Page number for pagination', 'popup-maker' ),
'required' => false,
'minimum' => 1,
],
];
}
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists