<?php

/**
 * @package anno
 * This file is part of the Annotum theme for WordPress
 * Built on the Carrington theme framework <http://carringtontheme.com>
 *
 * Copyright 2008-2015 Crowd Favorite, Ltd. All rights reserved. <http://crowdfavorite.com>
 * Released under the GPL license
 * http://www.opensource.org/licenses/gpl-license.php
 */

/**
 * Set acceptable custom tags for wp_kses
 */
$allowedposttags = array_merge($allowedposttags, array(
	'alt-text' => array(),
	'attrib' => array(),
	'bold' => array(),
	'cap' => array(),
	'copyright-statement' => array(),
	'copyright-holder' => array(),
	'disp-quote' => array(),
	'ext-link' => array(
		'type' => array(),
		'xlink:href' => array(),
		'title' => array(),
	),
	'fig' => array(),
	'inline-graphic' => array(
		'xlink:href' => array(),
	),
	'heading' => array(),
	'italic' => array(),
	'lbl' => array(),
	'license' => array(
		'license-type' => array(),
	),
	'license-p' => array(),
	'list' => array(
		array('list-type'),
	),
	'list-item' => array(),
	'long-desc' => array(),
	'media' => array(
		'xlink:href' => array(),
	),
	'monospace' => array(),
	'para' => array(),
	'preformat' => array(),
	'permissions' => array(),
	'sec' => array(),
	'title' => array(),
	'table-wrap' => array(),
	'underline' => array(),
	'uri' => array(
		'xlink:href' => array(),
	),
	'xref' => array(
		'ref-type' => array(),
		'rid' => array(),
	),
	'br' => array(),
));


/**
 * Load the editor and corresponding textarea the WP 3.3 way
 */
function anno_load_editor($content, $editor_id, $settings = array()) {
	$formats = array(
		'bold',
		'italic',
		'monospace',
		'preformat',
		'sup',
		'sub',
		'underline',
	);

	$extended_valid_elements = array_merge(array(
		'alt-text',
		'attrib',
		'cap',
		'copyright-statement',
		'copyright-holder',
		'disp-quote',
		'ext-link[ext-link-type:uri|xlink::href|title]',
		'fig',
		'heading',
		'inline-graphic[xlink::href]',
		'lbl',
		'license[license-type:creative-commons]',
		'license-p',
		'list[list-type]',
		'list-item',
		'long-desc',
		'media[xlink::href]',
		'monospace',
		'permissions',
		'para',
		'preformat',
		'sec',
		'table-wrap',
		'uri[xlink::href]',
		'xref[ref-type|rid]',
		'paste',
		'*[*]',
	), $formats);

	$custom_elements = array(
		'~bold',
		'~italic',
		'~sup',
		'~sub',
		'~monospace',
		'preformat',
		'~underline',
		'~ext-link',
		'~xref',
		'~inline-graphic',
		'~alt-text',
		'~lbl',
		'~long-desc',
		'~copyright-statement',
		'~copyright-holder',
		'~license',
		'~license-p',
		'~disp-quote',
		'~attrib',
		'heading',
		'sec',
		'list',
		'list-item',
		'fig',
		'title',
		'media',
		'permissions',
		'table-wrap',
		'cap',
		'disp-quote',
		'para',
		'paste',
		'uri',
		// Support for isBlock being case sensitive and nodeName returning capitalized version
		// tinymce 4.x+ no longer supports tinymce.html.Schema modifiction in plugin init (old way)
		'PARA',
		'CAP',
		'LABEL',
		'LIST',
		'LIST-ITEM',
	);

	$formats_as_children = implode('|', $formats);

	// Note the various html elements not defined by the DTD
	// This takes into account imported content and pasted content which gets inserted natively in divs and spans
	// BR accounts for being able to actually insert a line break, we handle removing or keep these later.
	$valid_children = array(
		'preformat[]',
		'body[sec|para|media|list|disp-formula|disp-quote|fig|table-wrap|preformat|div|span|heading|br]',
		'copyright-statement['.$formats_as_children.'|br]',
		'license-p['.$formats_as_children.'|xref|ext-link|br]',
		'heading['.$formats_as_children.'|div|span|br]',
		'media[uri|alt-text|long-desc|permissions|div|span|br]',
		'permissions[copyright-statement|copyright-holder|license|div|span|br]',
		'license[license-p|xref|div|span|br]',
		'license-p[preformat|br|'.$formats_as_children.']',
		'list[title|list-item|div|span|br]',
		'list-item[para|xref|list|div|span|br]',
		'disp-formula[lbl|tex-math|div|span|preformat|br]',
		'disp-quote[p|attrib|permissions|div|span|preformat|br]',
		'fig[lbl|cap|media|img|div|span|preformat|br]',
		'cap[title|para|xref|div|span|br]',
		'table-wrap[lbl|cap|table|table-wrap-foot|permissions|div|span|preformat|br]',
		'table-wrap-foot[para|div|span|br]',
		'td['.$formats_as_children.'|preformat|ext-link|break|list|media|inline-graphic|xref|br|span]',
		'th['.$formats_as_children.'|preformat|ext-link|break|list|media|inline-graphic|xref|br|span]',
		'para['.$formats_as_children.'|media|img|permissions|license|list|list-item|disp-formula|disp-quote|fig|cap|table-wrap|table-wrap-foot|table|h2|xref|img|table|ext-link|paste|div|span|div|span|a|br]',
		'sec[sec|heading|media|img|permissions|license|list|list-item|disp-formula|disp-quote|fig|cap|table-wrap|table-wrap-foot|para|h2|div|span|preformat|br]',
	);

	$default_settings = array(
		'wpautop' => false,
		'media_buttons' => false,
		'tinymce' => array(
			'remove_linebreaks' => false,
			'valid_elements' => '*[*]',
			'extended_valid_elements' => implode(',', $extended_valid_elements),
			'custom_elements' => implode(',', $custom_elements),
			'valid_children' => implode(',', $valid_children),
			//  Defines formats.
			'formats' => "{
				bold : {'inline' : 'strong', 'classes': 'bold', 'attributes' : {'data-xmlel' : 'bold'}, 'remove' : 'all', merge_siblings : false, exact : true},
				italic : {'inline' : 'em', 'classes': 'italic', 'attributes' : {'data-xmlel' : 'italic'}, 'remove' : 'all', merge_siblings : false, exact : true},
				monospace : {'inline' : 'tt', 'classes': 'monospace', 'attributes' : {'data-xmlel' : 'monospace'}, 'remove' : 'all', exact : false},
				preformat : {'block' : 'div', 'classes': 'preformat', 'attributes' : {'data-xmlel' : 'preformat'}, 'remove' : 'all'},
				underline : {'inline' : 'u', 'classes': 'underline', 'attributes' : {'data-xmlel' : 'underline'}, 'remove' : 'all'},
				superscript : {'inline' : 'sup', 'attributes' : {'data-xmlel' : 'sup'}, 'remove' : 'all', exact : false},
				subscript : {'inline' : 'sub', 'attributes' : {'data-xmlel' : 'sub'}, 'remove' : 'all', exact: false}
			}",
			'forced_root_block' => '',
			'debug' => 'true',
			'verify_html' => true,
			'force_p_newlines' => true,
			'force_br_newlines' => false,
			'content_css' => trailingslashit(get_template_directory_uri()).'assets/main/css/tinymce.css',
			'object_resizing' => false
		),
	);
	// Remove WP specific tinyMCE edit image plugin.
	add_filter('tiny_mce_before_init', 'anno_tiny_mce_before_init');
	// Load the editor
	$content = esc_textarea($content);
	wp_editor($content, $editor_id, array_merge($default_settings, $settings));
	remove_filter('tiny_mce_before_init', 'anno_tiny_mce_before_init');
}

/**
 * Remove filters on editor content
 *
 */
function anno_remove_editor_content_filters($editor_markup) {
	global $post_type;
	if ($post_type == 'article') {
		remove_filter('the_editor_content', 'wp_richedit_pre');
		// Shouldnt be needed as richedit is enforced, but just in case
		remove_filter('the_editor_content', 'wp_htmledit_pre');
	}
	return $editor_markup;
}
// This is the only place we can hook into to remove 'the_editor_content' filters
add_filter('the_editor', 'anno_remove_editor_content_filters');

// WP 4.3 introduced a new way of filtering content prior to getting to the editor
// Priority needs to be < 10 as `the_editor_content` (which is being removed) is run
// on the_editor_content at priority 10
function anno_remove_editor_content_filters_43( $content ) {
	remove_filter( 'the_editor_content', 'format_for_editor', 10, 2 );
	return $content;
}
add_filter( 'the_editor_content', 'anno_remove_editor_content_filters_43', 0 );

/**
 * Force rich editor for article post type.
 * This overrides user settings and preferences based on other post types
 */
function anno_force_richedit($editor_type) {
	global $post_type;
	if ($post_type == 'article') {
		$editor_type = 'tinymce';
	}
	return $editor_type;
}
add_filter('wp_default_editor', 'anno_force_richedit');

class Anno_tinyMCE {
	function Anno_tinyMCE() {
		add_filter('mce_external_plugins', array(&$this, 'plugins'));
		add_filter('mce_buttons', array(&$this, 'mce_buttons'), 10, 2);
		add_filter('mce_buttons_2', array(&$this, 'mce_buttons_2'), 10, 2);
		add_filter('mce_buttons_3', array(&$this, 'mce_buttons_3'), 10, 2);
		add_filter('mce_external_languages', array(&$this, 'external_languages'));
	}

	function mce_buttons($buttons, $ed_id) {

		if ($this->is_article()) {
			$buttons = explode(',', 'fullscreen,undo,redo,|,annopastetext,|,annosource');
			if ($ed_id != 'excerpt') {
				$buttons[] = '|';
				$buttons[] = 'annotree';
			}
		}
		return $buttons;
	}

