PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 4.0.1
Tutor LMS – eLearning and online course solution v4.0.1
4.0.1 4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / components / DateFilter.php
tutor / components Last commit date
Constants 4 days ago Accordion.php 4 days ago Alert.php 4 days ago AttachmentCard.php 4 days ago Avatar.php 4 days ago Badge.php 4 days ago BaseComponent.php 4 days ago Button.php 4 days ago ConfirmationModal.php 4 days ago CourseFilter.php 4 days ago DateFilter.php 4 days ago DropdownFilter.php 4 days ago EmptyState.php 4 days ago FileUploader.php 4 days ago InputField.php 4 days ago Modal.php 4 days ago Nav.php 4 days ago Pagination.php 4 days ago Popover.php 4 days ago PreviewTrigger.php 4 days ago Progress.php 4 days ago SearchFilter.php 4 days ago Sorting.php 4 days ago StarRating.php 4 days ago StarRatingInput.php 4 days ago StatusSelect.php 4 days ago SvgIcon.php 4 days ago Table.php 4 days ago Tabs.php 4 days ago Tooltip.php 4 days ago WPEditor.php 4 days ago
DateFilter.php
423 lines
1 <?php
2 /**
3 * Date Filter Component.
4 *
5 * @package Tutor\Components
6 * @author Themeum
7 * @link https://themeum.com
8 * @since 4.0.0
9 */
10
11 namespace Tutor\Components;
12
13 use TUTOR\Icon;
14 use TUTOR\Input;
15 use Tutor\Components\Constants\Size;
16 use Tutor\Components\Popover;
17
18 defined( 'ABSPATH' ) || exit;
19
20 /**
21 * DateFilter Component Class.
22 *
23 * Example usage:
24 *
25 * ```php
26 * DateFilter::make()
27 * ->type( DateFilter::TYPE_RANGE )
28 * ->placement( DateFilter::PLACEMENT_BOTTOM_START )
29 * ->render();
30 * ```
31 *
32 * ```php
33 * DateFilter::make()
34 * ->type( DateFilter::TYPE_SINGLE )
35 * ->placement( DateFilter::PLACEMENT_BOTTOM_END )
36 * ->render();
37 * ```
38 *
39 * @since 4.0.0
40 */
41 class DateFilter extends BaseComponent {
42
43 /**
44 * Date Filter Type Single
45 */
46 const TYPE_SINGLE = 'single';
47
48 /**
49 * Date Filter Type Range
50 */
51 const TYPE_RANGE = 'range';
52
53 /**
54 * Placement Bottom Start
55 */
56 const PLACEMENT_BOTTOM_START = 'bottom-start';
57
58 /**
59 * Placement Bottom End
60 */
61 const PLACEMENT_BOTTOM_END = 'bottom-end';
62
63 /**
64 * Component Type
65 *
66 * @var string
67 */
68 protected $type = self::TYPE_SINGLE;
69
70 /**
71 * Button Label
72 *
73 * @var string
74 */
75 protected $label = '';
76
77 /**
78 * Popover placement
79 *
80 * @var string
81 */
82 protected $placement = self::PLACEMENT_BOTTOM_START;
83
84 /**
85 * Button size.
86 *
87 * @var string
88 */
89 protected $size = Size::SMALL;
90
91 /**
92 * Icon size.
93 *
94 * @var integer
95 */
96 protected $icon_size = Size::SIZE_16;
97
98 /**
99 * Whether to display the label text.
100 *
101 * @since 4.0.0
102 *
103 * @var bool
104 */
105 protected $show_label = true;
106
107 /**
108 * Whether to hide the initial label when no date range is selected.
109 *
110 * @since 4.0.0
111 *
112 * @var bool
113 */
114 protected $hide_initial_label = false;
115
116 /**
117 * Query params to clear when a date filter is applied or cleared (e.g. 'current_page').
118 *
119 * @since 4.0.0
120 *
121 * @var array
122 */
123 protected $clear_params = array();
124
125 /**
126 * Set filter type.
127 *
128 * @param string $type Filter type (single|range).
129 *
130 * @return self
131 */
132 public function type( string $type ): self {
133 $this->type = $type;
134 return $this;
135 }
136
137 /**
138 * Set Button Size.
139 *
140 * @since 4.0.0
141 *
142 * @param string $size the size type (x-small|small|medium|large).
143 *
144 * @return self
145 */
146 public function trigger_size( string $size ): self {
147 $allowed_sizes = array( Size::X_SMALL, Size::SMALL, Size::MEDIUM, Size::LARGE );
148 if ( in_array( $size, $allowed_sizes, true ) ) {
149 $this->size = $size;
150 }
151 return $this;
152 }
153
154 /**
155 * Set the button icon size.
156 *
157 * @since 4.0.0
158 *
159 * @param integer $size the icon size.
160 *
161 * @return self
162 */
163 public function icon_size( int $size ): self {
164 $this->icon_size = $size;
165 return $this;
166 }
167
168 /**
169 * Set button label.
170 *
171 * @param string $label Button label.
172 *
173 * @return self
174 */
175 public function label( string $label ): self {
176 $this->label = $label;
177 return $this;
178 }
179
180 /**
181 * Set popover placement.
182 *
183 * @param string $placement Popover placement.
184 *
185 * @return self
186 */
187 public function placement( string $placement ): self {
188 $this->placement = $placement;
189 return $this;
190 }
191
192 /**
193 * Enable or disable the display of the label text.
194 *
195 * @since 4.0.0
196 *
197 * @param bool $show_label True to show the label, false to hide it.
198 *
199 * @return $this
200 */
201 public function show_label( bool $show_label ) {
202 $this->show_label = $show_label;
203 return $this;
204 }
205
206 /**
207 * Hide or show the initial label text before a date range is selected.
208 *
209 * @since 4.0.0
210 *
211 * @return self
212 */
213 public function hide_initial_label(): self {
214 $this->hide_initial_label = true;
215 return $this;
216 }
217
218 /**
219 * Set query params to clear when a date filter is applied or cleared.
220 *
221 * Useful for resetting pagination (e.g. 'current_page') or other
222 * context-specific params whenever the date selection changes.
223 *
224 * @since 4.0.0
225 *
226 * @param array $params List of query param keys to remove on apply/clear.
227 *
228 * @return self
229 */
230 public function clear_params( array $params ): self {
231 $this->clear_params = $params;
232 return $this;
233 }
234
235 /**
236 * Render the component.
237 *
238 * @return string
239 */
240 public function get(): string {
241 $is_range = self::TYPE_RANGE === $this->type;
242
243 if ( empty( $this->label ) ) {
244 $this->label = $this->calculate_label();
245 }
246
247 // Default settings based on type.
248 $calendar_options = array(
249 'type' => 'default',
250 'clearParams' => $this->clear_params,
251 );
252
253 $button_classes = 'tutor-btn tutor-btn-outline';
254
255 if ( $this->size ) {
256 $button_classes .= ' tutor-btn-' . $this->size;
257 }
258
259 $popover_classes = 'tutor-popover';
260 $icon = Icon::CALENDAR_2;
261
262 if ( $is_range ) {
263 $calendar_options = array(
264 'type' => 'multiple',
265 'selectionDatesMode' => 'multiple-ranged',
266 'clearParams' => $this->clear_params,
267 );
268 $popover_classes .= ' tutor-range-calendar-popover';
269 }
270
271 if ( empty( $this->label ) ) {
272 $button_classes .= ' tutor-btn-icon';
273 } else {
274 $button_classes .= ' tutor-gap-2';
275 }
276
277 $options_json = wp_json_encode( $calendar_options );
278
279 $origin = Popover::TRANSFORM_ORIGIN_MAP[ $this->placement ] ?? 'center.top';
280
281 ob_start();
282 ?>
283 <div x-data="tutorPopover({ placement: '<?php echo esc_attr( $this->placement ); ?>' })" <?php echo $this->get_attributes_string(); //phpcs:ignore -- Sanitization is performed inside get_attributes_string. ?>>
284
285 <button
286 type="button"
287 x-ref="trigger"
288 @click="toggle()"
289 class="<?php echo esc_attr( $button_classes ); ?>"
290 <?php if ( empty( $this->label ) ) : ?>
291 aria-label="<?php echo $is_range ? esc_attr__( 'Filter by date range', 'tutor' ) : esc_attr__( 'Filter by date', 'tutor' ); ?>"
292 <?php endif; ?>
293 >
294 <?php SvgIcon::make()->name( $icon )->size( $this->icon_size )->render(); ?>
295 <?php if ( ! empty( $this->label ) ) : ?>
296 <span><?php echo esc_html( $this->label ); ?></span>
297 <?php endif; ?>
298
299 <?php if ( $this->has_selection() ) : ?>
300 <span @click.stop="$dispatch('tutor-calendar:clear')" class="tutor-cursor-pointer tutor-icon-secondary tutor-flex tutor-align-center">
301 <?php SvgIcon::make()->name( Icon::CROSS_2 )->render(); ?>
302 </span>
303 <?php endif; ?>
304 </button>
305
306 <div
307 x-ref="content"
308 x-show="open"
309 x-cloak
310 x-transition.origin.<?php echo esc_attr( $origin ); ?>
311 @click.outside="handleClickOutside()"
312 class="<?php echo esc_attr( $popover_classes ); ?>"
313 >
314 <div x-data="tutorCalendar({ options: <?php echo esc_attr( $options_json ); ?>, hidePopover: () => hide() })"></div>
315 </div>
316 </div>
317 <?php
318 return ob_get_clean();
319 }
320
321 /**
322 * Check if filter has active selection.
323 *
324 * @return bool
325 */
326 protected function has_selection(): bool {
327 if ( self::TYPE_SINGLE === $this->type ) {
328 return ! empty( Input::get( 'date' ) );
329 }
330 return ! empty( Input::get( 'start_date' ) ) && ! empty( Input::get( 'end_date' ) );
331 }
332
333 /**
334 * Calculate dynamic label based on URL parameters.
335 *
336 * @return string
337 */
338 protected function calculate_label(): string {
339 if ( self::TYPE_SINGLE === $this->type ) {
340 return Input::get( 'date', '' );
341 }
342
343 if ( ! $this->show_label ) {
344 return '';
345 }
346
347 $start_date = Input::get( 'start_date' );
348 $end_date = Input::get( ( 'end_date' ) );
349
350 if ( ! $start_date || ! $end_date ) {
351 return $this->hide_initial_label ? '' : __( 'All Time', 'tutor' );
352 }
353
354 $presets = array(
355 'today' => __( 'Today', 'tutor' ),
356 'yesterday' => __( 'Yesterday', 'tutor' ),
357 'last-7' => __( 'Last 7 Days', 'tutor' ),
358 'last-14' => __( 'Last 14 Days', 'tutor' ),
359 'last-30' => __( 'Last 30 Days', 'tutor' ),
360 'this-month' => __( 'This Month', 'tutor' ),
361 'last-month' => __( 'Last Month', 'tutor' ),
362 'last-year' => __( 'Last Year', 'tutor' ),
363 );
364
365 $current_time = time();
366
367 foreach ( $presets as $key => $label ) {
368 $range = $this->get_preset_dates( $key, $current_time );
369 if ( $range && $range[0] === $start_date && $range[1] === $end_date ) {
370 return $label;
371 }
372 }
373
374 $start_format = date_i18n( 'M j', strtotime( $start_date ) );
375 $end_format = date_i18n( 'M j', strtotime( $end_date ) );
376
377 return sprintf( '%s - %s', $start_format, $end_format );
378 }
379
380 /**
381 * Get preset dates.
382 *
383 * @param string $preset Preset key.
384 * @param int $current_time Current timestamp.
385 *
386 * @return array|null
387 */
388 protected function get_preset_dates( $preset, $current_time ) {
389 $today = gmdate( 'Y-m-d', $current_time );
390
391 switch ( $preset ) {
392 case 'today':
393 return array( $today, $today );
394 case 'yesterday':
395 $d = gmdate( 'Y-m-d', strtotime( '-1 day', $current_time ) );
396 return array( $d, $d );
397 case 'last-7':
398 $start = gmdate( 'Y-m-d', strtotime( '-6 days', $current_time ) );
399 return array( $start, $today );
400 case 'last-14':
401 $start = gmdate( 'Y-m-d', strtotime( '-13 days', $current_time ) );
402 return array( $start, $today );
403 case 'last-30':
404 $start = gmdate( 'Y-m-d', strtotime( '-29 days', $current_time ) );
405 return array( $start, $today );
406 case 'this-month':
407 $start = gmdate( 'Y-m-01', $current_time );
408 $end = gmdate( 'Y-m-t', $current_time );
409 return array( $start, $end );
410 case 'last-month':
411 $first_day_last_month = strtotime( 'first day of previous month', $current_time );
412 $start = gmdate( 'Y-m-d', $first_day_last_month );
413 $end = gmdate( 'Y-m-t', $first_day_last_month );
414 return array( $start, $end );
415 case 'last-year':
416 $start = gmdate( 'Y-01-01', strtotime( '-1 year', $current_time ) );
417 $end = gmdate( 'Y-12-31', strtotime( '-1 year', $current_time ) );
418 return array( $start, $end );
419 }
420 return null;
421 }
422 }
423