PageRenderTime 70ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

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