	function mce_buttons_2($buttons, $ed_id) {
		if ($this->is_article()) {
			if ($ed_id == 'excerpt') {
				$buttons = array('bold,italic,underline,superscript,subscript,charmap,annosection');
			}
			else {
				$buttons = explode(',', 'annoorderedlist,annobulletlist,annooutdentlist,annoindentlist,bold,italic,underline,annopreformat,annomonospace,superscript,subscript,charmap,|,annolink,announlink,|,annosection,annosubsection,mysplitbutton,|,annoreferences,|,annoimages,|,annoquote,annoequations');
			}
		}
		return $buttons;
	}


	function mce_buttons_3($buttons, $ed_id) {
		if ($this->is_article()) {
			if ($ed_id == 'excerpt') {
				$buttons = array();
			}
			else {
				$buttons = explode(',', 'table,row_before,row_after,delete_row,col_before,col_after,delete_col,split_cells,merge_cells');
			}
		}
		return $buttons;
	}

	function plugins($plugins) {
		if ($this->is_article()) {
			$textorum_dir = trailingslashit(get_template_directory_uri()).'js/textorum/dist/';
			$plugins['textorum'] = $textorum_dir . 'textorum/editor_plugin.js';

			$plugins_dir = trailingslashit(get_template_directory_uri()).'js/tinymce/plugins/';

			$plugins['annoLink_base'] = $plugins_dir.'annolink/annolink.js';
			$plugins['annoLink']  =  $plugins_dir.'annolink/editor_plugin.js';

			$plugins['annoReferences_base'] = $plugins_dir.'annoreferences/annoreferences.js';
			$plugins['annoReferences']  =  $plugins_dir.'annoreferences/editor_plugin.js';

			$plugins['annoImages']  =  $plugins_dir.'annoimages/editor_plugin.js';

			$plugins['annoTable'] = $plugins_dir.'annotable/editor_plugin.js';
			$plugins['annoTable_base'] = $plugins_dir.'annotable/annotable.js';

			$plugins['annoQuote'] = $plugins_dir.'annoquote/editor_plugin.js';
			$plugins['annoQuote_base'] = $plugins_dir.'annoquote/annoquote.js';

			$plugins['annoLists'] = $plugins_dir.'annolists/editor_plugin.js';

			$plugins['annoFormats'] = $plugins_dir.'annoformats/editor_plugin.js';

			$plugins['annoEquations'] = $plugins_dir.'annoequations/editor_plugin.js';
			$plugins['annoequationedit'] = $plugins_dir.'annoequationedit/editor_plugin.js';

			$plugins['annoPaste'] = $plugins_dir.'annopaste/editor_plugin.js';

			$plugins['annoTree'] = $plugins_dir.'annotree/editor_plugin.js';

			$plugins['annoSource'] = $plugins_dir.'annosource/editor_plugin.js';
			$plugins['annoSource_base'] = $plugins_dir.'annosource/annosource.js';

			$plugins['annoUtility'] = $plugins_dir.'annoutility/editor_plugin.js';

			$plugins['textorumInsertion']  =  $plugins_dir.'textorum-insertion/editor_plugin.js';

		}
		return $plugins;
	}

	function external_languages($langs) {
		$plugins_dir = trailingslashit(get_template_directory()).'js/tinymce/plugins/';
		$dirs = array(
			'annoequationedit' => $plugins_dir.'annoequationedit/langs/lang.php',
			'annoequations' => $plugins_dir.'annoequations/langs/lang.php',
			'annoformats' => $plugins_dir.'annoformats/langs/lang.php',
			'annoimages' => $plugins_dir.'annoimages/langs/lang.php',
			'annolink' => $plugins_dir.'annolink/langs/lang.php',
			'annolists' => $plugins_dir.'annolists/langs/lang.php',
			'annopaste' => $plugins_dir.'annopaste/langs/lang.php',
			'annoquote' => $plugins_dir.'annoquote/langs/lang.php',
			'annoreferences' => $plugins_dir.'annoreferences/langs/lang.php',
			'annosource' => $plugins_dir.'annosource/langs/lang.php',
			'annotable' => $plugins_dir.'annotable/langs/lang.php',
			'annotips' => $plugins_dir.'annotips/langs/lang.php',
			'annotree' => $plugins_dir.'annotree/langs/lang.php',
			'annotextorum' => $plugins_dir.'textorum-insertion/langs/lang.php',

		);

		return array_merge($langs, $dirs);
	}

	/**
	 * Returns whether or not the current post (post_type) is an article
	 */
	private function is_article() {
		global $post_type;
		return $post_type == 'article';
	}
}
/**
 * Remove the wpeditimage plugin from tinyMCE plugins. This prevents edit image buttons popping up on hover
 */
function anno_tiny_mce_before_init($init_array) {
	if (isset($init_array['plugins'])) {
		$init_array['plugins'] = str_replace('wpeditimage,', '', $init_array['plugins']);
		$init_array['plugins'] = str_replace('wpeditimage', '', $init_array['plugins']);
	};

	//show Kitchen Sink by default
	$init_array['wordpress_adv_hidden'] = false;

	$init_array['setup'] = 'function(ed) { ed.onInit.add(function(ed) { jQuery("#" + ed.id).siblings(".mceEditor").find(".mce_code").attr("title", "Show Codes") }); }';

	return $init_array;
}

/**
 * Load Annotum tinyMCE plugins
 */
function anno_load_tinymce_plugins() {
	$load = new Anno_tinyMCE();
}
if (is_admin()) {
	add_action('init', 'anno_load_tinymce_plugins');
}

function anno_popup_paste() {
?>
<div id="anno-popup-paste" class="anno-mce-popup">
	<form id="anno-tinymce-paste-form" class="" tabindex="-1" name="source" onsubmit="return AnnoPasteWordDialog.insert();" action="#">
		<div class="anno-mce-popup-fields">
			<textarea id="annotest"></textarea>
		</div>
		<input type="submit" value="submit" />
	</form>
</div>
<?php
}

/**
 * Popup Dialog for linking in the tinyMCE
 */
function anno_popup_link() {
?>
<div id="anno-popup-link" class="anno-mce-popup">
	<form id="anno-tinymce-link-form" class="" tabindex="-1">
		<div class="anno-mce-popup-fields">
			<label>
				<span><?php _ex('URL', 'input label', 'anno'); ?></span>
				<input type="text" name="link-href" id="anno-link-url-field" />
			</label>
			<label>
				<span><?php _ex('Title', 'input label', 'anno'); ?></span>
				<input type="text" name="link-title" id="anno-link-title-field" />
			</label>
		</div>
		<div class="anno-mce-popup-footer">
			<?php _anno_popup_submit_button('anno-link-submit', _x('Save', 'button value', 'anno')) ?>
		</div>
	</form>
</div>
<?php
}

/**
 * Popup Dialog for table insertion in the tinyMCE
 */
function anno_popup_table() {
?>
	<div id="anno-popup-table" class="anno-mce-popup">
		<form id="anno-tinymce-table-form" class="" tabindex="-1">
			<div class="anno-mce-popup-fields">
				<form>
					<label for="table-label">
						<span><?php _ex('Label', 'input label for defining tables', 'anno'); ?></span>
						<input type="text" name="label" id="table-label" />
					</label>
					<label for="table-caption">
						<span><?php _ex('Caption', 'input label for defining tables', 'anno'); ?></span>
						<textarea name="caption" id="table-caption" rows="2"></textarea>
					</label>
					<fieldset>
					<legend><?php _ex('Table Properties', 'legend', 'anno'); ?></legend>
						<label for="table-cols">
							<span><?php _ex('Columns', 'input label for defining tables', 'anno'); ?></span>
							<input type="text" class="short-text" name="cols" id="table-cols" />
						</label>
						<label for="table-rows">
							<span><?php _ex('Rows', 'input label for defining tables', 'anno'); ?></span>
							<input type="text" class="short-text" name="rows" id="table-rows" />
						</label>
					</fieldset>
				</form>
			</div>
			<div class="anno-mce-popup-footer">
				<?php _anno_popup_submit_button('anno-table-submit', _x('Insert', 'button value', 'anno')); ?>
			</div>
		</form>
	</div>
<?php
}


/**
 * Row brief markup for references display in the popup Dialog for tinyMCE.
 */
function anno_popup_references_row_display($reference_key, $reference) {
?>
	<table>
	<tr>
		<td class="reference-checkbox">
			<input id="<?php echo esc_attr('reference-checkbox-'.$reference_key); ?>" class="js-reference-checkbox" type="checkbox" />
		</td>
		<td class="reference-text">
			<label for="<?php echo esc_attr('reference-checkbox-'.$reference_key); ?>" class="js-reference-checkbox-label">
				<span class="reference-number js-reference-number"><?php echo $reference_key + 1; ?>.</span> <?php echo esc_html($reference['text']); ?>
			</label>
		</td>
		<td class="reference-actions">
<?php
		if (anno_current_user_can_edit()) {
?>
			<a href="#" data-id="<?php echo esc_attr($reference_key); ?>" class="edit-reference"><?php _ex('Edit', 'reference action', 'anno'); ?></a>
			<a href="#" data-id="<?php echo esc_attr($reference_key); ?>" class="delete-reference"><?php _ex('Delete', 'reference action', 'anno'); ?></a>
			<?php  wp_nonce_field('anno_delete_reference', '_ajax_nonce-delete-reference'); ?>
<?php
		}
		else {
?>
			<a href="#" data-id="<?php echo esc_attr($reference_key); ?>" class="edit"><?php _ex('Show', 'reference action', 'anno'); ?></a>
<?php
		}
?>
		</td>
	</tr>
	</table>
<?php
}

/**
 * Row edit markup for references display in the popup Dialog for tinyMCE.
 *
 * @param int $reference_key Key of the reference
 * @param array $reference Array of reference data
 * @param int $post_id ID of the post
 * @param bool $doi_enabled Determines if the DOI lookup should be enabled. Passed as parameter to prevent lookup on every row display
 *
 * @return void
 */
