<?php
/**
 * Functions which enhance the theme by hooking into WordPress
 *
 * @package pixigo
 */

/**
 * Adds custom classes to the array of body classes.
 *
 * @param array $classes Classes for the body element.
 * @return array
 */
function pixigo_body_classes( $classes ) {
	// Adds a class of hfeed to non-singular pages.
	if ( ! is_singular() ) {
		$classes[] = 'hfeed';
	}

	if ( is_active_sidebar( 'sidebar-1' ) && pixigo_is_sidebar_available() ) {
		$classes[] = 'has-sidebar';
	}

	return $classes;
}
add_filter( 'body_class', 'pixigo_body_classes' );

/**
 * Add a pingback url auto-discovery header for singularly identifiable articles.
 */
function pixigo_pingback_header() {
	if ( is_singular() && pings_open() ) {
		echo '<link rel="pingback" href="', esc_url( get_bloginfo( 'pingback_url' ) ), '">';
	}
}
add_action( 'wp_head', 'pixigo_pingback_header' );

/**
 * Adds async/defer attributes to enqueued / registered scripts.
 *
 * If #12009 lands in WordPress, this function can no-op since it would be handled in core.
 *
 * @link https://core.trac.wordpress.org/ticket/12009
 * @param string $tag    The script tag.
 * @param string $handle The script handle.
 * @return array
 */
function pixigo_filter_script_loader_tag( $tag, $handle ) {

	foreach ( array( 'async', 'defer' ) as $attr ) {
		if ( ! wp_scripts()->get_data( $handle, $attr ) ) {
			continue;
		}

		// Prevent adding attribute when already added in #12009.
		if ( ! preg_match( ":\s$attr(=|>|\s):", $tag ) ) {
			$tag = preg_replace( ':(?=></script>):', " $attr", $tag, 1 );
		}

		// Only allow async or defer, not both.
		break;
	}

	return $tag;
}

add_filter( 'script_loader_tag', 'pixigo_filter_script_loader_tag', 10, 2 );

/**
 * Generate preload markup for stylesheets.
 *
 * @param object $wp_styles Registered styles.
 * @param string $handle The style handle.
 */
function pixigo_get_preload_stylesheet_uri( $wp_styles, $handle ) {
	$preload_uri = $wp_styles->registered[ $handle ]->src . '?ver=' . $wp_styles->registered[ $handle ]->ver;
	return $preload_uri;
}

/**
 * Adds preload for in-body stylesheets depending on what templates are being used.
 * Disabled when AMP is active as AMP injects the stylesheets inline.
 *
 * @link https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
 */
function pixigo_add_body_style() {

	// If AMP is active, do nothing.
	if ( pixigo_is_amp() ) {
		return;
	}

	// Get registered styles.
	$wp_styles = wp_styles();

	$preloads = array();

	// Preload content.css.
	$preloads['pixigo-content'] = pixigo_get_preload_stylesheet_uri( $wp_styles, 'pixigo-content' );

	// Preload sidebar.css and widget.css.
	if ( is_active_sidebar( 'sidebar-1' ) && pixigo_is_sidebar_available() ) {
		$preloads['pixigo-widgets'] = pixigo_get_preload_stylesheet_uri( $wp_styles, 'pixigo-widgets' );
	}

	// Preload comments.css.
	if ( ! post_password_required() && is_singular() && ( comments_open() || get_comments_number() ) ) {
		$preloads['pixigo-comments'] = pixigo_get_preload_stylesheet_uri( $wp_styles, 'pixigo-comments' );
	}

	// Output the preload markup in <head>.
	foreach ( $preloads as $handle => $src ) {
		echo '<link rel="preload" id="' . esc_attr( $handle ) . '-preload" href="' . esc_url( $src ) . '" as="style" />';
		echo "\n";
	}

}
add_action( 'wp_head', 'pixigo_add_body_style' );

/**
 * Add dropdown symbol to nav menu items with children.
 *
 * Adds the dropdown markup after the menu link element,
 * before the submenu.
 *
 * Javascript converts the symbol to a toggle button.
 *
 * @TODO:
 * - This doesn't work for the page menu because it
 *   doesn't have a similar filter. So the dropdown symbol
 *   is only being added for page menus if JS is enabled.
 *   Create a ticket to add to core?
 *
 * @param string   $item_output The menu item's starting HTML output.
 * @param WP_Post  $item        Menu item data object.
 * @param int      $depth       Depth of menu item. Used for padding.
 * @param stdClass $args        An object of wp_nav_menu() arguments.
 * @return string Modified nav menu HTML.
 */
function pixigo_add_header_menu_dropdown_symbol( $item_output, $item, $depth, $args ) {

	// Only for our header menu location.
	if ( empty( $args->theme_location ) || 'header' !== $args->theme_location ) {
		return $item_output;
	}

	// Add the dropdown for items that have children.
	if ( ! empty( $item->classes ) && in_array( 'menu-item-has-children', $item->classes, true ) ) {
		return $item_output . '<span class="dropdown"><i class="dropdown-symbol"></i></span>';
	}

	return $item_output;
}
add_filter( 'walker_nav_menu_start_el', 'pixigo_add_header_menu_dropdown_symbol', 10, 4 );

/**
 * Filters the HTML attributes applied to a menu item's anchor element.
 *
 * Checks if the menu item is the current menu
 * item and adds the aria "current" attribute.
 *
 * @param array   $atts   The HTML attributes applied to the menu item's `<a>` element.
 * @param WP_Post $item  The current menu item.
 * @return array Modified HTML attributes
 */
