: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
'show_post_count' => false,
'year' => get_query_var( 'year' ),
'monthnum' => get_query_var( 'monthnum' ),
'day' => get_query_var( 'day' ),
'w' => get_query_var( 'w' ),
$parsed_args = wp_parse_args( $args, $defaults );
$post_type_object = get_post_type_object( $parsed_args['post_type'] );
if ( ! is_post_type_viewable( $post_type_object ) ) {
$parsed_args['post_type'] = $post_type_object->name;
if ( '' === $parsed_args['type'] ) {
$parsed_args['type'] = 'monthly';
if ( ! empty( $parsed_args['limit'] ) ) {
$parsed_args['limit'] = absint( $parsed_args['limit'] );
$parsed_args['limit'] = ' LIMIT ' . $parsed_args['limit'];
$order = strtoupper( $parsed_args['order'] );
if ( 'ASC' !== $order ) {
// This is what will separate dates on weekly archive links.
$archive_week_separator = '–';
$sql_where = $wpdb->prepare( "WHERE post_type = %s AND post_status = 'publish'", $parsed_args['post_type'] );
* Filters the SQL WHERE clause for retrieving archives.
* @param string $sql_where Portion of SQL query containing the WHERE clause.
* @param array $parsed_args An array of default arguments.
$where = apply_filters( 'getarchives_where', $sql_where, $parsed_args );
* Filters the SQL JOIN clause for retrieving archives.
* @param string $sql_join Portion of SQL query containing JOIN clause.
* @param array $parsed_args An array of default arguments.
$join = apply_filters( 'getarchives_join', '', $parsed_args );
$last_changed = wp_cache_get_last_changed( 'posts' );
$limit = $parsed_args['limit'];
if ( 'monthly' === $parsed_args['type'] ) {
$query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date $order $limit";
$key = "wp_get_archives:$key:$last_changed";
$results = wp_cache_get( $key, 'post-queries' );
$results = $wpdb->get_results( $query );
wp_cache_set( $key, $results, 'post-queries' );
$after = $parsed_args['after'];
foreach ( (array) $results as $result ) {
$url = get_month_link( $result->year, $result->month );
if ( 'post' !== $parsed_args['post_type'] ) {
$url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
/* translators: 1: Month name, 2: 4-digit year. */
$text = sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $result->month ), $result->year );
if ( $parsed_args['show_post_count'] ) {
$parsed_args['after'] = ' (' . $result->posts . ')' . $after;
$selected = is_archive() && (string) $parsed_args['year'] === $result->year && (string) $parsed_args['monthnum'] === $result->month;
$output .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
} elseif ( 'yearly' === $parsed_args['type'] ) {
$query = "SELECT YEAR(post_date) AS `year`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date) ORDER BY post_date $order $limit";
$key = "wp_get_archives:$key:$last_changed";
$results = wp_cache_get( $key, 'post-queries' );
$results = $wpdb->get_results( $query );
wp_cache_set( $key, $results, 'post-queries' );
$after = $parsed_args['after'];
foreach ( (array) $results as $result ) {
$url = get_year_link( $result->year );
if ( 'post' !== $parsed_args['post_type'] ) {
$url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
$text = sprintf( '%d', $result->year );
if ( $parsed_args['show_post_count'] ) {
$parsed_args['after'] = ' (' . $result->posts . ')' . $after;
$selected = is_archive() && (string) $parsed_args['year'] === $result->year;
$output .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
} elseif ( 'daily' === $parsed_args['type'] ) {
$query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, DAYOFMONTH(post_date) AS `dayofmonth`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date), DAYOFMONTH(post_date) ORDER BY post_date $order $limit";
$key = "wp_get_archives:$key:$last_changed";
$results = wp_cache_get( $key, 'post-queries' );
$results = $wpdb->get_results( $query );
wp_cache_set( $key, $results, 'post-queries' );
$after = $parsed_args['after'];
foreach ( (array) $results as $result ) {
$url = get_day_link( $result->year, $result->month, $result->dayofmonth );
if ( 'post' !== $parsed_args['post_type'] ) {
$url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
$date = sprintf( '%1$d-%2$02d-%3$02d 00:00:00', $result->year, $result->month, $result->dayofmonth );
$text = mysql2date( get_option( 'date_format' ), $date );
if ( $parsed_args['show_post_count'] ) {
$parsed_args['after'] = ' (' . $result->posts . ')' . $after;
$selected = is_archive() && (string) $parsed_args['year'] === $result->year && (string) $parsed_args['monthnum'] === $result->month && (string) $parsed_args['day'] === $result->dayofmonth;
$output .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
} elseif ( 'weekly' === $parsed_args['type'] ) {
$week = _wp_mysql_week( '`post_date`' );
$query = "SELECT DISTINCT $week AS `week`, YEAR( `post_date` ) AS `yr`, DATE_FORMAT( `post_date`, '%Y-%m-%d' ) AS `yyyymmdd`, count( `ID` ) AS `posts` FROM `$wpdb->posts` $join $where GROUP BY $week, YEAR( `post_date` ) ORDER BY `post_date` $order $limit";
$key = "wp_get_archives:$key:$last_changed";
$results = wp_cache_get( $key, 'post-queries' );
$results = $wpdb->get_results( $query );
wp_cache_set( $key, $results, 'post-queries' );
$after = $parsed_args['after'];
foreach ( (array) $results as $result ) {
if ( $result->week != $arc_w_last ) {
$arc_w_last = $result->week;
$arc_week = get_weekstartend( $result->yyyymmdd, get_option( 'start_of_week' ) );
$arc_week_start = date_i18n( get_option( 'date_format' ), $arc_week['start'] );
$arc_week_end = date_i18n( get_option( 'date_format' ), $arc_week['end'] );
if ( 'post' !== $parsed_args['post_type'] ) {
$url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
$text = $arc_week_start . $archive_week_separator . $arc_week_end;
if ( $parsed_args['show_post_count'] ) {
$parsed_args['after'] = ' (' . $result->posts . ')' . $after;
$selected = is_archive() && (string) $parsed_args['year'] === $result->yr && (string) $parsed_args['w'] === $result->week;
$output .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
} elseif ( ( 'postbypost' === $parsed_args['type'] ) || ( 'alpha' === $parsed_args['type'] ) ) {
$orderby = ( 'alpha' === $parsed_args['type'] ) ? 'post_title ASC ' : 'post_date DESC, ID DESC ';
$query = "SELECT * FROM $wpdb->posts $join $where ORDER BY $orderby $limit";
$key = "wp_get_archives:$key:$last_changed";
$results = wp_cache_get( $key, 'post-queries' );
$results = $wpdb->get_results( $query );
wp_cache_set( $key, $results, 'post-queries' );
foreach ( (array) $results as $result ) {
if ( '0000-00-00 00:00:00' !== $result->post_date ) {
$url = get_permalink( $result );
if ( $result->post_title ) {
/** This filter is documented in wp-includes/post-template.php */
$text = strip_tags( apply_filters( 'the_title', $result->post_title, $result->ID ) );
$selected = get_the_ID() === $result->ID;
$output .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
if ( $parsed_args['echo'] ) {
* Gets number of days since the start of the week.
* @param int $num Number of day.
* @return float Days since the start of the week.
function calendar_week_mod( $num ) {
return ( $num - $base * floor( $num / $base ) );
* Displays calendar with days that have posts as links.
* The calendar is cached, which will be retrieved, if it exists. If there are
* no posts for the month, then it will not be displayed.
* @global wpdb $wpdb WordPress database abstraction object.
* @global WP_Locale $wp_locale WordPress date and time locale object.
* @param bool $initial Optional. Whether to use initial calendar names. Default true.
* @param bool $display Optional. Whether to display the calendar output. Default true.
* @return void|string Void if `$display` argument is true, calendar HTML if `$display` is false.
function get_calendar( $initial = true, $display = 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 ( ! is_array( $cache ) ) {
// Quick check. If we have no posts at all, abort!
$gotsome = $wpdb->get_var( "SELECT 1 as test FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 1" );
wp_cache_set( 'get_calendar', $cache, 'calendar' );
if ( isset( $_GET['w'] ) ) {
// week_begins = 0 stands for Sunday.
$week_begins = (int) get_option( 'start_of_week' );
// Let's figure out when we are.
if ( ! empty( $monthnum ) && ! empty( $year ) ) {
$thismonth = zeroise( (int) $monthnum, 2 );
} 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 = zeroise( (int) substr( $m, 4, 2 ), 2 );
$thisyear = current_time( 'Y' );
$thismonth = current_time( 'm' );
$unixmonth = mktime( 0, 0, 0, $thismonth, 1, $thisyear );
$last_day = gmdate( '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
WHERE post_date < '$thisyear-$thismonth-01'
AND post_type = 'post' AND post_status = 'publish'
"SELECT MONTH(post_date) AS month, YEAR(post_date) AS year
WHERE post_date > '$thisyear-$thismonth-{$last_day} 23:59:59'
AND post_type = 'post' AND post_status = 'publish'
/* 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" class="wp-calendar-table">
$wp_locale->get_month( $thismonth ),
gmdate( 'Y', $unixmonth )
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 );
$calendar_output .= "\n\t\t<th scope=\"col\" title=\"$wd\">$day_name</th>";
$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'",
foreach ( (array) $dayswithposts as $daywith ) {
$daywithpost[] = (int) $daywith[0];
// See how much we should pad in the beginning.
$pad = calendar_week_mod( gmdate( 'w', $unixmonth ) - $week_begins );
$calendar_output .= "\n\t\t" . '<td colspan="' . esc_attr( $pad ) . '" class="pad"> </td>';
$daysinmonth = (int) gmdate( 't', $unixmonth );
for ( $day = 1; $day <= $daysinmonth; ++$day ) {
if ( isset( $newrow ) && $newrow ) {
$calendar_output .= "\n\t</tr>\n\t<tr>\n\t\t";
if ( current_time( 'j' ) == $day &&
current_time( 'm' ) == $thismonth &&
current_time( 'Y' ) == $thisyear ) {
$calendar_output .= '<td id="today">';
$calendar_output .= '<td>';
if ( in_array( $day, $daywithpost, true ) ) {
$date_format = gmdate( _x( 'F j, Y', 'daily archives date format' ), strtotime( "{$thisyear}-{$thismonth}-{$day}" ) );
/* translators: Post calendar label. %s: 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 ),
$calendar_output .= $day;
$calendar_output .= '</td>';
if ( 6 == calendar_week_mod( gmdate( 'w', mktime( 0, 0, 0, $thismonth, $day, $thisyear ) ) - $week_begins ) ) {
$pad = 7 - calendar_week_mod( gmdate( 'w', mktime( 0, 0, 0, $thismonth, $day, $thisyear ) ) - $week_begins );
if ( 0 != $pad && 7 != $pad ) {
$calendar_output .= "\n\t\t" . '<td class="pad" colspan="' . esc_attr( $pad ) . '"> </td>';
$calendar_output .= "\n\t</tr>\n\t</tbody>";
$calendar_output .= "\n\t</table>";
$calendar_output .= '<nav aria-label="' . __( 'Previous and next months' ) . '" class="wp-calendar-nav">';
$calendar_output .= "\n\t\t" . '<span class="wp-calendar-nav-prev"><a href="' . get_month_link( $previous->year, $previous->month ) . '">« ' .
$wp_locale->get_month_abbrev( $wp_locale->get_month( $previous->month ) ) .
$calendar_output .= "\n\t\t" . '<span class="wp-calendar-nav-prev"> </span>';
$calendar_output .= "\n\t\t" . '<span class="pad"> </span>';
$calendar_output .= "\n\t\t" . '<span class="wp-calendar-nav-next"><a href="' . get_month_link( $next->year, $next->month ) . '">' .
$wp_locale->get_month_abbrev( $wp_locale->get_month( $next->month ) ) .
$calendar_output .= "\n\t\t" . '<span class="wp-calendar-nav-next"> </span>';
$cache[ $key ] = $calendar_output;
wp_cache_set( 'get_calendar', $cache, 'calendar' );
* Filters the HTML calendar output.
* @param string $calendar_output HTML output of the calendar.
echo apply_filters( 'get_calendar', $calendar_output );
/** This filter is documented in wp-includes/general-template.php */
return apply_filters( 'get_calendar', $calendar_output );
* Purges the cached results of get_calendar.
function delete_get_calendar_cache() {
wp_cache_delete( 'get_calendar', 'calendar' );
* Displays all of the allowed tags in HTML format with attributes.
* This is useful for displaying in the comment area, which elements and
* attributes are supported. As well as any plugins which want to display it.
* @since 4.4.0 No longer used in core.
* @global array $allowedtags
* @return string HTML allowed tags entity encoded.
function allowed_tags() {
foreach ( (array) $allowedtags as $tag => $attributes ) {
if ( 0 < count( $attributes ) ) {
foreach ( $attributes as $attribute => $limits ) {