function anno_popup_references_row_edit($reference_key, $reference, $post_id, $doi_enabled = false) {
?>
	<table id="<?php echo esc_attr('reference-edit-'.$reference_key); ?>" class="js-reference-edit">
		<tr>
			<td class="anno-references-edit-td" colspan="3">
				<div></div>
					<form id="<?php echo esc_attr('reference-form-'.$reference_key); ?>" class="anno-reference-edit js-reference-form">
						<div id="<?php echo esc_attr('lookup-error-'.$reference_key); ?>" class="popup-error js-lookup-error"></div>
						<label>
						<?php
							$doi_value = $doi_enabled ? esc_attr($reference['doi']) : _x('CrossRef Credentials Required', 'disabled DOI lookup message', 'anno');
						?>
							<span><?php _ex('CrossRef DOI', 'input label for DOI lookup', 'anno'); ?></span>
							<input type="text" class="short js-doi" name="doi" id="<?php echo esc_attr('doi-'.$reference_key); ?>" value="<?php echo $doi_value; ?>"<?php disabled($doi_enabled, false, true); ?>/>
<?php if (anno_current_user_can_edit()): ?>
							<input type="button" class="blue js-doi-import" name="import_doi" id="<?php echo esc_attr('doi-import-'.$reference_key); ?>" value="<?php _ex('Import', 'button label', 'anno'); ?>"<?php disabled($doi_enabled, false, true); ?>>
							<img src="<?php echo esc_url(admin_url('images/wpspin_light.gif' )); ?>" class="ajax-loading" />
							<?php wp_nonce_field('anno_import_doi', '_ajax_nonce-import-doi', false); ?>
<?php endif; ?>
						</label>
						<label>
							<span><?php _ex('PubMed ID (PMID)', 'input for PubMed ID lookup', 'anno'); ?></span>
							<input type="text" class="short js-pmid" name="pmid" id="<?php echo esc_attr('pmid-'.$reference_key); ?>" value="<?php echo esc_attr($reference['pmid']) ?>" />
<?php if (anno_current_user_can_edit()): ?>
							<input type="button" class="blue js-pmid-import" name="import_pubmed" data-id="<?php echo esc_attr($reference_key); ?>" value="<?php _ex('Import', 'button label', 'anno'); ?>">
							<img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-loading" />
							<?php wp_nonce_field('anno_import_pubmed', '_ajax_nonce-import-pubmed', false); ?>
<?php endif; ?>
						</label>
						<label>
							<span><?php _ex('Text', 'input label for defining tables', 'anno'); ?></span>
							<textarea type="text" name="text" class="js-pmid-text" id="<?php echo esc_attr('text-'.$reference_key); ?>"><?php echo esc_textarea($reference['text']) ?></textarea>
						</label>
						<label>
							<span><?php _ex('URL', 'input label for defining tables', 'anno'); ?></span>
							<input type="text" name="url" id="url" value="<?php echo esc_attr($reference['url']) ?>" />
						</label>
<?php if (anno_current_user_can_edit()): ?>
						<div class="reference-edit-actions clearfix">
							<a href="#" data-id="<?php echo esc_attr($reference_key); ?>" class="save-reference left"><?php _e('Save', 'anno'); ?></a>
							<a href="#" data-id="<?php echo esc_attr($reference_key); ?>" class="cancel-reference right"><?php _e('Cancel', 'anno'); ?></a>
							<input type="hidden" class="js-ref-id" name="ref_id" value="<?php echo esc_attr($reference_key); ?>" />
							<input type="hidden" name="post_id" value="<?php echo esc_attr($post_id); ?>" />
							<input type="hidden" name="action" value="anno-reference-save" />
							<?php wp_nonce_field('anno_save_reference', '_ajax_nonce-save-reference'); ?>
						</div>
<?php endif; ?>
						<div class="clearfix"></div>
					</form>
				</div>
			</td>
		</tr>
	</table>
<?php
}

/**
 * Row markup for references display in the popup Dialog for tinyMCE.
 *
 * @param int $reference_key Key of the reference
 * @param array $reference Array of reference data
 * @param int $post_id ID of the post
 * @param bool $doi_enabled Determines if the DOI lookup should be enabled. Passed as parameter to prevent lookup on every row display
 *
 * @return void
 */
function anno_popup_reference_row($reference_key, $reference, $post_id, $doi_enabled = false) {
?>
	<tr id="<?php echo esc_attr('reference-'.$reference_key); ?>" class="js-reference-row">
		<td colspan="3">
			<?php anno_popup_references_row_display($reference_key, $reference); ?>
			<?php anno_popup_references_row_edit($reference_key, $reference, $post_id, $doi_enabled); ?>
		</td>
	</tr>
<?php
}

/**
 * Popup dialog for references in the tinyMCE
 */
function anno_popup_references() {
	global $post;
	$references = get_post_meta($post->ID, '_anno_references', true);

?>
	<div id="anno-popup-references" class="anno-mce-popup">
		<div class="anno-mce-popup-fields">
			<table id="anno-references">
				<thead>
					<tr>
						<th class="reference-checkbox"></th>
						<th class="reference-text"></th>
						<th class="reference-actions"></th>
					</tr>
				</thead>
				<tbody>
<?php
	$doi_enabled = anno_doi_lookup_enabled();
	if (!empty($references) && is_array($references)) {
		foreach ($references as $reference_key => $reference) {
			//prevent undefined index errors;
			$reference_keys = array('text', 'doi', 'pmid', 'url', 'figures');
			foreach ($reference_keys as $key_val) {
				$reference[$key_val] = isset($reference[$key_val]) ? $reference[$key_val] : '';
			}

			anno_popup_reference_row($reference_key, $reference, $post->ID, $doi_enabled);
		}
	}
?>
<?php if (anno_current_user_can_edit()): ?>
					<tr id="<?php echo esc_attr('reference-new'); ?>">
						<td colspan="3">
							<?php anno_popup_references_row_edit('new', array('text' => '', 'doi' => '', 'pmid' => '', 'url' => '', 'figures' => ''), $post->ID, $doi_enabled); ?>
						</td>
					<tr>
						<td colspan="3" class="anno-mce-popup-footer">
							<?php _anno_popup_submit_button('anno-references-new', _x('New Reference', 'button value', 'anno')); ?>
						</td>
					</tr>
<?php endif; ?>
				</tbody>
			</table>
		</div>
		<div class="anno-mce-popup-footer">
			<?php _anno_popup_submit_button('anno-references-submit', _x('Insert Reference(s)', 'button value', 'anno')); ?>
		</div>
	</div>
<?php
}

/**
 * Popup dialog for quote insertion in the tinyMCE
 */
function anno_popup_quote() {
?>
<div id="anno-popup-quote" class="anno-mce-popup">
	<form id="anno-popup-quote-form" class="" tabindex="-1">
		<div class="anno-mce-popup-fields">
				<label for="quote-text">
					<span><?php _ex('Text', 'input label for defining quotes', 'anno'); ?></span>
					<input type="text" name="text" id="quote-text" />
				</label>
				<label for="quote-attribution">
					<span><?php _ex('Attribution', 'input label for defining quotes', 'anno'); ?></span>
					<input type="text" name="attribution" id="quote-attribution" />
				</label>
				<fieldset>
					<legend><?php _ex('Permissions', 'legend', 'anno'); ?></legend>
					<label for="quote-copy-statement">
						<span><?php _ex('Copyright Statement', 'input label for defining quotes', 'anno'); ?></span>
						<input type="text" name="copyright-statement" id="quote-copy-statement" />
					</label>
					<label for="quote-copy-holder">
						<span><?php _ex('Copyright Holder', 'input label for defining quotes', 'anno'); ?></span>
						<input type="text" name="copyright-holder" id="quote-copy-holder" />
					</label>
					<label for="quote-license">
						<span><?php _ex('License', 'input label for defining quotes', 'anno'); ?></span>
						<input type="text" name="license" id="quote-license" />
					</label>
				</fieldset>
			</form>
		</div>
		<div class="anno-mce-popup-footer">
			<?php _anno_popup_submit_button('anno-quote-submit', _x('Insert', 'button value', 'anno')); ?>
		</div>
	</form>
</div>

<?php
}

/**
 * Popup Dialog for equation editor in the tinyMCE
 */
function anno_popup_equations() {
?>
<div id="anno-popup-equations" class="anno-mce-popup">
	<form id="anno-tinymce-equations-form" class="" tabindex="-1">
		<div class="anno-mce-popup-fields">
			<div class="equation-edit-details">
				<label for="equation-alttext">
					<div><?php _ex('Alt Text', 'input label', 'anno'); ?></div>
					<input name="alt_text" type="text" id="equation-alttext" />
				</label>
				<label for="equation-description">
					<div><?php _ex('Description', 'input label', 'anno'); ?></div>
					<textarea name="description" id="equation-description"></textarea>
				</label>
			</div>
			<fieldset class="equation-display">
				<legend><?php _ex('Display', 'legend', 'anno'); ?></legend>
				<label for="equation-display-figure" class="radio">
					<input type="radio" value="figure" name="display" class="equation-display-selection equation-display-figure" id="equation-display-figure"<?php checked(true, true, true); ?> />
					<span><?php _ex('Display as Figure', 'input label', 'anno'); ?></span>
				</label>
				<label for="equation-display-inline" class="radio">
					<input type="radio" value="inline" name="display" class="equation-display-selection equation-display-inline" id="equation-display-inline" />
					<span><?php _ex('Display Inline', 'input label', 'anno'); ?></span>
				</label>
				<div id="equation-figure-details">
					<label for="equation-label">
						<span><?php _ex('Label', 'input label', 'anno'); ?></span>
						<input type="text" name="label" id="equation-label" />
					</label>
					<label for="equation-caption">
						<span><?php _ex('Caption', 'input label', 'anno'); ?></span>
						<textarea id="equation-caption" name="caption"></textarea>
					</label>
				</div>
			</fieldset>
		</div>
		<div class="anno-mce-popup-footer">
			<?php _anno_popup_submit_button('anno-equations-insert', _x('Insert', 'button value', 'anno')) ?>
		</div>
	</form>
</div>
<?php
}

