<?php 
/*
Plugin Name: Typekit for Redux Framework
Plugin URI: themes.develoved.com
Description: This is a plugin that is meant to add typekit integration to the Redux Framework for compatible themes by Develoved.
Version: 1.1.0
Author: develoved
Author URI: themes.develoved.com
Text Domain: dvl-redux-typekit
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

require_once( 'typekit-client.php' );


/**
 * Load plugin textdomain.
 */
function shrk_redux_typekit_load_textdomain() {
	load_plugin_textdomain( 'dvl-redux-typekit', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); 
}
add_action( 'init', 'shrk_redux_typekit_load_textdomain' );


if ( class_exists( 'typekit' ) && !class_exists( 'ReduxTypekit' ) ) {
	
	class ReduxTypekit extends Typekit {

		private $kit_id         = null;
		private $kit_enabled    = false;
		private $kit_async      = true;
		private $kit_fonts      = null;
		public  $kit_fonts_full = null;
		private $reduxInstance  = null;

		function __construct() {
			// Disregard WP AJAX 'heartbeat'call. Why waste resources?
			if ( isset ( $_POST ) && isset ( $_POST['action'] ) && $_POST['action'] == 'heartbeat' ) {
				// Buh bye!
				return;
			}

			add_action( 'init', array( $this, 'get_theme_options' ) );
			add_action( 'init', array( $this, 'check_for_webfontloader' ), 20 );

			add_action( 'wp_ajax_reduxtypekit_testkit', array( $this, 'refresh_test_kit') );
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_backend_scripts' ) );

			add_filter( 'redux/options/shrk_theme_options/sections', array( $this, 'add_options') );
			add_filter( 'redux/shrk_theme_options/field/typography/custom_fonts', array( $this, 'add_fonts_to_redux') );
			add_action( 'redux/loaded', array( $this, 'getInstance' ) );
		}

		/**
		 * Get the parent redux instance
		 */
		function getInstance( $redux ) {
			$this->reduxInstance = $redux;
		}

		/**
		 * get_theme_options setup object vars from theme options on init
		 * @return none
		 */
		function get_theme_options() {
			global $shrk_options;
			$this->kit_id      = isset( $shrk_options['typekit_kit_id'] ) ? $shrk_options['typekit_kit_id'] : null;
			$this->kit_enabled = isset( $shrk_options['typekit_module'] ) && $shrk_options['typekit_module'] == 1 ? true : false;
			$this->enqueue_fonts();

			if ( false === ( $this->kit_fonts = get_transient( 'typekit_kit_fonts' ) ) ) {
				$this->kit_fonts = $this->get_fonts_array();
				set_transient( 'typekit_kit_fonts', $this->kit_fonts, 24 * HOUR_IN_SECONDS );
			}

			if ( false === ( $this->kit_fonts_full = get_transient( 'typekit_kit_fonts_full' ) ) ) {
				$this->kit_fonts_full = $this->get_fonts_full_array();
				set_transient( 'typekit_kit_fonts_full', $this->kit_fonts_full, 24 * HOUR_IN_SECONDS );
			}
		}


		/**
		 * add_options adds typekit section in redux options
		 * @param [arr] $sections - redux sections
		 * @return [arr] modified sections
		 */
		function add_options( $sections ) {
			$sections[] = array(
				'title' => esc_html__( 'Typekit', 'dvl-redux-typekit' ),
				'icon' => 'el-icon-fontsize',
				'fields' => array(
					array(
						'id'      => 'typekit_module',
						'on'      => esc_html__( 'Enabled', 'dvl-redux-typekit' ),
						'off'     => esc_html__( 'Disabled', 'dvl-redux-typekit' ),
						'type'    => 'switch',
						'title'   => esc_html__( 'Enable Typekit module', 'dvl-redux-typekit' ),
						'default' => 0,
						),
					array(
						'id'                => 'typekit_kit_id',
						'type'              => 'text',
						'title'             => esc_html__( 'Typekit Kit ID', 'dvl-redux-typekit' ),
						'desc'              => esc_html__( 'After you have created your Typekit Kit, publish it, and enter here the Kit ID. ', 'dvl-redux-typekit' ),
						'required'          => array('typekit_module', '=', 1),
						'validate_callback' => 'shrk_typekit_validate_kit_id',
						'default'           => '',
						),
					array(
						'id'       => 'typekit_testkit_field',
						'type'     => 'callback',
						'title'    => esc_html__( 'Test your Kit', 'dvl-redux-typekit' ),
						'callback' => 'shrk_typekit_testkit_field',
						'desc'     => esc_html__( 'Please refresh the page after making changes to your kit.', 'dvl-redux-typekit' )
					),
					array(
						'id'      => 'hide_until_fonts_typekit',
						'on'      => esc_html__( 'Yes', 'dvl-redux-typekit' ),
						'off'     => esc_html__( 'No', 'dvl-redux-typekit' ),
						'type'    => 'switch',
						'title'   => esc_html__( 'Hide page until fonts are loaded', 'dvl-redux-typekit' ),
						'desc'    => esc_html__( 'Some browsers (like Chrome after version 50) load all external fonts asyncronously. In that case you can hide the page until the fonts have loaded in order to avoid the flash of unstyled text.', 'dvl-redux-typekit' ),
						'default' => 0,
						),


				),
			);
			return $sections;
		}


		/**
		 * add_fonts_to_redux get fonts array
		 * for current kit, +gets custom theme fonts
		 * and returns them. +enqueues fonts in backend
		 * Note: this is called in the frontend by redux 
		 * to determine if you have added a custom font, 
		 * so to exclude it from the typography object
		 * (which would try to load it from google)
		 *
		 * @return  [arr] fonts array
		 */
		function add_fonts_to_redux( $fonts = array() ) {
			if ( !$this->kit_enabled || empty($this->kit_fonts) || !is_array($this->kit_fonts) ) {
				return $fonts;
			}

			$fonts_label = esc_html__( 'Typekit Fonts', 'dvl-redux-typekit' );
			$fonts       = array_merge( $fonts, $this->kit_fonts );

			if ( function_exists( 'shrk_get_extra_fonts' ) ) {
				$fonts_label = esc_html__( 'Extra Fonts (inc. Typekit)', 'dvl-redux-typekit' );
				$extra_fonts = shrk_get_extra_fonts();
				$fonts = array_merge( $fonts, reset( $extra_fonts ) );
			}

			if ( is_array( $fonts ) ) {
				$this->enqueue_fonts_admin();
				return array( $fonts_label => $fonts );
			}
		}


		/**
		 * get_fonts_array gets fonts array for $kit_id or $this->kit_id
		 * in an array compatible with redux options
		 * 
		 * @param  string $kit_id optional
		 * @return [arr] fonts array
		 */
		function get_fonts_array( $kit_id = false ) {
			$force 	= $kit_id !== false ? true : false;
			$kit_id = $kit_id ? $kit_id : $this->kit_id;

			if ( !$kit_id ) {
				return false;
			}
			
			if ( $this->kit_enabled || $force ) {
				$kit = $this->get( $kit_id );
			}
			
			$ret = array();

			if ( isset( $kit['kit']['families'] ) ) {
				foreach ( $kit['kit']['families'] as $family ) {
					$slug = $family['slug'];
					$name = $family['name'];
					$ret[$slug] = $name;
				}
				return $ret;
			} else {
				return false;
			}
		}

		/**
		 * get_fonts_full_array gets fonts array for $kit_id or $this->kit_id
		 * in an array, includes variations
		 * 
		 * @param  string $kit_id optional
		 * @return [arr] fonts array
		 */
		function get_fonts_full_array( $kit_id = false ) {
			$force 	= $kit_id !== false ? true : false;
			$kit_id = $kit_id ? $kit_id : $this->kit_id;

			if ( !$kit_id ) {
				return false;
			}
			
			if ( $this->kit_enabled || $force ) {
				$kit = $this->get( $kit_id );
			}
			
			$ret = array();

			if ( isset( $kit['kit']['families'] ) ) {
				foreach ( $kit['kit']['families'] as $family ) {
					$ret[$family['slug']] = array(
						'name'       => $family['name'],
						'variations' => $this->parse_typekit_variations( $family['variations'] )
						);
				}
				return $ret;
			} else {
				return false;
			}
		}

		function parse_typekit_variations( $variations ) {
			$ret = array();

			foreach ($variations as $variation) {
				$s = substr($variation, 0, 1);
				$w = substr($variation, 1, 1);

				switch ($s) {
					case 'n':
						$style = 'normal';
						break;
					case 'i':
						$style = 'italic';
						break;
					default:
						$style = 'normal';
						break;
				}

				switch ($w) {
					case '1':
						$weight = '100';
						break;
					case '2':
						$weight = '200';
						break;
					case '3':
						$weight = '300';
						break;
					case '4':
						$weight = '400';
						break;
					case '5':
						$weight = '500';
						break;
					case '6':
						$weight = '600';
						break;
					case '7':
						$weight = '700';
						break;
					case '8':
						$weight = '800';
						break;
					case '9':
						$weight = '900';
						break;
					default:
						$weight = '400';
						break;
				}

				$ret[] = array(
					'style' => $style,
					'weight' => $weight
					);
			}

			return $ret;
		}

		/**
		 * render_status_text return report text
		 * about fonts returned for stored kit id
		 * 
		 * @return string HTML text
		 */
		function render_status_text() {
			$fonts = $this->kit_fonts_full;

			if ( !$this->kit_id ) {
				return esc_html__( 'Kit ID not set!', 'dvl-redux-typekit' );
			}

			if ( $fonts && is_array( $fonts ) ) {
				$output = sprintf( esc_html__( '%d font(s) found in kit [%s]', 'dvl-redux-typekit' ), count( $fonts ), $this->kit_id );
				$output .= '<ul>';
				foreach ( $fonts as $font) {
					$font_style_string = '';
					foreach ($font['variations'] as $variation) {
						$font_style_string .= implode(':', $variation) . ' ';
					}

					$output .= '<li>' . esc_html( $font['name'] . ' [' . $font_style_string . ']' ) . '</li>';
				}
				$output .= '</ul>';

				return $output;
			}

			return esc_html__( 'No fonts found.', 'dvl-redux-typekit' );
		}


		/**
		 * refresh_test_kit fires via ajax call,
		 * resets the font transient and returns the 
		 * status text with the found kit fonts
		 */
		function refresh_test_kit() {
			check_ajax_referer( 'shrk_nonce' );
			delete_transient( 'typekit_kit_fonts' );
			delete_transient( 'typekit_kit_fonts_full' );
			$this->kit_id         = $_POST['kit_id'];
			$this->kit_fonts      = $this->get_fonts_array( $_POST['kit_id'] );
			$this->kit_fonts_full = $this->get_fonts_full_array( $_POST['kit_id'] );
			echo $this->render_status_text();
			exit;
		}

		/**
		 * enqueue_fonts enqueue fonts in frontend.
		 * @return none
		 */
		function enqueue_fonts() {
			if ( !$this->kit_enabled || !$this->kit_id ) { return; }

			add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_async_js' ), 155 );
		}


		/**
		 * enqueue_fonts_admin enqueue fonts in backend
		 * @return none
		 */
		function enqueue_fonts_admin() {
			if ( !$this->kit_enabled || !$this->kit_id ) { return; }

			add_action( 'admin_footer', array( $this, 'enqueue_async_js' ), 30 );
		}


		/**
		 * enqueue_async_js echoes ASYNC typekit js
		 * @return echoes JS
		 */
		function enqueue_async_js() {

			// Handle Google fonts 
			if ( $this->reduxInstance ) {
				$typography = new ReduxFramework_typography( null, null, $this->reduxInstance );

				if ( ! empty ( $this->reduxInstance->typography ) ) {
					$families = array();
					foreach ( $this->reduxInstance->typography as $key => $value ) {
						$families[] = $key;
					}

					$google_script = 'var WebFontConfig = WebFontConfig || {}; WebFontConfig[\'google\'] = {families: [' . $typography->makeGoogleWebfontString ( $this->reduxInstance->typography ) . ']};';
					wp_add_inline_script( 'shrk-theme-js', $google_script, 'before' );
				}
			}

			// Add typekit kit id
			$script = 'var WebFontConfig = WebFontConfig || {}; WebFontConfig[\'typekit\'] = { id: \'' . esc_js($this->kit_id) . '\' };';
			wp_add_inline_script( 'shrk-theme-js', $script, 'before' );
		}

		function enqueue_webfontloader() {
			ob_start(); ?>
				var WebFontConfig = WebFontConfig || {};
				WebFontConfig['events'] = true;
				WebFontConfig['timeout'] = 5000;
				WebFontConfig['active'] = function() {
					if ( typeof ( window.jQuery ) !== 'undefined' ) {
						jQuery(window).trigger('shrk_async_fonts_active');
					}
				};
				WebFontConfig['inactive'] = function() {
					if ( typeof ( window.jQuery ) !== 'undefined' ) {
						jQuery(window).trigger('shrk_async_fonts_inactive');
					}
				};

				(function(d) {
					var wf = d.createElement('script'), s = d.scripts[0];
					wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.16/webfont.js';
					s.parentNode.insertBefore(wf, s);
				})(document);
			<?php 
			$script = ( ob_get_clean() );
			wp_add_inline_script( 'shrk-theme-js', $script, 'before' );
		}


		/**
		 * Only way to get in before redux's 
		 * webfont.js init routine.
		 */
		function set_callbacks_notypekit() {
			?>
			<script type="text/javascript">
			var WebFontConfig = WebFontConfig || {};
			WebFontConfig['active'] = function() {
				if ( typeof ( window.jQuery ) !== 'undefined' ) {
					jQuery(window).trigger('shrk_async_fonts_active');
				}
			};
			WebFontConfig['inactive'] = function() {
				if ( typeof ( window.jQuery ) !== 'undefined' ) {
					jQuery(window).trigger('shrk_async_fonts_inactive');
				}
			};
			</script>
			<?php
		}
		

		function check_for_webfontloader( $redux ) {
			if ( !$this->kit_enabled || !$this->kit_id ) { 
				add_action('wp_enqueue_scripts', array( $this, 'set_callbacks_notypekit'), 145); // Webfont.js enqueued at wp_enqueue_scripts::150
				return; 
			}

			if ( $this->reduxInstance->args['async_typography'] === true ) {
				add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_webfontloader' ), 160); // Webfont.js enqueued at wp_enqueue_scripts::150
			}

			// Stop redux from handing fonts
			$this->reduxInstance->args['async_typography']          = false;
			$this->reduxInstance->args['disable_google_fonts_link'] = true;
		}

		/**
		 * enqueue_backend_scripts
		 */
		function enqueue_backend_scripts() {
			wp_enqueue_script( 'shrk-redux-typekit-js', plugin_dir_url( __FILE__ ) . 'js/typekit.min.js', array( 'jquery' ), false, false );

			if ( $this->kit_enabled && !empty( $this->kit_fonts ) ) {
				wp_localize_script( 'shrk-redux-typekit-js', 'redux_typekit', array( 
					'fonts' => $this->kit_fonts
				) );
			}
		}

	}

	new ReduxTypekit;
}

