public function test_bp_docs_is_existing_doc_pre_wp_query() { // Fake that we're pre-query global $wp_query; $wpq = $wp_query; $wp_query = null; $this->assertFalse(bp_docs_is_existing_doc()); $wp_query = $wpq; }
/** * Detects wiki-style bracket linking * * @since 1.2 */ function bracket_links($content) { // Don't do this on a non-Doc if (!bp_docs_is_existing_doc()) { return $content; } // Find the text enclosed in double brackets. // Letters, numbers, spaces, parentheses, pipes $pattern = '|\\[\\[([a-zA-Z\\s0-9\\-\\(\\)\\|]+?)\\]\\]|'; $content = preg_replace_callback($pattern, array($this, 'process_bracket_content'), $content); return $content; }
/** * Renders the Add Files button area * * @since 1.4 */ function bp_docs_media_buttons($editor_id) { if (bp_docs_is_existing_doc() && !current_user_can('bp_docs_edit')) { return; } $post = get_post(); if (!$post && !empty($GLOBALS['post_ID'])) { $post = $GLOBALS['post_ID']; } wp_enqueue_media(array('post' => $post)); $img = '<span class="wp-media-buttons-icon"></span> '; echo '<a href="#" id="insert-media-button" class="button add-attachment add_media" data-editor="' . esc_attr($editor_id) . '" title="' . esc_attr__('Add Files', 'bp-docs') . '">' . $img . __('Add Files', 'bp-docs') . '</a>'; }
/** * Are we looking at something that needs docs theme compatability? * * @since 1.3 */ public function is_docs() { // Bail if not looking at the docs component if (!bp_docs_is_docs_component()) { return; } add_filter('bp_get_template_stack', array($this, 'add_plugin_templates_to_stack')); add_filter('bp_get_buddypress_template', array($this, 'query_templates')); if (bp_docs_is_global_directory()) { bp_update_is_directory(true, 'docs'); do_action('bp_docs_screen_index'); add_action('bp_template_include_reset_dummy_post_data', array($this, 'directory_dummy_post')); add_filter('bp_replace_the_content', array($this, 'directory_content')); } else { if (bp_docs_is_existing_doc()) { if (bp_docs_is_doc_history()) { $this->single_content_template = 'docs/single/history'; add_filter('bp_force_comment_status', '__return_false'); } else { if (bp_docs_is_doc_edit()) { $this->single_content_template = 'docs/single/edit'; add_filter('bp_force_comment_status', '__return_false'); } else { $this->single_content_template = 'docs/single/index'; add_filter('bp_docs_allow_comment_section', '__return_false'); } } add_action('bp_template_include_reset_dummy_post_data', array($this, 'single_dummy_post')); add_filter('bp_replace_the_content', array($this, 'single_content')); } else { if (bp_docs_is_doc_create()) { add_action('bp_template_include_reset_dummy_post_data', array($this, 'create_dummy_post')); add_filter('bp_replace_the_content', array($this, 'create_content')); } } } }
/** * Filter the location of the comments.php template * * This function uses a little trick to make sure that the comments.php file can be * overridden by child themes, yet still has a fallback in the plugin folder. * * If you find this annoying, I have provided a filter for your convenience. * * @package BuddyPress Docs * @since 1.0-beta * * @param str $path The path (STYLESHEETPATH . $file) from comments_template() * @return str The path of the preferred template */ function comments_template($path) { if (!bp_docs_is_existing_doc()) { return $path; } $original_path = $path; if (!($path = locate_template('docs/single/comments.php'))) { $path = BP_DOCS_INSTALL_PATH . 'includes/templates/docs/single/comments.php'; } return apply_filters('bp_docs_comment_template_path', $path, $original_path); }
/** * add our own downloader with Content-Disposition: inline */ function rw_catch_attachment_request() { global $bp; if (!empty($_GET['bp-attachment'])) { $fn = $_GET['bp-attachment']; // Sanity check - don't do anything if this is not a Doc if (!bp_docs_is_existing_doc()) { return; } if (!$bp->bp_docs->attachments->filename_is_safe($fn)) { wp_die(__('File not found.', 'bp-docs')); } $uploads = wp_upload_dir(); $filepath = $uploads['path'] . DIRECTORY_SEPARATOR . $fn; if (!file_exists($filepath)) { wp_die(__('File not found.', 'bp-docs')); } $headers = $bp->bp_docs->attachments->generate_headers($filepath); foreach ($headers as $name => $field_value) { if ('Content-Disposition' != $name) { $field_value = str_replace('attachment', 'inline', $field_value); @header("{$name}: {$field_value}"); } } readfile($filepath); exit; } }
/** * Add user information to individual Doc breadcrumbs. * * Hooked very late to ensure it's the first item on the list. * * @since 1.9.0 * * @param array $crumbs * @return array */ function bp_docs_user_single_breadcrumb($crumbs, $doc = null) { if (is_a($doc, 'WP_Post')) { $doc_id = $doc->ID; } else { if (bp_docs_is_existing_doc()) { $doc_id = get_queried_object_id(); } } if (bp_docs_enable_folders() && !empty($doc_id)) { $folder_id = bp_docs_get_doc_folder($doc_id); if ($folder_id) { $user_id = bp_docs_get_folder_user($folder_id); } } if (!empty($user_id)) { $user_crumbs = array(sprintf('<a href="%s">%s’s Docs</a>', bp_core_get_user_domain($user_id) . bp_docs_get_slug() . '/', bp_core_get_user_displayname($user_id))); $crumbs = array_merge($user_crumbs, $crumbs); } return $crumbs; }
/** * Returns the content of the doc currently being edited, when it exists * * @package BuddyPress Docs * @since 1.0-beta * * @return string Doc content */ function bp_docs_get_edit_doc_content() { global $post; $content = bp_docs_is_existing_doc() ? $post->post_content : ''; return apply_filters('bp_docs_get_edit_doc_content', $content); }
/** * Give users the 'upload_files' cap, when appropriate * * @since 1.4 * * @param array $caps The mapped caps * @param string $cap The cap being mapped * @param int $user_id The user id in question * @param $args * @return array $caps */ public static function map_meta_cap($caps, $cap, $user_id, $args) { if ('upload_files' !== $cap) { return $caps; } $maybe_user = new WP_User($user_id); if (!is_a($maybe_user, 'WP_User') || empty($maybe_user->ID)) { return $caps; } $is_doc = false; // DOING_AJAX is not set yet, so we cheat $is_ajax = isset($_SERVER['REQUEST_METHOD']) && 'POST' === $_SERVER['REQUEST_METHOD'] && 'async-upload.php' === substr($_SERVER['REQUEST_URI'], strrpos($_SERVER['REQUEST_URI'], '/') + 1); if ($is_ajax) { // Clean up referer $referer = $_SERVER['HTTP_REFERER']; $qp = strpos($referer, '?'); if (false !== $qp) { $referer = substr($referer, 0, $qp); } $referer = trailingslashit($referer); // Existing Doc $item_id = self::get_doc_id_from_url($referer); if ($item_id) { $item = get_post($item_id); $is_doc = bp_docs_get_post_type_name() === $item->post_type; } // Create Doc if (!$is_doc) { $is_doc = $referer === bp_docs_get_create_link(); } } else { $is_doc = bp_docs_is_existing_doc() || bp_docs_is_doc_create(); } if ($is_doc) { $caps = array('exist'); // Since we've already done the permissions check, // we can filter future current_user_can() checks on // this pageload add_filter('map_meta_cap', array(__CLASS__, 'map_meta_cap_supp'), 10, 4); } return $caps; }
/** * Display post tags form fields. Based on WP core's post_tags_meta_box() * * @since 1.0-beta * * @param object $post */ function bp_docs_post_tags_meta_box() { global $bp; require_once ABSPATH . '/wp-admin/includes/taxonomy.php'; $defaults = array('taxonomy' => $bp->bp_docs->docs_tag_tax_name); if (!isset($box['args']) || !is_array($box['args'])) { $args = array(); } else { $args = $box['args']; } extract(wp_parse_args($args, $defaults), EXTR_SKIP); $tax_name = esc_attr($taxonomy); $taxonomy = get_taxonomy($taxonomy); // If this is a failed submission, use the value from the POST cookie if (!empty(buddypress()->bp_docs->submitted_data->{$tax_name})) { $terms = buddypress()->bp_docs->submitted_data->{$tax_name}; // If it's an existing Doc, look up the terms } else { if (bp_docs_is_existing_doc()) { $terms = get_terms_to_edit(get_the_ID(), $bp->bp_docs->docs_tag_tax_name); // Otherwise nothing to show } else { $terms = ''; } } ?> <textarea name="<?php echo "{$tax_name}"; ?> " class="the-tags" id="tax-input-<?php echo $tax_name; ?> "><?php echo esc_textarea($terms); ?> </textarea> <?php }
/** * Are we looking at something that needs docs theme compatability? * * @since 1.3 */ public function is_docs() { $is_docs = bp_docs_is_docs_component(); if (bp_is_active('groups') && bp_is_group() && bp_is_current_action(buddypress()->bp_docs->slug)) { $is_docs = true; } // Bail if not looking at the docs component if (!$is_docs) { return; } add_filter('bp_get_template_stack', array($this, 'add_plugin_templates_to_stack')); add_filter('bp_get_buddypress_template', array($this, 'query_templates')); add_filter('bp_use_theme_compat_with_current_theme', 'bp_docs_do_theme_compat'); if (bp_docs_is_global_directory() || bp_docs_is_mygroups_directory()) { bp_update_is_directory(true, 'docs'); do_action('bp_docs_screen_index'); add_action('bp_template_include_reset_dummy_post_data', array($this, 'directory_dummy_post')); add_filter('bp_replace_the_content', array($this, 'directory_content')); } else { if (bp_docs_is_existing_doc()) { if (bp_docs_is_doc_history()) { $this->single_content_template = 'docs/single/history'; add_filter('bp_force_comment_status', '__return_false'); } else { if (bp_docs_is_doc_edit()) { $this->single_content_template = 'docs/single/edit'; add_filter('bp_force_comment_status', '__return_false'); } else { $this->single_content_template = 'docs/single/index'; add_filter('bp_docs_allow_comment_section', '__return_false'); // Necessary as of BP 1.9.2 remove_action('bp_replace_the_content', 'bp_theme_compat_toggle_is_page', 9999); } } add_action('bp_template_include_reset_dummy_post_data', array($this, 'single_dummy_post')); add_filter('bp_replace_the_content', array($this, 'single_content')); } else { if (bp_docs_is_doc_create()) { add_action('bp_template_include_reset_dummy_post_data', array($this, 'create_dummy_post')); add_filter('bp_replace_the_content', array($this, 'create_content')); } } } }
</table> </div> </div> </div> </div> <div style="clear: both"> </div> <div id="doc-submit-options"> <?php wp_nonce_field('bp_docs_save'); ?> <?php $doc_id = bp_docs_is_existing_doc() ? get_the_ID() : 0; ?> <input type="hidden" id="doc_id" name="doc_id" value="<?php echo $doc_id; ?> " /> <input type="submit" name="doc-edit-submit" id="doc-edit-submit" value="<?php _e('Save', 'bp-docs'); ?> "> <a href="<?php bp_docs_cancel_edit_link(); ?> " class="action safe"><?php _e('Cancel', 'bp-docs'); ?> </a>
/** * Determines what the user is trying to do on this page view. * * This determination is made mostly on the basis of the information passed in the URL * parameters. This function is also responsible for some of the object setup (getting the * revision post(s), etc). * * This is cribbed nearly wholesale from wp-admin/revision.php. In the future I would like * to clean it up to be less WordPressy and more pluginish. * * @package BuddyPress Docs * @since 1.1 */ function setup_action() { global $bp; if (!bp_docs_is_existing_doc()) { return; } wp_enqueue_script('list-revisions'); $redirect = false; switch ($this->action) { case 'restore': if (!($this->revision = wp_get_post_revision($this->revision_id))) { break; } if (!current_user_can('bp_docs_edit')) { break; } if (!($post = get_post($this->revision->post_parent))) { break; } // Revisions disabled and we're not looking at an autosave if (!wp_revisions_enabled($post) && !wp_is_post_autosave($this->revision)) { $redirect = 'edit.php?post_type=' . $post->post_type; break; } $referer = 'restore-post_' . $post->ID . '|' . $this->revision->ID; check_admin_referer($referer); wp_restore_post_revision($this->revision->ID); bp_core_add_message(sprintf(__('You have successfully restored the Doc to the revision from %s.', 'bp-docs'), $this->revision->post_date)); $redirect = get_permalink($post->ID) . '/' . BP_DOCS_HISTORY_SLUG . '/'; break; case 'diff': if (!($this->left_revision = get_post($this->left))) { break; } if (!($this->right_revision = get_post($this->right))) { break; } // Don't allow reverse diffs? if (strtotime($this->right_revision->post_modified_gmt) < strtotime($this->left_revision->post_modified_gmt)) { $redirect = add_query_arg(array('left' => $this->right, 'right' => $this->left)); break; } if ($this->left_revision->ID == $this->right_revision->post_parent) { // right is a revision of left $post =& $this->left_revision; } elseif ($this->left_revision->post_parent == $this->right_revision->ID) { // left is a revision of right $post =& $this->right_revision; } elseif ($this->left_revision->post_parent == $this->right_revision->post_parent) { // both are revisions of common parent $post = get_post($this->left_revision->post_parent); } else { break; } // Don't diff two unrelated revisions if (!wp_revisions_enabled($post)) { // Revisions disabled if (!wp_is_post_autosave($this->left_revision) && !wp_is_post_autosave($this->right_revision) || $post->ID !== $this->left_revision->ID && $post->ID !== $this->right_revision->ID) { $redirect = 'edit.php?post_type=' . $post->post_type; break; } } if ($this->left_revision->ID == $this->right_revision->ID || !wp_get_post_revision($this->left_revision->ID) && !wp_get_post_revision($this->right_revision->ID)) { break; } $post_title = '<a href="' . get_edit_post_link() . '">' . get_the_title() . '</a>'; $h2 = sprintf(__('Compare Revisions of “%1$s”', 'bp-docs'), $post_title); $title = __('Revisions', 'bp-docs'); $this->left = $this->left_revision->ID; $this->right = $this->right_revision->ID; $redirect = false; break; case 'view': default: if (!($this->revision = wp_get_post_revision($this->revision_id))) { if ($this->revision = get_post($this->revision_id)) { $this->is_latest = true; } else { break; } } if (!($post = get_post($this->revision->post_parent))) { break; } // Revisions disabled and we're not looking at an autosave if (!wp_revisions_enabled($post) && !wp_is_post_autosave($this->revision)) { $redirect = 'edit.php?post_type=' . $post->post_type; break; } $post_title = '<a href="' . get_edit_post_link() . '">' . get_the_title() . '</a>'; $revision_title = wp_post_revision_title($this->revision, false); $h2 = sprintf(__('Revision for “%1$s” created on %2$s', 'bp-docs'), $post_title, $revision_title); $title = __('Revisions', 'bp-docs'); // Sets up the diff radio buttons $this->left = $this->revision->ID; $this->right = $post->ID; $redirect = false; break; } if ($redirect) { bp_core_redirect($redirect); } $this->setup_is_identical(); }
/** * Give users the 'edit_post' and 'upload_files' cap, when appropriate * * @since 1.4 * * @param array $caps The mapped caps * @param string $cap The cap being mapped * @param int $user_id The user id in question * @param $args * @return array $caps */ public static function map_meta_cap($caps, $cap, $user_id, $args) { if ('upload_files' !== $cap && 'edit_post' !== $cap) { return $caps; } $maybe_user = new WP_User($user_id); if (!is_a($maybe_user, 'WP_User') || empty($maybe_user->ID)) { return $caps; } $is_doc = false; // DOING_AJAX is not set yet, so we cheat $is_ajax = isset($_SERVER['REQUEST_METHOD']) && 'POST' === $_SERVER['REQUEST_METHOD'] && 'async-upload.php' === substr($_SERVER['REQUEST_URI'], strrpos($_SERVER['REQUEST_URI'], '/') + 1); if ($is_ajax) { // WordPress sends the 'media-form' nonce, which we use // as an initial screen $nonce = isset($_REQUEST['_wpnonce']) ? stripslashes($_REQUEST['_wpnonce']) : ''; $post_id = isset($_REQUEST['post_id']) ? intval($_REQUEST['post_id']) : ''; if (wp_verify_nonce($nonce, 'media-form') && $post_id) { $post = get_post($post_id); // The dummy Doc created during the Create // process should pass this test, in addition to // existing Docs $is_doc = isset($post->post_type) && bp_docs_get_post_type_name() === $post->post_type; } } else { $is_doc = bp_docs_is_existing_doc() || bp_docs_is_doc_create(); } if ($is_doc) { $caps = array('exist'); // Since we've already done the permissions check, // we can filter future current_user_can() checks on // this pageload add_filter('map_meta_cap', array(__CLASS__, 'map_meta_cap_supp'), 10, 4); } return $caps; }
/** * Builds the subnav for the Docs group tab * * This method is copied from bp_group_admin_tabs(), which itself is a hack for the fact that BP * has no native way to register subnav items on a group tab. Component subnavs (for user docs) will * be properly registered with bp_core_new_subnav_item() * * @package BuddyPress Docs * @since 1.0-beta * * @param obj $group optional The BP group object. */ function bp_docs_group_tabs($group = false) { global $bp, $groups_template, $post, $bp_version; if (!$group) { $group = $groups_template->group ? $groups_template->group : $bp->groups->current_group; } // BP 1.2 - 1.3 support $groups_slug = !empty($bp->groups->root_slug) ? $bp->groups->root_slug : $bp->groups->slug; ?> <li<?php if ($bp->bp_docs->current_view == 'list') { ?> class="current"<?php } ?> ><a href="<?php echo $bp->root_domain . '/' . $groups_slug; ?> /<?php echo $group->slug; ?> /<?php echo $bp->bp_docs->slug; ?> /"><?php _e('View Docs', 'bp-docs'); ?> </a></li> <?php if (bp_docs_current_user_can('create')) { ?> <li<?php if ('create' == $bp->bp_docs->current_view) { ?> class="current"<?php } ?> ><a href="<?php echo $bp->root_domain . '/' . $groups_slug; ?> /<?php echo $group->slug; ?> /<?php echo $bp->bp_docs->slug; ?> /create"><?php _e('New Doc', 'bp-docs'); ?> </a></li> <?php } ?> <?php if (bp_docs_is_existing_doc()) { ?> <li class="current"><a href="<?php echo $bp->root_domain . '/' . $groups_slug; ?> /<?php echo $group->slug; ?> /<?php echo $bp->bp_docs->slug; ?> /<?php echo $post->post_name; ?> "><?php the_title(); ?> </a></li> <?php } ?> <?php }
/** * Gets the list of terms used by a group's docs * * At the moment, this method (and the next one) assumes that you want the terms of the * current group. At some point, that should be abstracted a bit. * * @since 1.0-beta * * @return array $terms */ function get_group_terms($terms = array()) { global $bp; // Either it's a group directory... if (!($group_id = bp_get_current_group_id())) { // ... or a single doc associated with a group... if (bp_docs_is_existing_doc()) { $doc = get_post(); $group_id = bp_docs_get_associated_group_id($doc->ID, $doc); } } if (!$group_id) { return $terms; } $query_args = array('post_type' => bp_docs_get_post_type_name(), 'update_meta_cache' => false, 'update_term_cache' => true, 'showposts' => '-1', 'posts_per_page' => '-1', 'tax_query' => array(self::tax_query_arg_for_groups($group_id))); $group_doc_query = new WP_Query($query_args); $terms = array(); foreach ($group_doc_query->posts as $p) { $p_terms = wp_get_post_terms($p->ID, buddypress()->bp_docs->docs_tag_tax_name); foreach ($p_terms as $p_term) { if (!isset($terms[$p_term->slug])) { $terms[$p_term->slug] = array('name' => $p_term->name, 'posts' => array()); } if (!in_array($p->ID, $terms[$p_term->slug]['posts'])) { $terms[$p_term->slug]['posts'][] = $p->ID; } } } foreach ($terms as &$t) { $t['count'] = count($t['posts']); } if (empty($terms)) { $terms = array(); } return apply_filters('bp_docs_taxonomy_get_group_terms', $terms); }
<?php /* Subnavigation on user pages is handled by BP's core functions */ if (!bp_is_user()) { ?> <div class="item-list-tabs no-ajax" id="subnav" role="navigation"> <?php bp_docs_tabs(); ?> </div><!-- .item-list-tabs --> <?php } ?> <?php if (bp_docs_is_existing_doc()) { ?> <div id="bp-docs-single-doc-header"> <h2 class="doc-title"><?php the_title(); ?> </h2> <?php if (apply_filters('bp_docs_allow_access_settings', true)) { ?> <div class="doc-permissions"> <?php bp_docs_doc_permissions_snapshot();
/** * Generate folder breadcrumbs for the current item. * * @since 1.9.0 */ function bp_docs_get_folder_breadcrumbs($doc = null) { $folder_id = 0; if (is_a($doc, 'WP_Post')) { $folder_id = bp_docs_get_doc_folder($doc->ID); } else { if (bp_docs_is_existing_doc()) { $folder_id = bp_docs_get_doc_folder(get_queried_object_id()); } else { if (isset($_GET['folder'])) { $folder_id = intval($_GET['folder']); } } } $folder_id = intval($folder_id); $descendants = array(); $this_folder_id = $folder_id; // Recurse up the tree while (0 !== $this_folder_id) { $folder = get_post($this_folder_id); $descendants[] = array('id' => $folder->ID, 'parent' => $folder->post_parent, 'name' => $folder->post_title); $this_folder_id = intval($folder->post_parent); } // Sort from top to bottom $descendants = array_reverse($descendants); $breadcrumb_items = array(); foreach ($descendants as $d) { $breadcrumb_items[] = sprintf('<span class="bp-docs-folder-breadcrumb" id="bp-docs-folder-breadcrumb-%s">%s<a href="%s">%s</a></span>', $d['id'], bp_docs_get_genericon('category', $d['id']), esc_url(bp_docs_get_folder_url($d['id'])), esc_html($d['name'])); } return $breadcrumb_items; }
/** * Returns the content of the doc currently being edited, when it exists * * @package BuddyPress Docs * @since 1.0-beta * * @return string Doc content */ function bp_docs_get_edit_doc_content() { global $post; if (!empty(buddypress()->bp_docs->submitted_data->doc_content)) { $content = buddypress()->bp_docs->submitted_data->doc_content; } else { $content = bp_docs_is_existing_doc() ? $post->post_content : ''; } return apply_filters('bp_docs_get_edit_doc_content', $content); }
/** * Display post tags form fields. Based on WP core's post_tags_meta_box() * * @package BuddyPress Docs * @since 1.0-beta * * @param object $post */ function bp_docs_post_tags_meta_box() { global $bp; require_once ABSPATH . '/wp-admin/includes/taxonomy.php'; $defaults = array('taxonomy' => $bp->bp_docs->docs_tag_tax_name); if (!isset($box['args']) || !is_array($box['args'])) { $args = array(); } else { $args = $box['args']; } extract(wp_parse_args($args, $defaults), EXTR_SKIP); $tax_name = esc_attr($taxonomy); $taxonomy = get_taxonomy($taxonomy); $terms = bp_docs_is_existing_doc() ? get_terms_to_edit(get_the_ID(), $bp->bp_docs->docs_tag_tax_name) : ''; ?> <textarea name="<?php echo "{$tax_name}"; ?> " class="the-tags" id="tax-input-<?php echo $tax_name; ?> "><?php echo $terms; // textarea_escaped by esc_attr() ?> </textarea> <?php }