/**
 * Markup for insertion/save buttons in popup dialogs for the tinyMCE
 */
function _anno_popup_submit_button($id, $value, $type = 'button') {
?>
	<input id="<?php echo esc_attr($id); ?>" type="<?php echo esc_attr($type); ?>" class="button" value="<?php echo esc_attr($value); ?>" />
<?php
}

function anno_popup_tips() {
?>
<div id="anno-popup-tips" class="anno-mce-popup">
		<dl>
			<dt><?php _ex('Use Ctrl+Enter', 'tinyMCE tip dt', 'anno'); ?></dt>
			<dd><?php _ex('To insert new sections (when within a section) or add new paragraphs when inside elements like a table, or figure caption.', 'tinyMCE tip dd', 'anno'); ?></dd>
		</dl>
</div>
<?php
}

function anno_source_editor() {
?>
<div id="anno-popup-source" class="anno-mce-popup">
	<input type="button" id="anno-source-validate" class="button button-primary js-source-button js-source-validate" value="<?php _e('Validate', 'anno'); ?>" />
	<input type="button" id="anno-source-insert" class="button  button-primary js-source-button js-source-insert" value="<?php _e('Insert', 'anno'); ?>" />
	<input type="button" id="anno-source-close" class="button  button-primary js-source-button js-source-close" value="<?php _e('Close Without Inserting', 'anno'); ?>" />
	<ul id="validation-status"></ul>
	<textarea name="htmlSource" id="htmlSource" value=""></textarea>
</div>
<?php
}

/**
 * Markup for the tinyMCE dialog popups
 */
function anno_preload_dialogs($init) {
	global $pagenow, $post_type;
	if (($pagenow == 'post-new.php' || $pagenow == 'post.php') && $post_type == 'article') {
?>
	<div style="display:none;">
	<?php anno_popup_link(); ?>
	</div>

	<div style="display:none;">
	<?php anno_popup_paste(); ?>
	</div>

	<div style="display:none;">
	<?php anno_popup_references(); ?>
	</div>

	<div style="display:none;">
	<?php anno_popup_table(); ?>
	</div>

	<div style="display:none;">
	<?php anno_popup_quote(); ?>
	</div>

	<div style="display:none;">
	<?php anno_popup_equations(); ?>
	</div>

	<div style="display:none;">
	<?php anno_popup_tips(); ?>
	</div>

	<aside id="anno-tree-fullscreen-wrapper" class="hidden js-mce_fullscreen-tree-pop-up tree-pop-up" >
		<div id="anno-tree-mce_fullscreen">
	</aside>
	<script type="text/javascript">
		jQuery('#anno-tree-fullscreen-wrapper').appendTo('body');
	</script>
	</div>

	<div style="display:none;">
	<?php anno_source_editor(); ?>
	</div>

<?php
	}
}
add_action('after_wp_tiny_mce', 'anno_preload_dialogs', 10, 1 );

/**
 * Ajax Handler for creating/updating references
 */
function anno_tinymce_reference_save() {
	check_ajax_referer('anno_save_reference', '_ajax_nonce-save-reference');

	$success = true;
	$response = array();
	$messages = array();

	if (!isset($_POST['post_id'])) {
		$message = _x('Could not evaluate Article ID please try again.', 'error message', 'anno');
		$success = false;
	}
	else if (empty($_POST['text'])) {
		$message = _x('Text cannot be blank.', 'error message', 'anno');
		$success = false;
	}
	else if (!isset($_POST['ref_id'])) {
		$message = _x('Could not evaluate Reference ID please try again.', 'error message', 'anno');
		$success = false;
	}

	if ($success) {
		$reference = anno_insert_reference($_POST);
		if (!$reference) {
			$success = false;
			$message = _x('Could not save reference, please try again.', 'error message', 'anno');
		}
		else {
			$response['ref_id'] = $reference['ref_id'];
			ob_start();
				$doi_enabled = anno_doi_lookup_enabled();
				anno_popup_reference_row($reference['ref_id'], $reference, $_POST['post_id'], $doi_enabled);
				$response['markup'] = ob_get_contents();
			ob_end_clean();
			$response['ref_text'] = '<span class="reference-number js-reference-number">'.($response['ref_id'] + 1).'.</span> '.$reference['text'];
			$message =  _x('Reference Saved.', 'success message', 'anno');
		}
	}

	$response['message'] = $success ? 'success' : 'error';
	$response['text'] = $message;

	echo json_encode($response);
	die();
}
add_action('wp_ajax_anno-reference-save', 'anno_tinymce_reference_save');

function anno_tinymce_reference_delete() {
	check_ajax_referer('anno_delete_reference', '_ajax_nonce-delete-reference');
	$response = array(
		'result' => 'error',
		'refTotal' => 0
	);
	if (anno_delete_reference($_POST['post_id'], $_POST['ref_id'])) {
		$response['result'] = 'success';
		$references = get_post_meta(absint($_POST['post_id']), '_anno_references', true);
		$response['refTotal'] = count($references);
	}
	echo json_encode($response);
	die();
}
add_action('wp_ajax_anno-reference-delete', 'anno_tinymce_reference_delete');

/**
 * Updates or creates a new reference for a given post.
 * New posts should be passed in without a 'ref_id' key, or with 'new' as a value
 *
 * @param array $ref_array Array of reference data
 * @return mixed bool|Array array of the updated/created reference false otherwise
 */
function anno_insert_reference($ref_array) {

	if (!isset($ref_array['post_id']) || !isset($ref_array['text'])) {
		return false;
	}

	$ref_args = array(
		'doi' => isset($ref_array['doi']) ? $ref_array['doi'] : '',
		'pmid' => isset($ref_array['pmid']) ? $ref_array['pmid'] : '',
		'text' => isset($ref_array['text']) ? $ref_array['text'] : '',
		'figures' => isset($ref_array['figures']) ? $ref_array['figures'] : '',
		'url' => isset($ref_array['url']) ? $ref_array['url'] : '',
	);

	$references = get_post_meta(absint($ref_array['post_id']), '_anno_references', true);
	$ref_key = absint($ref_array['ref_id']);

	// Do new item
	if (!isset($ref_array['ref_id']) || $ref_array['ref_id'] == 'new') {
		$references[] = $ref_args;
		// Grab the key of our newly created reference
		$ref_args['ref_id'] = array_pop(array_keys($references));
	}
	else if (array_key_exists($ref_key, $references)) {
		$references[$ref_key] = $ref_args;
		$ref_args['ref_id'] = $ref_key;
	}
	else {
		return false;
	}

	update_post_meta(absint($ref_array['post_id']), '_anno_references', array_values($references));
	return $ref_args;
}

function anno_delete_reference($post_id, $ref_id) {
	$references = get_post_meta($post_id, '_anno_references', true);
	if (array_key_exists($ref_id, $references)) {
		unset($references[$ref_id]);
		update_post_meta($post_id, '_anno_references', array_values($references));
		return true;
	}
	return false;
}

//@todo Update success response
function anno_tinymce_image_save() {
	if (isset($_POST['attachment_id'])) {
		$attachment = get_post($_POST['attachment_id']);
		if (!empty($attachment)) {
			$attachment->post_content = isset($_POST['description']) ? $_POST['description'] : '';
			$attachment->post_excerpt = isset($_POST['caption']) ? $_POST['caption'] : '';
			// Pass in as array to prevent double escaping
			wp_update_post((array) $attachment);
			$meta_fields = array(
				'alt_text',
				'display',
				'label',
				'copyright_statement',
				'copyright_holder',
				'license',
				'size',
				'url',
			);
			foreach ($meta_fields as $meta_field) {
				$meta_value = isset($_POST[$meta_field]) ? $_POST[$meta_field] : '';
				switch ($meta_field) {
					case 'alt_text':
						update_post_meta($attachment->ID, '_wp_attachment_image_alt', $meta_value);
						break;
					case 'display':
						if (empty($_POST['display'])) {
							$meta_value = 'figure';
						}
						update_post_meta($attachment->ID, '_anno_attachment_image_display', $meta_value);
						break;
					default:
						update_post_meta($attachment->ID, '_anno_attachment_image_'.$meta_field, $meta_value);
						break;
				}
			}
		}
	}

	die();
}
add_action('wp_ajax_anno-img-save', 'anno_tinymce_image_save');

/**
 * Prior to outputting the value of the textarea, convert a couple
 * entities that wouldn't be able to be seen, into HTML.  This is
 * done on the fly, so that the XML stored in the DB is correct.
 *
 * @param string $content
 * @return void
 */
function anno_process_editor_content($content) {
	// Break to BR
	$content = str_replace('<break />', '<br />', $content);

	// Load the XML source
	$xml = new DOMDocument;
	$xml->loadXML('<textorum>' . $content . '</textorum>');

	$xsl = new DOMDocument;
	$xsl->load(trailingslashit(get_template_directory()) . 'js/textorum/dist/textorum/xsl/xml2cke.xsl');

	// Configure the transformer
	$proc = new XSLTProcessor;
	$proc->importStyleSheet($xsl); // attach the xsl rules

	$proc->setParameter(null, 'inlineelements', 'named-content,ext-link,inline-graphic,alt-text,lbl,long-desc,copyright-statement,permissions,copyright-holder,license,license-p,attrib,inline-formula,xref');
	$proc->setParameter(null, 'bold', 'bold');
	$proc->setParameter(null, 'italic', 'italic');
	$proc->setParameter(null, 'monospace', 'monospace');
	$proc->setParameter(null, 'underline', 'underline');
	$proc->setParameter(null, 'fixedelements', 'textorum,table,thead,tbody,td,tr,th,sub,sup');

	$content = $proc->transformToXML($xml);
	$content = preg_replace('/<\/?textorum[^>]*>/', '', $content);
	return $content;

	phpQuery::newDocument($content);

	// Convert inline-graphics to <img> tags so they display
	anno_xml_to_html_replace_inline_graphics($content);

	// Convert caption to cap
	anno_replace_caption_tag($content);

	// Convert label to lbl
	anno_replace_label_tag($content);

	// Remove p tags wrapping list items
	anno_remove_p_from_list_items($content);

	// Remove p tags from disp-quotes
	//anno_remove_p_from_disp_quote_items($content);

	// We need a clearfix for floated images.
	$figs = pq('fig');
	foreach ($figs as $fig) {
		$fig = pq($fig);

		$img_src = '';

		// Check if we're using bugged version of libxml
		if (version_compare(LIBXML_DOTTED_VERSION, '2.6.29', '<')) {
				$img_src = anno_get_attribute_value_regex($fig, 'media', 'xlink:href');
			}
		else {
			$img_src = $fig->find('media')->attr('xlink:href');
		}
		$fig->prepend('<img src="'.$img_src.'" />');

		// _mce_bogus stripped by tinyMCE on save
		$fig->append('<div _mce_bogus="1" class="clearfix"></div>');
	}

	return phpQuery::getDocument();
}