function pixigo_add_nav_menu_aria_current( $atts, $item ) {
	/*
	 * First, check if "current" is set,
	 * which means the item is a nav menu item.
	 *
	 * Otherwise, it's a post item so check
	 * if the item is the current post.
	 */
	if ( isset( $item->current ) ) {
		if ( $item->current ) {
			$atts['aria-current'] = 'page';
		}
	} elseif ( ! empty( $item->ID ) ) {
		global $post;
		if ( ! empty( $post->ID ) && $post->ID === $item->ID ) {
			$atts['aria-current'] = 'page';
		}
	}

	return $atts;
}
add_filter( 'nav_menu_link_attributes', 'pixigo_add_nav_menu_aria_current', 10, 2 );
add_filter( 'page_menu_link_attributes', 'pixigo_add_nav_menu_aria_current', 10, 2 );

/**
 * Custom excerpt length
 *
 * @param String $length Default length.
 */
function pixigo_excerpt_length( $length ) {
	return 30;
}
add_filter( 'excerpt_length', 'pixigo_excerpt_length' );

/**
 * Custom excerpt end string
 *
 * @param String $more Default string.
 */
function pixigo_excerpt_more( $more ) {
	return '...';
}
add_filter( 'excerpt_more', 'pixigo_excerpt_more' );

/**
 * Declare customizer page section settings
 * Used in the customizer to generate checkboxes
 *
 * @return Array Key-value pairs of ID and string
 */
function pixigo_page_customization_options() {
	$page_options = array(
		'sidebar'        => 'Sidebar',
		'featured_image' => 'Featured Image',
	);
	return $page_options;
}

/**
 * Declare post section settings
 * Used in the post metabox
 *
 * @return Array Key-value pairs of ID and string
 */
function pixigo_post_customization_options() {
	$post_options = array(
		'sidebar'           => 'Sidebar',
		'featured_image'    => 'Featured Image',
		'related_posts'     => 'Related Posts',
		'tag_display'       => 'Tags',
		'authorbox'         => 'Author Box',
	);
	return $post_options;
}

/**
 * Declare archive section settings
 * Used in the archive metabox
 *
 * @return Array Key-value pairs of ID and string
 */
function pixigo_archive_customization_options() {
	$archive_options = array(
		'sidebar'          => 'Sidebar',
		'featured_image'   => 'Featured Image',
	);
	return $archive_options;
}

/**
 * Adds a metabox to post screens
 *
 * @param Object $post The current post object.
 */
function add_pixigo_metabox( $post ) {
	add_meta_box(
		'pixigo_metabox', __( 'PixiGo Post Options', 'pixigo' ), 'pixigo_metabox',
		'post', 'side', 'high'
	);
}

/**
 * Renders the metabox in the post-edit page
 *
 * @param Object $post The current post object.
 */
function pixigo_metabox( $post ) {
	get_template_part( 'inc/metabox' );
}

/**
 * Metabox save function
 *
 * @param Integer $post_id  The Post ID.
 * @param Object  $post     The Post Object.
 */
function save_pixigo_metabox( $post_id, $post ) {

	if ( ! isset( $_POST['pixigo_metabox_nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['pixigo_metabox_nonce'] ), 'pixigo_metabox' ) ) { //phpcs:ignore
		return;
	}

	// return if autosave.
	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}

	// Check the user's permissions.
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}

	$options = array();

	$pixigo_page_customization_options = pixigo_post_customization_options();

	foreach ( $pixigo_page_customization_options as $name => $string ) {
		$post_field       = 'pixigo_indi_post_options';
		$options[ $name ] = isset( $_POST[ $post_field ][ $name ] ) ? true : false;
	}

	update_post_meta( $post_id, '_pixigo_indi_post_options', $options );
}

/**
 * Returns an appropriate sidebar for the respective post selected in the customizer
 *
 * @return Boolean Whether sidebar should be shown or not
 */
function pixigo_is_sidebar_available() {
	global $post;

	$default_sidebar = 'sidebar-1';

	if ( is_single() ) {

		if ( get_theme_mod( 'post_hide_sidebar', 0 ) ) {
			// Hidden for posts globally.
			return false;
		}

		// Per post.
		$post_meta_options = get_post_meta( $post->ID, '_pixigo_indi_post_options', true );

		// If hide sidebar option is active from metabox.
		if ( isset( $post_meta_options['sidebar'] ) && $post_meta_options['sidebar'] ) {
			// Hidden for current post.
			return false;
		}
	} elseif ( is_page() ) {
		if ( get_theme_mod( 'page_hide_sidebar', 1 ) ) {
			// Hidden for pages globally.
			return false;
		}
	} else {
		if ( get_theme_mod( 'archive_hide_sidebar', 0 ) ) {
			// Hidden for archives globally.
			return false;
		}
	}

	// Sidebar available.
	return true;
}

/**
 * Outputs breadcrumb if the plugin is installed
 */
function pixigo_yoast_breadcrumb() {
	if ( function_exists( 'yoast_breadcrumb' ) ) {
		yoast_breadcrumb( '<p id="breadcrumbs">', '</p>' );
	}
}

/**
 * Check if disqus comment system is active
 *
 * @return Boolean
 */
function pixigo_is_disqus_active() {
	include_once ABSPATH . 'wp-admin/includes/plugin.php';
	if ( is_plugin_active( 'disqus-comment-system/disqus.php' ) || is_plugin_active( 'disqus-conditional-load/disqus-conditional-load.php' ) ) {
		return true;
	}
	return false;
}

/**
 * Check if flying pages plugin is active
 *
 * @return Boolean
 */
function pixigo_is_flying_pages_active() {
	include_once ABSPATH . 'wp-admin/includes/plugin.php';
	if ( is_plugin_active( 'flying-pages/flying-pages.php' ) ) {
		return true;
	}
	return false;
}
