PageRenderTime 1107ms CodeModel.GetById 101ms app.highlight 615ms RepoModel.GetById 132ms app.codeStats 1ms

/code/cake/app/webroot/research/wp-content/themes/annotum-base/functions.php

https://github.com/DigitalPaulScholtenProject/DPSP-Platform
PHP | 1509 lines | 1040 code | 178 blank | 291 comment | 167 complexity | 4fae0739e3752295cb93c5fb8324184e MD5 | raw file
   1<?php
   2
   3/**
   4 * @package anno
   5 * This file is part of the Annotum theme for WordPress
   6 * Built on the Carrington theme framework <http://carringtontheme.com>
   7 *
   8 * Copyright 2008-2011 Crowd Favorite, Ltd. All rights reserved. <http://crowdfavorite.com>
   9 * Released under the GPL license
  10 * http://www.opensource.org/licenses/gpl-license.php
  11 */
  12if (__FILE__ == $_SERVER['SCRIPT_FILENAME']) { die(); }
  13
  14define('CFCT_DEBUG', false);
  15define('CFCT_PATH', trailingslashit(TEMPLATEPATH));
  16define('ANNO_VER', '1.1');
  17
  18include_once(CFCT_PATH.'carrington-core/carrington.php');
  19include_once(CFCT_PATH.'functions/Anno_Keeper.php');
  20include_once(CFCT_PATH.'functions/article-post-type.php');
  21include_once(CFCT_PATH.'functions/appendix-repeater.php');
  22include_once(CFCT_PATH.'functions/taxonomies.php');
  23include_once(CFCT_PATH.'functions/capabilities.php');
  24include_once(CFCT_PATH.'functions/featured-articles.php');
  25include_once(CFCT_PATH.'functions/template.php');
  26include_once(CFCT_PATH.'functions/widgets.php');
  27include_once(CFCT_PATH.'functions/profile.php');
  28include_once(CFCT_PATH.'functions/tinymce.php');
  29include_once(CFCT_PATH.'functions/tinymce-upload/tinymce-uploader.php');
  30include_once(CFCT_PATH.'functions/tinymce-upload/image-popup.php');
  31include_once(CFCT_PATH.'functions/phpquery/phpquery.php');
  32include_once(CFCT_PATH.'functions/anno-xml-download.php');
  33include_once(CFCT_PATH.'functions/subscribe.php');
  34include_once(CFCT_PATH.'functions/snapshot.php');
  35
  36if (!function_exists('write_log')) {
  37	function write_log ( $log )  {
  38		if ( true === WP_DEBUG ) {
  39			if ( is_array( $log ) || is_object( $log ) ) {
  40				error_log( print_r( $log, true ) );
  41			} else {
  42				error_log( $log );
  43			}
  44		}
  45	}
  46}
  47
  48
  49
  50function anno_setup() {
  51	$path = trailingslashit(TEMPLATEPATH);
  52	
  53	// i18n support
  54	load_theme_textdomain('anno', $path . 'languages');
  55	$locale = get_locale();
  56	$locale_file = $path . '/languages/' . $locale . '.php';
  57	if ( is_readable( $locale_file ) ) {
  58		require_once( $locale_file );
  59	}
  60	
  61	add_theme_support('automatic-feed-links');
  62	//add_theme_support('post-thumbnails', array( 'article', 'post' ) );
  63	add_image_size( 'post-excerpt', 140, 120, true);
  64	add_image_size( 'post-teaser', 100, 79, true);
  65	add_image_size( 'featured', 270, 230, true);
  66	add_image_size( 'header', 500, 500, false);
  67	
  68	$header_image = Anno_Keeper::retrieve('header_image');
  69	$header_image->add_custom_image_header();
  70	
  71	$menus = array(
  72		'main' => 'Main Menu (Header)',
  73		'secondary' => 'Secondary Menu (Header)',
  74		'footer' => 'Footer Menu',
  75	);
  76	register_nav_menus($menus);
  77	
  78	$sidebar_defaults = array(
  79		'before_widget' => '<aside id="%1$s" class="widget clearfix %2$s">',
  80		'after_widget' => '</aside>',
  81		'before_title' => '<h1 class="title">',
  82		'after_title' => '</h1>'
  83	);
  84	register_sidebar(array_merge($sidebar_defaults, array(
  85		'name' => __('Default Sidebar', 'anno'),
  86		'id' => 'default'
  87	)));
  88	register_sidebar(array_merge($sidebar_defaults, array(
  89		'name' => __('Page Sidebar', 'anno'),
  90		'id' => 'sidebar-page',
  91		'description' => __('This sidebar will be shown on Pages.', 'anno')
  92	)));
  93	register_sidebar(array_merge($sidebar_defaults, array(
  94		'name' => __('Article Sidebar', 'anno'),
  95		'id' => 'sidebar-article',
  96		'description' => __('This sidebar will be shown single Articles.', 'anno')
  97	)));
  98	register_sidebar(array_merge($sidebar_defaults, array(
  99		'name' => __('Masthead Teasers', 'anno'),
 100		'id' => 'masthead',
 101		'description' => __('Display items on the home page masthead.','anno'),
 102		'before_widget' => '<aside id="%1$s" class="teaser clearfix %2$s">'
 103	)));
 104	// Customize the Carrington Core Admin Settings Form Title
 105	add_filter('cfct_admin_settings_menu', 'anno_admin_settings_menu_form_title');
 106	add_filter('cfct_admin_settings_form_title', 'anno_admin_settings_menu_form_title');
 107	add_filter('cfct_admin_settings_title', 'anno_admin_settings_menu_form_title');
 108}
 109add_action('after_setup_theme', 'anno_setup');
 110
 111
 112if (!function_exists('anno_load_plugins')) {
 113	// Plugins specific to certain themes can be loaded with this function
 114	function anno_load_plugins() {
 115		// Only include color picker in the annotum-base theme.
 116		include_once(CFCT_PATH.'plugins/anno-colors/anno-colors.php');
 117	}
 118	add_action('init', 'anno_load_plugins');
 119}
 120
 121// Filter to customize the Carrington Core Admin Settings Form Title
 122function anno_admin_settings_menu_form_title() {
 123	return _x('Annotum Settings', 'menu and options heading', 'anno');
 124}
 125
 126/**
 127 * Add theme CSS, JS here. Everything should run through the enqueue system so that
 128 * child themes/plugins have access to override whatever they need to.
 129 * Run at 'wp' hook so we have access to conditional functions, like is_single(), etc.
 130 */
 131function anno_assets() {
 132	// Do not load with cfct_template as it will use the child them only if load.php exists there
 133	include_once(CFCT_PATH.'assets/load.php');
 134}
 135add_action('wp_enqueue_scripts', 'anno_assets');
 136
 137/**
 138 * Bring in our main.css on the dashboard page.  Should be cached
 139 * already so it shouldn't be a big thing, even though we only need
 140 * one definition from it.
 141 *
 142 * @return void
 143 */
 144function anno_dashboard_assets($hook_suffix) {
 145	if ($hook_suffix == 'index.php') {
 146		wp_enqueue_style('anno', trailingslashit(get_template_directory_uri()) .'assets/main/css/main.css', array(), ANNO_VER);
 147	}
 148}
 149add_action('load-index.php', 'anno_dashboard_assets');
 150
 151/**
 152 * Register custom widgets extended from WP_Widget
 153 */
 154function anno_widgets_init() {
 155	include_once(CFCT_PATH . 'functions/Anno_Widget_Recently.php');
 156	register_widget('Anno_Widget_Recently');
 157	register_widget('WP_Widget_Solvitor_Ad');
 158}
 159add_action('widgets_init', 'anno_widgets_init');
 160
 161// Adding favicon, each theme has it's own which we get with stylesheet directory
 162function anno_favicon() {
 163	echo '<link rel="shortcut icon" href="/favicon.ico" />';//JVDP
 164}
 165add_action('wp_head', 'anno_favicon');
 166
 167/*
 168 * Outputs a few extra semantic tags in the <head> area.
 169 * Hook into 'wp_head' action.
 170 */
 171function anno_head_extra() {
 172	echo '<link rel="pingback" href="'.get_bloginfo('pingback_url').'" />'."\n";
 173	$args = array(
 174		'type' => 'monthly',
 175		'format' => 'link'
 176	);
 177	wp_get_archives($args);
 178}
 179add_action('wp_head', 'anno_head_extra');
 180
 181/**
 182 * Filter the default menu arguments
 183 */
 184function anno_wp_nav_menu_args($args) {
 185	$args['fallback_cb'] = null;
 186	if ($args['container'] == 'div') {
 187		$args['container'] = 'nav';
 188	}
 189	if ($args['depth'] == 0) {
 190		$args['depth'] = 2;
 191	}
 192	if ($args['menu_class'] == 'menu') {
 193		$args['menu_class'] = 'nav';
 194	}
 195	
 196	return $args;
 197}
 198add_filter('wp_nav_menu_args', 'anno_wp_nav_menu_args');
 199
 200/**
 201 * Filter the post class to add a .has-featured-image class when featured image
 202 * is present.
 203 * @return array $classes array of post classes
 204 */
 205function anno_post_class($classes, $class) {
 206	$has_img = 'has-featured-image';
 207	
 208	/* An array of classes that we want to create an additional faux compound class for.
 209	This lets us avoid having to do something like
 210	.article-excerpt.has-featured-image, which doesn't work in IE6.
 211	Instead, we can do .article-excerpt-has-featured-image. While a bit verbose,
 212	it will nonetheless do the trick. */
 213	$compoundify = array(
 214		'article-excerpt'
 215	);
 216	
 217	if (has_post_thumbnail()) {
 218		$classes[] = $has_img;
 219		
 220		foreach ($compoundify as $compound_plz) {
 221			if (in_array($compound_plz, $classes)) {
 222				$classes[] = $compound_plz . '-' . $has_img;
 223			}
 224		}
 225	}
 226	
 227	return $classes;
 228}
 229add_filter('post_class', 'anno_post_class', 10, 2);
 230
 231function anno_post_category_list($separator) {
 232	$html = '';
 233	
 234	$cat_list = get_the_category_list( $separator);
 235	if(!empty($cat_list)) {
 236		$html.=' &middot; ' . $cat_list;
 237	}
 238	return $html;
 239	
 240}
 241
 242/**
 243 * Customize comment form defaults
 244 */
 245function anno_comment_form_defaults($defaults) {
 246	$req = get_option( 'require_name_email' );
 247	$req_attr = ( $req ? ' required' : '' );
 248	$req_label = ( $req ? '<abbr class="required" title="'.__('Required', 'anno').'">*</abbr>' : '');
 249	$commenter = wp_get_current_commenter();
 250	
 251	$fields = apply_filters('comment_form_default_fields', array(
 252		'author' => '<p class="row author">' . '<label for="author">' . __('Your Name', 'anno') . $req_label . '</label> <input id="author" class="type-text" name="author" type="text" value="' . esc_attr($commenter['comment_author']) . '"' . $req_attr . '></p>',
 253		'email' => '<p class="row email"><label for="email">' . __('Email Address', 'anno') . $req_label . '</label> <input id="email" class="type-text" name="email" type="email" value="' . esc_attr(  $commenter['comment_author_email'] ) . '"' . $req_attr . '></p>',
 254		'url' => '<p class="row url"><label for="url">' . __( 'Website', 'anno' ) . '</label> <input id="url" class="type-text" name="url" type="url" value="' . esc_attr( $commenter['comment_author_url'] ) . '"></p>'
 255	));
 256	
 257	$new = array(
 258		'comment_field' => '<p class="row"><label for="comment">' . _x('Comment', 'noun', 'anno') . '</label> <textarea id="comment" name="comment" required></textarea></p>',
 259		'fields' => $fields,
 260		'cancel_reply_link' => __('(cancel)', 'anno'),
 261		'title_reply' => __('Leave a Comment', 'anno'),
 262		'title_reply_to' => __('Leave a Reply to %s', 'anno'),
 263		'label_submit' => __('Submit', 'anno'),
 264		'comment_notes_after' => '',
 265		'comment_notes_before' => ''
 266	);
 267	
 268	return array_merge($defaults, $new);
 269}
 270add_filter('comment_form_defaults', 'anno_comment_form_defaults');
 271
 272/**
 273 * Register Theme settings
 274 */
 275function anno_settings($settings) {
 276	unset($settings['cfct']['fields']['login']);
 277	unset($settings['cfct']['fields']['copyright']);
 278	unset($settings['cfct']['fields']['credit']);
 279	unset($settings['cfct']['fields']['about']);
 280	
 281	$yn_options = array(
 282		'1' => __('Yes', 'anno'),
 283		'0' => __('No', 'anno')
 284	);
 285	
 286	$anno_settings_top = array(
 287		'anno_top' => array(
 288			'label' => _x('Theme Settings', 'options heading', 'anno'),
 289			'fields' => array(
 290				'callout-left-title' => array(
 291					'type' => 'text',
 292					'name' => 'anno_callouts[0][title]',
 293					'label' => _x('Home Page Callout Left Title', 'Label text for settings screen', 'anno'),
 294					'class' => 'cfct-text-long',
 295				),
 296				'callout-left-url' => array(
 297					'type' => 'text',
 298					'name' => 'anno_callouts[0][url]',
 299					'label' => _x('Home Page Callout Left URL', 'Label text for settings screen', 'anno'),
 300					'class' => 'cfct-text-long',
 301				),
 302				'callout_left-content' => array(
 303					'type' => 'textarea',
 304					'name' => 'anno_callouts[0][content]',
 305					'label' => _x('Home Page Callout Left Content', 'Label text for settings screen', 'anno'),
 306				),
 307				'callout-right-title' => array(
 308					'type' => 'text',
 309					'name' => 'anno_callouts[1][title]',
 310					'label' => _x('Home Page Callout Right Title', 'Label text for settings screen', 'anno'),
 311					'class' => 'cfct-text-long',
 312				),
 313				'callout-right-url' => array(
 314					'type' => 'text',
 315					'name' => 'anno_callouts[1][url]',
 316					'label' => _x('Home Page Callout Right URL', 'Label text for settings screen', 'anno'),
 317					'class' => 'cfct-text-long',
 318				),
 319				'callout-right-content' => array(
 320					'type' => 'textarea',
 321					'name' => 'anno_callouts[1][content]',
 322					'label' => _x('Home Page Callout Right Content', 'Label text for settings screen', 'anno'),
 323				),
 324			),		
 325		),
 326	);
 327	
 328	$settings = array_merge($anno_settings_top, $settings);
 329	
 330	$anno_settings_bottom = array(
 331		'anno_bottom' => array(
 332			'label' => '',
 333			'fields' => array(
 334				'callout-right-content' => array(
 335					'type' => 'select',
 336					'name' => 'anno_home_post_type',
 337					'label' => _x('Front Page Post Type', 'Label text for settings screen', 'anno'),
 338					'options' => array(
 339						'article' => _x('Article', 'post type name for select option', 'anno'),
 340						'post' => _x('Post', 'post type name for select option', 'anno'),
 341					),
 342				),
 343			),		
 344		),
 345		'anno_ga' => array(
 346			'label' =>  _x('Google Analytics', 'options heading', 'anno'),
 347			'fields' => array(
 348				'anno_ga_id' => array(
 349					'label' => _x('Google Analytics ID', 'options label', 'anno'),
 350					'label_for' => 'anno-ga-id',
 351					'name' => 'ga_id',
 352					'type' => 'text',
 353					'help' => ' <span class="cfct-help">'._x('ex: UA-123456-12', 'help text for option input', 'anno').'</span>',
 354				),
 355			),
 356		),
 357		'annowf_settings' => array(
 358			'label' =>  _x('Workflow Options', 'options heading', 'anno'),
 359			'fields' => array(
 360				'workflow' => array(
 361					'label' => _x('Enable Workflow', 'options label', 'anno'),
 362					'name' => 'workflow_settings[workflow]',
 363					'type' => 'radio',
 364					'options' => $yn_options,
 365				),
 366				'author_reviewer' => array(
 367					'label' => _x('Allow article authors to see reviewers', 'options label', 'anno'),
 368					'name' => 'workflow_settings[author_reviewer]',
 369					'type' => 'radio',
 370					'options' => $yn_options,
 371				),
 372				'notifications' => array(
 373					'label' => _x('Enable workflow notifications', 'options label', 'anno'),
 374					'name' => 'workflow_settings[notifications]',
 375					'type' => 'radio',
 376					'options' => $yn_options,
 377				),
 378				'listing_filter' => array(
 379					'label' => _x('Enable article and media list page filter', 'options label', 'anno'),
 380					'name' => 'workflow_settings[listing_filter]',
 381					'type' => 'radio',
 382					'options' => $yn_options,
 383				),
 384			),
 385		),
 386		'anno_journal' => array(
 387			'label' =>  _x('Journal Options', 'options heading', 'anno'),
 388			'fields' => array(
 389				'journal_name' => array(
 390					'label' => _x('Journal Name', 'options label', 'anno'),
 391					'name' => 'journal_name',
 392					'type' => 'text',
 393				),
 394				'journal_abbr' => array(
 395					'label' => _x('Journal Abbreviation', 'options label', 'anno'),
 396					'name' => 'journal_abbr',
 397					'type' => 'text',
 398				),
 399				'journal_id' => array(
 400					'label' => _x('Journal ID', 'options label', 'anno'),
 401					'name' => 'journal_id',
 402					'type' => 'text',
 403				),
 404				'journal_id_type' => array(
 405					'label' => _x('Journal ID Type', 'options label', 'anno'),
 406					'name' => 'journal_id_type',
 407					'type' => 'text',
 408				),
 409				'journal_issn' => array(
 410					'label' => _x('Journal ISSN', 'options label', 'anno'),
 411					'name' => 'journal_issn',
 412					'type' => 'text',
 413				),
 414				'publisher_name' => array(
 415					'label' => _x('Publisher Name', 'options label', 'anno'),
 416					'name' => 'publisher_name',
 417					'type' => 'text',
 418				),
 419				'publisher_location' => array(
 420					'label' => _x('Publisher Location', 'options label', 'anno'),
 421					'name' => 'publisher_location',
 422					'type' => 'text',
 423				),
 424				'publisher_issn' => array(
 425					'label' => _x('Publisher ISSN', 'options label', 'anno'),
 426					'name' => 'publisher_issn',
 427					'type' => 'text',
 428				),
 429			),
 430		),
 431		'anno_crossref' => array(
 432			'label' =>  _x('CrossRef Credentials', 'options heading', 'anno'),
 433			'fields' => array(
 434				'crossref_login' => array(
 435					'label' => _x('Login', 'options label', 'anno'),
 436					'name' => 'crossref_login',
 437					'type' => 'text',
 438				),
 439				'crossref_pass' => array(
 440					'label' => _x('Password', 'options label', 'anno'),
 441					'name' => 'crossref_pass',
 442					'type' => 'password',
 443				),
 444				'registrant_code' => array(
 445					'label' => _x('Registrant Code', 'options label', 'anno'),
 446					'name' => 'registrant_code',
 447					'type' => 'text',
 448				),
 449				'doi_prefix' => array(
 450					'label' => _x('DOI Prefix', 'options label', 'anno'),
 451					'name' => 'doi_prefix',
 452					'type' => 'text',
 453				),
 454			),
 455		),
 456	);
 457	
 458	$settings = array_merge($settings, $anno_settings_bottom);
 459	
 460	return $settings;
 461}
 462add_filter('cfct_options', 'anno_settings');
 463
 464function anno_sanitize_ga_id($new_value) {
 465	// Enforces a aa-a1234b-0 pattern
 466	if ($new_value == '' || (bool)preg_match('/^[a-zA-Z]{2,}-[a-zA-Z0-9]{2,}-[a-zA-Z0-9]{1,}$/', $new_value)) {
 467		$new_value = anno_sanitize_string($new_value);
 468	}
 469	else {
 470		$new_value = cfct_get_option('ga_id');
 471		if (function_exists('add_settings_error')) {
 472			add_settings_error('anno_ga_id', 'invalid_ga_id', _x('Invalid Google Analytics ID', 'error message', 'anno'));
 473		}
 474	}
 475	return $new_value;
 476}
 477
 478add_action('sanitize_option_anno_ga_id', 'anno_sanitize_ga_id');
 479
 480/**
 481 * Check to see if anno_home_post_type is set to article. If so, and we're on the
 482 * home page, intercept the default query and change the post type to article.
 483 * Hook @ 'pre_get_posts'.
 484 */
 485function anno_modify_home_query($query) {
 486	if (!is_admin()) {
 487		global $wp_the_query;
 488		// Check if this is the main loop (so we don't interfere with nav menus, etc)
 489		if ($query === $wp_the_query && $query->is_home) {
 490			$show_post_type = get_option('anno_home_post_type', 'article');
 491			if ($show_post_type == 'article') {
 492				$query->set('post_type', 'article');
 493			}
 494		}
 495	}
 496}
 497add_action('pre_get_posts', 'anno_modify_home_query');
 498
 499/**
 500 * Register default option values
 501 */ 
 502function anno_defaults($defaults) {
 503	$defaults['anno_home_post_type'] = 'article';
 504	$defaults['anno_workflow_settings'] = array(
 505		'workflow' => 0,
 506		'author_reviewer' => 0,
 507		'notifications' => 0,
 508		'listing_filter' => 0,
 509	);
 510	return $defaults;
 511}
 512add_filter('cfct_option_defaults', 'anno_defaults');
 513
 514/**
 515 * Override the default cfct prefix if we've already name spaced our options.
 516 */ 
 517function anno_option_prefix($prefix) {
 518	return 'anno';
 519}
 520add_filter('cfct_option_prefix', 'anno_option_prefix', 10, 2);
 521
 522/**
 523 * Determines whether or not an email address is valid
 524 * 
 525 * @param string $email email to check
 526 * @return bool true if it is a valid email, false otherwise
 527 */ 
 528function anno_is_valid_email($email) {
 529	return filter_var($email, FILTER_VALIDATE_EMAIL);
 530}
 531
 532/**
 533 * Determines whether or not a username is valid
 534 * 
 535 * @param string $username username to check
 536 * @return bool true if it is a valid username, false otherwise
 537 */ 
 538function anno_is_valid_username($username) {
 539	return (strcasecmp($username, sanitize_user($username, true)) == 0);
 540}
 541
 542/**
 543 * Returns an appropriate link for editing a given user.
 544 * Based on code found in WP Core 3.2
 545 * 
 546 * @param int $user_id The id of the user to get the url for
 547 * @return string edit user url
 548 */ 
 549function anno_edit_user_url($user_id) {
 550	if ( get_current_user_id() == $user_id ) {
 551		$edit_url = 'profile.php';
 552	}
 553	else {
 554		$edit_url = admin_url(esc_url( add_query_arg( 'wp_http_referer', urlencode(stripslashes($_SERVER['REQUEST_URI'])), "user-edit.php?user_id=$user_id" )));
 555	}
 556	return $edit_url;
 557	
 558}
 559
 560/**
 561 * Function to limit front-end display of comments. 
 562 * Wrap this filter around comments_template();
 563 * 
 564 * @todo Update to WP_Comment_Query filter when WP updates core to use non-hardcoded queries.
 565 */
 566function anno_internal_comments_query($query) {
 567	$query = str_replace('WHERE', 'WHERE comment_type NOT IN (\'article_general\', \'article_review\') AND', $query);
 568	return $query;
 569}
 570add_filter('comment_feed_where', 'anno_internal_comments_query');
 571
 572
 573/**
 574 * Output Google Analytics Code if a GA ID is present
 575 */
 576function anno_ga_js() {
 577	$ga_id = cfct_get_option('ga_id');
 578	if (!empty($ga_id)) {
 579?>
 580<script type="text/javascript">
 581
 582  var _gaq = _gaq || [];
 583  _gaq.push(['_setAccount', '<?php echo esc_js($ga_id); ?>']);
 584  _gaq.push(['_trackPageview']);
 585
 586  (function() {
 587    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
 588    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
 589    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
 590  })();
 591
 592</script>
 593<?php
 594	}
 595}
 596if (!is_admin()) {
 597	add_action('wp_print_scripts', 'anno_ga_js');
 598}
 599
 600/**
 601 * Get a list of authors for a given post
 602 * 
 603 * @param int post_id post ID to retrieve users from
 604 * @return array Array of user IDs
 605 */ 
 606function anno_get_authors($post_id) {
 607	return array_unique(anno_get_post_users($post_id, 'author'));
 608}
 609
 610/**
 611 * Get a list of reviewers for a given post
 612 * 
 613 * @param int post_id post ID to retrieve users from
 614 * @return array Array of user IDs
 615 */
 616function anno_get_reviewers($post_id) {
 617	return array_unique(anno_get_post_users($post_id, 'reviewer'));
 618}
 619
 620/**
 621 * Gets all user of a certain role for a given post 
 622 *
 623 * @param int $post_id ID of the post to check
 624 * @param string $type the type/role of user to get. Accepts meta key or role.
 625 * @return array Array of reviewers (or empty array if none exist)
 626 */
 627function anno_get_post_users($post_id, $type) {
 628	$type = str_replace('-', '_', $type);
 629	if ($type == 'reviewer' || $type == 'author') {
 630		$type = '_anno_'.$type.'_order';
 631	}
 632	$users = get_post_meta($post_id, $type, true);
 633
 634	if (!is_array($users)) {
 635		return array();
 636	}
 637	else {
 638		return $users;
 639	}
 640}
 641
 642/**
 643 * Add author to meta co-author for more efficient author archive queries
 644 */ 
 645function anno_wp_insert_post($post_id, $post) {
 646	if (($post->post_type == 'article' || $post->post_type == 'post') && !in_array($post->post_status,  array('inherit', 'auto-draft'))) {
 647		
 648		$authors = get_post_meta($post_id, '_anno_author_order', true);
 649		if (!is_array($authors)) {
 650			update_post_meta($post_id, '_anno_author_order', array($post->post_author));
 651			add_post_meta($post_id, '_anno_author_'.$post->post_author, $post->post_author, true);
 652		}
 653		else if (!in_array($post->post_author, $authors)) {
 654			// Make sure the primary author is first
 655			array_unshift($authors, $post->post_author);
 656			update_post_meta($post_id, '_anno_author_order', array_unique($authors));
 657			add_post_meta($post_id, '_anno_author_'.$post->post_author, $post->post_author, true);
 658		}
 659	}
 660// 	if(empty($post->excerpt)){
 661// 		wp_update_post(array('ID'=>$post_id,'excerpt'=>"asdf"));
 662// 	}
 663}
 664add_action('wp_insert_post', 'anno_wp_insert_post', 10, 2);
 665
 666
 667add_filter( 'wp_insert_post_data' , 'modify_post_title' , '99', 2 );
 668
 669function modify_post_title( $data , $postarr )//JVDP to prevent connection reset error
 670{
 671	write_log($data);
 672	if(empty($data['post_excerpt'])){
 673  		$data['post_excerpt'] = 'No abstract';
 674  	}
 675  return $data;
 676}
 677
 678function anno_format_name($prefix, $first, $last, $suffix) {
 679	$name = $first.' '.$last;
 680	$name = ($prefix!='')?$prefix.' '.$name:$name;
 681	$name = ($suffix!='')?$name.', '.$suffix:$name;
 682	
 683	return $name;
 684}
 685
 686/**
 687 * Sanitizes a string for insertion into DB
 688 * @param string $option The string to be sanitized
 689 * @return string Sanitized string
 690 */ 
 691function anno_sanitize_string($option) {
 692	$option = addslashes($option);
 693	$option = wp_filter_post_kses($option); // calls stripslashes then addslashes
 694	$option = stripslashes($option);
 695	$option = esc_html($option);
 696	
 697	return $option;
 698}
 699
 700/**
 701 * Exhaustive search for a post ID.
 702 * 
 703 * @return int Post ID
 704 */ 
 705function anno_get_post_id() {
 706	global $post_id;
 707	
 708	$local_post_id = 0;
 709	
 710	if (empty($post_id)) {
 711		global $post;
 712		if (isset($post->ID)) {
 713			$local_post_id = $post->ID;
 714		}
 715		// Used in ajax requests where global aren't populated, attachments, etc...
 716		else if (isset($_POST['post'])) {
 717			$local_post_id = $_POST['post'];
 718		}
 719		else if (isset($_POST['post_ID'])) {
 720			$local_post_id = $_POST['post_ID'];
 721		}
 722		else if (isset($_POST['post_id'])) {
 723			$local_post_id = $_POST['post_id'];
 724		}
 725		else if (isset($_GET['post'])) {
 726			$local_post_id = $_GET['post'];
 727		}
 728		else if (isset($_GET['post_id'])) {
 729			$local_post_id = $_GET['post_id'];
 730		}
 731	}
 732	else {
 733		$local_post_id = $post_id;
 734	}
 735	return intval($local_post_id);
 736}
 737
 738/**
 739 * Returns a user's display. First Name Last Name if either exist, otherwise just their login name.
 740 *
 741 * @param int|stdObj $user WP user object, or user ID
 742 * @return string A string displaying a users name.
 743 */
 744function anno_user_display($user) {
 745	if (is_numeric($user)) {
 746		$user = get_userdata(intval($user));
 747	}
 748	
 749	return !empty($user->display_name) ? $user->display_name : '';
 750}
 751
 752/**
 753 * Returns a user's email given their user object.
 754 *
 755 * @param stdObj $user WP user object
 756 * @return string The email of the given user
 757 */
 758function anno_user_email($user) {
 759	if (is_numeric($user)) {
 760		$user = get_userdata(intval($user));
 761	}
 762	return $user->user_email;
 763}
 764
 765/**
 766 * Creates a new user, and sends that user an email. Returns a WP Error if the user was unable to be created.
 767 * 
 768 * @param string $username Username to create
 769 * @param string $email Email of user to create
 770 * @return int|WP_Error ID of new user, or, WP_Error 
 771 */ 
 772function anno_invite_contributor($user_login, $user_email, $extra = array()) {
 773	// Wish to be able to invite other contributors, so no create_user check
 774	
 775	$current_user = wp_get_current_user();
 776	
 777	// wp_insert_user handles all other errors
 778	if (!anno_is_valid_email($user_email)) {
 779		return new WP_Error('invalid_email', _x('Invalid email address', 'error for creating new user', 'anno'));
 780	}
 781	
 782	// We don't want wp_insert_user to just sanitize the username stripping characters, the user should be alerted if the user input is wrong
 783	if (!anno_is_valid_username($user_login)) {
 784		return new WP_Error('invalid_username', _x('Invalid username', 'error for creating new user', 'anno'));
 785	}
 786		
 787	// Create User
 788	$user_pass = wp_generate_password();	
 789	$user_login = esc_sql($user_login);
 790	$user_email = esc_sql($user_email);
 791	$role = 'contributor';
 792	$userdata = compact('user_login', 'user_pass', 'user_email', 'role');
 793
 794	array_merge($extra, $userdata);
 795
 796	$user_id = wp_insert_user($userdata);
 797
 798	$blogname = get_bloginfo('name');
 799	
 800	// Send notifiction with PW, Username.	
 801	if (!is_wp_error($user_id)) {
 802		$subject = sprintf(_x('You have been invited to join %s', 'email subject %s represents blogname', 'anno'), $blogname);
 803		$message =  sprintf(_x(
 804'%s has created a user with your email address for %s.
 805Please use the following credentials to login and change your password:
 806
 807Username: %s
 808Password: %s
 809%s', 'User creation email body. %s mapping: User who created this new user, blogname, username, password, profile url.', 'anno'),
 810		$current_user->display_name, $blogname, $user_login, $user_pass, esc_url(admin_url('profile.php')));
 811		
 812		wp_mail($user_email, $subject, $message);
 813	}
 814
 815	return $user_id;
 816}
 817
 818/**
 819 * Get published post ids for a given post type
 820 *
 821 * @param array $posts_types 
 822 * @return array of post ids that are published for the posts types defined
 823 */
 824function anno_get_published_posts($post_types = array('article')) {
 825	$posts = array();
 826		
 827	// author will always be stored in post_meta
 828	$query = new WP_Query(array(
 829		'fields' => 'ids',
 830		'post_type' => $post_types,
 831		'post_status' => array('publish'),
 832		'cache_results' => false,
 833		'posts_per_page' => -1,
 834	));
 835	
 836	if (isset($query->posts) && is_array($query->posts)) {
 837		$posts = $query->posts;
 838	}
 839	
 840	wp_reset_query();
 841	
 842	return $posts;
 843}
 844
 845/**
 846 * Get a list of posts a user is the author or co-author on
 847 *
 848 * @param int $user_id User id to look up, else uses current user id
 849 * @param array $post_type Post types to find posts for, defaults to article
 850 * @param array $post_stati Post statuses to look up 
 851 * @return array Empty array or array of post ids
 852 * @author Evan Anderson
 853 */
 854function anno_get_owned_posts($user_id = false, $post_types = array('article'), $post_statuses = array('draft', 'pending', 'private', 'future')) {
 855	$posts = array();
 856	
 857	if (empty($user_id)) {
 858		$user_id = get_current_user_id();
 859	}
 860	
 861	// author will always be stored in post_meta
 862	$query = new WP_Query(array(
 863		'fields' => 'ids',
 864		'post_type' => $post_types,
 865		'post_status' => $post_statuses,
 866		'cache_results' => false,
 867		'posts_per_page' => -1,
 868		'author' => $user_id,
 869	));
 870	
 871	if (isset($query->posts) && is_array($query->posts)) {
 872		$posts = $query->posts;
 873	}
 874	
 875	wp_reset_query();
 876	
 877	return $posts;
 878}
 879
 880
 881/**
 882 * Get a list of posts a user is the author or co-author on
 883 *
 884 * @param int $user_id User id to look up, else uses current user id
 885 * @param array $post_type Post types to find posts for, defaults to article
 886 * @param array $post_stati Post statuses to look up 
 887 * @return array Empty array or array of post ids
 888 * @author Evan Anderson
 889 */
 890function anno_get_authored_posts($user_id = false, $post_types = array('article'), $post_statuses = array('draft', 'pending', 'private', 'publish', 'future')) {
 891	$posts = array();
 892	
 893	if (empty($user_id)) {
 894		$user_id = get_current_user_id();
 895	}
 896	
 897	// author will always be stored in post_meta
 898	$query = new WP_Query(array(
 899		'fields' => 'ids',
 900		'post_type' => $post_types,
 901		'post_status' => $post_statuses,
 902		'cache_results' => false,
 903		'posts_per_page' => -1,
 904		'meta_query' => array(
 905			'relation' => 'OR',
 906			array(
 907				'key' => '_anno_author_'.$user_id,
 908			),
 909			array(
 910				'key' => '_anno_reviewer_'.$user_id,
 911			),
 912		),
 913	));
 914	
 915	if (isset($query->posts) && is_array($query->posts)) {
 916		$posts = $query->posts;
 917	}
 918	
 919	wp_reset_query();
 920	
 921	return $posts;
 922}
 923
 924/**
 925 * Get count of available articles that a user can see/edit
 926 * 
 927 * @param int $user_id ID of the user to count for, otherwise uses current user
 928 * @return object|int Object if user is admin or editor of all the states and counts. Single int count otherwise
 929 */
 930function anno_viewable_article_count($user_id = false) {	
 931	$count = 0;
 932	
 933	if (empty($user_id)) {
 934		$user = wp_get_current_user();
 935	}
 936	else{
 937		$user = get_user_by('id', (int) $user_id);
 938	}
 939	
 940	if ($user) {
 941		if ($user->has_cap('editor') || $user->has_cap('administrator')) {
 942			return wp_count_posts('article', 'readable');
 943		}
 944		// The user is not an editor, nor an admin, so only count published posts and ones they are an author/co-author on.
 945		else {
 946			$author_posts = anno_get_authored_posts($user->ID);
 947						
 948			$count += count($author_posts);
 949			
 950			wp_reset_query();
 951		}
 952	}
 953	
 954	return $count;
 955}
 956
 957/**
 958 * Output general stats in dashboard widget
 959 *
 960 * @return void
 961 */
 962function anno_activity_information() {
 963	global $current_site, $avail_post_stati;
 964	$article_post_type = 'article';
 965	$status_text = array(
 966		'publish' => array(
 967			'i18n' 	=> __('Published', 'anno'),
 968			'class' => 'approved',
 969		),
 970		'pending' => array(
 971			'i18n' 	=> __('Pending', 'anno'),
 972			'class' => 'waiting',
 973		),
 974		'draft' => array(
 975			'i18n' 	=> __('Draft', 'anno'),
 976			'class' => 'waiting',
 977		),
 978		'trash' => array(
 979			'i18n' 	=> __('Trash', 'anno'),
 980			'class' => 'spam',
 981		),
 982	);
 983	
 984	$num_posts = anno_viewable_article_count();
 985	
 986	if (!is_int($num_posts)) {
 987	
 988		// Get the absolute total of $num_posts
 989		$total_records = array_sum( (array) $num_posts );
 990		
 991		// Subtract post types that are not included in the admin all list.
 992		foreach (get_post_stati(array('show_in_admin_all_list' => false)) as $state) {
 993			$total_records -= $num_posts->$state;
 994		}
 995	}
 996	else {
 997		$total_records = $num_posts;
 998	}
 999	
1000	// Default
1001	$detailed_counts = array();
1002	
1003	$base_edit_link = add_query_arg(array('post_type' => $article_post_type), admin_url('edit.php'));
1004	
1005	// Only build detailed string if user is an editor or administrator
1006	if (current_user_can('editor') || current_user_can('administrator')) {
1007		foreach (get_post_stati(array('show_in_admin_status_list' => true), 'objects') as $status) {
1008			$status_slug = $status->name;
1009			
1010			// If this status is in our $status_text array
1011			if (!in_array($status_slug, array_keys($status_text)))
1012				continue;
1013			
1014			// If we don't have any, don't output...this is debatable
1015			if ( empty( $num_posts->$status_slug ) )
1016				continue;
1017			
1018			$detailed_counts[] = array(
1019				'status_slug' 	=> $status->name,
1020				'i18n' 			=> $status_text[$status_slug]['i18n'],
1021				'count' 		=> $num_posts->$status_slug,
1022				'url' 			=> add_query_arg(array('post_status' => $status_slug), $base_edit_link),
1023				'class' 		=> $status_text[$status_slug]['class'],
1024			);
1025		}
1026	}
1027	?>
1028	</table> <!-- /close up the other table -->
1029		
1030	<table>
1031		<tr>
1032			<td class="first b"><a href="<?php echo esc_url($base_edit_link); ?>"><?php echo number_format_i18n($total_records); ?></a></td>
1033			<td class="t"><a href="<?php echo esc_url($base_edit_link); ?>"><?php _e('Articles', 'anno'); ?></a></td>
1034		</tr>
1035		<?php
1036		foreach ($detailed_counts as $details) {
1037			?>
1038			<tr>
1039				<td class="first b"><a href="<?php echo esc_url($details['url']); ?>"><?php echo esc_html(number_format_i18n($details['count'])); ?></a></td>
1040				<td class="t"><a class="<?php echo esc_attr($details['class']); ?>" href="<?php echo esc_url($details['url']); ?>"><?php echo esc_html($details['i18n']); // already i18n'd ?></a></td>
1041			</tr>
1042			<?php
1043		}
1044		?>
1045	<?php 
1046}
1047add_action('right_now_content_table_end', 'anno_activity_information');
1048
1049
1050/**
1051 * Clear footer transient when we update the items in the menu it is currently using
1052 */ 
1053function anno_update_nav_menu($menu_id) {
1054 	// Accounts for orphans where menu_id = 0
1055	if (!empty($menu_id)) {
1056		$locations = get_theme_mod('nav_menu_locations');
1057		if (isset($locations['footer']) && $menu_id == $locations['footer']) {
1058			// Clear our transient
1059			delete_transient('anno_footer_menu');
1060		}
1061	}
1062}
1063add_action('wp_update_nav_menu', 'anno_update_nav_menu');
1064
1065/**
1066 * Clear footer transient when we change which menu it is using
1067 */
1068function anno_update_nav_menu_location_add_action() {
1069	$theme = get_option( 'stylesheet' );
1070	add_action('update_option_theme_mods_'.$theme, 'anno_update_nav_menu_location');
1071}
1072add_action('admin_head-nav-menus.php', 'anno_update_nav_menu_location_add_action');
1073
1074function anno_update_nav_menu_location() {
1075	delete_transient('anno_footer_menu');
1076}
1077
1078/**
1079 * Display default menus if a given menu is empty
1080 * Handles the case where the theme location has a menu but it has no menu items
1081 * @see anno_build_default_menu() for other case
1082 */ 
1083function anno_nav_menu_items($items, $args) {
1084	if (empty($items)) {
1085		$items = anno_default_menu_items($args->theme_location);
1086	}
1087	return $items;
1088}
1089add_filter('wp_nav_menu_items', 'anno_nav_menu_items', 10, 2);
1090
1091/**
1092 * Build default nav menu items based on theme location
1093 */ 
1094function anno_default_menu_items($location) {
1095	$items = '';
1096	$default_classes = 'menu-item menu-item-type-taxonomy menu-item-object-category';
1097	switch ($location) {
1098		case 'main':
1099			$items .= '<li class="'.$default_classes.'"><a href="'.home_url().'">'.__('Home', 'anno').'</a></li>';
1100			break;
1101		case 'secondary':
1102			$items .= '<li class="'.$default_classes.'">'.wp_loginout('', false).'</li>';
1103		break;
1104		case 'footer':
1105			$items .= '<li class="'.$default_classes.'"><a href="http://www.annotum.org">'._x('About Annotum', 'Default link description', 'anno').'</a></li>';
1106			break;
1107		default:
1108			break;
1109	}
1110	
1111	return $items;
1112}
1113
1114/**
1115 * Build a default menu based on theme location
1116 * Handles the case where the theme location does not have a nav menu
1117 * @see anno_nav_menu_items() for other case
1118 */ 
1119function anno_build_default_menu($args) {
1120	$menu = '';
1121	// The only arg that Annotum uses and cares about is menu_class and theme_location	
1122	if (!empty($args['theme_location'])) {
1123		$items = anno_default_menu_items($args['theme_location']);
1124		if (!empty($items)) {
1125
1126			$class = !empty($args['menu_class']) ? ' class="'.esc_attr($args['menu_class']).'"' : 'class="nav"';
1127			$menu = '<ul '.$class.'>'.$items.'</ul>';
1128		}
1129	}
1130	return $menu;
1131}
1132
1133/**
1134 * Output a nav menu or fall back to a constructed default one
1135 */ 
1136function anno_nav_menu($args) {
1137	$args['echo'] = false;
1138	$menu = wp_nav_menu($args);
1139	if (empty($menu)) {
1140		$menu = anno_build_default_menu($args);
1141	}
1142
1143	echo $menu;
1144}
1145
1146/**
1147 * Display 'default' widgets (used when a sidebar is loaded but doesn't have widgets)
1148 * @see sidebar/sidebar-deafult.php
1149 */ 
1150function anno_default_widgets() {
1151	global $wp_widget_factory;
1152	if (isset($wp_widget_factory->widgets['Anno_Widget_Recently'])) {
1153		the_widget('Anno_Widget_Recently');
1154	}
1155	if (isset($wp_widget_factory->widgets['WP_Widget_Meta'])) {
1156		the_widget('WP_Widget_Meta');
1157	}
1158}
1159
1160/**
1161 * Print the article ID used in many JS scripts
1162 * 
1163 */ 
1164function anno_js_post_id($hook_suffix) {
1165	global $post;
1166	if (($hook_suffix == 'post-new.php' || $hook_suffix == 'post.php') && (!empty($post->post_type) && $post->post_type == 'article')) {
1167?>
1168<script type="text/javascript">var ANNO_POST_ID = <?php echo esc_js($post->ID); ?>;</script>
1169<?php 
1170		// Popups don't load in iframes, so this needs to be loaded on every edit page
1171		// This was previously done in  < WP 3.5 but now 3.5 conditionally loads it for the media popup
1172		wp_enqueue_script( 'media-upload' );
1173	}
1174}
1175add_action('admin_enqueue_scripts', 'anno_js_post_id', 0);
1176
1177/**
1178 * Determines whether or not a user can edit, based on the workflow being active or not
1179 */ 
1180function anno_current_user_can_edit() {
1181	// User must have the WP permissions
1182	if (current_user_can('edit_article')) {
1183		$post_id = null;
1184		if (isset($_POST['attachment_id'])) {
1185			$post = get_post($_POST['attachment_id']);
1186			$post_id = $post->post_parent;
1187		}
1188		// Do an additional check if the workflow is enabled
1189		if (anno_workflow_enabled()) {
1190			if (anno_user_can('edit_post', null, $post_id)) {
1191				return true;
1192			}
1193			else {
1194				return false;
1195			}
1196		}
1197		return true;
1198	}
1199	return false;
1200}
1201
1202// Remove autop, inserts unnecessary br tags in the nicely formatted HTML
1203// Carlthewebmaster 15-Dec-11 - but only for Articles
1204		global $post_type;
1205		if ($post_type == 'article') {
1206			remove_filter('the_content','wpautop');
1207		}
1208
1209// Remove this filter which strips links from articles.
1210remove_filter( 'content_save_pre', 'balanceTags', 50 );
1211
1212/**
1213 * Get the number of authors for an article via the snapshot.
1214 * @param int post_id ID of the post to get the number from 
1215 * @return Number of authors, 1 if no snapshot found (default WP)
1216 **/
1217function anno_num_authors($post_id) {
1218	$authors = get_post_meta($post_id, '_anno_author_snapshot', true);
1219	if (is_array($authors)) {
1220		return count($authors);
1221	}
1222
1223	// Default WP, only one author
1224	return 1;
1225}
1226
1227 /**
1228 * Typeahead user search AJAX handler. Based on code in WP Core 3.1.2
1229 * note this searches the entire users table - on multisite you can add existing users from other blogs to this one.
1230 */ 
1231function anno_user_search() {
1232	global $wpdb;
1233	$s = stripslashes($_GET['q']);
1234
1235	$s = trim( $s );
1236	if ( strlen( $s ) < 2 )
1237		die; // require 2 chars for matching
1238
1239	$results = $wpdb->get_col($wpdb->prepare("
1240		SELECT user_login
1241		FROM $wpdb->users
1242		WHERE user_login LIKE %s",
1243		'%'.like_escape($s).'%'
1244	));
1245
1246	echo join($results, "\n");
1247	die;
1248}
1249add_action('wp_ajax_anno-user-search', 'anno_user_search');
1250
1251/**
1252 * Enqueue the custom JS on the edit post page (currently used
1253 * for TinyMCE trigger usage during article save)
1254 *
1255 * @return void
1256 */
1257function anno_edit_post_assets($hook_suffix) {
1258	if ($hook_suffix == 'post.php' || $hook_suffix == 'post-new.php') {
1259		global $post;
1260		$main =  trailingslashit(get_template_directory_uri()) . 'assets/main/';
1261		if ($post->post_type == 'article') {
1262			wp_enqueue_script('anno-article-admin', $main.'js/article-admin.js', array('jquery-ui-sortable'), ANNO_VER);
1263			if ($post->post_status == 'publish') {
1264				wp_enqueue_script('anno-article-admin-snapshot', $main.'js/article-admin-snapshot.js', array('jquery', 'jquery-ui-sortable'), ANNO_VER);
1265			}
1266		}
1267	}
1268}
1269add_action('admin_enqueue_scripts', 'anno_edit_post_assets');
1270
1271/**
1272 * Print styles for article post type.
1273 */ 
1274function anno_article_admin_print_styles() {
1275	global $post;
1276	if ((isset($post->post_type) && $post->post_type == 'article') || (isset($_GET['anno_action']) && $_GET['anno_action'] == 'image_popup')) {
1277		$main =  trailingslashit(get_template_directory_uri()) . 'assets/main/';
1278		wp_enqueue_style('article-admin', $main.'css/article-admin.css', array(), ANNO_VER);
1279		wp_enqueue_style('article-admin-tinymce-ui', $main.'css/tinymce-ui.css', array(), ANNO_VER);
1280	}
1281}
1282add_action('admin_print_styles', 'anno_article_admin_print_styles');
1283
1284
1285/**
1286 * Adds a user to a given post with a given role
1287 *
1288 * @param string $type Type of user to add. Can be the meta_key.
1289 * @param int $user_id ID of the user being added to the post
1290 * @param int $post_id ID of the post to add the user to. Loads from global if nothing is passed.
1291 * @return bool True if successfully added or already a user associated with the post, false otherwise
1292 */
1293function anno_add_user_to_post($type, $user_id, $post_id) {
1294	$type = str_replace('-', '_', $type);
1295	if ($type == 'co_author') {
1296		$type = 'author';
1297	}
1298
1299	if ($type == 'reviewer' || $type == 'author') {
1300		$order = '_anno_'.$type.'_order';
1301		$type = '_anno_'.$type.'_'.$user_id;
1302	}
1303	else {
1304		return false;
1305	}
1306
1307	$users = get_post_meta($post_id, $order, true);
1308	if (!is_array($users)) {
1309		update_post_meta($post_id, $order, array($user_id));
1310		return add_post_meta($post_id, $type, $user_id, true);
1311	}
1312	else if (!in_array($user_id, $users)) {
1313		$users[] = $user_id;
1314		update_post_meta($post_id, $order, array_unique($users));
1315		return add_post_meta($post_id, $type, $user_id, true);
1316	}
1317
1318	return true;
1319}
1320
1321/**
1322 * Removes a user from a given post with a given role
1323 *
1324 * @param string $type Type of user to remove. Can be the meta_key.
1325 * @param int $user_id ID of the user being removed to the post
1326 * @param int $post_id ID of the post to remove the user from. Loads from global if nothing is passed.
1327 * @return bool True if successfully removed, false otherwise
1328 */
1329function anno_remove_user_from_post($type, $user_id, $post_id) {
1330	$type = str_replace('-', '_', $type);
1331	if ($type == 'co_author') {
1332		$type = 'author';
1333	}
1334
1335	if ($type == 'reviewer' || $type == 'author') {
1336		$order = '_anno_'.$type.'_order';
1337		$type = '_anno_'.$type.'_'.$user_id;
1338	}
1339	else {
1340		return false;
1341	}
1342
1343	$users = get_post_meta($post_id, $order, true);
1344	if (is_array($users)) {
1345		$key = array_search($user_id, $users);
1346		if ($key !== false) {
1347			unset($users[$key]);
1348			update_post_meta($post_id, $order, array_unique($users));
1349		}
1350	}
1351
1352	return delete_post_meta($post_id, $type, $user_id);
1353}
1354
1355function custom_login_message() {
1356$message = "<br/>Welcome to the Digital Paul Scholten Project, new users need to <a href='wp-login.php?action=register'>register</a> first to be able to leave comments and submit articles.<br/><br/>";
1357return $message;
1358}
1359add_filter('login_message', 'custom_login_message');//JVDP
1360
1361// change default display name format
1362add_action('user_register', 'registration_save_displayname', 1000);
1363function registration_save_displayname($user_id) {
1364	if ( isset( $_POST['first_name']) &&  isset( $_POST['last_name']) ){
1365		$pretty_name = $_POST['first_name'] . ' '. $_POST['last_name'];
1366		wp_update_user( array ('ID' => $user_id, 'display_name'=> $pretty_name) ) ;
1367	}
1368}//JVDP
1369
1370function set_ps_cookie($user_login, $user) {
1371	if (!isset($_COOKIE['paulscholten_cookie'])) {
1372		setcookie('paulscholten_cookie', $user->display_name, time()+31536000, '/', COOKIE_DOMAIN, false);
1373	}
1374}
1375add_action( 'wp_login', 'set_ps_cookie',10,2); //JVDP
1376
1377function remove_ps_cookie() {
1378	if (isset($_COOKIE['paulscholten_cookie'])) {
1379		setcookie('paulscholten_cookie', '', time() - 3600, '/', COOKIE_DOMAIN, false);
1380	}
1381}
1382add_action('wp_logout','remove_ps_cookie');//JVDP
1383
1384
1385function getCrunchifyPostViews($postID){
1386	$count_key = 'post_views_count';
1387	$count = get_post_meta($postID, $count_key, true);
1388	if($count==''){
1389		delete_post_meta($postID, $count_key);
1390		add_post_meta($postID, $count_key, '0');
1391		return "0 View";
1392	}
1393	if($count=='1'){
1394		return "1 View";
1395	}
1396	return $count.' Views';
1397}
1398
1399function setCrunchifyPostViews($postID) {
1400	$count_key = 'post_views_count';
1401	$count = get_post_meta($postID, $count_key, true);
1402	if($count==''){
1403		$count = 0;
1404		delete_post_meta($postID, $count_key);
1405		add_post_meta($postID, $count_key, '1');
1406	}else{
1407		$count++;
1408		update_post_meta($postID, $count_key, $count);
1409	}
1410}
1411
1412function getCrunchifyPostViewsPDF($postID){
1413	$count_key = 'post_downloads_count';
1414	$count = get_post_meta($postID, $count_key, true);
1415	if($count==''){
1416		delete_post_meta($postID, $count_key);
1417		add_post_meta($postID, $count_key, '0');
1418		return "0 Downloads";
1419	}
1420	if($count=='1'){
1421		return "1 Download";
1422	}
1423	return $count.' Downloads';
1424}
1425
1426function setCrunchifyPostViewsPDF($postID) {
1427	$count_key = 'post_downloads_count';
1428	$count = get_post_meta($postID, $count_key, true);
1429	if($count==''){
1430		$count = 0;
1431		delete_post_meta($postID, $count_key);
1432		add_post_meta($postID, $count_key, '1');
1433	}else{
1434		$count++;
1435		update_post_meta($postID, $count_key, $count);
1436	}
1437	$count_key = 'post_views_count';
1438	$count = get_post_meta($postID, $count_key, true);
1439	if($count==''){
1440		$count = 0;
1441		delete_post_meta($postID, $count_key);
1442		add_post_meta($postID, $count_key, '0');
1443	}else{
1444		$count--;
1445		update_post_meta($postID, $count_key, $count);
1446	}	
1447}
1448
1449remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0);
1450
1451function posts_for_current_author($query) {
1452	global $pagenow;
1453
1454	if( 'edit.php' != $pagenow || !$query->is_admin )
1455		return $query;
1456
1457	if( !current_user_can( 'manage_options' ) ) {
1458		global $user_ID;
1459		$query->set('author', $user_ID );
1460	}
1461	return $query;
1462}
1463add_filter('pre_get_posts', 'posts_for_current_author');
1464
1465
1466/* --------------------------------------------------------------------
1467 Remove Unwanted Menu Items from the WordPress Dashboard
1468- Requires WordPress 3.1+
1469-------------------------------------------------------------------- */
1470function sb_remove_admin_menus (){
1471
1472	// Check that the built-in WordPress function remove_menu_page() exists in the current installation
1473	if ( function_exists('remove_menu_page') ) {
1474
1475		/* Remove unwanted menu items by passing their slug to the remove_menu_item() function.
1476		 You can comment out the items you want to keep. */
1477
1478
1479		remove_menu_page('edit.php'); // Posts
1480		remove_menu_page('edit.php?post_type=page'); // Pages
1481		remove_menu_page('tools.php'); // Tools
1482		remove_menu_page('options-general.php'); // Settings
1483		remove_menu_page('edit-comments.php'); // Settings
1484		remove_menu_page('upload.php'); // Settings
1485
1486	}
1487
1488}
1489// Add our function to the admin_menu action
1490add_action('admin_menu', 'sb_remove_admin_menus');
1491
1492// remove unwanted dashboard widgets for relevant users
1493function wptutsplus_remove_dashboard_widgets() {
1494	$user = wp_get_current_user();
1495	if ( ! $user->has_cap( 'manage_options' ) ) {
1496		remove_meta_box( 'dashboard_recent_comments', 'dashboard', 'normal' );
1497		remove_meta_box( 'dashboard_incoming_links', 'dashboard', 'normal' );
1498		remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' );
1499		remove_meta_box( 'dashboard_primary', 'dashboard', 'side' );
1500		remove_meta_box( 'dashboard_secondary', 'dashboard', 'side' );
1501	}
1502}
1503add_action( 'wp_dashboard_setup', 'wptutsplus_remove_dashboard_widgets' );
1504
1505// Hide the "Please update now" notification
1506function hide_update_notice() {
1507   remove_action( 'admin_notices', 'update_nag', 3 );
1508}
1509add_action( 'admin_notices', 'hide_update_notice', 1 );