WordPress как на ладони
wordpress jino

get_calendar() WP 1.0.0

Выводит календарь на экран (по умолчанию текущий месяц).

Дни в календаре станут ссылками на страницы архивов постов за день. Если постов в этот день не было, то день будет простым текстом (без ссылки).

Этот Тег шаблона может быть использован в любом месте шаблона.

Хуки из функции:
Возвращает

Ничего (выводит на экран) или код календаря, если во второй параметре $echo передать false.

Использование

<?php get_calendar( $initial ); ?>
$initial(логический)

Как отображать названия дня:

  • true — одной буквой (первая буква дня недели);
  • false — аббревиатурой (Понедельник будет показан как "Пн").

По умолчанию: true

$echo(логический)
Выводить на экран или возвращать для обработки?
По умолчанию: true (выводить)

Примеры

#1. Базовый пример

Выведем календарь, где каждый день, в который был написан хоть 1 пост, будет ссылкой.

<?php get_calendar(); ?>

#2. Выведем аббревиатуры дней недели, в текущей локализации (суббота: Сб):

<?php get_calendar(false); ?>

Код get calendar: wp-includes/general-template.php WP 4.9

<?php
function get_calendar( $initial = true, $echo = true ) {
	global $wpdb, $m, $monthnum, $year, $wp_locale, $posts;

	$key = md5( $m . $monthnum . $year );
	$cache = wp_cache_get( 'get_calendar', 'calendar' );

	if ( $cache && is_array( $cache ) && isset( $cache[ $key ] ) ) {
		/** This filter is documented in wp-includes/general-template.php */
		$output = apply_filters( 'get_calendar', $cache[ $key ] );

		if ( $echo ) {
			echo $output;
			return;
		}

		return $output;
	}

	if ( ! is_array( $cache ) ) {
		$cache = array();
	}

	// Quick check. If we have no posts at all, abort!
	if ( ! $posts ) {
		$gotsome = $wpdb->get_var("SELECT 1 as test FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 1");
		if ( ! $gotsome ) {
			$cache[ $key ] = '';
			wp_cache_set( 'get_calendar', $cache, 'calendar' );
			return;
		}
	}

	if ( isset( $_GET['w'] ) ) {
		$w = (int) $_GET['w'];
	}
	// week_begins = 0 stands for Sunday
	$week_begins = (int) get_option( 'start_of_week' );
	$ts = current_time( 'timestamp' );

	// Let's figure out when we are
	if ( ! empty( $monthnum ) && ! empty( $year ) ) {
		$thismonth = zeroise( intval( $monthnum ), 2 );
		$thisyear = (int) $year;
	} elseif ( ! empty( $w ) ) {
		// We need to get the month from MySQL
		$thisyear = (int) substr( $m, 0, 4 );
		//it seems MySQL's weeks disagree with PHP's
		$d = ( ( $w - 1 ) * 7 ) + 6;
		$thismonth = $wpdb->get_var("SELECT DATE_FORMAT((DATE_ADD('{$thisyear}0101', INTERVAL $d DAY) ), '%m')");
	} elseif ( ! empty( $m ) ) {
		$thisyear = (int) substr( $m, 0, 4 );
		if ( strlen( $m ) < 6 ) {
			$thismonth = '01';
		} else {
			$thismonth = zeroise( (int) substr( $m, 4, 2 ), 2 );
		}
	} else {
		$thisyear = gmdate( 'Y', $ts );
		$thismonth = gmdate( 'm', $ts );
	}

	$unixmonth = mktime( 0, 0 , 0, $thismonth, 1, $thisyear );
	$last_day = date( 't', $unixmonth );

	// Get the next and previous month and year with at least one post
	$previous = $wpdb->get_row("SELECT MONTH(post_date) AS month, YEAR(post_date) AS year
		FROM $wpdb->posts
		WHERE post_date < '$thisyear-$thismonth-01'
		AND post_type = 'post' AND post_status = 'publish'
			ORDER BY post_date DESC
			LIMIT 1");
	$next = $wpdb->get_row("SELECT MONTH(post_date) AS month, YEAR(post_date) AS year
		FROM $wpdb->posts
		WHERE post_date > '$thisyear-$thismonth-{$last_day} 23:59:59'
		AND post_type = 'post' AND post_status = 'publish'
			ORDER BY post_date ASC
			LIMIT 1");

	/* translators: Calendar caption: 1: month name, 2: 4-digit year */
	$calendar_caption = _x('%1$s %2$s', 'calendar caption');
	$calendar_output = '<table id="wp-calendar">
	<caption>' . sprintf(
		$calendar_caption,
		$wp_locale->get_month( $thismonth ),
		date( 'Y', $unixmonth )
	) . '</caption>
	<thead>
	<tr>';

	$myweek = array();

	for ( $wdcount = 0; $wdcount <= 6; $wdcount++ ) {
		$myweek[] = $wp_locale->get_weekday( ( $wdcount + $week_begins ) % 7 );
	}

	foreach ( $myweek as $wd ) {
		$day_name = $initial ? $wp_locale->get_weekday_initial( $wd ) : $wp_locale->get_weekday_abbrev( $wd );
		$wd = esc_attr( $wd );
		$calendar_output .= "\n\t\t<th scope=\"col\" title=\"$wd\">$day_name</th>";
	}

	$calendar_output .= '
	</tr>
	</thead>

	<tfoot>
	<tr>';

	if ( $previous ) {
		$calendar_output .= "\n\t\t".'<td colspan="3" id="prev"><a href="' . get_month_link( $previous->year, $previous->month ) . '">&laquo; ' .
			$wp_locale->get_month_abbrev( $wp_locale->get_month( $previous->month ) ) .
		'</a></td>';
	} else {
		$calendar_output .= "\n\t\t".'<td colspan="3" id="prev" class="pad">&nbsp;</td>';
	}

	$calendar_output .= "\n\t\t".'<td class="pad">&nbsp;</td>';

	if ( $next ) {
		$calendar_output .= "\n\t\t".'<td colspan="3" id="next"><a href="' . get_month_link( $next->year, $next->month ) . '">' .
			$wp_locale->get_month_abbrev( $wp_locale->get_month( $next->month ) ) .
		' &raquo;</a></td>';
	} else {
		$calendar_output .= "\n\t\t".'<td colspan="3" id="next" class="pad">&nbsp;</td>';
	}

	$calendar_output .= '
	</tr>
	</tfoot>

	<tbody>
	<tr>';

	$daywithpost = array();

	// Get days with posts
	$dayswithposts = $wpdb->get_results("SELECT DISTINCT DAYOFMONTH(post_date)
		FROM $wpdb->posts WHERE post_date >= '{$thisyear}-{$thismonth}-01 00:00:00'
		AND post_type = 'post' AND post_status = 'publish'
		AND post_date <= '{$thisyear}-{$thismonth}-{$last_day} 23:59:59'", ARRAY_N);
	if ( $dayswithposts ) {
		foreach ( (array) $dayswithposts as $daywith ) {
			$daywithpost[] = $daywith[0];
		}
	}

	// See how much we should pad in the beginning
	$pad = calendar_week_mod( date( 'w', $unixmonth ) - $week_begins );
	if ( 0 != $pad ) {
		$calendar_output .= "\n\t\t".'<td colspan="'. esc_attr( $pad ) .'" class="pad">&nbsp;</td>';
	}

	$newrow = false;
	$daysinmonth = (int) date( 't', $unixmonth );

	for ( $day = 1; $day <= $daysinmonth; ++$day ) {
		if ( isset($newrow) && $newrow ) {
			$calendar_output .= "\n\t</tr>\n\t<tr>\n\t\t";
		}
		$newrow = false;

		if ( $day == gmdate( 'j', $ts ) &&
			$thismonth == gmdate( 'm', $ts ) &&
			$thisyear == gmdate( 'Y', $ts ) ) {
			$calendar_output .= '<td id="today">';
		} else {
			$calendar_output .= '<td>';
		}

		if ( in_array( $day, $daywithpost ) ) {
			// any posts today?
			$date_format = date( _x( 'F j, Y', 'daily archives date format' ), strtotime( "{$thisyear}-{$thismonth}-{$day}" ) );
			/* translators: Post calendar label. 1: Date */
			$label = sprintf( __( 'Posts published on %s' ), $date_format );
			$calendar_output .= sprintf(
				'<a href="%s" aria-label="%s">%s</a>',
				get_day_link( $thisyear, $thismonth, $day ),
				esc_attr( $label ),
				$day
			);
		} else {
			$calendar_output .= $day;
		}
		$calendar_output .= '</td>';

		if ( 6 == calendar_week_mod( date( 'w', mktime(0, 0 , 0, $thismonth, $day, $thisyear ) ) - $week_begins ) ) {
			$newrow = true;
		}
	}

	$pad = 7 - calendar_week_mod( date( 'w', mktime( 0, 0 , 0, $thismonth, $day, $thisyear ) ) - $week_begins );
	if ( $pad != 0 && $pad != 7 ) {
		$calendar_output .= "\n\t\t".'<td class="pad" colspan="'. esc_attr( $pad ) .'">&nbsp;</td>';
	}
	$calendar_output .= "\n\t</tr>\n\t</tbody>\n\t</table>";

	$cache[ $key ] = $calendar_output;
	wp_cache_set( 'get_calendar', $cache, 'calendar' );

	if ( $echo ) {
		/**
		 * Filters the HTML calendar output.
		 *
		 * @since 3.0.0
		 *
		 * @param string $calendar_output HTML output of the calendar.
		 */
		echo apply_filters( 'get_calendar', $calendar_output );
		return;
	}
	/** This filter is documented in wp-includes/general-template.php */
	return apply_filters( 'get_calendar', $calendar_output );
}

Cвязанные функции

Из раздела: Дата/время

get_calendar 10 комментариев
  • Velimudr-1 cайт: freelance.ru/tim4ik

    Добрый вечер, Тимур.
    Подскажите, куда выводит календарь статьи, на которые указывают дни? нажимаю на номер, страница пуста, куда ни нажму, всё пусто.
    Может мало просто посадить его в виджет? может нужен вывод? иначе как объяснить отсутствие статей?

    Ответить2.9 года назад #
    • Kama4660

      Календарь - это архив статей по дням. Куда вы нажимаете и что у вас "пусто", там либо "не найдено" должно быть либо ошибка 404? Если вы имеете ввиду что в календаре даты не кликабельные, то просто нет записей в этот день... Будут записи, будет ссылка. А еще, может тема неправильно работает и не выводит архив по датам, но это вряд ли.

      Ответить2.9 года назад #
  • Радмир

    Здравствуйте, а можно ли заставить календарь выводить future_posts ?

    Ответить2.6 года назад #
    • Kama4660

      Как вы себе это представляете? Поста нет, но ссылка на него есть или как?

      Ответить2.6 года назад #
      • Радмир

        Пост есть, но дата у него стоит например, 2 мая 2015. (то есть в календаре с настройками по умолчанию он не отобразится).

        Суть такая, что на сайте отображается анонс будущих событий (каждое будущее событие это запись в рубрике с конкретной датой).

        Ответить2.6 года назад #
  • campusboy1946 cайт: www.youtube.com/c/wpplus

    Странно, что get_calendar вместо того, чтобы возвратить, выводит на экран. Как-то не по семантике движка название функции. Но, если надо возвратить, то можно вторым параметром передать false. Кстати, он не указан в описании функции.

    Ответить1.4 года назад #
    • Kama4660

      Да немного не привычно... Спасибо, добавил второй параметр в описание.

      Ответить1.4 года назад #
  • Илья @

    Скажите пожалуйста, а можно как то сделать, чтобы в календаре указывались посты не по дате создания, а например, по датам указным в произвольных полях?
    Если нет, то есть ли какие-то решения? Спасибо.

  • А возможно ли как-нибудь организовать вывод названия месяца (предыдущий / следующий) не в виде аббревиатуры, а полностью? На текущий момент я этой делаю правкой непосредственно в ядре, но это всякий раз до очередного обновления. Строки 2000 и 2010.

  • Вячеслав

    Доброго времени суток. Не подскажите как можно сделать чтобы ссылки prev и next листали месяцы в виджете, а не перекидовал на страницу архива? Заранее спасибо

    Ответить3 месяца назад #

Здравствуйте, !

Ваш комментарий