<?php
/*
	Author: t31os_
	Description: Create jQuery UI tabs inside the post editor using shortcodes
	Domain Path: /lang
	Plugin Name: Post UI Tabs
	Plugin URI: 
	Text Domain: post-ui-tabs
	Version: 1.0.5
*/

if( !function_exists( 'add_action' ) ) {
	header('Status: 403 Forbidden');
	header('HTTP/1.1 403 Forbidden');
	exit;
}
if( version_compare( PHP_VERSION, '5.0.0', '<' ) ) {
	add_action( 'admin_notices', 'put_version_require' );
	function put_version_require() {
		if( current_user_can( 'manage_options' ) )
			echo '<div class="error"><p>The Post Tabs UI plugin requires at least PHP 5.</p></div>';
	}
	return;
}

class Post_UI_Tabs {
	
	private $options;
	private $skin_dir;
	private $pagehook;
	private $ui_version = '1.8.15';
	private $version    = '1.0.5';
	private $textdom    = 'post-ui-tabs';
	private $opt_group  = 'post-ui-tabs_group';
	private $opt_name   = 'post-ui-tabs_settings';
	private $config   = array();
	private $tabs     = array();
	private $empties  = array();
	private $skins    = array( 
		'base', 'black-tie', 'blitzer', 'cupertino', 'dark-hive', 
		'dot-luv', 'eggplant', 'excite-bike', 'flick', 'hot-sneaks', 
		'humanity', 'le-frog', 'mint-choc', 'overcast', 'pepper-grinder', 
		'redmond', 'smoothness', 'south-street', 'start', 'sunny', 
		'swanky-purse', 'trontastic', 'ui-darkness', 'ui-lightness', 'vader' 
	);
	private $index    = 1;
	private $set      = 1;
	public $has_tabs = false;
	private $is_feed  = false;
	
	// For testing
	public function switch_locale( $locale ) {
		$locale = 'TESTLOCALE';
		return $locale;
	}
	
