<?php
/**
 * Add WPML compatibility to GravityView, including registering scripts and styles to GravityView no-conflict list
 *
 * @file      class-gravityview-theme-hooks-wpml.php
 * @package   GravityView
 * @license   GPL2+
 * @author    GravityKit <hello@gravitykit.com>
 * @link      http://www.gravitykit.com
 * @copyright Copyright 2015, Katz Web Services, Inc.
 *
 * @since 1.19.2
 */

/**
 * Requires WPML 3.6.2 or newer
 *
 * @inheritDoc
 */
class GravityView_Theme_Hooks_WPML extends GravityView_Plugin_and_Theme_Hooks {

	/**
	 * @inheritDoc
	 * @since 1.19.2
	 */
	protected $script_handles = array(
		'wpml-cpi-scripts',
		'sitepress-scripts',
		'sitepress-post-edit',
		'sitepress-post-list-quickedit',
		'sitepress-languages',
		'sitepress-troubleshooting',
	);

	/**
	 * @inheritDoc
	 * @since 1.19.2
	 */
	protected $style_handles = array(
		'sitepress-style',
		'wpml-select-2',
		'wpml-tm-styles',
		'wpml-tm-queue',
		'wpml-dialog',
		'wpml-tm-editor-css',
		'otgs-dialogs',
		'otgs-ico',
	);

	/**
	 * @inheritDoc
	 * @since 1.19.2
	 */
	protected $constant_name = 'ICL_SITEPRESS_VERSION';

	/**
	 * Add filters for WPML links
	 *
	 * @since 1.19.4
	 */
	public function add_hooks() {

		parent::add_hooks();

		add_filter( 'icl_ls_languages', array( $this, 'wpml_ls_filter' ) );

		add_filter( 'gravityview_directory_link', array( $this, 'filter_gravityview_back_link' ) );
	}

	/**
	 * Add WPML filters to GravityView directory link
	 *
	 * This also modifies all the Edit Entry, Cancel Edit, Go Back links
	 *
	 * @since 1.19.4
	 *
	 * @see GravityView_API::directory_link
	 * @uses WPML_URL_Filters::permalink_filter
	 *
	 * @param string $link Permalink to the GravityView directory, without language params
	 *
	 * @return string $link, with language params added by WPML
	 */
	function filter_gravityview_back_link( $link ) {
		global $wpml_url_filters;

		if ( $wpml_url_filters ) {
			$link = $wpml_url_filters->permalink_filter( $link, GravityView_frontend::getInstance()->getPostId() );
		}

		return $link;
	}

	/**
	 * Remove WPML permalink filters
	 *
	 * @since 1.19.4
	 *
	 * @return void
	 */
	private function remove_url_hooks() {
		global $wpml_url_filters;

		if ( ! $wpml_url_filters ) {
			return;
		}

		// WPML 3.6.1 and lower does not have this method, avoid a fatal error.
		if ( method_exists( $wpml_url_filters, 'remove_global_hooks' ) ) {
			$wpml_url_filters->remove_global_hooks();
		} else {
			gravityview()->log->error( 'WPML missing remove_global_hooks method. Needs version 3.6.2+.' );
		}

		if ( true === $wpml_url_filters->frontend_uses_root() ) {
			remove_filter( 'page_link', array( $wpml_url_filters, 'page_link_filter_root' ), 1 );
		} else {
			remove_filter( 'page_link', array( $wpml_url_filters, 'page_link_filter' ), 1 );
		}
	}

	/**
	 * Add the WPML permalink filters back in
	 *
	 * @since 1.19.4
	 *
	 * @return void
	 */
	private function add_url_hooks() {
		global $wpml_url_filters;

		if ( ! $wpml_url_filters ) {
			return;
		}

		// WPML 3.6.1 and lower does not have this method, avoid a fatal error.
		if ( method_exists( $wpml_url_filters, 'add_global_hooks' ) ) {
			$wpml_url_filters->add_global_hooks();
		} else {
			gravityview()->log->error( 'WPML missing add_global_hooks method. Needs version 3.6.2+.' );
		}

		if ( true === $wpml_url_filters->frontend_uses_root() ) {
			add_filter( 'page_link', array( $wpml_url_filters, 'page_link_filter_root' ), 1, 2 );
		} else {
			add_filter( 'page_link', array( $wpml_url_filters, 'page_link_filter' ), 1, 2 );
		}
	}

	/**
	 * Modify the language links to fix /entry/ var from being stripped
	 *
	 * @since 1.19.4
	 *
	 * @param array $languages Array of active languages with their details
	 *
	 * @return array If currently a single entry screen, re-generate URL after removing WPML filters
	 */
	public function wpml_ls_filter( $languages ) {

		/**
		 * @global SitePress $sitepress
		 * @global WP_Post $post
		 * @global WPML_URL_Converter $wpml_url_converter
		 */
		global $sitepress, $post, $wpml_url_converter;

		if ( ! method_exists( $sitepress, 'get_setting' ) ) {
			gravityview()->log->error( 'This version of WPML is outdated and does not include the required method get_setting().' );

			return $languages;
		}

		$entry = gravityview()->request->is_entry();

		if ( ! $entry ) {
			return $languages;
		}

		$entry_slug = $entry->get_slug();

		$trid         = $sitepress->get_element_trid( $post->ID );
		$translations = $sitepress->get_element_translations( $trid );

		if ( ! $translations ) {
			return $languages;
		}

		$language_url_setting = $sitepress->get_setting( 'language_negotiation_type' );

		$this->remove_url_hooks();

		foreach ( $languages as $lang_code => $language ) {

			if ( ! isset( $translations[ $lang_code ] ) || ! is_object( $translations[ $lang_code ] ) ) {
				continue;
			}

			$lang_post_id = $translations[ $lang_code ]->element_id;

			$entry_link = GravityView_API::entry_link( $entry_slug, $lang_post_id );

			// How is WPML handling the language?
			switch ( intval( $language_url_setting ) ) {

				// Subdomains or directories
				case 1:
				case 2:
					// For sites using directories or sub-domains for languages, rewrite base URL
					$entry_link = $wpml_url_converter->convert_url( $entry_link, $lang_code );
					break;

				// URL Parameters
				case 3:
				default:
					if ( ! empty( $translations[ $lang_code ]->original ) ) {

						// The original language doesn't need a language parameter
						$entry_link = remove_query_arg( 'lang', $entry_link );

					} elseif ( $entry_link ) {

						// Every other language does
						$entry_link = add_query_arg( array( 'lang' => $lang_code ), $entry_link );
					}
					break;
			}

			$languages[ $lang_code ]['url'] = $entry_link;
		}

		$this->add_url_hooks();

		return $languages;
	}
}

new GravityView_Theme_Hooks_WPML();