/**
 * Validates the XML to only allow tags defined in the DTD
 *
 * @param string $html_content
 * @return string - DTD valid XML
 */
function anno_validate_xml_content_on_save($html_content) {
	// Strip all tags not defined by DTD
	$content = anno_to_xml($html_content);

	// Convert remaining br to break tags. Unable to do this with phpQuery, it thinks break tag should be opened and closed
	$content = str_replace(array('<br />', '<br>'), '<break />', $content);

	$content = str_replace('&nbsp;', '&#xA0;', $content);

	$content = strip_tags($content, implode('', array_unique(anno_get_dtd_valid_elements())));
	return $content;
}

function anno_get_dtd_valid_elements() {
	// Build big list of valid XML elements (listed in DTD)
	// This is after the editor content is processed and converted to XML defined by DTD
	$tags = array(
		// Formats
		'bold',
		'italic',
		'sup',
		'sub',
		'monospace',
		'underline',

		// Inlines
		'named-content',
		'ext-link',
		'inline-graphic',
			'alt-text',

		// Paragraph-level
		'media',
			'uri',
			'alt-text',
			'long-desc',
			'permissions',
				'copyright-statement',
				'copyright-holder',
				'license',
					'license-p',
						'xref',
		'list',
			'title',
			'list-item',
				'p',
					'xref',
				'list', // allow nested lists
		'disp-formula',
			'label',
			'tex-math',
		'disp-quote',
			'p',
				'xref',
			'attrib',
			'permissions',
				'copyright-statement',
				'copyright-holder',
				'license',
					'license-p',
						'xref',
		'fig',
			'label',
			'caption',
				'title',
				'p',
					'xref',
			'media',
				'uri',
				'alt-text',
				'long-desc',
				'permissions',
					'copyright-statement',
					'copyright-holder',
					'license',
						'license-p',
							'xref',
		'table-wrap',
			'label',
			'caption',
				'title',
				'p',
					'xref',
				'media',
					'alt-text',
					'long-desc',
				'table',
					'thead',
						'th',
							'td',
								'xref',
					'tbody',
						'tr',
							'td',
								'break',
								'xref',
				'table-wrap-foot',
					'p',
						'xref',
				'permissions',
					'copyright-statement',
					'copyright-holder',
					'license',
						'license-p',
							'xref',

		'preformat',
		'article',
			'sec',
			'para',
			'br',
	);
	$processed_tags = array();
	foreach ($tags as $tag) {
		$processed_tags[] = '<'.$tag.'>';
		$processed_tags[] = '<'.$tag.'/>';
		$processed_tags[] = '<'.$tag.' />';
	}

	return apply_filters('anno_valid_dtd_elements', $processed_tags);
}

/**
 * Save our appendices as HTML versions to be used on the front end when updating
 */
function anno_update_appendices_xml_as_html($meta_id, $post_id, $meta_key, $meta_value) {
	anno_save_appendices_xml_as_html($post_id, $meta_key, $meta_value);
}
add_action('update_post_metadata', 'anno_update_appendices_xml_as_html', 10, 4);

/**
 * Save our appendices as HTML versions to be used on the front end when adding for the first time
 * This function is also called when the appendices are updated, not just created
 */
function anno_save_appendices_xml_as_html($post_id, $meta_key, $meta_value) {
	if ($meta_key === '_anno_appendices') {
		if (is_array($meta_value)) {
			$meta_html = array();
			foreach ($meta_value as $appendix) {
				$meta_html[] = anno_xml_to_html($appendix);
			}
			update_post_meta($post_id, '_anno_appendices_html', $meta_html);
		}
	}
}
add_action('add_post_meta', 'anno_save_appendices_xml_as_html', 10, 3);

/**
 * Switcheroo! Raw XML content gets switched with HTML formatted content.
 * Save the raw XML to the post_content_formatted column
 * Save the formatted HTML to the post_content column
 */
function anno_insert_post_data($data, $postarr) {
	// This is the quick edit action, we don't want to mess around with the content.
	if (isset($_POST['action']) && $_POST['action']  == 'inline-save') {
		return $data;
	}

	if (
		$postarr['post_type'] == 'article'
		|| (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && get_post_type($postarr['post_parent']) == 'article')
	) {
		// Get our XML content for the revision
		$content = stripslashes($data['post_content']);

		// Remove non-ascii gremlins
		$content = preg_replace('/(\xc2\xa0)/',' ', $content);
		$content = str_replace(array("\r", "\r\n", "\n"), '', $content);
		// Set XML as backup content. Filter markup and strip out tags not on whitelist.
		$xml = anno_validate_xml_content_on_save($content);
		$data['post_content_filtered'] = addslashes($xml);
		// Set formatted HTML as the_content
		$data['post_content'] = addslashes(anno_xml_to_html($xml));

		$data['post_excerpt'] = addslashes(anno_validate_xml_content_on_save(stripslashes($data['post_excerpt'])));
	}
	return $data;
}
add_filter('wp_insert_post_data', 'anno_insert_post_data', null, 2);

/**
 * Don't process incoming content from revisions, its already in the forms expected
 */
function anno_remove_insert_filter_for_restore() {
	remove_filter('wp_insert_post_data', 'anno_insert_post_data', null, 2);
}
add_action('admin_action_restore', 'anno_remove_insert_filter_for_restore');

/**
 * Allow post_content_filtered to be managed by revisions
 */
function anno_post_revision_fields($fields) {
	$fields['post_content_filtered'] = _x('Post Content Filtered', 'Title for revision management', 'anno');
	return $fields;
}
add_filter( '_wp_post_revision_fields', 'anno_post_revision_fields');

/**
 * Only maintain line breaks on certain tags (title, td, th)
 */
function anno_handle_br($xml) {
	$tags = pq('br');
	$save = pq('title > br, td > br, th > br');
	//  ->not() with selector pattern is bugged
	$tags = $tags->not($save);
	$tags->remove();
}
add_action('anno_to_xml', 'anno_handle_br', 99);

function anno_wp_insert_post_update_import($post_id) {
	// If we've saved an imported post (Knol), we've likely changed the structure so we don't need to run
	// the post import filters on it next save
	$imported = get_post_meta($post_id ,'_anno_knol_import', true);
	if ($imported) {
		update_post_meta($post_id ,'_anno_knol_import', 0);
	}
}
add_action('wp_insert_post', 'anno_wp_insert_post_update_import', 10, 1);
/**
 * Swap real HTML post content with XML formatted post content for editing
 */
function anno_edit_post_content($content, $id) {
	$post = get_post( $id );
	if ( $post && $post->post_type == 'article' ) {
		$content = $post->post_content_filtered;
	}
	return $content;
}
add_filter( 'edit_post_content', 'anno_edit_post_content', 10, 2 );

function anno_edit_post_content_filtered( $content, $id ) {
	return $content;
}
add_filter( 'edit_post_content_filtered', 'anno_edit_post_content_filtered', 10, 2 );

/**
 * Utility function to convert our HTML into XML
 * By default, this doesn't do anything by itself, but it runs the
 * 'anno_to_xml' action to allow various actions to change
 * small specific portions of the HTML
 *
 * @see anno_xml_to_html_replace_bold() for simple example on usage
 *
 * @param string $xml_content
 * @return void
 */
function anno_to_xml($html_content) {
	$post_id = anno_get_post_id();

	if (strpos($html_content, 'data-xmlel') === false) {
		# Already an XML document (or at least not an editable-HTML translation of an XML document)
		return $html_content;
	}

	// Load the XML source
	$xml = new DOMDocument;
	$xml->loadXML('<div data-xmlel="textorum">' . $html_content . '</div>');

	$xsl = new DOMDocument;
	$xsl->load(trailingslashit(get_template_directory()) . 'js/textorum/dist/textorum/xsl/cke2xml.xsl');

	// Configure the transformer
	$proc = new XSLTProcessor;
	$proc->importStyleSheet($xsl); // attach the xsl rules

	$content = $proc->transformToXML($xml);

	$content = preg_replace('/^.*?<textorum>/ms', '', $content);
	$content = preg_replace('/<\/textorum>.*?$/ms', '', $content);

	return $content;

	// Strip out Textorum's DOCTYPE declaration
	$html_content = preg_replace("/^<!DOCTYPE[^>]*?>/", "", $html_content);

	return $html_content;
	// Load our phpQuery document up, so filters should be able to use the pq() function to access its elements
	phpQuery::newDocument($html_content);

	// Let our various actions alter the document into XML
	do_action('anno_to_xml', $html_content);

	$imported = get_post_meta($post_id, '_anno_knol_import', true);
	if ($imported) {
		do_action('anno_to_xml_imported', $html_content);
	}

	// Return the newly formed HTML
	return phpQuery::getDocument()->__toString();
}

/**
 * Change HTML formatting to XML defined by the DTD.
 * Knol imported content comes with b, em etc... tags
 *
 * @param string $orig_html
 * @return void
 */