	public function __construct() {
		
		#add_filter( 'plugin_locale' ,      array( $this , 'switch_locale' ) ); // Quick way to fake locale
		add_action( 'admin_menu',          array( $this, 'on_admin_menu' ) );
		add_action( 'admin_init',          array( $this, 'on_admin_init' ) );
		
		$this->config   = get_option( $this->opt_name );
		
		$this->skin_dir = apply_filters( 'post_ui_tabs_dir', 'http://ajax.googleapis.com/ajax/libs/jqueryui/' . $this->ui_version . '/themes' );
		$this->skins    = apply_filters( 'post_ui_tabs_skins', $this->skins );
		
		if( !is_admin() )
			// Only check for shortcode on non-admin pages
			add_action( 'the_posts',        array( $this, 'on_the_posts' ) );
			
		add_filter( 'the_content',         array( $this, 'on_the_content' ), 7 ); // Priority 7 - ie. before wpautop at priority 8
		
		add_action( 'wp_enqueue_scripts',  array( $this, 'on_wp_enqueue' ) );
		add_action( 'wp_footer',           array( $this, 'on_wp_footer' ) );

	}
	public function on_admin_menu() {
		
		$this->pagehook = add_options_page( 'Post UI Tabs', 'Post UI Tabs', 'manage_options' , 'post-ui-tabs', array( $this, 'on_settings_page' ) );
		
		add_action( "admin_enqueue_scripts",                array( $this, 'on_admin_enqueue' ) ); // Ideal for both scripts and styles
		add_action( "admin_print_styles-{$this->pagehook}", array( $this, 'on_plugin_styles' ) ); // CSS specifically for the plugin config page
	}
	public function on_admin_init() {
		
		global $plugin_page;
		
		register_setting( $this->opt_group, $this->opt_name, array( $this, 'on_plugin_save' ) );
		
		if( 'post-ui-tabs' == $plugin_page )
			load_plugin_textdomain( $this->textdom, false, basename( dirname( __FILE__ ) ) . '/lang' );
			
		// The plugin options(needs to defined here so the sanitization function has access to the data)
		$this->options = array(
			'skin'           => array( 
				'type'        => 'dropdown', 
				'name'        => __( 'Choose a UI skin', $this->textdom ), 
				'desc'        => __( 'Select a skin', $this->textdom ),
				'label'       => __( 'Select which jQuery UI skin to apply to the tabs - ignored if skins have been disabled', $this->textdom ),
				'options'     => $this->skins
			),
			'disable_css'    => array( 
				'type'        => 'checkbox', 
				'name'        => __( 'Disable skins', $this->textdom ), 
				'desc'        => __( 'Disable the plugin stylesheet', $this->textdom ),
				'label'       => __( 'Enable this option if you want to define your own CSS for the tabs', $this->textdom )
			),
			'use_cookies'    => array( 
				'type'        => 'checkbox', 
				'name'        => __( 'Enable jQuery cookies', $this->textdom ), 
				'desc'        => __( 'Should the script be included', $this->textdom ),
				'label'       => __( 'Enable the jquery cookie script to remember selected tabs.', $this->textdom )
			),
			'on_archives'    => array( 
				'type'        => 'checkbox', 
				'name'        => __( 'Enable tabs for archives', $this->textdom ), 
				'desc'        => __( 'Use tabs on more pages', $this->textdom ),
				'label'       => __( 'Whether to enable tabs on non-single pages, such as category archives, date archives, the index and so on.', $this->textdom )
			),
			'show_nav'       => array( 
				'type'        => 'checkbox', 
				'name'        => __( 'Enable tab navigation', $this->textdom ), 
				'desc'        => __( 'Next and previous links', $this->textdom ),
				'label'       => __( 'Enabling this feature adds next and previos tabs links to all tab sets', $this->textdom )
			),
			'disable_empty'  => array( 
				'type'        => 'checkbox', 
				'name'        => __( 'Use disabled tabs', $this->textdom ), 
				'desc'        => __( 'Disable empty tabs', $this->textdom ),
				'label'       => __( 'Using this option will prevent users being able to click on empty tabs', $this->textdom )
			),
			'rw_feed_html'   => array( 
				'type'        => 'checkbox', 
				'name'        => __( 'Rewrite feed HTML', $this->textdom ), 
				'desc'        => __( 'Replace tabs and content with headings and paragraphs', $this->textdom ),
				'label'       => __( 'If this option is not enabled tabs are removed from feeds', $this->textdom )
			)
		);
	}
	public function on_the_posts( $posts ) {
		
		if( is_feed() )
			$this->is_feed = true;
		
		if( empty( $posts ) || $this->has_tabs )
			return $posts;
			
		if( !$this->get_plugin_option( 'on_archives' ) && !is_singular() )
			return $posts;

		foreach( $posts as $post ) {
			if( !stripos( $post->post_content, '[end_tabset]' ) )
				continue;
			$this->has_tabs = true;
		}
	
		return $posts;
	}
	public function on_the_content( $content ) {
		
		if( !$this->has_tabs )
			return $content;
			
		global $shortcode_tags;

		// Backup current registered shortcodes and clear them all out
		$orig_shortcode_tags = $shortcode_tags;
		$shortcode_tags = array();

		add_shortcode( 'tab',              array( $this, 'on_tab_shortcode' ) );
		add_shortcode( 'end_tabset',       array( $this, 'on_tab_end_shortcode' ) );

		// Do the shortcode (only the one above is registered)
		$content = do_shortcode( $content );

		// Put the original shortcodes back
		$shortcode_tags = $orig_shortcode_tags;

		return $content;
	}
	public function on_wp_footer() {
		
		if( !$this->has_tabs || $this->is_feed )
			return;
		
		$script_deps = array( 'jquery-ui-core', 'jquery-ui-tabs' );
		
		$tab_settings = array();
		$tab_settings['total'] = $this->set - 1;
		
		if( $this->get_plugin_option( 'use_cookies' ) ) {
			$script_deps[] = 'jquery-cookie';
			wp_register_script( 'jquery-cookie', plugins_url( '/js/cookie.js', __FILE__ ), array(), null );
			$tab_settings['use_cookies'] = 1;
		}
		
		if( $this->get_plugin_option( 'disable_empty' ) )
			foreach( $this->empties as $set => $empty_keys )
				$tab_settings[$set] = implode( ',', $empty_keys );
		
		wp_register_script( 'post-ui-tabs', plugins_url( '/js/post-ui-tabs.js', __FILE__ ), $script_deps, $this->version, true );
		wp_localize_script( 'post-ui-tabs', 'tab_settings', $tab_settings );
		wp_print_scripts( 'post-ui-tabs' );
	}
	public function on_wp_enqueue() {
		
		if( !$this->has_tabs || $this->is_feed )
			return;
		
		if( $this->get_plugin_option( 'disable_css' ) )
			return;
		
		if( $this->get_plugin_option( 'skin' ) ) {
			$skin = $this->get_plugin_option( 'skin' );
			if( in_array( $skin, $this->skins ) )
				wp_enqueue_style( 'jquery-ui-tabs', "{$this->skin_dir}/$skin/jquery.ui.all.css", array(), '1.8.11' );
		}
	}
	public function on_settings_page() {
	?>
	<div class="wrap">
		<h2><?php _e( 'Post UI Tabs', $this->textdom ); ?></h2>
		<p class="description"><?php _e( 'Welcome to the Post UI Tabs plugin configuration page.', $this->textdom ) ?></p>
		<form method="post" action="options.php" >
			<table class="form-table">
				<tbody>
					<?php $this->plugin_rows(); ?>
				</tbody>
			</table>
			<p class="submit">
				<?php settings_fields( $this->opt_group ); ?>
				<input type="submit" name="submit" class="button-secondary action" value="<?php _e( 'Save', $this->textdom ) ?>" />
			</p>
		</form>
		<?php if( !$this->get_plugin_option( 'disable_css' ) ) $this->style_preview(); ?>
	</div>
	<?php
	}
	public function on_tab_shortcode( $atts, $content = null ) {
		global $post;
		
		$id = ( is_admin() ) ? '9999999999999' : $post->ID;
			
		// Remove any leading/trailing whitespace
		$content = trim( $content );
		
		$this->tabs[$id][$this->index] = shortcode_atts( array( 'name' => 'Tab ' . $this->index ), $atts );
		$this->tabs[$id][$this->index]['content'] = !empty( $content ) ? $content : '';
		
		$this->index++;
		
		unset( $atts, $content );
		
		return '';
	}
	public function on_tab_end_shortcode() {
		global $post;
		
		$id = ( is_admin() ) ? '9999999999999' : $post->ID;
		
		if( !isset( $this->tabs[$id] ) )
			return '';
		
		if( !$this->has_tabs )
			return '';
		
		if( $this->get_plugin_option( 'show_nav' ) && !is_admin() ) {
			
			$next_text    = apply_filters( 'post_ui_tabs_next', 'Next' );
			$prev_text    = apply_filters( 'post_ui_tabs_prev', 'Previous' );
			
			$next_classes = apply_filters( 'post_ui_tabs_class', array( 'ui-icon', 'ui-icon-circle-triangle-e' ), 'next' );
			$prev_classes = apply_filters( 'post_ui_tabs_class', array( 'ui-icon', 'ui-icon-circle-triangle-w' ), 'prev' );
			
			$next_classes = array_map( 'esc_attr', $next_classes );
			$prev_classes = array_map( 'esc_attr', $prev_classes );
			
			array_push( $next_classes, 'alignright', 'put-next' );
			array_push( $prev_classes, 'alignleft',  'put-prev' );
			
			$next_classes = join( ' ', $next_classes );
			$prev_classes = join( ' ', $prev_classes );
		}
		//$this->has_tabs = true;
		
		$tab_html    = 
		$box_html    = 
		$before_html =
		$after_html  = '';
		
		if( !$this->is_feed ) {
			$before_html  = "<div id='".$this->get_tab_id()."'>";
			
			if( $this->get_plugin_option( 'show_nav' ) && !is_admin() )
				$after_html   .= '<div class="put-nav">'. $this->get_nav_link( $next_classes, $next_text ) . $this->get_nav_link( $prev_classes, $prev_text ) . "<br style='clear:both;' /></div>";
			
			$after_html  .= '</div>';
		}
		// Store tabs
		$tabs = $this->tabs[$id];
		
		// Unset class property ready for the next set iteration
		unset( $this->tabs[$id] );
		
		if( $this->is_feed ) {
			
			foreach( $tabs as $index => $tab ) 
				$tab_html .= !empty( $tab['content'] ) 
					? $this->tab_list_item( $index, esc_html( $tab['name'] ), true ) . $this->tab_box_item( $index, $tab['content'], true ) 
					: ''; // Remove tab names from feeds if the content is empty
		}
		else {
			
			$hide_empty = ( $this->get_plugin_option( 'disable_empty' ) ) ? true : false;

			foreach( $tabs as $index => $tab ) {
				$tab_html .= $this->tab_list_item( $index, esc_html( $tab['name'] ) ); // No HTML in tab names
				$box_html .= $this->tab_box_item( $index, $tab['content'] ); 
				
				if( $hide_empty && empty( $tab['content'] ) )
					$this->empties[$this->set][] = $index;	
			}
			$tab_html = '<ul>' . $tab_html . '</ul>';
		}

		
		// Reset the index
		$this->index = 1;
		// Increment the set index
		$this->set++;
		
		return $before_html . $tab_html . $box_html . $after_html;
	}
	private function get_plugin_option( $name ) {
		
		if( !isset( $this->config[$name] ) )
			return false;
		
		if( empty( $this->config[$name] ) || !$this->config[$name] )
			return false;
		
		return $this->config[$name];
	}
	private function get_tab_id( $index = '' ) {
		
		if( !empty( $index ) )
			$index = "-$index";
		
		return "tabs-{$this->set}{$index}";
	}
	private function get_nav_link( $classes, $text ) {
		return sprintf( '<a href="#%s" class="%s">%s</a>', $this->get_tab_id(), $classes, $text );
	}
	private function tab_list_item( $index, $name, $feed = false ) {
		return $feed ? sprintf( '<h3>%s</h3>', $name ) : sprintf( '<li><a href="#%s">%s</a></li>', $this->get_tab_id( $index ), $name );
	}
	private function tab_box_item( $index, $content, $feed = false ) {
		return $feed ? sprintf( '<div>%s</div>', $content ) : sprintf( '<div id="%s"><p>%s</p></div>', $this->get_tab_id( $index ), $content );
	}
	private function plugin_rows() {
		foreach( $this->options as $name => $data )
			$this->plugin_field( $name, $data ); 
	}
	private function plugin_field( $input_name, $properties ) {
		
		$current = $this->get_plugin_option( $input_name );
		
		$row = "<tr>";

		switch( $properties['type'] ) {
			case 'checkbox':
				
				$row .= sprintf( '<th scope="row">%s<p class="description">%s</p></th>', $properties['name'], $properties['desc'] );
				$row .= sprintf( "<td><input type='checkbox' name='%s[%s]' value='1'%s /> ", $this->opt_name, $input_name, checked( $current, true, false ) );
				$row .= sprintf( '<label for="%s-%s">%s</label></td>', $this->opt_name, $input_name, $properties['label'] );

			break;
			case 'dropdown':
				
				$row .= sprintf( '<th scope="row">%s<p class="description">%s</p></th>', $properties['name'], $properties['desc'] );
				$row .= sprintf( '<td><select name="%s[%s]">', $this->opt_name, $input_name );

				foreach( $properties['options'] as $option ) 
					$row .= sprintf( '<option%s>%s</option>', selected( $option == $current, true, false ), $option );
				
				$row .= sprintf( '</select><br /><label for="%s-%s">%s</label></td>', $this->opt_name, $input_name, $properties['label'] );		
				
			break;
		}
		$row .= "</tr>";
		
		echo $row;
	}
	public function on_plugin_styles() {
		?>
		<style type="text/css">
		form { width: 55%;float:left }
		.ui-tabs.ui-widget { width: 40%;float:right }
		</style>
		<?php
	}
	public function on_admin_enqueue( $hook ) {
		
		if( $this->pagehook != $hook )
			return;
		
		if( $this->get_plugin_option( 'disable_css' ) || empty( $this->config ) )
			return;
		
		$script_parameters   = array_merge( array( 0 => '', 'skin_dir' => $this->skin_dir ), $this->skins );
		$script_dependancies = array( 'jquery-ui-core', 'jquery-ui-tabs' );
		
		wp_enqueue_script(  'post-ui-tabs', plugins_url( '/js/demo.js', __FILE__ ), $script_dependancies, $this->version, true );
		wp_localize_script( 'post-ui-tabs', 'skins', $script_parameters );
			
		$skin = $this->get_plugin_option( 'skin' );
		
		if( !$skin )
			return;
		
		if( in_array( $skin, $this->skins ) )
			wp_enqueue_style( 'jquery-ui-tabs', "{$this->skin_dir}/$skin/jquery.ui.all.css", array(), $this->ui_version );
	}
	public function on_plugin_save( $_post_data ) {
		
		if( empty( $_post_data ) || !is_array( $_post_data ) )
			return array();
		
		$clean = array();
		$_post_data = array_map( 'trim', $_post_data );
		
		foreach( $_post_data as $option_name => $option_value ) {
			
			if( !isset( $this->options[$option_name] ) )
				return $this->config;
			
			switch( $this->options[$option_name]['type'] ) {
				case 'checkbox':
					$clean[$option_name] = 1;
				break;
				case 'dropdown':
					foreach( $this->options[$option_name]['options'] as $valid_option ) {
						if( $option_value != $valid_option )
							continue;
						$clean[$option_name] = $valid_option;
					}
				break;
			}
		}
		return $clean;
	}
	private function style_preview() {
		
		$this->has_tabs = true;
		
		add_shortcode( 'tab',              array( $this, 'on_tab_shortcode' ) );
		add_shortcode( 'end_tabset',       array( $this, 'on_tab_end_shortcode' ) );
		
		echo do_shortcode( '
			[tab]'.$this->sample_text(0).'[/tab] 
			[tab]'.$this->sample_text(1).'[/tab] 
			[tab]'.$this->sample_text(2).'[/tab] 
			[end_tabset]
		' );
		
		remove_shortcode( 'tab' );
		remove_shortcode( 'end_tabset' );
		
		$this->has_tabs = false;
	}
	private function sample_text( $key ) {
		$sample_text = array( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sem justo, lobortis mollis rutrum non, imperdiet vel eros. Morbi ut libero odio. Donec metus mauris, scelerisque sed consequat at, rutrum id lacus. Nam consectetur elit nec mi tristique condimentum fermentum nisi dictum. Sed sed ligula urna. Ut tellus dui, sollicitudin et congue eget, auctor eu felis. Duis interdum odio eu metus tristique quis porttitor leo eleifend. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla facilisi. Nam mattis pulvinar sapien et porttitor. Nam et nibh ac dui convallis interdum. Fusce ornare volutpat metus, quis consectetur ipsum tempor a. Integer in velit vitae erat venenatis laoreet vitae eu tortor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris eu nunc at urna luctus convallis. Vestibulum et dolor imperdiet ligula placerat ornare.
<br /><br />
Mauris et justo augue. Quisque tempor nisl eu lorem varius pharetra. Donec sed lacus nisl, non ultricies erat. Cras posuere fringilla enim, eu porttitor sapien condimentum adipiscing. Pellentesque elementum velit nec turpis blandit nec aliquet nunc suscipit. Phasellus suscipit sapien a ipsum gravida quis consectetur leo semper. Ut faucibus dui et velit tincidunt eget adipiscing augue posuere. Sed eu consectetur lorem. Donec vulputate, metus vel scelerisque pharetra, felis ligula pellentesque metus, vel vestibulum dui nulla vulputate nibh. Vivamus venenatis, neque eget pharetra facilisis, ligula diam iaculis tortor, at vehicula mi tortor interdum purus. Nulla sodales congue nisi nec blandit. Donec lacinia condimentum tellus ut tincidunt. Nunc eleifend, purus ac facilisis ornare, urna justo accumsan dolor, nec laoreet ligula tortor non metus.', 'Nulla facilisi. Sed eget orci id nibh sagittis facilisis. Proin nec pulvinar ante. Donec dignissim pretium ipsum, pulvinar vulputate sem volutpat ac. Donec hendrerit est eu eros laoreet sagittis. Duis vel viverra ipsum. Nam sit amet lectus risus. Pellentesque quis ante bibendum nisi sollicitudin tempor. Aliquam orci nulla, pharetra in scelerisque et, imperdiet id massa. Pellentesque nec dolor et nulla gravida pretium at quis nisl. Nullam venenatis ultrices nunc nec mattis. Maecenas consectetur tempor erat nec commodo. Phasellus ac porttitor nulla. Morbi malesuada urna id nisl egestas vel tempus tellus pharetra. Vestibulum a augue sit amet tellus interdum dictum vitae ac ante. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam sodales, tellus non convallis fermentum, neque sem vehicula nibh, eu dictum libero nulla sed justo. In vitae volutpat odio. Etiam sollicitudin nibh et erat scelerisque a mollis mi eleifend.
<br /><br />
Donec dui purus, vulputate ac pulvinar ut, tincidunt ut eros. Praesent sit amet nisl odio. Nulla id augue augue. Phasellus placerat sollicitudin lorem eu placerat. Fusce tincidunt nisi sed arcu tincidunt ut suscipit lorem viverra. Praesent urna libero, laoreet eu rhoncus vitae, elementum at leo. Quisque ut magna urna, eu tempor arcu. Nullam massa tellus, feugiat in posuere vitae, vulputate ac justo. Maecenas et molestie massa. Donec lectus eros, cursus at posuere sed, semper id erat. Mauris eget mi magna.', 'Mauris tristique fringilla dictum. Vivamus pulvinar neque sed magna sagittis molestie. Ut fermentum sem at mi lacinia dictum. Mauris sed adipiscing justo. Nulla a ornare massa. Sed felis orci, venenatis at gravida ac, feugiat vel elit. Praesent fringilla, lectus a fringilla rhoncus, urna leo gravida magna, at porta justo metus eget nisl. Integer porta enim ut velit luctus nec condimentum velit feugiat. Pellentesque elementum convallis molestie. Aliquam mattis ligula at libero rhoncus vehicula. Vestibulum in erat id nunc tincidunt elementum ac eu metus. Pellentesque sit amet odio metus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc congue malesuada felis at euismod. Cras mattis ullamcorper neque, vitae tristique urna blandit in. Donec volutpat tempus lorem nec mattis. Cras fermentum sollicitudin ipsum et convallis. Donec sollicitudin tempus nisi, malesuada interdum arcu posuere vel. Duis sit amet magna purus, dignissim lobortis ipsum. Quisque at pellentesque justo.
<br /><br />
Maecenas non volutpat nulla. Duis placerat aliquam odio, at rhoncus tellus faucibus nec. Integer vitae erat nisi. Sed congue ante eget libero ultricies rutrum vestibulum quam pellentesque. Proin molestie tristique nisi, a fringilla nulla mollis in. Nullam faucibus imperdiet dignissim. Proin nec nisl libero, id mollis nisl. Vivamus varius dignissim augue, eu facilisis augue cursus non. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vestibulum eget est vitae nulla aliquam scelerisque mattis at turpis. Nunc dignissim consectetur facilisis. Mauris magna eros, cursus eu vestibulum sed, pretium sit amet lectus. Nam quis enim magna, venenatis venenatis metus. Integer pharetra auctor ipsum, quis suscipit velit lacinia quis. Aliquam non eros in felis sollicitudin mattis nec non felis. Nullam consequat elementum pharetra. Quisque nunc augue, auctor a fermentum sed, congue consequat nulla. ' );
		return $sample_text[$key];
	}
}

$Post_UI_Tabs = new Post_UI_Tabs;