if (!function_exists('shrk_typekit_validate_kit_id')) {
	/**
	 * Helper used in redux post action
	 * to validate kit_id
	 * 
	 * @param  [type] $field
	 * @param  [type] $value
	 * @param  [type] $existing_value
	 * @return [object]
	 */
	function shrk_typekit_validate_kit_id( $field, $value, $existing_value ) {
		global $shrk_options;
		$tk = new ReduxTypekit;
		$error = false;

		delete_transient( 'typekit_kit_fonts' );

		if ( $shrk_options['typekit_module'] == 1 && !$tk->get_fonts_array( $value ) ) {
			$error = true;
			$value = $existing_value;
			$field['msg'] = esc_html__( 'The kit ID you entered is not valid. Make sure you have entered it correctly, and you have published it. Also note, it may take some minutes for a newly published kit to be available.', 'dvl-redux-typekit' );
		} 
		
		$return['value'] = $value;
		if ( $error == true ) {
		    $return['error'] = $field;
		}
		return $return;
	}
}

if ( ! function_exists( 'shrk_typekit_testkit_field' ) ) {
	/**
	 * Helper for custom typekit field
	 */
	function shrk_typekit_testkit_field( $field, $value ) {
		?>
		<fieldset id="redux-option_<?php echo $field['id']; ?>" class="redux-field-container redux-field redux-field-init redux-container-text " data-id="typekit_kit_id" data-type="text">
			<a href="#" id="typekit-testkit-button" class="button-primary"><?php echo esc_html__( 'Refresh & show kit fonts', 'dvl-redux-typekit' ); ?></a><span class="spinner" ></span>
			<div id="typekit-testkit-output" class="redux-normal redux-info-field redux-field-info" style="display: none;"><p class="redux-info-desc"></div>
			<div class="description field-desc"><?php echo $field['desc']; ?></div>
		</fieldset>
		<?php
	}
}

?>