Completed
Push — master ( 615d80...e47c17 )
by
unknown
03:19
created

Grouped_Calendars::update_array_timestamp()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 2
1
<?php
2
/**
3
 * Grouped Calendars Feed
4
 *
5
 * @package SimpleCalendar/Feeds
6
 */
7
namespace SimpleCalendar\Feeds;
8
9
use SimpleCalendar\Abstracts\Calendar;
10
use SimpleCalendar\Abstracts\Feed;
11
use SimpleCalendar\Feeds\Admin\Grouped_Calendars_Admin;
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Grouped calendars feed.
19
 *
20
 * Feed made of multiple calendar feeds combined together.
21
 *
22
 * @since  3.0.0
23
 */
24
class Grouped_Calendars extends Feed {
25
26
	/**
27
	 * Feed ids to get events from.
28
	 *
29
	 * @access public
30
	 * @var array
31
	 */
32
	public $calendars_ids = array();
33
34
	/**
35
	 * Set properties.
36
	 *
37
	 * @since 3.0.0
38
	 *
39
	 * @param string|Calendar $calendar
40
	 */
41
	public function __construct( $calendar = '' ) {
42
43
		parent::__construct( $calendar );
44
45
		$this->type = 'grouped-calendars';
46
		$this->name = __( 'Grouped Calendar', 'google-calendar-events' );
47
48
		if ( $this->post_id > 0 ) {
49
			$this->set_source();
50
			if ( ! is_admin() || defined( 'DOING_AJAX' ) ) {
51
				$this->events = $this->get_events();
52
			}
53
		}
54
55
		if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
56
			new Grouped_Calendars_Admin( $this );
57
		}
58
	}
59
60
	/**
61
	 * Set source.
62
	 *
63
	 * @since 3.0.0
64
	 *
65
	 * @param array $ids Array of calendar ids.
66
	 */
67
	public function set_source( $ids = array() ) {
68
69
		$source = get_post_meta( $this->post_id, '_grouped_calendars_source', true );
70
71
		if ( 'ids' == $source ) {
72
73
			if ( empty( $ids ) ) {
74
				$ids = get_post_meta( $this->post_id, '_grouped_calendars_ids', true );
75
			}
76
77
			$this->calendars_ids = ! empty( $ids ) && is_array( $ids ) ? array_map( 'absint', $ids ) : array();
78
79
		} elseif ( 'category' == $source ) {
80
81
			$categories = get_post_meta( $this->post_id, '_grouped_calendars_category', true );
82
83
			if ( $categories && is_array( $categories ) ) {
84
85
				$tax_query = array(
86
					'taxonomy' => 'calendar_category',
87
					'field'    => 'term_id',
88
					'terms'    => array_map( 'absint', $categories ),
89
				);
90
91
				$calendars = get_posts( array(
92
					'post_type' => 'calendar',
93
					'tax_query' => array( $tax_query ),
94
					'nopaging'  => true,
95
					'fields'    => 'ids',
96
				) );
97
98
				$this->calendars_ids = ! empty( $calendars ) && is_array( $calendars ) ? $calendars : array();
99
			}
100
101
		}
102
	}
103
104
	/**
105
	 * Get events from multiple calendars.
106
	 *
107
	 * @since  3.0.0
108
	 *
109
	 * @return array
110
	 */
