/** * Displays the random-image widget. * * @uses ClassBlogs_Plugins_RandomImage to get a random image to display */ public function widget($args, $instance) { $instance = $this->maybe_apply_instance_defaults($instance); $plugin = ClassBlogs::get_plugin('random_image'); $image = $plugin->get_random_image(); if ($image) { $this->start_widget($args, $instance); ClassBlogs_NXTClass::switch_to_blog($image->blog_id); // If the image is associated with a specific post, provide a link // to the post. If it has no post linkages, show a link to the blog. if ($image->post_id) { $post_link = sprintf('<a href="%s">%s</a>', esc_url(get_permalink($image->post_id)), esc_html(get_post($image->post_id)->post_title)); // Show a link to a post on a blog when running in multisite // mode, or a link to the post by a particular user when not if (ClassBlogs_Utils::is_multisite()) { $caption = sprintf(__('From the post %1$s on %2$s', 'classblogs'), $post_link, sprintf('<a href="%s">%s</a>', esc_url(ClassBlogs_NXTClass::get_blogaddress_by_id($image->blog_id)), esc_html(ClassBlogs_NXTClass::get_blog_option($image->blog_id, 'blogname')))); } else { $user = get_userdata($image->user_id); $caption = sprintf(__('From the post %1$s by %2$s', 'classblogs'), $post_link, sprintf('<a href="%s">%s</a>', esc_url(get_author_posts_url($image->user_id)), esc_html($user->display_name))); } } else { // Show a link to the source blog when running in multisite mode, // or show the image's title when not if (ClassBlogs_Utils::is_multisite()) { $caption = sprintf(__('From the blog %s', 'classblogs'), sprintf('<a href="%s">%s</a>', esc_url(ClassBlogs_NXTClass::get_blogaddress_by_id($image->blog_id)), esc_html(ClassBlogs_NXTClass::get_blog_option($image->blog_id, 'blogname')))); } else { $caption = sprintf('<a href="%s">%s</a>', esc_url($image->url), esc_attr($image->title)); } } // Display the link to the image with an appropriate caption printf('<ul> <li> <a href="%1$s"><img src="%1$s" alt="%2$s" title="%2$s" width="80%%" /></a> <br /> %3$s </li> </ul>', esc_url($image->url), esc_attr($image->title), $caption); ClassBlogs_NXTClass::restore_current_blog(); $this->end_widget($args); } }
/** * Updates the student-blogs widget. * * @uses ClassBlogs_Plugins_StudentBlogList to clear the blog cache */ public function update($new, $old) { // Update the widget options $instance = $old; $instance['display'] = ClassBlogs_Utils::sanitize_user_input($new['display']); $instance['title'] = ClassBlogs_Utils::sanitize_user_input($new['title']); // Clear the cached blog list and return the new instance $plugin = ClassBlogs::get_plugin('student_blogs'); $plugin->clear_blog_cache(); return $instance; }
/** * Displays the sitewide tag cloud widget. * * @uses ClassBlogs_Plugins_Aggregation_SitewideTags to get all sitewide tags */ public function widget($args, $instance) { $instance = $this->maybe_apply_instance_defaults($instance); $plugin = ClassBlogs::get_plugin('sitewide_tags'); $most_usage = $plugin->get_max_usage_count(); $least_usage = $plugin->get_min_usage_count(); if (!$most_usage && !$least_usage) { return; } $this->start_widget($args, $instance); $most_usage = max($most_usage, $instance['min_usage']); $least_usage = max($least_usage, $instance['min_usage']); $max_font = $instance['max_font_size']; $min_font = $instance['min_font_size']; // Display each tag as a weighted link a list echo "<div class='tagcloud'>"; foreach ($plugin->get_tags_for_tag_cloud($instance['min_usage']) as $tag) { printf('<a class="tag-link" href="%s" rel="tag" title="%s" style="font-size: %dpt;">%s</a> ', esc_url($tag->url), esc_attr(sprintf(_n('%d topic', '%d topics', $tag->count), $tag->count)), $min_font + floor(($tag->count - $least_usage) / max($most_usage - $least_usage, 1) * ($max_font - $min_font)), esc_html($tag->name)); } echo "</div>"; $this->end_widget($args); }
<?php ClassBlogs::require_cb_file('Utils.php'); /** * A base class for any widgets used in the class-blogs suite. * * This provides a few basic methods to a descending widget, mainly to help * with handling options and validating user input on the widget admin panel. * * Any child widgets should provide definitions for the functions expected * by NXTClass, being `widget()`, `update()`, and `form()`. In addition to * these, they should also provide definitions for the functions expected by * this class that provide the widget with a name and description, being `get_name()` * and `get_description()`, respectively. Additionaly, a child widget can also * provide a `$css_class` attribute that defines the CSS class to be applied * to the widget and the default options for the widget via `$default_options`. * * An example of a possible child widget is as follows: * * class MyWidget extends ClassBlogs_Widget { * * protected $default_options = array( * 'option_one' => 1, * 'option_two' => 2 * ); * * protected $css_class = 'my-widget'; * * protected function get_name() { * return 'My Widget'; * }
* * @access private * @since 0.1 */ private function _add_gravatar_signup_link_to_message($user_id, $message) { // Get the user, aborting if none can be found $user_data = get_userdata($user_id); if (empty($user_data)) { return $message; } // Add the messge and link to the Gravatar signup page to the email $parts = array("\n", __('To keep track of your posts on the class blog, you should configure a Gravatar, which is an image of your choosing that will appear next to any posts or comments that you create. You can sign up for a Gravatar for free by visiting the following URL:', 'classblogs'), $this->_get_gravatar_signup_url($user_data), "\n"); return $message . implode("\n", $parts); } /** * Returns the URL at which the given user can sign up for a gravatar. * * @param object $user an instance of a NXTClass user * @return string the URL at which the user can sign up for a Gravatar * * @access private * @since 0.1 */ private function _get_gravatar_signup_url($user) { return self::_GRAVATAR_SIGNUP_URL . urlencode($user->user_email); } } ClassBlogs::register_plugin('gravatar_signup', 'ClassBlogs_Plugins_GravatarSignup', __('Gravatar Signup', 'classblogs'), __('Adds a link allowing your students to sign up for a gravatar to their account activation emails.', 'classblogs'));
function _classblogs_deactivate() { ClassBlogs::deactivate_suite(); }
*/ class ClassBlogs_Plugins_ClassmateComments extends ClassBlogs_BasePlugin { /** * Registers the auto-approval comment hook. */ public function __construct() { add_action('nxt_insert_comment', array($this, '_approve_classmate_comments'), 10, 2); } /** * Automatically approve any comments left by a classmate. * * @param int $id the database ID of the comment * @param object $comment the saved comment object * * @access private * @since 0.1 */ public function _approve_classmate_comments($id, $comment) { if (!$comment->comment_approved) { if ($comment->user_id || get_user_by('email', $comment->comment_author_email)) { $comment->comment_approved = 1; nxt_update_comment((array) $comment); } } } } ClassBlogs::register_plugin('classmate_comments', 'ClassBlogs_Plugins_ClassmateComments', __('Classmate Comments', 'classblogs'), __("Automatically approves any comment left by a logged-in student on another student's blog.", 'classblogs'));
* * @access private * @since 0.1 */ private function _titlecase_name($name) { $name = preg_replace('/[^a-z\\-\\s\\.]/', "", $name); $name = preg_replace('/\\s{2,}/', " ", $name); return preg_replace_callback('/(^\\w)|(\\-\\w)|(\\s\\w)/', array($this, '_titlecase_name_parts'), $name); } /** * Titlecases parts of names as found by a name part regex. * * This is the callback function used to titlecase name parts found by the * `_titlecase_name` function. When given a name of "first", it returns "First". * * @param array $name_matches a matches array as returned by a * `preg_replace_callback` function, with the * array containing strings * @return string a titlecased version of the matched string * * @access private * @since 0.1 */ private function _titlecase_name_parts($name_matches) { return strtoupper($name_matches[0]); } } ClassBlogs::register_plugin('new_user_configuration', 'ClassBlogs_Plugins_NewUserConfiguration', __('New User Configuration', 'classblogs'), __('Creates a first and last name for a newly added student based on their email address.', 'classblogs'));
<?php nxt_nonce_field($this->get_uid()); ?> <p class="submit"> <input type="submit" class="button-primary" name="Submit" value="<?php _e('Update Sudent Data Options', 'classblogs'); ?> " /> <input type="submit" name="Refresh" value="<?php _e('Refresh Student Data', 'classblogs'); ?> " /> </p> </form> </div> <?php } /** * Update the tables whenever an upgrade is needed. * * @since 0.3 */ public function upgrade($old, $new) { $this->_create_tables(); } } ClassBlogs::register_plugin('sitewide_aggregator', 'ClassBlogs_Plugins_Aggregation_Aggregator', __('Sitewide Aggregator', 'classblogs'), __('Handles post, comment and tag data from all blogs on the site.', 'classblogs'), false);
?> </label> <input type="radio" name="comment_status" value="disabled" id="comments-disabled" <?php if ($this->get_option('comments_disabled')) { ?> checked="checked"<?php } ?> /> <label for="comments-disabled"><?php _e('Disabled', 'classblogs'); ?> </label> </td> </tr> </table> <?php nxt_nonce_field($this->get_uid()); ?> <p class="submit"><input type="submit" class="button-primary" name="Submit" value="<?php _e('Update Commenting Status', 'classblogs'); ?> " /></p> </form> </div> <?php } } ClassBlogs::register_plugin('disable_comments', 'ClassBlogs_Plugins_DisableComments', __('Disable Comments', 'classblogs'), __('Provides you with the option of disabling commenting on all current and future posts published by you and your students.', 'classblogs'));
/** * Calculates the number of words produced by a student in the given date window. * * @param int $user_id the ID of the user * @param object $start_dt a DateTime of the start date * @param object $end_dt a DateTime of the end date * @return int the number of words produced by the student * * @uses ClassBlogs_Plugins_Aggregation_SitewidePosts to get all sitewide posts * @uses ClassBlogs_Plugins_Aggregation_SitewideComments to get all sitewide comments * * @access private * @since 0.1 */ private function _get_word_count_for_student($user_id, $start_dt, $end_dt) { $words = 0; // Be explicit about the times of the given dates, making the start date // begin at midnight an the end date end at one second before midnight $start_dt->setTime(0, 0, 0); $end_dt->setTime(23, 59, 59); // Start with the word counts from the posts $sitewide_posts = ClassBlogs::get_plugin('sitewide_posts'); $posts = $sitewide_posts->filter_posts($user_id, $start_dt, $end_dt); foreach ($posts as $post) { $words += $this->_get_word_count_for_text($post->post_content); } // Add the word count from all comments $sitewide_comments = ClassBlogs::get_plugin('sitewide_comments'); $comments = $sitewide_comments->filter_comments($user_id, $start_dt, $end_dt); foreach ($comments as $comment) { $words += $this->_get_word_count_for_text($comment->comment_content); } return $words; }
" value="<?php echo esc_url($link['url']); ?> " /> <a href="#delete-link" class="delete-link"><?php _e('Delete', 'classblogs'); ?> </a> </td> </tr> <?php } ?> </tbody> </table> <?php nxt_nonce_field($this->get_uid()); ?> <p class="submit"><input type="submit" class="button-primary" name="Submit" value="<?php _e('Update Links', 'classblogs'); ?> " /></p> </form> </div> <?php } } ClassBlogs::register_plugin('student_links', 'ClassBlogs_Plugins_StudentBlogLinks', __('Student Blog Links', 'classblogs'), __('Allows you to put links of your choosing in a sidebar on all student blogs.', 'classblogs'));
{ global $nxtdb; // Update the student's username $nxtdb->update($nxtdb->users, array('user_login' => $new_username), array('ID' => $user_id), array('%s'), array('%d')); // Deal with the implications of the updated username in multisite if (ClassBlogs_Utils::is_multisite()) { ClassBlogs_NXTClass::switch_to_blog($blog_id); $old_url = trailingslashit(home_url()); // Update the blog URL to reflect their new username $site = get_current_site(); $new_path = trailingslashit($site->path . $new_username); $new_url = 'http://' . $site->domain . $new_path; update_option('siteurl', $new_url); update_option('home', $new_url); update_blog_details($blog_id, array('path' => $new_path)); delete_option('rewrite_rules'); // Replace any occurrences of the old URL in the blog's posts $referring_posts = $nxtdb->get_results("\n\t\t\t\tSELECT ID, post_content FROM {$nxtdb->posts}\n\t\t\t\tWHERE post_content LIKE '%%" . like_escape($old_url) . "%%' "); foreach ($referring_posts as $post) { $nxtdb->update($nxtdb->posts, array('post_content' => str_replace($old_url, $new_url, $post->post_content)), array('ID' => $post->ID), array('%s'), array('%d')); } ClassBlogs_NXTClass::restore_current_blog(); } // Flag that the user has changed their username $changed = $this->get_option('changed_users'); $changed[$new_username] = true; $this->update_option('changed_users', $changed); } } ClassBlogs::register_plugin('student_pseudonym', 'ClassBlogs_Plugins_StudentPseudonym', __('Student Pseudonym', 'classblogs'), __('Adds a student admin page that allows them to change their username.', 'classblogs'));
/** * Populates the YouTube playlist from the videos in all posts on the site. * * @access private * @since 0.4 */ private function _sync_playlist() { $plugin = ClassBlogs::get_plugin('sitewide_posts'); if (!empty($plugin)) { // Create records of all videos used foreach ($plugin->get_sitewide_posts() as $post) { ClassBlogs_NXTClass::switch_to_blog($post->cb_sw_blog_id); $this->_update_videos_on_post_save($post->ID); ClassBlogs_NXTClass::restore_current_blog(); } // Request information on all added videos from YouTube $this->_retrieve_queued_video_info(); } }
/** * Handles the display of the class blogs base admin page. * * @access private * @since 0.2 */ public function _class_blogs_admin_page() { // Disable any plugins that are not checked if ($_POST) { check_admin_referer('classblogs_admin'); // Get a list of all plugins that are checked to be enabled $enabled = array(); foreach ($_POST as $field => $value) { $plugin = str_replace('plugin_', '', $field); if ($plugin !== $field) { $enabled[$plugin] = true; } } // Enable any plugins that were previously disabled, and disable any // that were previously enabled foreach (ClassBlogs::get_user_controlled_plugins() as $plugin) { if (array_key_exists($plugin->id, $enabled)) { if (!$plugin->enabled) { ClassBlogs::enable_plugin($plugin->id); } } else { if ($plugin->enabled) { ClassBlogs::disable_plugin($plugin->id); } } } self::show_admin_message(__('Enabled class-blogs plugins have been updated. You must refresh the page to see the effects of this.'), 'classblogs'); } ?> <div class="wrap"> <?php ClassBlogs_Admin::show_admin_icon(); ?> <h2><?php _e('Class Blogs', 'classblogs'); ?> </h2> <p> <?php _e('The class blogs plugin suite will help you manage a blog for a class where you have control over the main blog and each student has full ownership of a child blog.', 'classblogs'); ?> </p> <p> <?php _e('The plugins that are part of this suite are provided in the list below. Not every plugin has configurable options, but the ones that do will appear as links in the Class Blogs admin menu. If you do not wish to use a certain component of the class-blogs suite, you can uncheck it in the list below and click on the "Update Enabled Plugins" button.', 'classblogs'); ?> </p> <h3><?php _e('Enabled Plugins', 'classblogs'); ?> </h3> <form method="post" action=""> <table id="cb-enabled-plugins"> <thead> <tr> <th class="toggle"><?php _e('Enabled', 'classblogs'); ?> </th> <th class="name"><?php _e('Name', 'classblogs'); ?> </th> <th class="description"><?php _e('Description', 'classblogs'); ?> </th> </tr> </thead> <tbody> <?php // Display each user-controlled plugin $plugins = ClassBlogs::get_user_controlled_plugins(); foreach ($plugins as $plugin) { $field = 'plugin_' . $plugin->id; $name = $plugin->name ? $plugin->name : get_class($plugin->plugin); printf(' <tr> <td class="toggle"> <input type="checkbox" id="%1$s" name="%1$s" %2$s /> </td> <td class="name"> <label for="%1$s">%3$s</label> </td> <td class="description">%4$s</td> </tr>', esc_attr($field), $plugin->enabled ? 'checked="checked"' : '', esc_html($name), esc_html($plugin->description)); } ?> </tbody> </table> <?php nxt_nonce_field('classblogs_admin'); ?> <p class="submit"> <input type="submit" class="button-primary" name="Submit" value="<?php _e('Update Enabled Plugins', 'classblogs'); ?> " /> </p> </form> </div> <?php }
* @since 0.1 */ public static function create_plugin_page($name, $content = '', $page_id = null) { $conflicts = true; $counter = 0; $page_name = $name; // If a page with the given ID already exists, abort early if ($page_id && get_page($page_id)) { self::_register_plugin_page($page_id); return $page_id; } // Find a name for the new page that doesn't conflict with others while ($conflicts) { $page = get_page_by_title($page_name); if (isset($page)) { $counter++; $page_name = sprintf('%s %d', $name, $counter); } else { $conflicts = false; } } // Create the new page and store its ID $new_page = array('post_author' => ClassBlogs_Settings::get_admin_user_id(), 'post_content' => $content, 'post_status' => 'publish', 'post_title' => $page_name, 'post_type' => 'page'); $page_id = nxt_insert_post($new_page); self::_register_plugin_page($page_id); return $page_id; } } ClassBlogs::register_plugin('plugin_page', 'ClassBlogs_PluginPage', __('Plugin Page', 'classblogs'), __('Manages pages associated with a plugin.', 'classblogs'), false);
<? ClassBlogs::require_cb_file( 'Schema.php' ); /** * Schemata for tables used by the sitewide plugins. * * These schemata represent the tables that the sitewide plugins use to keep * track of the sitewide data. Some of the tables, such as the comments and * posts table, are more or less identical to NXTClass's core comments and posts * tables, with the addition of a few ID fields and modified indexes. Other * tables, such as those used to keep track of sitewide tags, adhere less * closely to the NXTClass tables. * * Note that these objects simply represent the table structure. The actual * names of the tables to which these schemata are bound are set via the * `ClassBlogs_Plugins_Aggregation_Settings` class. * * @package ClassBlogs_Plugins_Aggregation * @subpackage Schemata * @since 0.2 */ class ClassBlogs_Plugins_Aggregation_Schemata { /** * Get the schema used for the sitewide comments table * * @return ClassBlogs_Schema an instance of the comment schema * * @since 0.2
<?php ClassBlogs::require_cb_file('Settings.php'); /** * NXTClass abstraction functions. * * This abstraction layer exists primarily to allow the class blogs suite to * run either in multisite mode, where each student is given a dedicated blog, * or in standard mode, where each student simply has a user account. * * @package ClassBlogs * @subpackage NXTClass * @since 0.4 */ class ClassBlogs_NXTClass { /** * Switches to a blog with the given ID. * * This switches to the given blog when in multisite mode, or does nothing * when running a normal installation with only a single blog defined. * * @param int $blog_id the ID of a blog * * @since 0.4 */ public static function switch_to_blog($blog_id) { if (function_exists('switch_to_blog')) { switch_to_blog($blog_id); }
<?php // Load the components of the aggregation suite ClassBlogs::load_php_files(dirname(__FILE__) . '/Aggregation'); /** * A collection of plugins that deal with aggregated data from all of the blogs * on the current site. * * @package ClassBlogs_Plugins * @subpackage Aggregation * @since 0.3 */ class ClassBlogs_Plugins_Aggregation { }
/** * Updates the sitewide comments widget. * * @uses ClassBlogs_Plugins_Aggregation_SitewideComments to clear the cached widget */ public function update($new, $old) { // Update the widget options $instance = $old; $instance['max_comments'] = absint(ClassBlogs_Utils::sanitize_user_input($new['max_comments'])); $instance['max_comments_per_blog'] = absint(ClassBlogs_Utils::sanitize_user_input($new['max_comments_per_blog'])); $instance['meta_format'] = ClassBlogs_Utils::sanitize_user_input($new['meta_format']); $instance['show_excerpt'] = ClassBlogs_Utils::checkbox_as_bool($new, 'show_excerpt'); $instance['title'] = ClassBlogs_Utils::sanitize_user_input($new['title']); // Clear the cached sidebar widget $plugin = ClassBlogs::get_plugin('sitewide_comments'); $plugin->clear_cached_widget(); return $instance; }
<?php ClassBlogs::require_cb_file('BasePlugin.php'); ClassBlogs::require_cb_file('Utils.php'); ClassBlogs::require_cb_file('NXTClass.php'); ClassBlogs::require_cb_file('Plugins/Aggregation/Settings.php'); /** * The base class for any plugin that deals with sitewide data. * * This provides descended classes with a few utility methods to manipulate * sitewide data, a set of methods that are used to properly inject sitewide * data into the normal NXTClass loop, some methods that allow for easy * management of cached sitewide data, and a list of the names of the tables * used to track sitewide data. * * @package ClassBlogs_Plugins_Aggregation * @subpackage SitewidePlugin * @since 0.1 */ abstract class ClassBlogs_Plugins_Aggregation_SitewidePlugin extends ClassBlogs_BasePlugin { /** * The names of the sitewide tables. * * This works similarly to NXTClass's `$nxtdb` global, with each table name * being available through a short term that is a property of the `$tables` * object. The available table keys and their natures are as follows: * * posts - a master list of any published posts on any blog on the site * comments - a master list of all comments left on any blog on the site * tags - a list of all tags used across the site with usage counts
<?php ClassBlogs::require_cb_file('NXTClass.php'); /** * Logic for determining student identity and blog URLs. * * When running NXTClass as a single-site installation where students are added * as users to the same blog on which the professor is a user, a student will be * any user who is not an administrator and not a subscriber. Their blog URL * will be the author archive view associated with their user account. * * When running NXTClass in multisite mode, a student is any user who is the * only adminstrator on a blog that is not the root blog. Their blog URL will * be the URL of that blog. * * An example of using the functions of this class is as follows: * * // Two students are added to the blog with user IDs of 2 and 3, and the * // admin user has an ID of 1. * $student_ids = ClassBlogs_Students::get_student_user_ids(); * assert( in_array( 2, $student_ids ) ); * assert( in_array( 3, $student_ids ) ); * assert( count( $student_ids ) === 2 ); * assert( ! ClassBlogs_Students::user_is_student( 1 ) ); * assert( ClassBlogs_Students::user_is_student( 2 ) ); * * // A blog with an ID of 2 is created for a student with an ID of 3. This * // blog is called 'Example' and is located at http://www.example.com. * $blogs = ClassBlogs_Students::get_student_blogs(); * assert( count( $blogs ) === 1 ); * assert( array_key_exists( 3, $blogs ) );
/** * Returns the number of comments that a student has left * * @param int $user_id the user ID of a student * @return string the number of comments left by the student */ function classblogging_get_total_comments_for_student($user_id) { $sitewide_comments = ClassBlogs::get_plugin('sitewide_comments'); return $sitewide_comments->get_total_comments_for_student($user_id); }