function anno_to_xml_replace_formatting($orig_markup) {
	$formats = array(
		'b' => 'bold',
		'strong' => 'bold',
		'em' => 'italic',
		'i' => 'italic',
		'u' => 'underline',
	);

	foreach ($formats as $html => $kipling_xml) {
		anno_convert_tag($html, $kipling_xml);
	}
}
add_action('anno_to_xml', 'anno_to_xml_replace_formatting');

/**
 * Change HTML inline <img> to XML <inline-graphic>
 *
 * @param string $orig_markup
 * @return void
 */
function anno_to_xml_import_replace_images($orig_markup) {
	$imgs = pq('img');
	foreach ($imgs as $img) {
		$img = pq($img);
		$img_src = $img->attr('src');
		$img_alt = $img->attr('alt');
		if (!empty($img_alt)) {
			$img_alt == '<alt-text>'.$img_alt.'</alt-text>';
		}
		$xml = '<inline-graphic xlink:href="'.$img_src.'" >'.$img_alt.'</inline-graphic>';
		$img->replaceWith($xml);
	}
}
add_action('anno_to_xml_imported', 'anno_to_xml_import_replace_images');

/**
 * Change HTML inline <a> to XML <ext-link>
 *
 * @param string $orig_markup
 * @return void
 */
function anno_to_xml_import_replace_links($orig_markup) {
	$a_tags = pq('a');
	foreach ($a_tags as $a_tag) {
		$a_tag = pq($a_tag);
		$link_content = $a_tag->html();
		$link_url = $a_tag->attr('href');

		$xml = '<ext-link ext-link-type="uri" xlink:href="'.$link_url.'" >'.$link_content.'</ext-link>';
		$a_tag->replaceWith($xml);
	}
}
add_action('anno_to_xml_imported', 'anno_to_xml_import_replace_links');

/**
 * Change HTML inline <img> to XML <inline-graphic>
 *
 * @param string $orig_markup
 * @return void
 */
function anno_to_xml_replace_inline_graphics($orig_markup) {
	$imgs = pq('img[class="_inline_graphic"]');
	foreach ($imgs as $img) {
		$img = pq($img);
		$img_src = $img->attr('src');
		$img_alt = $img->attr('alt');
		$xml = '<inline-graphic xlink:href="'.$img_src.'" ><alt-text>'.$img_alt.'</alt-text></inline-graphic>';
		$img->replaceWith($xml);
	}
}
add_action('anno_to_xml', 'anno_to_xml_replace_inline_graphics');

/**
 * Utility function to convert our XML into HTML
 * By default, this doesn't do anything by itself, but it runs the
 * 'anno_xml_to_html' action to allow various actions to change
 * small specific portions of the XML
 *
 * @see anno_xml_to_html_replace_bold() for simple example on usage
 *
 * @param string $xml_content
 * @return void
 */
function anno_xml_to_html($xml_content) {
	// Most translation is done by xslt - disabled broadly for now.  Some tweaking
	// will likely be done here later.
	//
	// Unable to do this with phpQuery, break tag doesn't register as self closing element
	$xml_content = str_replace('<break />', '<br />', $xml_content);

	// Load our phpQuery document up, so filters should be able to use the pq() function to access its elements
	phpQuery::newDocument($xml_content);

	// Let our various actions alter the document into HTML
	do_action('anno_xml_to_html', $xml_content);

	// Return the newly formed HTML
	return phpQuery::getDocument()->__toString();
}


/**
 * Loop over each formatting tag and do the proper HTML replacement
 *
 * @param string $orig_xml
 * @return void
 */
function anno_xml_to_html_replace_formatting($orig_xml) {
	$mapping = array(
		'bold' => array(
			'tag' => 'strong',
			'class' => '',
		),
		'italic' => array(
			'tag' => 'em',
			'class' => '',
		),
		'underline' => array(
			'tag' => 'mark',
			'class' => 'underline',
		),
		'monospace' => array(
			'tag' => 'code',
			'class' => '',
		),
		'sup' => array(
			'tag' => 'sup',
			'class' => '',
		),
		'sub' => array(
			'tag' => 'sub',
			'class' => '',
		),
		'title' => array(
			'tag' => 'h2',
			'class' => 'title',
		),
	);
	foreach ($mapping as $format => $html_info) {
		$nodes = pq($format);
		foreach ($nodes as $node) {
			// Get our HTML information from the mapping array
			extract($html_info);

			// Build our class string if we need to
			$class = empty($class) ? '' : ' class="'.$class.'"';

			$pq_node = pq($node); // Create a phpQuery object from the node
			$pq_node->replaceWith('<'.$tag.$class.'>'.$pq_node->html().'</'.$tag.'>');
		}
	}
}
add_action('anno_xml_to_html', 'anno_xml_to_html_replace_formatting');

/**
 * Replace inline graphics in the XML document with HTML elements
 *
 * @param string $orig_xml - Original XML, prob. shouldn't need
 * @return void
 */
function anno_xml_to_html_replace_inline_graphics($orig_xml) {
	$inline_imges = pq('inline-graphic');
	foreach ($inline_imges as $img) {
		$img = pq($img);
		if (version_compare(LIBXML_DOTTED_VERSION, '2.6.29', '<')) {
			$img_src = anno_get_attribute_value_regex($img, 'inline-graphic', 'xlink:href');
		}
		else {
			$img_src = $img->attr('xlink:href');
		}

		if (!empty($img_src)) {
			$alt_text = $img->children('alt-text:first')->html();

			$html = '<img src="'.$img_src.'" class="_inline_graphic" alt="'.$alt_text.'" />';
			$img->replaceWith($html);
		}
	}
}
add_action('anno_xml_to_html', 'anno_xml_to_html_replace_inline_graphics');


/**
 * Replace <fig> nodes in the XML document with HTML elements
 *
 * @param string $orig_xml - Original XML, prob. shouldn't need
 * @return void
 */
function anno_xml_to_html_replace_figures($orig_xml) {
	$tpl = new Anno_Template_Utils();
	$figs = pq('fig');

	$count = 0;
	if (count($figs)) {
		foreach ($figs as $fig) {

			// Get a phpQuery obj
			$fig = pq($fig);

			// Grab our media element in the fig
			$media = $fig->find('media');

			// Get some img tag properties. Check for lower versions of libxml which do not support : in attributes
			if (version_compare(LIBXML_DOTTED_VERSION, '2.6.29', '<')) {
				$img_src = anno_get_attribute_value_regex($media, 'media', 'xlink:href');
			}
			else {
				$img_src = $media->attr('xlink:href');
			}
			$alt = $media->children('alt-text')->html();
			$title = $media->children('long-desc')->html();
			$uri = pq($media->children('uri'));
			$uri_href = $uri->attr('xlink:href');

			// Build our img tag
			$img_tag = $tpl->to_tag('img', null, array(
				'src' => $img_src,
				'title' => $title,
				'alt' => $alt,
				'class' => 'photo'
			));

			// add start and end a tags if we have a uri to which to link the image
			if (!empty($uri_href)) {
				$linked_img_tag_start = '<a href="'.$uri_href.'">';
				$linked_img_tag_end = '</a>';
			}
			else {
				$linked_img_tag_start = '';
				$linked_img_tag_end = '';
			}

			$label = $fig->children('label')->html();
			$label = ($label ? sprintf(__('Fig. %d', 'anno'), ++$count).': '.strip_tags($label) : '');
			$label_tag = $tpl->to_tag('h2', $label, array('class' => 'label'));

			$cap = $fig->children('caption')->html();
			$cap_tag = $tpl->to_tag('div', $cap, array('class' => 'fn'));

			$permissions = $fig->find('permissions');
			$permissions_tag = anno_convert_permissions_to_html($permissions);
			$permissions->remove();

			$figcaption = $tpl->to_tag('figcaption', $label_tag.$cap_tag.$permissions_tag);

			$html = '
				<figure class="figure hmedia clearfix">
					'.$linked_img_tag_start.$img_tag.$linked_img_tag_end.'
					'.$figcaption.'
				</figure>';

			// Replace our figure with valid HTML
			$fig->replaceWith($html);
		}
	}
}
add_action('anno_xml_to_html', 'anno_xml_to_html_replace_figures');

/**
 * Change XML <sec> tags to HTML5 <section> tags
 */
function anno_xml_to_html_replace_sec($orig_xml) {
	$sections = pq('sec');
	if (count($sections)) {
		foreach ($sections as $sec) {
			$sec = pq($sec);
			// Replace sections
			$sec->replaceWith('<section class="sec">'.$sec->html().'</section>');
		}
		anno_xml_to_html_replace_sec($orig_xml);
	}
}
add_action('anno_xml_to_html', 'anno_xml_to_html_replace_sec');


/**
 * Change XML <title> tags to HTML5 <h2> tags
 * Run at priority 9 so we change the titles before global title changes happen.
 */
function anno_xml_to_html_replace_title($orig_xml) {
	// Replace Titles
	$titles = pq('title');
	if (count($titles)) {
		foreach ($titles as $title) {
			$title = pq($title);
			$title->replaceWith('<h2 class="title"><span>'.$title->html().'</span></h2>');
		}
	}
}
add_action('anno_xml_to_html', 'anno_xml_to_html_replace_title', 9);

/**
 * Change the XML <list> elements to proper HTML
 *
 * @param string $orig_xml
 * @return void
 */
