prefix . 'collabnotes'; $ppn_db_generalnotes = $wpdb->prefix . 'generalnotes'; $ppn_version = '1.3.1'; /* -------------------------------------------- Helper functions -----------------------------------------------*/ class ppnFunctionCollection { function is_super( $user, $super_roles, $super_caps ) { $is_super = false; foreach( $super_roles as $super_role ) { if( in_array( $super_role, $user->roles ) ) { $is_super = true; break; } } if( !$is_super ) { foreach( $super_caps as $super_cap ) { if( in_array( $super_cap, $user->allcaps ) ) { $is_super = true; break; } } } return $is_super; } function note_scrub( $text ) { global $ppn_charset, $ppn_allow_html; if( $ppn_allow_html ) { return str_replace( "\n", '
', ppnFunctionCollection::kses_data( $text ) ); } else { return str_replace( "\n", '
', htmlentities( $text, ENT_QUOTES, $ppn_charset ) ); } } function preserve_code( $text ) { global $ppn_allow_html, $ppn_charset; $text = str_replace( '
', "\n", stripslashes( $text ) ); if( $ppn_allow_html ) { // Double-encode anything within so that it is preserved preg_match_all( "/(.*?)\<\/code>/is", $text, $out ); foreach( $out[1] as $instance => $inner_match ) { $target_string = htmlentities( $out[1][ $instance ], ENT_QUOTES, $ppn_charset ); $text = str_replace( $inner_match, $target_string, $text ); } } return $text; } function kses_data( $text ) { // This function is a copy of wp_kses_data that was introduced in WordPress 2.9 // It's copied in this plugin to retain compatibility with WordPress 2.8 global $allowedtags; return wp_kses( $text, $allowedtags ); } function prepare_js_from_kses( $text ) { return preg_replace( '/([^\\\\])"/', '$1\\"', $text ); } // Return the author's display name if the author exists; otherwise, default to a generic name function get_author_name( $author_id ) { $author = get_userdata( $author_id ); // If the user does not exist (if they've been removed, for example, show a default name) if( !$author ) { $author_name = __( 'User', 'peters_post_notes' ); } else { $author_name = $author->display_name; } return $author_name; } // Defines the header for the "Latest note" column on the manage posts page function notes_column_header( $columns ) { $columns['ppn_notes'] = __( 'Latest note' ); return $columns; } // Defines the actual "Latest note" column content on the manage posts page function notes_column_content( $name ) { global $post, $ppn_db_notes, $wpdb; switch( $name ) { case 'ppn_notes': $latest_note = $wpdb->get_row( 'SELECT noteid, notecontent, author, notetime FROM ' . $ppn_db_notes . ' WHERE postid = ' . $post->ID . ' ORDER BY notetime DESC LIMIT 1', OBJECT ); if( $latest_note ) { $author_name = ppnFunctionCollection::get_author_name( $latest_note->author ); print '[' . date( __( 'M j, Y \a\t G:i', 'peters_post_notes' ), strtotime( $latest_note->notetime ) ) . ', ' . $author_name . ']
' . $latest_note->notecontent; } else { print '-'; } } } } /* -------------------------------------------- Add meta box ---------------------------------------------*/ function ppn_add_meta_box() { global $ppn_post_types; foreach( $ppn_post_types as $ppn_post_type ) { add_meta_box('collaboration', __('Notes', 'peters_post_notes'), 'ppn_meta_contents', $ppn_post_type, 'side', 'high'); } } /* -------------------------------------------- Output within meta box ---------------------------------------------*/ function ppn_meta_contents($post) { global $wpdb, $ppn_db_notes, $ppn_add_post_note_in_publish_panel, $ppn_superedit_roles, $ppn_superedit_caps; // Get information about the currently logged in user $current_user = wp_get_current_user(); // Show all notes for this post $ppn_notes = $wpdb->get_results('SELECT noteid, notecontent, author, notetime FROM ' . $ppn_db_notes . ' WHERE postid = ' . $post->ID . ' ORDER BY notetime DESC', OBJECT); // If they are part of groups, get the moderator info for each group if( $ppn_notes ) { $ppn_num_notes = count($ppn_notes); $ppn_this_note = 1; $is_supereditor = ppnFunctionCollection::is_super( $current_user, $ppn_superedit_roles, $ppn_superedit_caps ); foreach ($ppn_notes as $ppn_note) { $author_name = ppnFunctionCollection::get_author_name( $ppn_note->author ); print '
' . "\n"; print '

' . $author_name . '

' . "\n"; print '

' . date(__('M j, Y \a\t G:i', 'peters_post_notes'), strtotime($ppn_note->notetime)) . '

' . "\n"; print '
' . "\n"; print '
' . "\n"; print '
'; print '

' . stripslashes($ppn_note->notecontent) . '

' . "\n"; if( $current_user->ID == $ppn_note->author || $is_supereditor ) { print '

' . __('Edit', 'peters_post_notes') . '

' . "\n"; } print '
'; if( $current_user->ID == $ppn_note->author || $is_supereditor ) { print '' . "\n"; } // Show a divider if this isn't the last note if( $ppn_this_note != $ppn_num_notes ) { print '


' . "\n"; } print '
' . "\n"; ++$ppn_this_note; } } else { print '

' . __('No notes for this post.', 'peters_post_notes') . '

'; } if ( $ppn_add_post_note_in_publish_panel ) { print ''; } else { print '

'; } print '

'; } /* -------------------------------------------- Add a note during any post save or update action ---------------------------------------------*/ function ppn_save_note($post_id, $post) { global $wpdb, $ppn_db_notes, $_POST; // Get information about the currently logged in user, as the person submitting the post for review or approving it $current_user = wp_get_current_user(); // Check to see whether anybody wrote anything if( isset($_POST['ppn_post_note']) && $_POST['ppn_post_note'] != '' ) { // Post note $ppn_post_note = ppnFunctionCollection::note_scrub( $_POST['ppn_post_note'] ); // Check whether this exact note already exists, and whether it was the last note written on this post // This is to allow people to write things like "Thanks!" multiple times in a note as long as someone else has posted in between $latest_note = $wpdb->get_var( $wpdb->prepare( "SELECT `notecontent` FROM $ppn_db_notes WHERE `postid` = $post_id ORDER BY `notetime` DESC LIMIT 1;" ) ); if( $ppn_post_note != $latest_note ) { // Insert the note into the database if they haven't already posted the same thing $wpdb->insert( $ppn_db_notes, array('postid' => $post_id, 'notecontent' => $ppn_post_note, 'author' => $current_user->ID, 'notetime' => current_time('mysql') ) ); } } } /* -------------------------------------------- When a post is deleted, remove all notes related to it ---------------------------------------------*/ function ppn_delete_notes($post_id) { global $wpdb, $ppn_db_notes; $wpdb->query('DELETE FROM ' . $ppn_db_notes . ' WHERE postid = ' . $post_id); } /* -------------------------------------------- Show latest notes on dashboard ---------------------------------------------*/ function ppn_add_dashboard() { wp_add_dashboard_widget( 'ppn_dashboard', __('Collaboration Notes', 'peters_post_notes'), 'ppn_dashboard' ); } function ppn_dashboard() { global $wpdb, $ppn_db_notes, $ppn_show_which_notes, $ppn_num_notes_limit, $ppn_super_roles, $ppn_super_caps; $current_user = wp_get_current_user(); // Basic variable setup $ppn_relevant_post_list = ''; $ppn_newest_posts = false; $ppn_query_options = ''; // Do we need to filter the list of notes? if( $ppn_show_which_notes != 'all' ) { // Do another check to see whether this user has an exempted role or capability to be able to view all notes $is_super = ppnFunctionCollection::is_super( $current_user, $ppn_super_roles, $ppn_super_caps ); if( !$is_super ) { // Get posts this author has written $ppn_author_posts = query_posts('author=' . $current_user->ID . '&orderby=modified&order=DESC&showposts=100'); $ppn_relevant_posts = array(); if( $ppn_author_posts ) { foreach ($ppn_author_posts as $ppn_author_post) { $ppn_relevant_posts[] = $ppn_author_post->ID; } } // Now we want to grab any posts on which this person has created a note $ppn_associated_posts = $wpdb->get_results('SELECT postid FROM ' . $ppn_db_notes . ' WHERE author = ' . $current_user->ID . ' ORDER BY notetime DESC', OBJECT); if( $ppn_associated_posts ) { foreach($ppn_associated_posts as $ppn_associated_post) { $ppn_relevant_posts[] = $ppn_associated_post->postid; } } $ppn_relevant_posts = array_unique($ppn_relevant_posts); $ppn_relevant_post_list = implode(',', $ppn_relevant_posts); // Make sure there are actually relevant posts if( '' != $ppn_relevant_post_list ) { // Grab notes for posts on which the current user was an author or already made a comment $ppn_query_options .= ' WHERE postid IN (' . $ppn_relevant_post_list . ') '; if( $ppn_show_which_notes == 'others' ) { // Grab notes written by people other than the author, for posts on which the current user was an author or already made a comment $ppn_query_options .= ' AND author != ' . $current_user->ID; } } } } if( $ppn_show_which_notes == 'all' || $is_super || '' != $ppn_relevant_post_list) { if( !$ppn_num_notes_limit ) { $ppn_num_notes = ''; } else { $ppn_num_notes = ' LIMIT ' . $ppn_num_notes_limit; } $ppn_newest_posts = $wpdb->get_results('SELECT postid, author, notetime, notecontent FROM ' . $ppn_db_notes . $ppn_query_options . ' ORDER BY notetime DESC' . $ppn_num_notes, OBJECT); } if( $ppn_newest_posts ) { print '' . "\n"; } else { print '

' . __('No relevant notes.', 'peters_post_notes') . '

'; } } function ppn_add_dashboard_general() { wp_add_dashboard_widget( 'ppn_dashboard_general', __('General Notes', 'peters_post_notes'), 'ppn_dashboard_general' ); } function ppn_dashboard_general() { global $wpdb, $ppn_db_generalnotes; $current_user = wp_get_current_user(); if( isset( $_POST['ppn_submit_generalnote'] ) ) { if( !empty( $_POST['ppn_post_generalnote'] ) ) { // Is the private checkbox marked? $ppn_private = 0; if( isset( $_POST['ppn_private'] ) && 'on' == $_POST['ppn_private'] ) { $ppn_private = 1; } $ppn_post_generalnote = ppnFunctionCollection::note_scrub( $_POST['ppn_post_generalnote'] ); $wpdb->insert( $ppn_db_generalnotes, array('notecontent' => $ppn_post_generalnote, 'author' => $current_user->ID, 'notetime' => current_time('mysql'), 'personal' => $ppn_private ) ); } } $ppn_dashboard_general_newest = ppn_dashboard_general_newest(0, 0); if( !empty($ppn_dashboard_general_newest) ) { print '
' . "\n"; print $ppn_dashboard_general_newest; print '
' . "\n"; } $ppn_dashboard_general_personal = ppn_dashboard_general_newest(0, 1); if( !empty($ppn_dashboard_general_personal) ) { print '

'; print '

Personal notes:

' . "\n"; print '
' . "\n"; print $ppn_dashboard_general_personal; print '
' . "\n"; } if( empty($ppn_dashboard_general_newest) && empty($ppn_dashboard_general_personal) ) { print '

' . __('No general notes.', 'peters_post_notes') . '

'; } print '

' . "\n"; print '
'; print '
' . "\n"; print '
' . "\n"; print ' ' . __('Private note', 'peters_post_notes') . "\n"; print '' . "\n"; print '
' . "\n"; } function ppn_dashboard_general_newest($ppn_page=0, $ppn_personal=0) { global $wpdb, $ppn_num_notes_limit, $ppn_db_generalnotes, $ppn_superedit_roles, $ppn_superedit_caps; $out = ''; $current_user = wp_get_current_user(); // Find out what page of entries you are looking for $ppn_page = max( intval( $ppn_page ), 0 ); $ppn_personal = min( intval( $ppn_personal ), 1 ); if( 1 == $ppn_personal ) { $ppn_personal_query = $ppn_personal . ' AND author = ' . $current_user->ID; } else { $ppn_personal_query = $ppn_personal; } if( !$ppn_num_notes_limit ) { $ppn_num_notes = ''; } else { $ppn_start_at = $ppn_page * $ppn_num_notes_limit; $ppn_num_notes = ' LIMIT ' . $ppn_start_at . ', ' . $ppn_num_notes_limit; } $ppn_num_newest_posts = $wpdb->get_var('SELECT COUNT(*) FROM ' . $ppn_db_generalnotes . ' WHERE personal = ' . $ppn_personal_query); if( $ppn_num_newest_posts < $ppn_start_at ) { return 'Not enough entries to go that high.'; } // How many pages of content are there? $ppn_total_pages = ceil($ppn_num_newest_posts / $ppn_num_notes_limit); if( $ppn_num_newest_posts ) { $ppn_newest_posts = $wpdb->get_results('SELECT noteid, author, notetime, notecontent FROM ' . $ppn_db_generalnotes . ' WHERE personal = ' . $ppn_personal_query . ' ORDER BY notetime DESC' . $ppn_num_notes, OBJECT); $is_supereditor = ppnFunctionCollection::is_super( $current_user, $ppn_superedit_roles, $ppn_superedit_caps ); $out = '' . "\n"; if( 1 != $ppn_total_pages ) { $out .= '

'; if( ($ppn_page + 1) < $ppn_total_pages ) { $out .= '« prev'; } if( 0 != $ppn_page ) { if( ($ppn_page + 1) != $ppn_total_pages ) { $out .= ' |'; } $out .= ' next »'; } $out .= '

' . "\n"; } } return $out; } /* -------------------------------------------- Add and remove tables when installing and uninstalling ---------------------------------------------*/ function ppn_install() { global $wpdb, $ppn_db_notes, $ppn_db_generalnotes, $ppn_version; $return = ''; // Add the table to hold post-specific notes if($wpdb->get_var('SHOW TABLES LIKE \'' . $ppn_db_notes . '\'') != $ppn_db_notes) { $sql = 'CREATE TABLE ' . $ppn_db_notes . ' ( `noteid` bigint(20) NOT NULL auto_increment, `postid` bigint(20) NOT NULL, `notecontent` text NOT NULL, `author` bigint(20) NOT NULL, `notetime` datetime NOT NULL, UNIQUE KEY `noteid` (noteid) ) AUTO_INCREMENT=1;'; $added_notes_table = $wpdb->query($sql); if( $added_notes_table === 0 ) { $return .= __('

Added notes table!

', 'peters_post_notes'); } } // Add the table to hold general notes if($wpdb->get_var('SHOW TABLES LIKE \'' . $ppn_db_generalnotes . '\'') != $ppn_db_generalnotes) { $sql = 'CREATE TABLE ' . $ppn_db_generalnotes . ' ( `noteid` bigint(20) NOT NULL auto_increment, `notecontent` text NOT NULL, `author` bigint(20) NOT NULL, `notetime` datetime NOT NULL, `personal` BINARY NOT NULL DEFAULT \'1\', UNIQUE KEY `noteid` (noteid) ) AUTO_INCREMENT=1;'; $added_generalnotes_table = $wpdb->query($sql); if( $added_generalnotes_table === 0 ) { $return .= __('

Added general notes table!

', 'peters_post_notes'); } } // Store version number in the database add_option( 'ppn_version', $ppn_version, '', 'no' ); return $return; } function ppn_install_link($action_links, $plugin_file, $plugin_data, $context) { if( $context == 'active' ) { $action_links[] = 'Update DB'; } return $action_links; } function ppn_upgrade_page() { $ppn_install = ppn_install(); ?>

Database tables for this plugin are properly installed.

', 'peters_post_notes'); } else { print $ppn_install; } ?>
get_var('SHOW TABLES LIKE \'' . $ppn_db_notes . '\'') ) { $sql = 'DROP TABLE ' . $ppn_db_notes; $wpdb->query($sql); } if( $ppn_db_generalnotes == $wpdb->get_var('SHOW TABLES LIKE \'' . $ppn_db_generalnotes . '\'') ) { $sql = 'DROP TABLE ' . $ppn_db_generalnotes; $wpdb->query($sql); } delete_option( 'ppn_version' ); } /* -------------------------------------------- JavaScript used in this plugin ---------------------------------------------*/ function ppn_js_admin_header() { wp_enqueue_script( 'sack' ); // Load jQuery as well, although not for Ajax in our case wp_enqueue_script( 'jquery' ); wp_register_script( 'peters_post_notes', WP_PLUGIN_URL . '/' . dirname(plugin_basename(__FILE__)) . '/peters_post_notes.js', array( 'sack' ) ); wp_enqueue_script( 'peters_post_notes' ); } /* -------------------------------------------- Function to edit notes ---------------------------------------------*/ add_action('wp_ajax_ppn_edit_note', 'ppn_edit_note' ); function ppn_edit_note() { global $wpdb, $ppn_db_notes, $ppn_db_generalnotes, $ppn_superedit_roles, $ppn_superedit_caps; $current_user = wp_get_current_user(); $is_supereditor = ppnFunctionCollection::is_super( $current_user, $ppn_superedit_roles, $ppn_superedit_caps ); // read submitted information $note_id = intval($_POST['note_id']); $note_text = ppnFunctionCollection::note_scrub( $_POST['note_text'] ); $note_type = substr($_POST['note_type'], 0, 7); switch( $note_type ) { case 0: $ppn_db_table = $ppn_db_generalnotes; break; case 1: $ppn_db_table = $ppn_db_notes; break; } $ppn_author = $wpdb->get_var('SELECT author from ' . $ppn_db_table . ' WHERE noteid = ' . $note_id . ' LIMIT 1'); // If this user allowed to edit this note? if( $current_user->ID != $ppn_author && !$is_supereditor) { die('document.getElementById("ppn_noteerror_' . $note_id . '").innerHTML = \'

' . __('Error: You can only edit notes that you wrote.', 'peters_post_notes') . '

\'; document.getElementById("ppn_noteform_' . $note_id . '").style.display = "none"; document.getElementById("ppn_notecontent_' . $note_id . '").style.display = "";'); } // Edit the note! $ppn_editnotesuccess = $wpdb->update( $ppn_db_table, array ('notecontent' => $note_text), array ('noteid' => $note_id)); if( $ppn_editnotesuccess ) { $note_text = str_replace( "\n", '\\n', $note_text ); $note_text = str_replace( "\r", '\\r', $note_text ); die( 'document.getElementById("ppn_noteerror_' . $note_id . '").innerHTML = ""; document.getElementById("ppn_notecontent_p_' . $note_id . '").innerHTML = "' . ppnFunctionCollection::prepare_js_from_kses( $note_text ) . '"; ppn_fadeedit("ppn_notecontent_p_' . $note_id . '"); document.getElementById("ppn_noteform_' . $note_id . '").style.display = "none"; document.getElementById("ppn_notecontent_' . $note_id . '").style.display = "";'); } // Database error elseif( $ppn_editnotesuccess === false ) { die( 'document.getElementById("ppn_noteerror_' . $note_id . '").innerHTML = \'

' . __('Error: Unknown or database problem when updating note.', 'peters_post_notes') . '

\'; document.getElementById("ppn_noteform_' . $note_id . '").style.display = "none"; document.getElementById("ppn_notecontent_' . $note_id . '").style.display = "";'); } // Here they actually didn't update anything else { die( 'document.getElementById("ppn_noteerror_' . $note_id . '").innerHTML = ""; document.getElementById("ppn_noteform_' . $note_id . '").style.display = "none"; document.getElementById("ppn_notecontent_' . $note_id . '").style.display = "";'); } } /* -------------------------------------------- Function to delete posts ---------------------------------------------*/ add_action('wp_ajax_ppn_delete_note', 'ppn_delete_note' ); function ppn_delete_note() { global $wpdb, $ppn_db_notes, $ppn_db_generalnotes, $ppn_superedit_roles, $ppn_superedit_caps; $current_user = wp_get_current_user(); $is_supereditor = ppnFunctionCollection::is_super( $current_user, $ppn_superedit_roles, $ppn_superedit_caps ); // read submitted information $note_id = intval($_POST['note_id']); $note_type = substr($_POST['note_type'], 0, 7); switch($note_type) { case 0: $ppn_db_table = $ppn_db_generalnotes; break; case 1: $ppn_db_table = $ppn_db_notes; break; } $ppn_author = $wpdb->get_var('SELECT author from ' . $ppn_db_table . ' WHERE noteid = ' . $note_id . ' LIMIT 1'); // If this user allowed to delete this note? if( $current_user->ID != $ppn_author && !$is_supereditor ) { die('document.getElementById("ppn_noteerror_' . $note_id . '").innerHTML = \'

