# ultimate-post-kit/4.5.3/includes/controls/select-input/dynamic-select-input-module.php

Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider &amp; Blog Layout Widgets, version 4.5.3. 330 lines.

- Page: https://pluginprobe.com/plugins/ultimate-post-kit/4.5.3/code/includes/controls/select-input/dynamic-select-input-module.php
- Raw: https://pluginprobe.com/plugins/ultimate-post-kit/4.5.3/raw/includes/controls/select-input/dynamic-select-input-module.php
- Modified: 2026-09-07T07:17:46+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/ultimate-post-kit/4.5.3/code/includes/controls/select-input/dynamic-select-input-module.php#L10-L20`.

```php
<?php

namespace UltimatePostKit\Includes\Controls\SelectInput;

defined('ABSPATH') || die();
class UltimatePostKit_Dynamic_Select_Input_Module {

	const ACTION = '';

	private static $instance = null;

	/**
	 * Returns the instance.
	 *
	 * @return object
	 * @since  1.0.0
	 */
	public static function get_instance() {
		// If the single instance hasn't been set, set it now.
		if (null == self::$instance) {
			self::$instance = new self;
		}

		return self::$instance;
	}

	/**
	 * Init method
	 */

	/**
	 * Constructor.
	 */
	public function init() {
		add_action('wp_ajax_upk_dynamic_select_input_data', array($this, 'getSelectInputData'));
	}

	/**
	 * get Ajax Data
	 */
	public function getSelectInputData() {
		$nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : '';

		try {
			if (!wp_verify_nonce($nonce, 'upk_dynamic_select')) {
				throw new \Exception('Invalid request');
			}

			if (!current_user_can('edit_posts')) {
				throw new \Exception('Unauthorized request');
			}

			$query = isset($_POST['query']) ? sanitize_text_field(wp_unslash($_POST['query'])) : '';

			if ($query == 'terms') {
				$data = $this->getTerms();
			} else if ($query == 'authors') {
				$data = $this->getAuthors();
			} else {
				$data = $this->getPosts();
			}

			wp_send_json_success($data);
		} catch (\Exception $e) {
			wp_send_json_error($e->getMessage());
		}

		die();
	}

	/**
	 * Get Post Type
	 * @return string
	 */
	protected function getPostType() {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified in getSelectInputData() before this helper runs.
		return isset($_POST['post_type']) ? sanitize_text_field(wp_unslash($_POST['post_type'])) : '';
	}

	/**
	 * @return string[]|\WP_Post_Type[]
	 */
	protected function getAllPublicPostTypes() {
		return array_values(get_post_types(['public' => true]));
	}

	/**
	 * @return string
	 */
	protected function getSearchQuery() {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified in getSelectInputData() before this helper runs.
		return isset($_POST['search_text']) ? sanitize_text_field(wp_unslash($_POST['search_text'])) : '';
	}

	/**
	 * @return array|mixed
	 */
	protected function getselecedIds() {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified in getSelectInputData() before this helper runs.
		return isset($_POST['ids']) ? sanitize_text_field(wp_unslash($_POST['ids'])) : [];
	}


	/**
	 * @param string $taxonomy
	 *
	 * @return mixed|string
	 */
	public function getTaxonomyName($taxonomy = '') {
		$taxonomies = get_taxonomies(['public' => true], 'objects');
		$taxonomies = array_column($taxonomies, 'label', 'name');

		return isset($taxonomies[$taxonomy]) ? $taxonomies[$taxonomy] : '';
	}

	/**
	 * @return string[]|\WP_Taxonomy[]
	 */
	protected function getAllPublicTaxonomies() {
		return array_values(get_taxonomies(['public' => true]));
	}

	/**
	 * Get Post Query Data
	 *
	 * @return array
	 */
	public function getPosts() {
		$include    = $this->getselecedIds();
		$searchText = $this->getSearchQuery();

		$args = [];

		$args['post_status'] = 'publish';

		$public_post_types = $this->getAllPublicPostTypes();
		$requested_post_type = $this->getPostType();

		// post_type comes straight from $_POST. Restrict it to the public post types this
		// control is meant to browse so it cannot be pointed at a private post type.
		if ($requested_post_type && in_array($requested_post_type, $public_post_types, true)) {
			$args['post_type'] = $requested_post_type;
		} else {
			$args['post_type'] = $public_post_types;
		}

		if (!empty($include)) {
			$args['post__in']     = $include;
			$args['posts_per_page'] = min(100, count($include));
		} else {
			// Never run this unbounded: it is reachable by any 'edit_posts' user and
			// -1 returns every published post of every public post type.
			$args['posts_per_page'] = 50;
		}
		if ($searchText) {
			$args['s'] = $searchText;
		}

		$query = new \WP_Query($args);
		$results = [];
		foreach ($query->posts as $post) {
			$post_type_obj = get_post_type_object($post->post_type);
			if (!empty($data['include_type'])) {
				$text = $post_type_obj->labels->name . ': ' . $post->post_title;
			} else {
				$text = ($post_type_obj->hierarchical) ? $this->get_post_name_with_parents($post) : $post->post_title;
			}

			$results[] = [
				'id' => $post->ID,
				'text' => esc_html($text),
			];
		}

		return $results;
	}

	private function get_post_name_with_parents($post, $max = 3) {
		if (0 === $post->post_parent) {
			return $post->post_title;
		}
		$separator = is_rtl() ? ' < ' : ' > ';
		$test_post = $post;
		$names = [];
		while ($test_post->post_parent > 0) {
			$test_post = get_post($test_post->post_parent);
			if (!$test_post) {
				break;
			}
			$names[] = $test_post->post_title;
		}

		$names = array_reverse($names);
		if (count($names) < ($max)) {
			return implode($separator, $names) . $separator . $post->post_title;
		}

		$name_string = '';
		for ($i = 0; $i < ($max - 1); $i++) {
			$name_string .= $names[$i] . $separator;
		}
		return $name_string . '...' . $separator . $post->post_title;
	}

	/**
	 * Get Terms query data
	 *
	 * @return array
	 */
	public function getTerms() {
		$search_text = $this->getSearchQuery();
		$taxonomies  = $this->getAllPublicTaxonomies();
		$include     = $this->getselecedIds();

		if ($this->getPostType() == '_ultimate_post_kit_pro_related_post_type') {
			$post_type = $this->getAllPublicPostTypes();
		} elseif ($this->getPostType()) {
			$post_type = $this->getPostType();
		}

		$post_taxonomies = get_object_taxonomies($post_type);
		$taxonomies      = array_intersect($post_taxonomies, $taxonomies);
		$data            = [];

		if (empty($taxonomies)) {
			return $data;
		}

		$args = [
			'taxonomy'   => $taxonomies,
			'hide_empty' => true,
		];

		if (!empty($include)) {
			$args['include'] = $include;
		}

		if ($search_text) {
			$args['number'] = 20;
			$args['search'] = $search_text;
		}

		$terms = get_terms($args);

		if (is_wp_error($terms) || empty($terms)) {
			return $data;
		}

		foreach ($terms as $term) {
			$label         = $term->name;
			$taxonomy_name = $this->getTaxonomyName($term->taxonomy);

			if ($taxonomy_name) {
				$label = "{$taxonomy_name}: {$label}";
			}

			$data[] = [
				'id'   => $term->term_taxonomy_id,
				'text' => $label,
			];
		}

		return $data;
	}

	/**
	 * Get Authors query Data
	 *
	 * @return array
	 */
	public function getAuthors() {
		$include     = $this->getselecedIds();
		$search_text = $this->getSearchQuery();

		$args = [
			'fields'  => ['ID', 'display_name'],
			'orderby' => 'display_name',
			// Always bound the result set. Without this an empty search returns every
			// user on the site, unpaged.
			'number'  => 20,
		];

		// This endpoint is only capability-gated on 'edit_posts', so a Contributor can
		// reach it. WordPress core restricts callers without 'list_users' to users who
		// have published something (see WP_REST_Users_Controller::get_items), so match
		// that restriction rather than exposing the full user table.
		if (!current_user_can('list_users')) {
			$args['has_published_posts'] = true;
		}

		if (!empty($include)) {
			$args['include'] = $include;
			// Resolving already-selected values needs room for all of them, but still
			// bounded so a long id list cannot be used to dump the table.
			$args['number'] = min(100, max(20, count($include)));
		}

		if ($search_text) {
			$args['search'] = "*$search_text*";
			// WP_User_Query searches user_email when the term contains "@", which turns
			// this into an address oracle. Core strips user_email from the searchable
			// columns for callers without 'list_users'; do the same here.
			$args['search_columns'] = ['ID', 'user_login', 'user_nicename', 'display_name'];
		}

		$users = get_users($args);

		$data = [];

		if (empty($users)) {
			return $data;
		}

		foreach ($users as $user) {
			$data[] = [
				'id'   => $user->ID,
				'text' => $user->display_name,
			];
		}

		return $data;
	}
}

function ultimatePostKit_dynamic_select_input_module() {

	return UltimatePostKit_Dynamic_Select_Input_Module::get_instance();
}
ultimatePostKit_dynamic_select_input_module()->init();

```