function anno_xml_to_html_replace_lists($orig_xml) {
	/*
	'<list>',
		'<title>',
		'<list-item>',
			'<p>',
				'<xref>',
			'<list>', // allow nested lists

	<figure>
		<figcaption>
		<ul/ol>
			<li>

	*/
	$lists = pq('list');
	while(count($lists)) {
		// Get the first list encountered, this is a top level list
		$pq_list = pq('list:first');
		// Process the children
		anno_xml_to_html_iterate_list($pq_list);

		$list_type = $pq_list->attr('list-type');
		$list_type = ($list_type == 'order') ? 'ol' : 'ul';

		// Get list title if there is one
		$figcaption = $pq_list->find('title:first')->html();

		// Now that we have the title, get rid of the element
		$pq_list->find('title:first')->remove();

		// Replace our list with our built-out HTML
		$html = '';
		$html .= '<figure class="list">';
		$html .= empty($figcaption) ? '' : '<figcaption>'.$figcaption.'</figcaption>';
		$html .= '<'.$list_type.'>'.$pq_list->html().'</'.$list_type.'>';
		$html .= '</figure>';
		// Remove wrapping p tags that are maintained in XML
		$html = str_replace(array('<p>', '</p>'), '', $html);
		$pq_list->replaceWith($html);

		// Update lists to double check for remaining lists in the document
		$lists = pq('list');
	}
}
add_action('anno_xml_to_html', 'anno_xml_to_html_replace_lists');


/**
 * Do stuff to the list elements
 *
 * @param pq obj $list
 * @param bool $child Whether or not this list is a child of another list (replace now vs with wrapping 'figure')
 * @return void
 */
function anno_xml_to_html_iterate_list($list, $child = false) {
	// Get list type
	$list_type = $list->attr('list-type');
	$list_type = ($list_type == 'order') ? 'ol' : 'ul';

	// Loop over our items
	$items = $list->children('list-item');
	if (count($items)) {
		foreach ($items as $item) {
			$pq_item = pq($item);
			anno_xml_to_html_iterate_list_item($pq_item);
		}
	}

	if ($child) {
		$list->replaceWith('<'.$list_type.'>'.$list->html().'</'.$list_type.'>');
	}
}

/**
 * Set the list items' HTML wrapper
  * @param pqObj $item
 * @return void
 */
function anno_xml_to_html_iterate_list_item($item) {
	$child_list = $item->find('list');
	if (!empty($child_list->elements)) {
		foreach ($child_list->elements as $list) {
			anno_xml_to_html_iterate_list(pq($list), true);
			$item->replaceWith('<li>'.$item->html().'</li>');
		}
	}
	else {
		$item->replaceWith('<li>'.$item->html().'</li>');
	}
}

/**
 * Replace the XML tables with proper HTML
 *
 * @param string $orig_xml
 * @return void
 */
function anno_xml_to_html_replace_tables($orig_xml) {
	/*
	'<table-wrap>',
		'<lbl>',
		'<caption>',
			'<title>',
			'<p>',
				'<xref>',
		'<media>',
			'<alt-text>',
			'<long-desc>',
		'<table>',
			'<thead>',
				'<tr>',
					'<td>',
						'<xref>',
			'<tbody>',
				'<tr>',
					'<td>',
						'<xref>',
		'<table-wrap-foot>',
			'<p>',
				'<xref>',
		'<permissions>',
			'<copyright-statement>',
			'<copyright-holder>',
			'<license>',
				'<license-p>',
					'<xref>',

	<figure class="table">
		<figcaption>Lemurs vs Other Things</figcaption>
		<table>
			<caption>An overview of the situation.</caption>
			<thead>
				<tr>
					<th>Animal</th>
			<tbody>
				<tr>
					<th scope="row">Lemurs</th>
		<div class="license">
			License: <a rel="license" href="http://example.come">CC Share-alike.</a>
		</div>
	*/
	$tables = pq('table-wrap');
	foreach ($tables as $table) {
		$pq_table = pq($table);
		anno_xml_to_html_iterate_table($pq_table);
	}
}
add_action('anno_xml_to_html', 'anno_xml_to_html_replace_tables');


/**
 * Do stuff to the table-wrap elements
 *
 * @param pq obj $table
 * @return void
 */
function anno_xml_to_html_iterate_table($table) {
	// Get table title & caption'
	$figcaption = $table->children('label:first')->html();
	$table_caption = $table->children('caption:first')->html();

	// Now that we have the title and caption, get rid of the elements
	$table->children('lbl:first')->remove();
	$table->children('caption:first')->remove();

	$inner_table = $table->children('table');

	// Loop over our table header
	$theads = $inner_table->children('thead');

	if (count($theads)) {
		foreach ($theads as $thead) {
			anno_xml_to_html_iterate_table_head(pq($thead));
		}
	}

	// Loop over our table body
	$tbodies = $inner_table->children('tbody');
	if (count($tbodies)) {
		foreach ($tbodies as $tbody) {
			anno_xml_to_html_iterate_table_body(pq($tbody));
		}
	}

	// Replace our table-wrap with our built-out HTML
	$html = '<figure class="table">';
	// PDF generation requires a figcaption element, even if its empty! Doesnt change html view.
	$html .= '<figcaption>'.$figcaption.'</figcaption>';
	$html .= '<table>';
	$html .= empty($table_caption) ? '' : '<caption>'.$table_caption.'</caption>';
	$html .= $table->children('table:first')->html();
	$html .= '</table>';
	$html .= '</figure><!-- /table -->';
	$table->replaceWith($html);
}


/**
 * Do stuff to the thead elements
 *
 * @param pq obj $thead
 * @return void
 */
function anno_xml_to_html_iterate_table_head($thead) {
	// Find our thead rows
	$trs = $thead->children('tr');
	if (count($trs)) {
		foreach ($trs as $tr) {
			anno_xml_to_html_iterate_table_head_row(pq($tr));
		}
	}
}


/**
 * Do stuff to the thead->tr elements
 *
 * @param pq obj $trow
 * @return void
 */
function anno_xml_to_html_iterate_table_head_row($trow) {
	$ths = $trow->children('th');
	if (count($ths)) {
		foreach ($ths as $th) {
			anno_xml_to_html_iterate_table_head_row_th(pq($th));
		}
	}
}

/**
 * Do stuff to the thead->tr->th elements
 *
 * Replace <br>s with <break>
 * the rest of it's HTML the same
 *
 * @param pq obj $th
 * @return void
 */
function anno_xml_to_html_iterate_table_head_row_th($th) {
	// Nothing to do here right now...just a stub function
}


/**
 * Iterate of elements of the tbody.  Not doing anything right now, just
 * here for when we need it.
 *
 * @param pq obj $tbody
 * @return void
 */
function anno_xml_to_html_iterate_table_body($tbody) {
	// Nothing to do here right now...just a stub function
}

/**
 * Replace xref's that are references with a hyperlink
 *
 * @param string $orig_xml - Original XML, prob. shouldn't need
 * @return void
 */
function anno_xml_to_html_replace_references($orig_xml) {
	$references = pq('xref[ref-type="bibr"]');
	foreach ($references as $ref) {
		$ref = pq($ref);
		$ref_id = $ref->attr('rid');
		$ref->replaceWith('<sup><a class="reflink" href="#'.esc_attr($ref_id).'">'.esc_html(preg_replace("/[^0-9]+/","",$ref_id)).'</a></sup>');
	}
}
add_action('anno_xml_to_html', 'anno_xml_to_html_replace_references');


/**
 * Replace external links with a hyperlink
 *
 * @param string $orig_xml - Original XML, prob. shouldn't need
 * @return void
 */
function anno_xml_to_html_replace_external_links($orig_xml) {
	$links = pq('ext-link');
	foreach ($links as $link) {
		$link = pq($link);
		if ($link->attr('ext-link-type') == 'uri') {
			if (version_compare(LIBXML_DOTTED_VERSION, '2.6.29', '<')) {
				$url = anno_get_attribute_value_regex($link, 'ext-link', 'xlink:href');
			}
			else {
				$url = $link->attr('xlink:href');
			}
			$title = $link->attr('title');
			$link->replaceWith('<a href="'.esc_url($url).'" title="'.esc_attr($title).'">'.esc_html($link->text()).'</a>');
		}
	}
}
add_action('anno_xml_to_html', 'anno_xml_to_html_replace_external_links');

/**
 * Replace disp-quotes with valid HTMl in <blockquote> style
 *
 * @param string $orig_xml - Original XML, prob. shouldn't need
 * @return void
 */
function anno_xml_to_html_replace_dispquotes( $orig_xml ) {
	$quotes = pq( 'disp-quote' );
	$tpl = new Anno_Template_Utils();

	foreach ( $quotes as $quote ) {
		$quote = pq( $quote );

		// Get our attribution
		$attrib = $quote->children( 'attrib:first' )->html();
		$by = $tpl->to_tag( 'span', '&mdash;', array( 'class' => 'by' ) );
		$attrib = $attrib ? $by.' '.$attrib : '';
		$attrib_tag = $tpl->to_tag( 'span', $attrib, array( 'class' => 'attribution' ) );

		$quote_markup = pq( 'p', $quote )->markupOuter();

		$blockquote_tag = $tpl->to_tag( 'blockquote', $quote_markup );

		$permissions = $quote->find( 'permissions' );
		$permissions_tag = anno_convert_permissions_to_html( $permissions );
		$permissions->remove();

		$quote_tag = $tpl->to_tag( 'div', $blockquote_tag.$attrib_tag.$permissions_tag, array( 'class' => 'quote' ) );

		// Do the actual HTML replacement
		$quote->replaceWith( $quote_tag );
	}
}
add_action( 'anno_xml_to_html', 'anno_xml_to_html_replace_dispquotes' );

/**
 * Swap preformat tags with pre tag.
 *
 * @param phpQueryObject $xml (unused, required by add_action)
 * @return void
 */
function anno_xml_to_html_preformat_tag($xml) {
	anno_convert_tag('preformat', 'pre');
}
add_action('anno_xml_to_html', 'anno_xml_to_html_preformat_tag');

/**
 * Convert permissions block to html
 *
 * @param phpQueryObject $permissions_pq_obj
 * @return void
 */