' . __('Error: You can only delete notes that you wrote.', 'peters_post_notes') . '

\'; document.getElementById("ppn_noteform_' . $note_id . '").style.display = "none"; document.getElementById("ppn_notecontent_' . $note_id . '").style.display = "";'); } // Delete the note! $ppn_deletenotesuccess = $wpdb->query('DELETE FROM ' . $ppn_db_table . ' WHERE noteid = ' . $note_id . ' LIMIT 1'); if( $ppn_deletenotesuccess ) { die( 'ppn_fadeout("ppn_entire_note_' . $note_id . '");'); } // Database error else { die( 'document.getElementById("ppn_noteerror_' . $note_id . '").innerHTML = \'

' . __('Error: Unknown or database problem when deleting note.', 'peters_post_notes') . '

\'; document.getElementById("ppn_noteform_' . $note_id . '").style.display = "none"; document.getElementById("ppn_notecontent_' . $note_id . '").style.display = "";'); } } /* -------------------------------------------- Function to load new page of notes ---------------------------------------------*/ add_action('wp_ajax_ppn_load_page', 'ppn_load_page' ); function ppn_load_page() { $ppn_page = intval($_POST['ppn_page']); $ppn_personal = intval($_POST['ppn_personal']); $ppn_dashboard_general_newest = ppn_dashboard_general_newest($ppn_page, $ppn_personal); $ppn_dashboard_general_newest = str_replace("\n", '\\n', $ppn_dashboard_general_newest); $ppn_dashboard_general_newest = str_replace("\r", '\\r', $ppn_dashboard_general_newest); if( 0 == $ppn_personal ) { die('document.getElementById("ppn_dashboard_general_newest").innerHTML = "' . ppnFunctionCollection::prepare_js_from_kses( $ppn_dashboard_general_newest ) . '";'); } if( 1 == $ppn_personal ) { die('document.getElementById("ppn_dashboard_general_personal").innerHTML = "' . ppnFunctionCollection::prepare_js_from_kses( $ppn_dashboard_general_newest ) . '";'); } } register_activation_hook( __FILE__, 'ppn_install' ); register_uninstall_hook( __FILE__, 'ppn_uninstall' ); add_action( 'admin_menu', 'ppn_add_meta_box' ); add_action( 'wp_dashboard_setup', 'ppn_add_dashboard' ); add_action( 'wp_dashboard_setup', 'ppn_add_dashboard_general' ); add_action( 'edit_post', 'ppn_save_note', 10, 2 ); add_action( 'delete_post', 'ppn_delete_notes', 10, 1 ); add_filter( 'plugin_action_links_' . basename(__FILE__), 'ppn_install_link', 10, 4 ); // Would be more efficient to only load the plugin's JS on certain admin pages, but with custom post types it's better not to frustrate the developer //if( $pagenow == 'post.php' || $pagenow == 'page.php' || $pagenow == 'index.php' ) add_action('admin_print_scripts', 'ppn_js_admin_header' ); if( $ppn_show_latest_notes_column ) { add_filter( 'manage_posts_columns', array( 'ppnFunctionCollection', 'notes_column_header' ) ); add_action( 'manage_posts_custom_column', array( 'ppnFunctionCollection', 'notes_column_content' ) ); } } // This closes that initial check to make sure someone is actually logged in ?>