Constants
17 hours ago
Accordion.php
17 hours ago
Alert.php
17 hours ago
AttachmentCard.php
17 hours ago
Avatar.php
17 hours ago
Badge.php
17 hours ago
BaseComponent.php
17 hours ago
Button.php
17 hours ago
ConfirmationModal.php
17 hours ago
CourseFilter.php
17 hours ago
DateFilter.php
17 hours ago
DropdownFilter.php
17 hours ago
EmptyState.php
17 hours ago
FileUploader.php
17 hours ago
InputField.php
17 hours ago
Modal.php
17 hours ago
Nav.php
17 hours ago
Pagination.php
17 hours ago
Popover.php
17 hours ago
PreviewTrigger.php
17 hours ago
Progress.php
17 hours ago
SearchFilter.php
17 hours ago
Sorting.php
17 hours ago
StarRating.php
17 hours ago
StarRatingInput.php
17 hours ago
StatusSelect.php
17 hours ago
SvgIcon.php
17 hours ago
Table.php
17 hours ago
Tabs.php
17 hours ago
Tooltip.php
17 hours ago
WPEditor.php
17 hours ago
SearchFilter.php
269 lines
| 1 | <?php |
| 2 | /** |
| 3 | * SearchFilter Component Class. |
| 4 | * |
| 5 | * Responsible for rendering a search filter component |
| 6 | * that handles server-side filtering via search param. |
| 7 | * |
| 8 | * @package Tutor\Components |
| 9 | * @author Themeum |
| 10 | * @link https://themeum.com |
| 11 | * @since 4.0.0 |
| 12 | */ |
| 13 | |
| 14 | namespace Tutor\Components; |
| 15 | |
| 16 | use Tutor\Components\Constants\Size; |
| 17 | use Tutor\Components\Constants\Color; |
| 18 | use TUTOR\Icon; |
| 19 | use TUTOR\Input; |
| 20 | |
| 21 | defined( 'ABSPATH' ) || exit; |
| 22 | |
| 23 | /** |
| 24 | * Class SearchFilter |
| 25 | * |
| 26 | * Example Usage: |
| 27 | * ``` |
| 28 | * SearchFilter::make() |
| 29 | * ->form_id( 'my-search-form' ) |
| 30 | * ->placeholder( 'Search items...' ) |
| 31 | * ->hidden_inputs( array( 'type' => 'course' ) ) |
| 32 | * ->action( 'https://example.com/search' ) |
| 33 | * ->input_name( 'search' ) |
| 34 | * ->method( 'GET' ) |
| 35 | * ->size( 'small' ) |
| 36 | * ->render(); |
| 37 | * ``` |
| 38 | * |
| 39 | * @since 4.0.0 |
| 40 | */ |
| 41 | class SearchFilter extends BaseComponent { |
| 42 | |
| 43 | /** |
| 44 | * Form ID |
| 45 | * |
| 46 | * @var string |
| 47 | */ |
| 48 | protected $form_id = 'tutor-search-filter-form'; |
| 49 | |
| 50 | /** |
| 51 | * Search Placeholder |
| 52 | * |
| 53 | * @var string |
| 54 | */ |
| 55 | protected $placeholder; |
| 56 | |
| 57 | /** |
| 58 | * Form Action URL |
| 59 | * |
| 60 | * @var string |
| 61 | */ |
| 62 | protected $action_url; |
| 63 | |
| 64 | /** |
| 65 | * Search Input Name |
| 66 | * |
| 67 | * @var string |
| 68 | */ |
| 69 | protected $input_name = 'search'; |
| 70 | |
| 71 | /** |
| 72 | * Additional hidden inputs |
| 73 | * |
| 74 | * @var array |
| 75 | */ |
| 76 | protected $hidden_inputs = array(); |
| 77 | |
| 78 | /** |
| 79 | * Input Size |
| 80 | * |
| 81 | * @var string |
| 82 | */ |
| 83 | protected $size = Size::MEDIUM; |
| 84 | |
| 85 | /** |
| 86 | * Form Method |
| 87 | * |
| 88 | * @var string |
| 89 | */ |
| 90 | protected $method = 'GET'; |
| 91 | |
| 92 | |
| 93 | /** |
| 94 | * Set form ID |
| 95 | * |
| 96 | * @param string $form_id form ID. |
| 97 | * |
| 98 | * @return self |
| 99 | */ |
| 100 | public function form_id( string $form_id ): self { |
| 101 | $this->form_id = $form_id; |
| 102 | return $this; |
| 103 | } |
| 104 | |
| 105 | /** |
| 106 | * Set placeholder |
| 107 | * |
| 108 | * @param string $placeholder placeholder. |
| 109 | * |
| 110 | * @return self |
| 111 | */ |
| 112 | public function placeholder( string $placeholder ): self { |
| 113 | $this->placeholder = $placeholder; |
| 114 | return $this; |
| 115 | } |
| 116 | |
| 117 | /** |
| 118 | * Set action URL |
| 119 | * |
| 120 | * @param string $url action URL. |
| 121 | * |
| 122 | * @return self |
| 123 | */ |
| 124 | public function action( string $url ): self { |
| 125 | $this->action_url = $url; |
| 126 | return $this; |
| 127 | } |
| 128 | |
| 129 | /** |
| 130 | * Set input name |
| 131 | * |
| 132 | * @param string $name input name. |
| 133 | * |
| 134 | * @return self |
| 135 | */ |
| 136 | public function input_name( string $name ): self { |
| 137 | $this->input_name = $name; |
| 138 | return $this; |
| 139 | } |
| 140 | |
| 141 | /** |
| 142 | * Add hidden inputs |
| 143 | * |
| 144 | * @param array $inputs Input array. |
| 145 | * |
| 146 | * @return self |
| 147 | */ |
| 148 | public function hidden_inputs( array $inputs ): self { |
| 149 | $this->hidden_inputs = array_merge( $this->hidden_inputs, $inputs ); |
| 150 | return $this; |
| 151 | } |
| 152 | |
| 153 | /** |
| 154 | * Set size of the input |
| 155 | * |
| 156 | * @param string $size size of the input. |
| 157 | * |
| 158 | * @return self |
| 159 | */ |
| 160 | public function size( string $size ): self { |
| 161 | $this->size = $size; |
| 162 | return $this; |
| 163 | } |
| 164 | |
| 165 | /** |
| 166 | * Set form method |
| 167 | * |
| 168 | * @param string $method form method. |
| 169 | * |
| 170 | * @return self |
| 171 | */ |
| 172 | public function method( string $method ): self { |
| 173 | $this->method = $method; |
| 174 | return $this; |
| 175 | } |
| 176 | |
| 177 | |
| 178 | /** |
| 179 | * Get component content |
| 180 | * |
| 181 | * @return string |
| 182 | */ |
| 183 | public function get(): string { |
| 184 | $form_id = $this->form_id; |
| 185 | $placeholder = $this->placeholder ?? __( 'Search...', 'tutor' ); |
| 186 | $current_url = $this->action_url ?? ''; |
| 187 | $input_name = $this->input_name; |
| 188 | $search_value = Input::get( $input_name, '' ); |
| 189 | $size = Size::SMALL === $this->size ? 'tutor-input-sm' : ( Size::LARGE === $this->size ? 'tutor-input-lg' : '' ); |
| 190 | $icon_size = Size::SMALL === $this->size ? 16 : ( Size::LARGE === $this->size ? 24 : 20 ); |
| 191 | $method = $this->method; |
| 192 | |
| 193 | if ( empty( $current_url ) ) { |
| 194 | // Fallback to current URL with preserved query args if not provided. |
| 195 | global $wp; |
| 196 | $current_url = add_query_arg( $_GET, home_url( $wp->request ) ); |
| 197 | } |
| 198 | |
| 199 | $clear_url = add_query_arg( |
| 200 | array_merge( |
| 201 | $this->hidden_inputs, |
| 202 | array( 'paged' => 1 ) |
| 203 | ), |
| 204 | remove_query_arg( $input_name, $current_url ) |
| 205 | ); |
| 206 | |
| 207 | $clear_action = 'GET' === strtoupper( $method ) |
| 208 | ? 'window.location.href = ' . wp_json_encode( $clear_url ) |
| 209 | : "setValue('" . esc_js( $input_name ) . "', ''); \$el.closest('form').submit();"; |
| 210 | |
| 211 | $this->attributes = array_merge( |
| 212 | array( |
| 213 | 'action' => esc_url( $current_url ), |
| 214 | 'method' => $method, |
| 215 | 'id' => $form_id, |
| 216 | 'x-data' => "tutorForm({ id: '" . esc_attr( $form_id ) . "', mode: 'onSubmit' })", |
| 217 | 'x-bind' => 'getFormBindings()', |
| 218 | '@submit' => 'handleSubmit((data) => { $el.submit(); })($event)', |
| 219 | ), |
| 220 | $this->attributes |
| 221 | ); |
| 222 | |
| 223 | ob_start(); |
| 224 | ?> |
| 225 | <form <?php echo $this->render_attributes(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>> |
| 226 | <input type="hidden" name="paged" value="1"> |
| 227 | |
| 228 | <?php foreach ( $this->hidden_inputs as $name => $value ) : ?> |
| 229 | <input type="hidden" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value ); ?>"> |
| 230 | <?php endforeach; ?> |
| 231 | |
| 232 | <div class="tutor-input-field"> |
| 233 | <div class="tutor-input-wrapper"> |
| 234 | <div class="tutor-input-content tutor-input-content-left"> |
| 235 | <?php |
| 236 | SvgIcon::make() |
| 237 | ->name( Icon::SEARCH_2 ) |
| 238 | ->size( $icon_size ) |
| 239 | ->color( Color::IDLE ) |
| 240 | ->render(); |
| 241 | ?> |
| 242 | </div> |
| 243 | <input |
| 244 | type="search" |
| 245 | name="<?php echo esc_attr( $input_name ); ?>" |
| 246 | placeholder="<?php echo esc_attr( $placeholder ); ?>" |
| 247 | class="tutor-input <?php echo esc_attr( $size ); ?> tutor-input-content-left tutor-input-content-clear" |
| 248 | x-bind="register('<?php echo esc_attr( $input_name ); ?>')" |
| 249 | x-init="$nextTick(() => setValue('<?php echo esc_attr( $input_name ); ?>', '<?php echo esc_attr( $search_value ); ?>'))" |
| 250 | /> |
| 251 | |
| 252 | <button |
| 253 | type="button" |
| 254 | class="tutor-input-clear-button" |
| 255 | x-show="values.<?php echo esc_attr( $input_name ); ?> && String(values.<?php echo esc_attr( $input_name ); ?>).length > 0" |
| 256 | x-cloak |
| 257 | aria-label="<?php esc_attr_e( 'Clear search', 'tutor' ); ?>" |
| 258 | @click="<?php echo esc_attr( $clear_action ); ?>" |
| 259 | > |
| 260 | <?php SvgIcon::make()->name( Icon::CROSS )->size( 16 )->render(); ?> |
| 261 | </button> |
| 262 | </div> |
| 263 | </div> |
| 264 | </form> |
| 265 | <?php |
| 266 | return ob_get_clean(); |
| 267 | } |
| 268 | } |
| 269 |