function anno_convert_permissions_to_html($permissions_pq_obj) {
	$permissions = pq($permissions_pq_obj);
	$tpl = new Anno_Template_Utils();
	$clauses = array();
	$clause_tag = '';

	foreach ($permissions as $permission) {
		$permission = pq($permission);

		$statement = $permission->find('copyright-statement')->text();
		$holder = $permission->find('copyright-holder')->text();
		$license = $permission->find('license > license-p')->text();

		$copyright = '';
		if ($statement && $holder) {
			$copyright = sprintf(
				_x('%1$s, %2$s.', 'Copyright statement, plus holder. E.g. "Copyright, Me".', 'anno'),
				$statement,
				$holder
			);
		}
		else if ($statement) {
			$copyright = sprintf(
				_x('%1$s.', 'Copyright statement sans holder. E.g. "Copyright"', 'anno'),
				$statement
			);
		}
		else if ($holder) {
			$copyright = sprintf(
				_x('Copyright, %1$s.', 'Copyright sans statement. We can assume copyright.', 'anno'),
				$holder
			);
		}

		$license = ($license ? $license : '');

		$clauses[] = sprintf('%1$s'."\n".'%2$s', $copyright, $license);
	}

	$clauses = implode(' ', $clauses);
	$clause_tag .= $tpl->to_tag('small', $clauses, array('class' => 'license'));

	return $clause_tag;
}

/**
 * Convert all tags that have been loaded in the phpQuery Document to a new type
 * Assumes a phpQuery object has been loaded. Modifies this object.
 *
 * @param string $old_tag Old tag to convert from
 * @param string $new_tag New tag to convert to
 * @param phpQueryObj $context context to search for tag within
 * @return void.
 */
function anno_convert_tag($old_tag, $new_tag, $context = null) {
	$tags = pq($old_tag);
	// Not the most efficient, phpQuery has no way to return elements that are inserted
	while(count($tags)) {
		foreach ($tags as $tag) {
			$tag = $tag_before = pq($tag);
			$tag_html = $tag->html();
			// $tag in memory is still tag from above, replaceWith created a new element, inserted into the document and then removed $tag from the document.
			$tag->replaceWith('<'.$new_tag.'>'.$tag_html.'</'.$new_tag.'>');
		}
		$tags = pq($old_tag);
	}
}

/**
 * Utilize RegEx to find the values of attributes given a specific element.
 * Bug libxml2 2.6.28 and previous with regards to selecting attributes with colons in their name
 *
 * @param phpQueryObject $element Element to preform the search on
 * @param string $element_name Name of the element to search for
 * @param string $attribute_name Name of the attribute to search for
 * @return string Value of the attribute for a given element, empty string otherwise
 *
 */
function anno_get_attribute_value_regex($element, $element_name, $attribute_name) {
	$outer_html = $element->markupOuter();

	// We only want to match everything in the media tag. Non greedy RegEx.
	if (preg_match('/<'.$element_name.' .*?>/', $outer_html, $element_match)) {
		// $media_match[0] should now just contain the opening media tag and its attribute
		// Match on attribute name where wrapping quotes can be any combination of ', ", or lack there of
		if (preg_match('/ '.$attribute_name.'=["\']?((?:.(?!["\']?\s+(?:\S+)=|[>"\']))+.)["\']?/', $element_match[0], $attribute_match)) {
			// $matches[1] should match data contained in parenthesis above
			if (isset($attribute_match[1])) {
				return $attribute_match[1];
			}
		}
	}
	return '';
}

/**
 * Convert caption tag to cap tag for display in editor
 * Browsers strip caption tags not wrapped in <table> tags.
 *
 * @param phpQueryObject $xml
 * @return void
 */
function anno_replace_caption_tag($xml) {
	anno_convert_tag('caption', 'cap');
}

/**
 * Convert p tag to para tag for display in editor
 * Browsers auto close <p> tag when it encounters another block level element.
 *
 * @param phpQueryObject $xml
 * @return void
 */
function anno_replace_p_tag($xml) {
	anno_convert_tag('p', 'para');
}

/**
 * Convert label tag to lbl tag for display in editor
 * Firefox has issues selecting inside a label tag when it is in a textarea
 *
 * @param phpQueryObject $xml
 * @return void
 */
function anno_replace_label_tag($xml) {
	anno_convert_tag('label', 'lbl');
}


/**
 * Swap para tags with p tag. P tag has issues with embedded block level elements
 *
 * @param phpQueryObject $xml (unused, required by add_action)
 * @return void
 */
function anno_to_xml_para_tag($xml) {
	anno_convert_tag('para', 'p');
}
add_action('anno_to_xml', 'anno_to_xml_para_tag');

/**
 * Swap lbl tags with label tag.
 *
 * @param phpQueryObject $xml (unused, required by add_action)
 * @return void
 */
function anno_to_xml_lbl_tag($xml) {
	anno_convert_tag('lbl', 'label');
}
add_action('anno_to_xml', 'anno_to_xml_lbl_tag');

/**
 * Format caption content and converts cap tags to caption to
 * match the DTD when saving editor content.
 * Browsers strip caption tags not wrapped in <table> tags.
 *
 * @param phpQueryObject $xml (unused, required by add_action)
 * @return void
 */
function anno_to_xml_cap_tag($xml) {
	$cap_tags = pq('cap');
	foreach ($cap_tags as $cap_tag) {
		// wpautop the Caption tags so there is no straggling text not wrapped in p
		$cap_tag = pq($cap_tag);

		$tag_html = wpautop($cap_tag->html());
		// Also need to convert cap to caption tags
		$cap_tag->replaceWith('<caption>'.$tag_html.'</caption>');
	}
}
add_action('anno_to_xml', 'anno_to_xml_cap_tag');

/**
 * Convert heading tags to title to match the DTD when saving editor content.
 * Browsers convert title content to html entities.
 *
 * @param phpQueryObject $xml
 * @return void
 */
function anno_to_xml_heading_tag($xml) {
	anno_convert_tag('heading', 'title');
}
add_action('anno_to_xml', 'anno_to_xml_heading_tag');

/**
 * Convert title tag to heading tag for display in editor
 * Browsers convert title content to html entities.
 *
 * @param phpQueryObject $xml
 * @return void
 */
function anno_replace_title_tag($xml) {
	anno_convert_tag('title', 'heading');
}

/**
 * Remove p tags which wrap list item content so the editor can handle the
 * unconventional xml structure as html.
 *
 * @param phpQueryObject $xml
 * @return void
 */
function anno_remove_p_from_list_items($xml) {
	anno_remove_p_from_items('list-item');
}

/**
 * Remove p tags which wrap disp-quote item content so the editor can handle the
 * unconventional xml structure as html.
 *
 * @param phpQueryObject $xml
 * @return void
 */
function anno_remove_p_from_disp_quote_items($xml) {
	anno_remove_p_from_items('disp-quote');
}

/**
 * Remove p tags from items stored in the phpQuery document based on name.
 *
 * @param string $tag_name Tag name to remove the p tags from
 * @return void
 */
function anno_remove_p_from_items($tag_name, $context = null) {
	$p_tags = pq($tag_name.' > para');
	while(count($p_tags)) {
		foreach ($p_tags as $p_tag) {
			$p_tag = pq($p_tag);
			$p_inner = $p_tag->html();
			$p_tag->replaceWith($p_inner);
		}
		$p_tags = pq($tag_name.' > para');
	}
}

/**
 * Add p tags which wrap list item content for valid XML on post save
 *
 * @param phpQueryObject $xml
 * @return void
 */
function anno_to_xml_list_item_p($xml) {
	$list_items = pq('list-item');
	foreach ($list_items as $list_item) {
		$list_item = pq($list_item);
		$list_item->wrapInner('<p />');
	}
}
add_action('anno_to_xml', 'anno_to_xml_list_item_p');

/**
 * Add p tags to disp-quote content
 *
 * @param phpQueryObject $xml not used
 * @return void
 */
function anno_to_xml_disp_quote_p($xml) {
	$quotes = pq('disp-quote');
	foreach ($quotes as $quote) {
		$quote = pq($quote);

		$attribution = $quote->find('attrib');
		$permissions = $quote->find('permissions');

		$attribution_markup = $attribution->htmlOuter();
		$permissions_markup = $permissions->htmlOuter();

		// Remove attribution and permissions so they don't get included in wpautop
		$attribution->remove();
		$permissions->remove();

		// wpautop the content
		$quote_content = wpautop($quote->html());
		$quote->html($quote_content);

		// "We can rebuild him, we have the technology"
		$quote->append($attribution_markup);
		$quote->append($permissions_markup);
	}
}
add_action('anno_to_xml', 'anno_to_xml_disp_quote_p');

/**
 * Determines whether or not a DOI lookup is feasible with the credentials given
 *
 * @return bool
 */
function anno_doi_lookup_enabled() {
	// A login (optional password) is required for DOI lookup.
	$crossref_login = cfct_get_option('crossref_login');
	return !empty($crossref_login);
}

function anno_tinymce_css($hook) {
	global $post_type;
	if ($post_type == 'article') {
		$main = trailingslashit(get_template_directory_uri());
		wp_enqueue_style('eqeditor', $main.'js/tinymce/plugins/annoequations/equationeditor.css');
		wp_enqueue_style('textorum', $main.'js/textorum/dist/textorum/css/editor.css', array('editor-buttons'));
	}
}
add_action('admin_print_styles-post.php', 'anno_tinymce_css');
add_action('admin_print_styles-post-new.php', 'anno_tinymce_css');

function anno_tinymce_js() {
	global $post_type;
	if ($post_type == 'article') {
		$main = trailingslashit(get_template_directory_uri());

		wp_enqueue_script('closure-goog', $main.'js/tinymce/plugins/annoequations/equation-editor-compiled.js');
	}
}
add_action('admin_print_scripts-post.php', 'anno_tinymce_js');
add_action('admin_print_scripts-post-new.php', 'anno_tinymce_js');

/**
 * Remove specific filters for non-admins for saving content properly
 */
function anno_remove_kses_from_content() {
	// If we don't remove these, WP treats <list-item> as <list> for non-admin users
	remove_filter('content_save_pre', 'wp_filter_post_kses');
	remove_filter('content_filtered_save_pre', 'wp_filter_post_kses');
}
add_action('init', 'anno_remove_kses_from_content');