111
	public function get_events() {
112
113
		$ids    = $this->calendars_ids;
114
		$events = get_transient( '_simple-calendar_feed_id_' . strval( $this->post_id ) . '_' . $this->type );
115
116
		if ( empty( $events ) && ! empty( $ids ) && is_array( $ids ) ) {
117
118
			$events = array();
119
120
			foreach ( $ids as $cal_id ) {
121
122
				$calendar = simcal_get_calendar( intval( $cal_id ) );
123
124
				simcal_delete_feed_transients( $cal_id );
125
126
				if ( $calendar instanceof Calendar ) {
127
128
					// Sometimes the calendars might have events at the same time from different calendars
129
					// When merging the arrays together some of the events will be lost because the keys are the same and one will overwrite the other
130
					// This snippet checks if the key already exists in the master events array and if it does it subtracts 1 from it to make the key unique and then unsets the original key.
131
					foreach( $calendar->events as $k => $v ) {
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...
132
						$calendar->events[ $this->update_array_timestamp( $events, $k ) ] = $v;
133
					}
134
135
					$events = is_array( $calendar->events ) ? $events + $calendar->events : $events;
136
				}
137
138
			}
139
140
			if ( ! empty( $events ) ) {
141
142
				// Trim events to set the earliest one as specified in feed settings.
143
				$earliest_event = intval( $this->time_min );
144
				if ( $earliest_event > 0 ) {
145
					$events = $this->array_filter_key( $events, array( $this, 'filter_events_before' ) );
146
				}
147
148
				// Trim events to set the latest one as specified in feed settings.
149
				$latest_event = intval( $this->time_max );
150
				if ( $latest_event > 0 ) {
151
					$events = $this->array_filter_key( $events, array( $this, 'filter_events_after' ) );
152
				}
153
154
				set_transient(
155
					'_simple-calendar_feed_id_' . strval( $this->post_id ) . '_' . $this->type,
156
					$events,
157
					absint( $this->cache )
158
				);
159
			}
160
161
		}
162
	
163
		// Sort events by start time before returning
164
		uasort( $events, array( $this, 'sort_by_start_time' ) );
165
166
		return $events;
167
	}
168
169
	/*
170
	 * Recursive function to adjust the timestamp array indices that are the same.
171
	 */
172
	public function update_array_timestamp( $arr, $i ) {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
173
174
		if ( array_key_exists( $i, $arr ) ) {
175
			$i = $this->update_array_timestamp( $arr, $i - 1 );
176
		}
177
178
		return $i;
179
	}
180
181
	/**
182
	 * uasort helper to sort events by start time.
183
	 *
184
	 * @since  3.0.13
185
	 * @access private
186
	 */
187
	private function sort_by_start_time( $a, $b ) {
188
		if ( $a == $b ) {
189
			return 0;
190
		}
191
192
		return ( $a[0]->start < $b[0]->start ) ? -1 : 1;
193
	}
194
195
196
197
	/**
198
	 * Array filter key.
199
	 *
200
	 * `array_filter` does not allow to parse an associative array keys before PHP 5.6.
201
	 *
202
	 * @since  3.0.0
203
	 * @access private
204
	 *
205
	 * @param  array        $array
206
	 * @param  array|string $callback
207
	 *
208
	 * @return array
209
	 */
210
	private function array_filter_key( array $array, $callback ) {
211
		$matched_keys = array_filter( array_keys( $array ), $callback );
212
		return array_intersect_key( $array, array_flip( $matched_keys ) );
213
	}
214
215
	/**
216
	 * Array filter callback.
217
	 *
218
	 * @since  3.0.0
219
	 * @access private
220
	 *
221
	 * @param  int $event Timestamp.
222
	 *
223
	 * @return bool
224
	 */
225
	private function filter_events_before( $event ) {
226
		if ( $this->time_min !== 0 ) {
0 ignored issues
show
introduced by
Found "!== 0". Use Yoda Condition checks, you must
Loading history...
227
			return intval( $event ) > intval( $this->time_min );
228
		}
229
		return true;
230
	}
231
232
	/**
233
	 * Array filter callback.
234
	 *
235
	 * @since  3.0.0
236
	 * @access private
237
	 *
238
	 * @param  int $event Timestamp.
239
	 *
240
	 * @return bool
241
	 */
242
	private function filter_events_after( $event ) {
243
		if ( $this->time_max !== 0 ) {
0 ignored issues
show
introduced by
Found "!== 0". Use Yoda Condition checks, you must
Loading history...
244
			return intval( $event ) < intval( $this->time_max );
245
		}
246
		return true;
247
	}
248
249
}
250