Completed
Push — master ( 71159f...86ffa1 )
by
unknown
06:54
created

Default_Calendar_Grid::html()   D

Complexity

Conditions 10
Paths 65

Size

Total Lines 97
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 2
Metric Value
dl 0
loc 97
rs 4.9163
c 4
b 0
f 2
cc 10
eloc 59
nc 65
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Default Calendar - Grid View
4
 *
5
 * @package SimpleCalendar/Calendars
6
 */
7
namespace SimpleCalendar\Calendars\Views;
8
9
use Carbon\Carbon;
10
use Mexitek\PHPColors\Color;
11
use SimpleCalendar\Abstracts\Calendar;
12
use SimpleCalendar\Abstracts\Calendar_View;
13
use SimpleCalendar\Events\Event;
14
use SimpleCalendar\Calendars\Default_Calendar;
15
16
if ( ! defined( 'ABSPATH' ) ) {
17
	exit;
18
}
19
20
/**
21
 * Default Calendar: Grid View.
22
 *
23
 * @since  3.0.0
24
 */
25
class Default_Calendar_Grid implements Calendar_View {
26
27
	/**
28
	 * Calendar.
29
	 *
30
	 * @access public
31
	 * @var Default_Calendar
32
	 */
33
	public $calendar = null;
34
35
	/**
36
	 * Current display start.
37
	 *
38
	 * @access private
39
	 * @var int
40
	 */
41
	private $start = 0;
42
43
	/**
44
	 * Current display end.
45
	 *
46
	 * @access private
47
	 * @var int
48
	 */
49
	private $end = 0;
50
51
	/**
52
	 * Constructor.
53
	 *
54
	 * @since 3.0.0
55
	 *
56
	 * @param string|Calendar $calendar
57
	 */
58
	public function __construct( $calendar = '' ) {
59
		$this->calendar = $calendar;
0 ignored issues
show
Documentation Bug introduced by
It seems like $calendar of type string or object<SimpleCalendar\Abstracts\Calendar> is incompatible with the declared type object<SimpleCalendar\Calendars\Default_Calendar> of property $calendar.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
60
	}
61
62
	/**
63
	 * Get the view parent calendar type.
64
	 *
65
	 * @since  3.0.0
66
	 *
67
	 * @return string
68
	 */
69
	public function get_parent() {
70
		return 'default-calendar';
71
	}
72
73
	/**
74
	 * Get the view type.
75
	 *
76
	 * @since  3.0.0
77
	 *
78
	 * @return string
79
	 */
80
	public function get_type() {
81
		return 'grid';
82
	}
83
84
	/**
85
	 * Get the view name.
86
	 *
87
	 * @since  3.0.0
88
	 *
89
	 * @return string
90
	 */
91
	public function get_name() {
92
		return __( 'Grid', 'google-calendar-events' );
93
	}
94
95
	/**
96
	 * Add ajax actions.
97
	 *
98
	 * @since 3.0.0
99
	 */
100
	public function add_ajax_actions() {
101
		add_action( 'wp_ajax_simcal_default_calendar_draw_grid', array( $this, 'draw_grid_ajax' ) );
102
		add_action( 'wp_ajax_nopriv_simcal_default_calendar_draw_grid', array( $this, 'draw_grid_ajax' ) );
103
	}
104
105
	/**
106
	 * Default calendar grid scripts.
107
	 *
108
	 * Scripts to load when this view is displayed.
109
	 *
110
	 * @since  3.0.0
111
	 *
112
	 * @param  string $min
113
	 *
114
	 * @return array
115
	 */
116
	public function scripts( $min = '' ) {
117
		return array(
118
			'simcal-qtip' => array(
119
				'src'       => SIMPLE_CALENDAR_ASSETS . 'js/vendor/qtip' . $min . '.js',
120
				'deps'      => array( 'jquery' ),
121
				'ver'       => '2.2.1',
122
				'in_footer' => true,
123
			),
124
			'simcal-default-calendar' => array(
125
				'src'       => SIMPLE_CALENDAR_ASSETS . 'js/default-calendar' . $min . '.js',
126
				'deps'      => array(
127
					'jquery',
128
					'simcal-qtip',
129
				),
130
				'var'       => SIMPLE_CALENDAR_VERSION,
131
				'in_footer' => true,
132
				'localize'  => array(
133
					'simcal_default_calendar' => simcal_common_scripts_variables(),
134
				),
135
			),
136
		);
137
	}
138
139
	/**
140
	 * Default calendar grid styles.
141
	 *
142
	 * Stylesheets to load when this view is displayed.
143
	 *
144
	 * @since  3.0.0
145
	 *
146
	 * @param  string $min = ''
147
	 *
148
	 * @return array
149
	 */
150
	public function styles( $min = '' ) {
151
		return array(
152
			'simcal-qtip' => array(
153
				'src'   => SIMPLE_CALENDAR_ASSETS . 'css/vendor/qtip' . $min . '.css',
154
				'ver'   => '2.2.1',
155
				'media' => 'all',
156
			),
157
			'simcal-default-calendar-grid' => array(
158
				'src'   => SIMPLE_CALENDAR_ASSETS . 'css/default-calendar-grid' . $min . '.css',
159
				'deps'  => array(
160
					'simcal-qtip',
161
				),
162
				'ver'   => SIMPLE_CALENDAR_VERSION,
163
				'media' => 'all',
164
			),
165
		);
166
	}
167
168
	/**
169
	 * Default calendar grid markup.
170
	 *
171
	 * @since  3.0.0
172
	 */
173
	public function html() {
174
175
		$calendar = $this->calendar;
176
177
		if ( $calendar instanceof Default_Calendar ) {
178
179
			?>
180
181
			<?php edit_post_link( __( 'Edit Calendar', 'google-calendar-events' ), '<p class="simcal-align-right"><small>', '</small></p>', $calendar->id ); ?>
182
183
			<table class="simcal-calendar-grid"
184
			       data-event-bubble-trigger="<?php echo $calendar->event_bubble_trigger; ?>">
185
				<thead class="simcal-calendar-head">
186
					<tr>
187
						<?php if ( ! $calendar->static ) { ?>
188
							<th class="simcal-nav simcal-prev-wrapper" colspan=colspan="<?php echo apply_filters( 'simcal_prev_cols', '1' ); ?>">
189
								<button class="simcal-nav-button simcal-month-nav simcal-prev" title="<?php _e( 'Previous Month', 'google-calendar-events' ); ?>"><i class="simcal-icon-left"></i></button>
190
							</th>
191
						<?php } ?>
192
						<th colspan="<?php echo apply_filters( 'simcal_current_cols', $calendar->static ? '7' : '5' ); ?>"
193
						    class="simcal-nav simcal-current"
194
						    data-calendar-current="<?php echo $calendar->start; ?>">
195
							<?php
196
197
							echo '<h3>';
198
199
							// Display month and year according to user date format preference.
200
201
							$year_pos  = strcspn( $calendar->date_format, 'Y y' );
202
							$month_pos = strcspn( $calendar->date_format, 'F M m n' );
203
204
							$current = array( 'month' => 'F', 'year' => 'Y' );
205
206
							if ( $year_pos < $month_pos ) {
207
								$current = array_reverse( $current );
208
							}
209
210
							foreach ( $current as $k => $v ) {
211
								echo ' <span class="simcal-current-' . $k , '">' . date_i18n( $v, $calendar->start ) . '</span> ';
212
							}
213
214
							echo '</h3>';
215
216
							?>
217
						</th>
218
						<?php if ( ! $calendar->static ) { ?>
219
							<th class="simcal-nav simcal-next-wrapper" colspan="<?php echo apply_filters( 'simcal_next_cols', '1' ); ?>">
220
								<button class="simcal-nav-button simcal-month-nav simcal-next" title="<?php _e( 'Next Month', 'google-calendar-events' ); ?>"><i class="simcal-icon-right"></i></button>
221
							</th>
222
						<?php } ?>
223
					</tr>
224
					<tr>
225
						<?php
226
227
						// Print day names in short or long form for different viewport sizes.
228
229
						$week_starts     = $calendar->week_starts;
230
						$week_days_short = simcal_get_calendar_names_i18n( 'day', 'short' );
231
						$week_days_full  = simcal_get_calendar_names_i18n( 'day', 'full' );
232
233
						for ( $i = $week_starts; $i <= 6; $i ++ ) :
234
235
							?>
236
							<th class="simcal-week-day simcal-week-day-<?php echo $i ?>"
237
								data-screen-small="<?php echo mb_substr( $week_days_short[ $i ], 0, 1, 'UTF-8' ); ?>"
238
							    data-screen-medium="<?php echo $week_days_short[ $i ]; ?>"
239
							    data-screen-large="<?php echo $week_days_full[ $i ]; ?>"><?php echo $week_days_short[ $i ]; ?></th>
240
							<?php
241
242
						endfor;
243
244
						if ( $week_starts !== 0 ) :
0 ignored issues
show
introduced by
Found "!== 0". Use Yoda Condition checks, you must
Loading history...
245
							for ( $i = 0; $i < $week_starts; $i ++ ) :
246
247
								?>
248
								<th class="simcal-week-day simcal-week-day-<?php echo $i ?>"
249
								    data-screen-small="<?php echo mb_substr( $week_days_short[ $i ], 0, 1, 'UTF-8' ); ?>"
250
								    data-screen-medium="<?php echo $week_days_short[ $i ]; ?>"
251
								    data-screen-large="<?php echo $week_days_full[ $i ]; ?>"><?php echo $week_days_short[ $i ]; ?></th>
252
								<?php
253
254
							endfor;
255
						endif;
256
257
						?>
258
					</tr>
259
				</thead>
260
261
				<?php echo $this->draw_month( date( 'n', $calendar->start ), date( 'Y', $calendar->start ) ); ?>
262
263
			</table>
264
265
			<?php
266
267
			echo '<div class="simcal-ajax-loader simcal-spinner-top" style="display: none;"><i class="simcal-icon-spinner simcal-icon-spin"></i></div>';
268
		}
269
	}
270
271
	/**
272
	 * Make a calendar grid.
273
	 *
274
	 * Outputs an html calendar according to month and year passed in arguments.
275
	 * Loosely inspired by: http://davidwalsh.name/php-calendar
276
	 * Adjusted by timezone and with an arbitrary week start day.
277
	 *
278
	 * @since  3.0.0
279
	 * @access private
280
	 *
281
	 * @param  int $month The month to print (two digits).
282
	 * @param  int $year  The corresponding year (four digits).
283
	 * @param  int $id    The calendar id.
284
	 *
285
	 * @return string
286
	 */
287
	private function draw_month( $month, $year, $id = 0 ) {
288
289
		$calendar = $this->calendar;
290
		if ( empty( $calendar ) ) {
291
			$calendar = simcal_get_calendar( intval( $id ) );
292
			if ( ! $calendar ) {
293
				return '';
294
			}
295
		}
296
		date_default_timezone_set( $calendar->timezone );
0 ignored issues
show
introduced by
Using date_default_timezone_set() and similar isn’t allowed, instead use WP internal timezone support.
Loading history...
297
		$events = $calendar->events;
298
299
		// Variables to cycle days in current month and find today in calendar.
300
		$now         = $calendar->now;
301
		$current     = Carbon::create( $year, $month, 1, 0, 0, 0, $calendar->timezone );
302
		$current_min = $current->getTimestamp();
303
		$current_max = $current->endOfDay()->getTimestamp();
304
305
		// Calendar grid variables.
306
		$week_starts   = $calendar->week_starts;
307
		$week_of_year  = $current->weekOfYear;   // Relative count of the week number of the year.
308
		$month_starts  = $current->dayOfWeek;    // Day upon which the month starts.
309
		$days_in_month = $current->daysInMonth;  // Number of days in the given month.
310
311
		// Set current month events timestamp boundaries.
312
		$this->start = $current_min;
313
		$this->end   = $current->endOfMonth()->timestamp;
314
315
		// Get daily events for this month.
316
		if ( $events && is_array( $events ) ) {
317
318
			// Filter events within the boundaries previously set above.
319
			$timestamps   = array_keys( $events );
320
			$lower_bound  = array_filter( $timestamps, array( $this, 'filter_events_before' ) );
321
			$higher_bound = array_filter( $lower_bound, array( $this, 'filter_events_after' ) );
322
			$filtered     = ( is_array( $events ) && is_array( $higher_bound) ) && ! empty( $events ) && ! empty( $higher_bound ) ? array_intersect_key( $events, array_combine( $higher_bound, $higher_bound ) ) : array();
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
323
324
			// Put resulting events in an associative array, with day of the month as key for easy retrieval in calendar days loop.
325
			$day_events = array();
326
			foreach ( $filtered as $timestamp => $events_in_day ) {
327
				foreach ( $events_in_day as $event ) {
328
					if ( $event instanceof Event ){
329
						$day = intval( Carbon::createFromTimestamp( $timestamp, $event->timezone )->endOfDay()->day );
330
						$day_events[ $day ][] = $event;
331
					}
332
				}
333
			}
334
335
			ksort( $day_events, SORT_NUMERIC );
336
		}
337
338
		ob_start();
339
340
		echo '<tbody class="simcal-month simcal-month-' . $month . '">' . "\n";
341
		echo "\t" . '<tr class="simcal-week simcal-week-' . $week_of_year . '">';
342
343
		$days_in_row = 0;
344
		// Week may start on an arbitrary day (sun, 0 - sat, 6).
345
		$week_day = $week_starts;
346
347
		// This fixes a possible bug when a month starts by Sunday (0).
348
		if ( 0 !== $week_starts ) {
349
			$b = $month_starts === 0 ? 7 : $month_starts;
350
		} else {
351
			$b = $month_starts;
352
		}
353
354
		// Void days in first week.
355
		for ( $a = $week_starts; $a < $b; $a++ ) :
356
357
			$last_void_day_class = ( $a === ( $b - 1 ) ) ? 'simcal-day-void-last' : '';
358
359
			echo '<td class="simcal-day simcal-day-void ' . $last_void_day_class . '"></td>' . "\n";
360
361
			// Reset day of the week count (sun, 0 - sat, 6).
362
			if ( $week_day === 6 ) {
0 ignored issues
show
introduced by
Found "=== 6". Use Yoda Condition checks, you must
Loading history...
363
				$week_day = -1;
364
			}
365
			$week_day++;
366
367
			$days_in_row++;
368
369
		endfor;
370
371
		// Actual days of the month.
372
		for ( $day = 1; $day <= $days_in_month; $day++ ) :
373
374
			$count = 0;
375
			$calendar_classes = array();
376
			$day_classes = 'simcal-day-' . $day . ' simcal-weekday-' . $week_day;
377
378
			$border_style = $bg_color = $color = '';
379
380
			// Is this the present, the past or the future, Doc?
381
			if ( $current_min <= $now && $current_max >= $now ) {
382
				$day_classes .= ' simcal-today simcal-present simcal-day';
383
				$the_color = new Color( $calendar->today_color );
384
				$bg_color = '#' . $the_color->getHex();
385
				$color = $the_color->isDark() ? '#ffffff' : '#000000';
386
				$border_style = ' style="border: 1px solid ' . $bg_color . ';"';
387
			} elseif ( $current_max < $now ) {
388
				$day_classes .= ' simcal-past simcal-day';
389
			} elseif ( $current_min > $now ) {
390
				$day_classes .= ' simcal-future simcal-day';
391
			}
392
393
			// Print events for the current day in loop, if found any.
394
			if ( isset( $day_events[ $day ] ) ) :
395
396
				$list_events = '<ul class="simcal-events">';
397
398
				foreach ( $day_events[ $day ] as $event ) :
399
400
					$event_classes = $event_visibility = '';
401
402
					if ( $event instanceof Event ) :
403
404
						// Store the calendar id where the event belongs (useful in grouped calendar feeds)
405
						$calendar_class  = 'simcal-events-calendar-' . strval( $event->calendar );
406
						$calendar_classes[] = $calendar_class ;
407
408
						$recurring     = $event->recurrence ? 'simcal-event-recurring ' : '';
409
						$has_location  = $event->venue ? 'simcal-event-has-location ' : '';
410
411
						$event_classes  .= 'simcal-event ' . $recurring . $has_location . $calendar_class . ' simcal-tooltip';
412
413
						// Toggle some events visibility if more than optional limit.
414
						if ( ( $calendar->events_limit > -1 )  && ( $count >= $calendar->events_limit ) ) :
415
							$event_classes    .= ' simcal-event-toggled';
416
							$event_visibility  = ' style="display: none"';
417
						endif;
418
419
						// Event title in list.
420
						$title = ! empty( $event->title ) ? trim( $event->title ) : __( 'Event', 'google-calendar-events' );
421
						if ( $calendar->trim_titles >= 1 ) {
422
							$title = strlen( $title ) > $calendar->trim_titles ? mb_substr( $title, 0, $calendar->trim_titles ) . '&hellip;' : $title;
423
						}
424
425
						// Event color.
426
						$bullet = '';
427
						$event_color = $event->get_color();
428
						if ( ! empty( $event_color ) ) {
429
							$bullet = '<span style="color: ' . $event_color . ';">&#9632;</span> ';
430
						}
431
432
						// Event contents.
433
						$list_events .= "\t" . '<li class="' . $event_classes . '"' . $event_visibility . ' itemscope itemtype="http://schema.org/Event">' . "\n";
434
						$list_events .= "\t\t" . '<span class="simcal-event-title">' . $bullet . $title . '</span>' . "\n";
435
						$list_events .= "\t\t" . '<div class="simcal-event-details simcal-tooltip-content" style="display: none;">' . $calendar->get_event_html( $event ) . '</div>' . "\n";
436
						$list_events .= "\t" . '</li>' . "\n";
437
438
						$count ++;
439
440
					endif;
441
442
				endforeach;
443
444
				if ( ( $current_min <= $now ) && ( $current_max >= $now ) ) {
445
					$day_classes .= ' simcal-today-has-events';
446
				}
447
				$day_classes .= ' simcal-day-has-events simcal-day-has-' . strval( $count ) . '-events';
448
449
				if ( $calendar_classes ) {
450
					$day_classes .= ' ' . trim( implode( ' ', array_unique( $calendar_classes ) ) );
451
				}
452
453
				$list_events .= '</ul>' . "\n";
454
455
				// Optional button to toggle hidden events in list.
456
				if ( ( $calendar->events_limit > -1 ) && ( $count > $calendar->events_limit ) ) :
457
					$list_events .= '<button class="simcal-events-toggle"><i class="simcal-icon-down simcal-icon-animate"></i></button>';
458
				endif;
459
460
			else :
461
462
				// Empty cell for day with no events.
463
				$list_events = '<span class="simcal-no-events"></span>';
464
465
			endif;
466
467
			// The actual days with numbers and events in each row cell.
468
			echo '<td class="' . $day_classes . '" data-events-count="' . strval( $count ) . '">' . "\n";
469
470
			if ( $color ) {
471
				$day_style = ' style="background-color: ' . $bg_color . '; color: ' . $color .'"';
472
			} elseif ( $count > 0 ) {
473
				$the_color = new Color( $calendar->days_events_color );
474
				$color = ! $color ? ( $the_color->isDark() ? '#ffffff' : '#000000' ) : $color;
475
				$bg_color = ! $bg_color ? '#' . $the_color->getHex() : $bg_color;
476
				$day_style = ' style="background-color: ' . $bg_color . '; color: ' . $color .'"';
477
			} else {
478
				$day_style = '';
479
			}
480
481
			echo "\t" . '<div' . $border_style . '>' . "\n";
482
			echo "\t\t" . '<span class="simcal-day-label simcal-day-number"' . $day_style . '>' . $day . '</span>' . "\n";
483
			echo "\t\t" . $list_events . "\n";
484
			echo "\t\t";
485
			echo '<span class="simcal-events-dots" style="display: none;">';
486
487
			// Event bullets for calendar mobile mode.
488
			for( $i = 0; $i < $count; $i++ ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
489
				echo '<b> &bull; </b>';
490
			}
491
492
			echo '</span>' . "\n";
493
			echo "\t" . '</div>' . "\n";
494
			echo '</td>' . "\n";
495
496
			// Reset day of the week count (sun, 0 - sat, 6).
497
			if ( $week_day === 6 ) {
0 ignored issues
show
introduced by
Found "=== 6". Use Yoda Condition checks, you must
Loading history...
498
				$week_day = - 1;
499
			}
500
			$week_day++;
501
502
			// Reset count of days for this row (0-6).
503
			if ( $days_in_row === 6 ) :
0 ignored issues
show
introduced by
Found "=== 6". Use Yoda Condition checks, you must
Loading history...
504
505
				// Close the week row.
506
				echo '</tr>';
507
508
				// Open a new week row.
509
				if ( $day < $days_in_month ) {
510
					echo '<tr class="simcal-week simcal-week-' . $week_of_year++ . '">' . "\n";
511
				}
512
513
				$days_in_row = -1;
514
515
			endif;
516
517
			$days_in_row++;
518
519
			$current_min = Carbon::createFromTimestamp( $current_min, $calendar->timezone )->addDay()->getTimestamp();
520
			$current_max = Carbon::createFromTimestamp( $current_max, $calendar->timezone )->addDay()->getTimestamp();
521
522
		endfor;
523
524
		// Void days at the end of the month.
525
		$remainder_days = ( 6 - $days_in_row );
526
527
		for ( $i = 0; $i <= $remainder_days; $i ++ ) {
528
529
			$last_void_day_class = ( $i == $remainder_days ) ? 'simcal-day-void-last' : '';
530
531
			echo '<td class="simcal-day simcal-day-void ' . $last_void_day_class . '"></td>' . "\n";
532
533
			$week_day++;
534
		}
535
536
		echo "\t" . '</tr>' . "\n";
537
		echo '</tbody>' . "\n";
538
539
		date_default_timezone_set( $calendar->site_timezone );
0 ignored issues
show
introduced by
Using date_default_timezone_set() and similar isn’t allowed, instead use WP internal timezone support.
Loading history...
540
541
		return ob_get_clean();
542
	}
543
544
	/**
545
	 * Ajax callback to request a new month.
546
	 *
547
	 * @since 3.0.0
548
	 */
549
	public function draw_grid_ajax() {
550
551
		if ( isset( $_POST['month'] ) && isset( $_POST['year'] ) && isset( $_POST['id'] ) ) {
552
553
			$month = absint( $_POST['month'] );
554
			$year  = absint( $_POST['year'] );
555
			$id    = absint( $_POST['id'] );
556
557
			wp_send_json_success( $this->draw_month( $month, $year, $id ) );
558
559
		} else {
560
561
			wp_send_json_error( 'Missing arguments in default calendar grid ajax request.' );
562
563
		}
564
565
	}
566
567
	/**
568
	 * Array filter callback.
569
	 *
570
	 * @since  3.0.0
571
	 * @access private
572
	 *
573
	 * @param  int $event Timestamp.
574
	 *
575
	 * @return bool
576
	 */
577
	private function filter_events_before( $event ) {
578
		return intval( $event ) >= intval( $this->start );
579
	}
580
581
	/**
582
	 * Array filter callback.
583
	 *
584
	 * @since  3.0.0
585
	 * @access private
586
	 *
587
	 * @param  int $event Timestamp.
588
	 *
589
	 * @return bool
590
	 */
591
	private function filter_events_after( $event ) {
592
		return intval( $event ) < intval( $this->end );
593
	}
594
595
}
596