<?php
/**
* URL Management. Create and manipulate calendar URLs.
*
* @category Utilities
* @package My Calendar
* @author Joe Dolson
* @license GPLv2 or later
* @link https://www.joedolson.com/my-calendar/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Build a URL for My Calendar views.
*
* @param array<string> $add keys and values to add to URL.
* @param array<string> $subtract keys to subtract from URL.
* @param string $root Root URL, optional.
*
* @return string URL.
*/
function mc_build_url( $add, $subtract, $root = '' ) {
$home = '';
$root = apply_filters( 'mc_build_url_root', $root );
if ( '' !== $root ) {
$home = $root;
}
if ( is_numeric( $root ) ) {
$home = get_permalink( $root );
}
if ( '' === $home ) {
if ( is_front_page() ) {
$home = home_url( '/' );
} elseif ( is_home() ) {
$page = get_option( 'page_for_posts' );
$home = get_permalink( $page );
} elseif ( is_archive() ) {
$home = '';
// An empty string seems to work best; leaving it open.
} else {
wp_reset_query();
// Break out of alternate loop. If theme uses query_posts to fetch, this causes problems. But themes should *never* use query_posts to replace the loop, so screw that.
$home = get_permalink();
}
}
$variables = map_deep( $_GET, 'sanitize_text_field' );
$subtract = array_merge( (array) $subtract, array( 'from', 'to', 'my-calendar-api', 's', 'embed' ) );
foreach ( $subtract as $value ) {
unset( $variables[ $value ] );
}
foreach ( $add as $key => $value ) {
$variables[ $key ] = $value;
}
unset( $variables['page_id'] );
$home = add_query_arg( $variables, $home );
$home = apply_filters( 'mc_build_url', $home, $add, $subtract, $root );
return esc_url( $home );
}
/**
* Is this URL being queried while in the primary content.
*
* @param string $url URL to attach query to.
*
* @return string
*/
function mc_url_in_loop( $url ) {
// Only if AJAX is enabled.
if ( ( '1' !== mc_get_option( 'ajax_javascript' ) ) && true === apply_filters( 'mc_use_embed_targets', false, $url ) ) {
if ( is_singular() && in_the_loop() && is_main_query() ) {
$url = esc_url( add_query_arg( 'embed', 'true', html_entity_decode( $url ) ) );
}
}
return $url;
}
/**
* Build the URL for use in the mini calendar
*
* @param int $start date timestamp.
* @param int $category current category.
* @param array $events array of event objects.
* @param array $args calendar view parameters.
* @param array $date view date.
*
* @return string URL
*/
function mc_build_mini_url( $start, $category, $events, $args, $date ) {
$open_day_uri = mc_get_option( 'open_day_uri' );
if ( 'false' === $open_day_uri ) {
return false;
}
$mini_uri = ( _mc_is_url( mc_get_option( 'mini_uri' ) ) ) ? mc_get_option( 'mini_uri' ) : mc_get_uri( reset( $events ) );
if ( is_singular() && 'current' === $open_day_uri ) {
global $post;
$mini_uri = get_permalink( $post->ID );
}
/**
* Filter the URI used to link days in the mini calendar.
*
* @hook mc_modify_day_uri
*
* @param string $mini_uri The URL generated from settings.
* @param array $args The arguments passed to the current calendar view.
*
* @return string URL.
*/
$mini_uri = apply_filters( 'mc_modify_day_uri', $mini_uri, $args );
if ( 'true' === $open_day_uri ) {
$target = array(
'yr' => mc_date( 'Y', $start, false ),
'month' => mc_date( 'm', $start, false ),
'dy' => mc_date( 'j', $start, false ),
'time' => 'day',
);
if ( $category ) {
$target['mcat'] = $category;
}
$day_url = mc_build_url( $target, array( 'month', 'dy', 'yr', 'ltype', 'loc', 'mcat', 'cid', 'mc_id' ), $mini_uri );
$link = ( '' !== $day_url ) ? $day_url : '#';
} else {
$atype = str_replace( 'anchor', '', $open_day_uri ); // List or grid.
$ad = str_pad( mc_date( 'j', $start, false ), 2, '0', STR_PAD_LEFT ); // Need to match format in ID.
$am = str_pad( $date['month'], 2, '0', STR_PAD_LEFT );
$date_url = mc_build_url(
array(
'yr' => $date['year'],
'month' => $date['month'],
'dy' => mc_date( 'j', $start, false ),
),
array( 'month', 'dy', 'yr', 'ltype', 'loc', 'mcat', 'cid', 'mc_id' ),
$mini_uri
);
$link = esc_url( ( '' !== $mini_uri ) ? $date_url . '#' . $atype . '-' . $date['year'] . '-' . $am . '-' . $ad : '#' );
}
return $link;
}
/**
* Re-parse URL for translation plug-ins.
*
* @param string $url Original URL.
*
* @return string
*/
function mc_translate_url( $url ) {
$is_default = true;
$home_url = home_url();
// Polylang support.
if ( function_exists( 'pll_home_url' ) ) {
$home_url = pll_home_url();
$is_default = ( pll_current_language() === pll_default_language() ) ? true : false;
}
// WPML support.
if ( function_exists( 'wpml_current_language' ) ) {
$home_url = apply_filters( 'wpml_home_url', home_url() );
$is_default = ( apply_filters( 'wpml_current_language', null ) === apply_filters( 'wpml_default_language', null ) ) ? true : false;
}
if ( ! $is_default ) {
$url = str_replace( home_url(), $home_url, $url );
}
return $url;
}
add_filter( 'mc_build_url', 'mc_translate_url' );
/**
* Filter Polylang translation URL in translation menu.
*
* @param string $url Translation URL.
* @param string $lang Language of translation.
*
* @return string
*/
function mc_pll_translation_url( $url, $lang ) {
if ( is_singular( 'mc-events' ) ) {
$mc_id = '';
if ( isset( $_GET['mc_id'] ) ) {
$mc_id = (int) $_GET['mc_id'];
}
$url = add_query_arg( 'mc_id', $mc_id, $url );
}
return $url;
}
add_filter( 'pll_translation_url', 'mc_pll_translation_url', 10, 2 );