PluginProbe
Polylang / 3.7
Polylang v3.7
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / include / widget-calendar.php

widget-calendar.php in Polylang 3.7, at include/widget-calendar.php

356 lines 11.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Polylang
4 */
5
6 if ( ! class_exists( 'WP_Widget_Calendar' ) ) {
7 require_once ABSPATH . '/wp-includes/default-widgets.php';
8 }
9
10 /**
11 * This classes rewrite the whole Calendar widget functionality as there is no filter on sql queries and only a filter on final output.
12 * Code last checked: WP 5.5.
13 *
14 * A request to add filters on sql queries exists: http://core.trac.wordpress.org/ticket/15202.
15 * Method used in 0.4.x: use of the get_calendar filter and overwrite the output of get_calendar function -> not very efficient (add 4 to 5 sql queries).
16 * Method used since 0.5: remove the WP widget and replace it by our own -> our language filter will not work if get_calendar is called directly by a theme.
17 *
18 * @since 0.5
19 */
20 class PLL_Widget_Calendar extends WP_Widget_Calendar {
21 protected static $pll_instance = 0; // Can't use $instance of WP_Widget_Calendar as it's private :/.
22
23 /**
24 * Outputs the content for the current Calendar widget instance.
25 * Modified version of the parent function to call our own get_calendar() method.
26 *
27 * @since 0.5
28 *
29 * @param array $args Display arguments including 'before_title', 'after_title',
30 * 'before_widget', and 'after_widget'.
31 * @param array $instance The settings for the particular instance of the widget.
32 */
33 public function widget( $args, $instance ) {
34 $title = ! empty( $instance['title'] ) ? $instance['title'] : '';
35
36 /** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
37 $title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
38
39 echo $args['before_widget'];
40 if ( $title ) {
41 echo $args['before_title'] . $title . $args['after_title'];
42 }
43 if ( 0 === self::$pll_instance ) { #modified#
44 echo '<div id="calendar_wrap" class="calendar_wrap">';
45 } else {
46 echo '<div class="calendar_wrap">';
47 }
48 empty( PLL()->curlang ) ? get_calendar() : self::get_calendar(); #modified#
49 echo '</div>';
50 echo $args['after_widget'];
51
52 ++self::$pll_instance; #modified#
53 }
54
55 /**
56 * Modified version of the WP `get_calendar()` function to filter the queries.
57 *
58 * @since 0.5
59 * @since 3.8 New argument $args added, with backward compatibility (WP 6.8).
60 *
61 * @param array $args {
62 * Optional. Arguments for the `get_calendar` function.
63 *
64 * @type bool $initial Whether to use initial calendar names. Default true.
65 * @type bool $display Whether to display the calendar output. Default true.
66 * @type string $post_type Optional. Post type. Default 'post'.
67 * }
68 * @return void|string Void if `$display` argument is true, calendar HTML if `$display` is false.
69 */
70 static function get_calendar( $args = array() ) {
71 global $wpdb, $m, $monthnum, $year, $wp_locale, $posts;
72
73 $defaults = array(
74 'initial' => true,
75 'display' => true,
76 'post_type' => 'post',
77 );
78
79 $original_args = func_get_args();
80 $args = array();
81
82 if ( ! empty( $original_args ) ) {
83 if ( ! is_array( $original_args[0] ) ) {
84 if ( isset( $original_args[0] ) && is_bool( $original_args[0] ) ) {
85 $defaults['initial'] = $original_args[0];
86 }
87 if ( isset( $original_args[1] ) && is_bool( $original_args[1] ) ) {
88 $defaults['display'] = $original_args[1];
89 }
90 } else {
91 $args = $original_args[0];
92 }
93 }
94
95 /** This filter is documented in wp-includes/general-template.php */
96 $args = apply_filters( 'get_calendar_args', wp_parse_args( $args, $defaults ) );
97
98 $args['lang'] = PLL()->curlang->slug; #added#
99
100 if ( ! post_type_exists( $args['post_type'] ) ) {
101 $args['post_type'] = 'post';
102 }
103
104 $w = 0;
105 if ( isset( $_GET['w'] ) ) {
106 $w = (int) $_GET['w'];
107 }
108
109 /*
110 * Normalize the cache key.
111 *
112 * The following ensures the same cache key is used for the same parameter
113 * and parameter equivalents. This prevents `post_type > post, initial > true`
114 * from generating a different key from the same values in the reverse order.
115 *
116 * `display` is excluded from the cache key as the cache contains the same
117 * HTML regardless of this function's need to echo or return the output.
118 *
119 * The global values contain data generated by the URL query string variables.
120 */
121 $cache_args = $args;
122 unset( $cache_args['display'] );
123
124 $cache_args['globals'] = array(
125 'm' => $m,
126 'monthnum' => $monthnum,
127 'year' => $year,
128 'week' => $w,
129 );
130
131 wp_recursive_ksort( $cache_args );
132 $key = md5( serialize( $cache_args ) );
133 $cache = wp_cache_get( 'get_calendar', 'calendar' );
134
135 if ( $cache && is_array( $cache ) && isset( $cache[ $key ] ) ) {
136 /** This filter is documented in wp-includes/general-template.php */
137 $output = apply_filters( 'get_calendar', $cache[ $key ], $args );
138
139 if ( $args['display'] ) {
140 echo $output;
141 return;
142 }
143
144 return $output;
145 }
146
147 if ( ! is_array( $cache ) ) {
148 $cache = array();
149 }
150
151 $post_type = $args['post_type'];
152
153 // Quick check. If we have no posts at all, abort!
154 if ( ! $posts ) {
155 $prepared_query = $wpdb->prepare( "SELECT 1 as test FROM $wpdb->posts WHERE post_type = %s AND post_status = 'publish' LIMIT 1", $post_type );
156 $gotsome = $wpdb->get_var( $prepared_query );
157 if ( ! $gotsome ) {
158 $cache[ $key ] = '';
159 wp_cache_set( 'get_calendar', $cache, 'calendar' );
160 return;
161 }
162 }
163
164 // week_begins = 0 stands for Sunday.
165 $week_begins = (int) get_option( 'start_of_week' );
166
167 // Let's figure out when we are.
168 if ( ! empty( $monthnum ) && ! empty( $year ) ) {
169 $thismonth = zeroise( (int) $monthnum, 2 );
170 $thisyear = (int) $year;
171 } elseif ( ! empty( $w ) ) {
172 // We need to get the month from MySQL.
173 $thisyear = (int) substr( $m, 0, 4 );
174 // It seems MySQL's weeks disagree with PHP's.
175 $d = ( ( $w - 1 ) * 7 ) + 6;
176 $thismonth = $wpdb->get_var( "SELECT DATE_FORMAT((DATE_ADD('{$thisyear}0101', INTERVAL $d DAY) ), '%m')" );
177 } elseif ( ! empty( $m ) ) {
178 $thisyear = (int) substr( $m, 0, 4 );
179 if ( strlen( $m ) < 6 ) {
180 $thismonth = '01';
181 } else {
182 $thismonth = zeroise( (int) substr( $m, 4, 2 ), 2 );
183 }
184 } else {
185 $thisyear = current_time( 'Y' );
186 $thismonth = current_time( 'm' );
187 }
188
189 $unixmonth = mktime( 0, 0, 0, $thismonth, 1, $thisyear );
190 $last_day = gmdate( 't', $unixmonth );
191
192 $join_clause = PLL()->model->post->join_clause(); #added#
193 $where_clause = PLL()->model->post->where_clause( PLL()->curlang ); #added#
194
195 // Get the next and previous month and year with at least one post.
196 $previous_prepared_query = $wpdb->prepare(
197 "SELECT MONTH(post_date) AS month, YEAR(post_date) AS year
198 FROM $wpdb->posts $join_clause
199 WHERE post_date < '$thisyear-$thismonth-01'
200 AND post_type = %s AND post_status = 'publish' $where_clause
201 ORDER BY post_date DESC
202 LIMIT 1",
203 $post_type
204 ); #modified#
205 $previous = $wpdb->get_row( $previous_prepared_query );
206
207 $next_prepared_query = $wpdb->prepare(
208 "SELECT MONTH(post_date) AS month, YEAR(post_date) AS year
209 FROM $wpdb->posts $join_clause
210 WHERE post_date > '$thisyear-$thismonth-{$last_day} 23:59:59'
211 AND post_type = %s AND post_status = 'publish' $where_clause
212 ORDER BY post_date ASC
213 LIMIT 1",
214 $post_type
215 ); #modified#
216 $next = $wpdb->get_row( $next_prepared_query );
217
218 /* translators: Calendar caption: 1: Month name, 2: 4-digit year. */
219 $calendar_caption = _x( '%1$s %2$s', 'calendar caption' );
220 $calendar_output = '<table id="wp-calendar" class="wp-calendar-table">
221 <caption>' . sprintf(
222 $calendar_caption,
223 $wp_locale->get_month( $thismonth ),
224 gmdate( 'Y', $unixmonth )
225 ) . '</caption>
226 <thead>
227 <tr>';
228
229 $myweek = array();
230
231 for ( $wdcount = 0; $wdcount <= 6; $wdcount++ ) {
232 $myweek[] = $wp_locale->get_weekday( ( $wdcount + $week_begins ) % 7 );
233 }
234
235 foreach ( $myweek as $wd ) {
236 $day_name = $args['initial'] ? $wp_locale->get_weekday_initial( $wd ) : $wp_locale->get_weekday_abbrev( $wd );
237 $wd = esc_attr( $wd );
238 $calendar_output .= "\n\t\t<th scope=\"col\" aria-label=\"$wd\">$day_name</th>";
239 }
240
241 $calendar_output .= '
242 </tr>
243 </thead>
244 <tbody>
245 <tr>';
246
247 $daywithpost = array();
248
249 // Get days with posts.
250 $dayswithposts_prepared_query = $wpdb->prepare(
251 "SELECT DISTINCT DAYOFMONTH(post_date)
252 FROM $wpdb->posts $join_clause WHERE post_date >= '{$thisyear}-{$thismonth}-01 00:00:00'
253 AND post_type = %s AND post_status = 'publish'
254 AND post_date <= '{$thisyear}-{$thismonth}-{$last_day} 23:59:59' $where_clause",
255 $post_type
256 ); #modified#
257 $dayswithposts = $wpdb->get_results( $dayswithposts_prepared_query, ARRAY_N );
258
259 if ( $dayswithposts ) {
260 foreach ( (array) $dayswithposts as $daywith ) {
261 $daywithpost[] = (int) $daywith[0];
262 }
263 }
264
265 // See how much we should pad in the beginning.
266 $pad = calendar_week_mod( (int) gmdate( 'w', $unixmonth ) - $week_begins );
267 if ( 0 != $pad ) {
268 $calendar_output .= "\n\t\t" . '<td colspan="' . esc_attr( $pad ) . '" class="pad">&nbsp;</td>';
269 }
270
271 $newrow = false;
272 $daysinmonth = (int) gmdate( 't', $unixmonth );
273
274 for ( $day = 1; $day <= $daysinmonth; ++$day ) {
275 if ( isset( $newrow ) && $newrow ) {
276 $calendar_output .= "\n\t</tr>\n\t<tr>\n\t\t";
277 }
278 $newrow = false;
279
280 if ( current_time( 'j' ) == $day &&
281 current_time( 'm' ) == $thismonth &&
282 current_time( 'Y' ) == $thisyear ) {
283 $calendar_output .= '<td id="today">';
284 } else {
285 $calendar_output .= '<td>';
286 }
287
288 if ( in_array( $day, $daywithpost, true ) ) {
289 // Any posts today?
290 $date_format = gmdate( _x( 'F j, Y', 'daily archives date format' ), strtotime( "{$thisyear}-{$thismonth}-{$day}" ) );
291 /* translators: Post calendar label. %s: Date. */
292 $label = sprintf( __( 'Posts published on %s' ), $date_format );
293 $calendar_output .= sprintf(
294 '<a href="%s" aria-label="%s">%s</a>',
295 get_day_link( $thisyear, $thismonth, $day ),
296 esc_attr( $label ),
297 $day
298 );
299 } else {
300 $calendar_output .= $day;
301 }
302
303 $calendar_output .= '</td>';
304
305 if ( 6 == calendar_week_mod( (int) gmdate( 'w', mktime( 0, 0, 0, $thismonth, $day, $thisyear ) ) - $week_begins ) ) {
306 $newrow = true;
307 }
308 }
309
310 $pad = 7 - calendar_week_mod( (int) gmdate( 'w', mktime( 0, 0, 0, $thismonth, $day, $thisyear ) ) - $week_begins );
311 if ( 0 != $pad && 7 != $pad ) {
312 $calendar_output .= "\n\t\t" . '<td class="pad" colspan="' . esc_attr( $pad ) . '">&nbsp;</td>';
313 }
314
315 $calendar_output .= "\n\t</tr>\n\t</tbody>";
316
317 $calendar_output .= "\n\t</table>";
318
319 $calendar_output .= '<nav aria-label="' . __( 'Previous and next months' ) . '" class="wp-calendar-nav">';
320
321 if ( $previous ) {
322 $calendar_output .= "\n\t\t" . '<span class="wp-calendar-nav-prev"><a href="' . get_month_link( $previous->year, $previous->month ) . '">&laquo; ' .
323 $wp_locale->get_month_abbrev( $wp_locale->get_month( $previous->month ) ) .
324 '</a></span>';
325 } else {
326 $calendar_output .= "\n\t\t" . '<span class="wp-calendar-nav-prev">&nbsp;</span>';
327 }
328
329 $calendar_output .= "\n\t\t" . '<span class="pad">&nbsp;</span>';
330
331 if ( $next ) {
332 $calendar_output .= "\n\t\t" . '<span class="wp-calendar-nav-next"><a href="' . get_month_link( $next->year, $next->month ) . '">' .
333 $wp_locale->get_month_abbrev( $wp_locale->get_month( $next->month ) ) .
334 ' &raquo;</a></span>';
335 } else {
336 $calendar_output .= "\n\t\t" . '<span class="wp-calendar-nav-next">&nbsp;</span>';
337 }
338
339 $calendar_output .= '
340 </nav>';
341
342 $cache[ $key ] = $calendar_output;
343 wp_cache_set( 'get_calendar', $cache, 'calendar' );
344
345 /** This filter is documented in wp-includes/general-template.php */
346 $calendar_output = apply_filters( 'get_calendar', $calendar_output, $args );
347
348 if ( $args['display'] ) {
349 echo $calendar_output;
350 return;
351 }
352
353 return $calendar_output;
354 }
355 }
356