'f5f5f5', 'border' => 'dddddd', 'text' => '555555', 'link' => '21759b' ); } $content_width = 488; // pixels /** * Register some dependencies at initialisation. * * @return void **/ function pp_init() { wp_register_script( 'pp-front', get_bloginfo('template_url') . '/prologue-projects.js', false, '20090218' ); wp_register_style( 'pp-reset-fonts', get_bloginfo('template_url') . '/reset-fonts.css', false, '20090218' ); wp_register_style( 'pp-front', get_bloginfo('template_url') . '/style.css', array('pp-reset-fonts'), '20090218' ); } add_action( 'init', 'pp_init' ); /** * Enqueue our dependencies for linking in the html head. * * @return void **/ function pp_head() { wp_enqueue_script( 'pp-front' ); wp_enqueue_style( 'pp-front' ); } add_action( 'wp_head', 'pp_head', 1 ); /** * Where the bloody hell are ya? * * @return string The current URL. **/ function pp_get_current_url() { $schema = is_ssl() ? 'https://' : 'http://'; return $schema . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; } /** * Get stored options for prologue_projects and merge them with the defaults. * * @return array All the options. **/ function pp_get_options() { $defaults = array( 'category_projects' => false, 'featured_project' => false, 'project_data' => array(), 'projects_sidebars' => false, 'category_updates' => false, 'category_tasks' => false, 'default_task_level' => false, 'category_questions' => false, 'default_question_state' => false, 'author_sidebars' => false ); $options = get_option( 'prologue_projects' ); return array_merge( $defaults, $options ); } /** * Get a single prologue_projects option * * @param string $key The key of the option to be retrieved. * @return mixed The value of the option or boolean false if not set. **/ function pp_get_option( $key ) { if ( !$key ) { return false; } $options = pp_get_options(); if ( !isset( $options[$key] ) ) { return false; } return $options[$key]; } /** * Shorthand function to retrieve the actual category id of a prologue_projects post type * * @param string $type The post type whose category id is to be returned, can be one of "projects", "updates", "tasks" or "questions". * @return int The category id or false if none is set. **/ function pp_get_category_id( $type ) { return pp_get_option( 'category_' . $type ); } /** * Allows for template customisation of individual projects by injecting new files named after the project slug into the template hierarchy. * * When a request is made for "updates" in the project "foo", WordPress will look for the following files in order: * 1. updates-foo.php * 2. updates.php * 3. index.php * 4. The originally determined category template, passed as parameter $template. * * @param string $template The originally determined category template. * @return void **/ function pp_category_template( $template ) { $requested_category_id = absint( get_query_var( 'cat' ) ); $types = array( 'projects' => pp_get_category_id( 'projects' ), 'updates' => pp_get_category_id( 'updates' ), 'tasks' => pp_get_category_id( 'tasks' ), 'questions' => pp_get_category_id( 'questions' ) ); foreach ( $types as $_type => $_category_id ) { if ( !$_category_id ) { continue; } $_category = get_category( absint( $_category_id ) ); if ( !$_category || is_wp_error( $_category ) ) { continue; } if ( $_category_id == $requested_category_id ) { return locate_template( array( $_type . '.php', 'index.php', $template ) ); } $_ids = get_categories( array( 'child_of' => $_category_id, 'hide_empty' => false, 'fields' => 'ids' ) ); if ( !in_array( $requested_category_id, $_ids ) ) { continue; } $_type_category = get_category( $requested_category_id ); if ( !$_type_category || is_wp_error( $_type_category ) ) { continue; } return locate_template( array( $_type . '-' . $_type_category->slug . '.php', $_type . '.php', 'index.php', $template ) ); } return $template; } add_filter( 'category_template', 'pp_category_template' ); /** * Allows the use of Trac-style shorthand for links to Trac tickets and changesets. * * @param string $text The text to be modified. * @return string The modified text. **/ function pp_make_tracable( $text ) { if ( !$text || !preg_match( '@(?:#[a-z0-9]+)|(?:\[[a-z0-9]+\])@i', $text ) ) { return $text; } global $id, $post; if ( !$category_ids = wp_get_post_categories( $id ) ) { return $text; } $project_tracs = array(); $i = 0; foreach ( $category_ids as $category_id ) { $project_data = pp_get_project_data( $category_id ); if ( isset( $project_data['trac'] ) && $project_data['trac'] ) { $i++; $project_tracs[$i][0][0] = '#' . preg_quote( $project_data['slug'] ) . '([0-9]+)'; $project_tracs[$i][0][1] = $project_data['trac'] . 'ticket/$1'; $project_tracs[$i][0][2] = '#' . $project_data['slug'] . '$1'; $project_tracs[$i][1][0] = '\[' . preg_quote( $project_data['slug'] ) . '([0-9]+)\]'; $project_tracs[$i][1][1] = $project_data['trac'] . 'changeset/$1'; $project_tracs[$i][1][2] = '[' . $project_data['slug'] . '$1]'; if ( isset( $project_data['intertrac'] ) && $project_data['intertrac'] ) { $project_tracs[$i][2][0] = '#' . preg_quote( $project_data['intertrac'] ) . '([0-9]+)'; $project_tracs[$i][2][1] = $project_data['trac'] . 'ticket/$1'; $project_tracs[$i][2][2] = '#' . $project_data['intertrac'] . '$1'; $project_tracs[$i][3][0] = '\[' . preg_quote( $project_data['intertrac'] ) . '([0-9]+)\]'; $project_tracs[$i][3][1] = $project_data['trac'] . 'changeset/$1'; $project_tracs[$i][3][2] = '[' . $project_data['intertrac'] . '$1]'; } } } if ( !count( $project_tracs ) ) { return $text; } if ( count( $project_tracs ) === 1 ) { $project_tracs[0][0][0] = '#([0-9]+)'; $project_tracs[0][0][1] = $project_tracs[1][0][1]; $project_tracs[0][0][2] = '#$1'; $project_tracs[0][1][0] = '\[([0-9]+)\]'; $project_tracs[0][1][1] = $project_tracs[1][1][1]; $project_tracs[0][1][2] = '[$1]'; } ksort( $project_tracs ); foreach ( $project_tracs as $pairs ) { foreach ( $pairs as $pair ) { $text = preg_replace( '@' . $pair[0] . '@', '' . $pair[2] . '', $text ); } } return $text; } add_filter( 'the_content', 'pp_make_tracable', 1 ); add_filter( 'the_content', 'make_clickable' ); /** * Get the meta data of a given project. * * @param integer $category_id The category id of the project. * @param string $type Optional. The specific meta data to get. Default is "all", which retrieves all meta data. * @return mixed The projects meta data in an associative array or the specific data as requested with the $type parameter. **/ function pp_get_project_data( $category_id = 0, $type = 'all', $context = '' ) { if ( !$category_id ) { global $cat; $category_id = $cat; } if ( !$category_id ) { return false; } if ( is_object( $category_id ) && !is_wp_error( $category_id ) ) { $category = $category_id; $category_id = $category->cat_ID; } if ( !$context && $cache = wp_cache_get( $category_id, 'pp_project_data' ) ) { if ( 'all' === $type ) { return $cache; } if ( !isset( $cache[$type] ) ) { return false; } return $cache[$type]; } if ( !isset( $category ) ) { $category = get_category( $category_id ); } if ( !$category || is_wp_error( $category ) ) { return false; } $data = array(); $data['id'] = $category->cat_ID; $data['name'] = $category->name; $data['parent_id'] = $category->parent; $data['slug'] = $category->slug; $data['url'] = get_category_link( $category->cat_ID ); $data['link'] = '' . $data['name'] . ''; $data['description'] = $category->description; $data['logo'] = ''; $data['website'] = ''; $data['blog'] = ''; $data['svn'] = ''; $data['trac'] = ''; $data['intertrac'] = ''; $data['activity'] = array(); $data['overheard'] = array(); if ( $meta = get_option( 'pp_project_meta_' . $data['id'] ) ) { foreach ( $meta as $key => $value ) { if ( in_array( $key, array( 'intertrac', 'logo' ) ) ) { $data[$key] = $value; } elseif ( in_array( $key, array( 'activity', 'overheard' ) ) && $value ) { $data[$key] = array_merge( $data[$key], $value ); } elseif ( $value ) { $data[$key] = rtrim( $value, '/' ) . '/'; } } if ( $data['trac'] && !$context ) { $data['activity'][] = $data['trac'] . 'timeline?milestone=on&ticket=on&changeset=on&wiki=on&format=rss&max=20'; } } if ( !$context ) { wp_cache_add( $category_id, $data, 'pp_project_data' ); } if ( 'all' === $type ) { return $data; } if ( !isset( $data[$type] ) ) { return false; } return $data[$type]; } /** * Callback to clean out the specific project data cache when categories are edited. * * @param $category_id The category id of the project. * @return boolean True if the cache was emptied. **/ function pp_delete_project_data_cache( $category_id ) { if ( !$category_id ) { return false; } return wp_cache_delete( $category_id, 'pp_project_data' ); } add_action( 'delete_category', 'pp_delete_project_data_cache', 10, 1 ); add_action( 'edit_category', 'pp_delete_project_data_cache', 10, 1 ); /** * Find out if the given category is a project. * * @param integer $category_id The id of the category. * @return boolean True if it is a project, otherwise false. **/ function pp_is_project( $category_id = 0 ) { $categories = pp_get_projects(); if ( !$categories || ! is_countable( $categories ) || count( $categories ) < 1 ) { return false; } if ( !$category_id = pp_get_project_data( $category_id, 'id' ) ) { return false; } $is_project = false; foreach ( $categories as $category ) { if ( $category_id == $category->cat_ID ) { $is_project = true; break; } } return $is_project; } function pp_get_projects( $parent_id = 0 ) { if ( $parent_id && !pp_is_project( $parent_id ) ) { // Narrowly avoiding circular logic here :) return; } elseif ( !$parent_id && !$parent_id = pp_get_category_id( 'projects' ) ) { return; } $categories = get_categories( array( 'child_of' => $parent_id, 'hierarchical' => 1, 'hide_empty' => 0 ) ); return $categories; } function pp_get_question_statuses() { if ( !$parent_id = pp_get_category_id( 'questions' ) ) { return; } $categories = get_categories( array( 'child_of' => $parent_id, 'hide_empty' => 0 ) ); return $categories; } function pp_is_question_status( $category_id ) { if ( !$category_id ) { return false; } $categories = pp_get_question_statuses(); if ( !$categories || ! is_countable( $categories ) || count( $categories ) < 1 ) { return false; } $is_status = false; foreach ( $categories as $category ) { if ( $category_id == $category->cat_ID ) { $is_status = true; break; } } return $is_status; } function pp_get_project_members( $category_id = 0 ) { $project_id = pp_get_project_data( $category_id, 'id' ); if ( !$project_id ) { return false; } global $wpdb, $blog_id; $query = "SELECT `user_id`, `user_login`, `user_nicename`, `display_name`, `user_email`, `meta_value` FROM `" . $wpdb->users . "`, `" . $wpdb->usermeta . "` WHERE `" . $wpdb->users . "`.`ID` = `" . $wpdb->usermeta . "`.`user_id` AND `meta_key` = 'prologue_projects_" . $blog_id . "' AND `meta_value` LIKE '%i:" . (int) $project_id . ";a:2:{i:0;i:1;%' ORDER BY `" . $wpdb->users . "`.`display_name`;"; $members = $wpdb->get_results( $query, ARRAY_A ); $_members = array(); if ( $members && is_countable( $members ) && count( $members ) ) { foreach ( $members as $member ) { $_member = $member; $_member['projects'] = maybe_unserialize( $member['meta_value'] ); unset( $_member['meta_value'] ); $_member['project_role'] = strip_tags( trim( wp_filter_kses( wp_specialchars( $_member['projects'][$category_id][1] ) ) ) ); unset( $_member['projects'] ); $_members[] = $_member; } } return $_members; } function pp_get_user_projects( $user_id = 0 ) { if ( !$user = new WP_User( $user_id ) ) { return false; } global $blog_id; $meta = 'prologue_projects_' . $blog_id; if ( !isset( $user->$meta ) || !$user->$meta || !is_array( $user->$meta ) ) { return false; } $projects = array(); foreach ( $user->$meta as $project_id => $project_settings ) { if ( $project_settings[0] ) { $projects[$project_id] = $project_settings[1]; } } if ( !count( $projects ) ) { return false; } return $projects; } /* Template */ function pp_all_projects_rss() { if ( !$url = get_feed_link() ) { return; } $r = ''; $r .= __( 'RSS', 'prologue-projects' ); $r .= ''; echo $r; } function pp_project_rss( $category_id = 0 ) { $data = []; // $data['slug'] below is possibly a bug; adding this init to fix rector. if ( !$category_id = pp_get_project_data( $category_id, 'id' ) ) { return; } if ( !$url = get_category_feed_link( $category_id ) ) { return; } $r = ''; $r .= __( 'RSS', 'prologue-projects' ); $r .= ''; echo $r; } function pp_project_logo( $category_id = 0 ) { if ( !$data = pp_get_project_data( $category_id ) ) { return; } if ( !isset( $data['logo'] ) || !$data['logo'] ) { return; } if ( !parse_url( $data['logo'] ) ) { return; } $r = ''; echo $r; } function pp_project_links( $category_id = 0 ) { if ( !$data = pp_get_project_data( $category_id ) ) { return; } $r = '