Index: src/wp-includes/general-template.php
===================================================================
--- src/wp-includes/general-template.php	(revision 38592)
+++ src/wp-includes/general-template.php	(working copy)
@@ -1863,6 +1863,8 @@
  * no posts for the month, then it will not be displayed.
  *
  * @since 1.0.0
+ * @since 4.7 arguments changed to accept an associative array $args.
+ * @since 4.7 `get_calendar_args` filter added.
  *
  * @global wpdb      $wpdb
  * @global int       $m
@@ -1871,21 +1873,52 @@
  * @global WP_Locale $wp_locale
  * @global array     $posts
  *
- * @param bool $initial Optional, default is true. Use initial calendar names.
- * @param bool $echo    Optional, default is true. Set to false for return.
- * @return string|void String when retrieving.
+ * @param array $args{
+ *    Optional. An array of arguments.
+ *    @type bool   $initial. Use initial calendar names. Default true.
+ *    @type bool   $echo. Should we echo the calendar. Default true.
+ *    @type string $post_type. The post type to be used on the calendar. Default `post`.
+ * }
+ *
+ * @return string|void String when $args['echo'] is set to true.
  */
-function get_calendar( $initial = true, $echo = true ) {
+function get_calendar( $args = array() ) {
 	global $wpdb, $m, $monthnum, $year, $wp_locale, $posts;
 
+	$defaults = array(
+		'initial'   => true,
+		'echo'      => true,
+		'post_type' => 'post',
+	);
+
+	if ( ! is_array( $args ) ) {
+		$backwards_compatible_args = func_get_args();
+
+		if ( isset( $backwards_compatible_args[0] ) && is_bool( $backwards_compatible_args[0] ) ){
+			$defaults['initial'] = $backwards_compatible_args[0];
+		}
+
+		if ( isset( $backwards_compatible_args[1] ) && is_bool( $backwards_compatible_args[1] ) ){
+			$defaults['echo'] = $backwards_compatible_args[1];
+		}
+	}
+
+	/**
+	 * Filter the `get_calander` function arguments before they are used.
+	 *
+	 * @since 4.7
+	 * @param array $args
+	 */
+	$args = apply_filters( 'get_calendar_args', wp_parse_args( $args, $defaults) );
+
 	$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 ] );
+		$output = apply_filters( 'get_calendar', $cache[ $key ], $args );
 
-		if ( $echo ) {
+		if ( $args['echo'] ) {
 			echo $output;
 			return;
 		}
@@ -1897,9 +1930,16 @@
 		$cache = array();
 	}
 
+	$post_type = $args['post_type'];
+	if ( ! post_type_exists( $post_type ) ) {
+		// set the post type back to 'post' if the filter value is not a valid post type
+		$post_type = 'post';
+	}
+
 	// 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");
+		$prepared_query = $wpdb->prepare( "SELECT 1 as test FROM $wpdb->posts WHERE post_type = %s AND post_status = 'publish' LIMIT 1", $post_type );
+		$gotsome = $wpdb->get_var( $prepared_query );
 		if ( ! $gotsome ) {
 			$cache[ $key ] = '';
 			wp_cache_set( 'get_calendar', $cache, 'calendar' );
@@ -1940,18 +1980,21 @@
 	$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
+	$previous_prepared_query = $wpdb->prepare( "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'
+		AND post_type = %s 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
+			LIMIT 1" , $post_type);
+	$previous = $wpdb->get_row( $previous_prepared_query );
+
+	$next_prepared_query = $wpdb->prepare( "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");
+		AND post_type = %s AND post_status = 'publish'
+		ORDER BY post_date ASC
+		LIMIT 1", $post_type );
+	$next = $wpdb->get_row( $next_prepared_query );
 
 	/* translators: Calendar caption: 1: month name, 2: 4-digit year */
 	$calendar_caption = _x('%1$s %2$s', 'calendar caption');
@@ -1971,7 +2014,7 @@
 	}
 
 	foreach ( $myweek as $wd ) {
-		$day_name = $initial ? $wp_locale->get_weekday_initial( $wd ) : $wp_locale->get_weekday_abbrev( $wd );
+		$day_name = $args['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>";
 	}
@@ -2011,10 +2054,12 @@
 	$daywithpost = array();
 
 	// Get days with posts
-	$dayswithposts = $wpdb->get_results("SELECT DISTINCT DAYOFMONTH(post_date)
+	$dayswithposts_prepared_query = $wpdb->prepare( "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);
+		AND post_type = %s AND post_status = 'publish'
+		AND post_date <= '{$thisyear}-{$thismonth}-{$last_day} 23:59:59'", $post_type);
+	$dayswithposts = $wpdb->get_results( $dayswithposts_prepared_query , ARRAY_N);
+
 	if ( $dayswithposts ) {
 		foreach ( (array) $dayswithposts as $daywith ) {
 			$daywithpost[] = $daywith[0];
@@ -2073,19 +2118,23 @@
 	$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 );
+	/**
+	 * Filters the HTML calendar output.
+	 *
+	 * @since 3.0.0
+	 * @since 4.7.0 new argument $args added.
+	 *
+	 * @param string $calendar_output HTML output of the calendar.
+	 * @param array $args passed into get_calender function. $args also filtered earlier in get_calender().
+	 */
+	$calendar_output = apply_filters( 'get_calendar', $calendar_output, $args );
+
+	if ( $args['echo'] ) {
+		echo $calendar_output;
 		return;
 	}
-	/** This filter is documented in wp-includes/general-template.php */
-	return apply_filters( 'get_calendar', $calendar_output );
+
+	return $calendar_output;
 }
 
 /**
