PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 4.0.0
Tutor LMS – eLearning and online course solution v4.0.0
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 21 hours ago Accordion.php 21 hours ago Alert.php 21 hours ago AttachmentCard.php 21 hours ago Avatar.php 21 hours ago Badge.php 21 hours ago BaseComponent.php 21 hours ago Button.php 21 hours ago ConfirmationModal.php 21 hours ago CourseFilter.php 21 hours ago DateFilter.php 21 hours ago DropdownFilter.php 21 hours ago EmptyState.php 21 hours ago FileUploader.php 21 hours ago InputField.php 21 hours ago Modal.php 21 hours ago Nav.php 21 hours ago Pagination.php 21 hours ago Popover.php 21 hours ago PreviewTrigger.php 21 hours ago Progress.php 21 hours ago SearchFilter.php 21 hours ago Sorting.php 21 hours ago StarRating.php 21 hours ago StarRatingInput.php 21 hours ago StatusSelect.php 21 hours ago SvgIcon.php 21 hours ago Table.php 21 hours ago Tabs.php 21 hours ago Tooltip.php 21 hours ago WPEditor.php 21 hours 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