',
- );
-
$form['directory_no_nodes'] = array(
'#type' => 'checkboxes',
'#title' => t('Exclude these node types from directory pages'),
@@ -140,10 +106,10 @@ function directory_admin_settings() {
$form['directory_show_child_counts'] = array(
'#type' => 'checkbox',
- '#title'=>t('Show count of nodes in categories'),
+ '#title'=> t('Show count of nodes in categories'),
'#default_value' => variable_get('directory_show_child_counts', TRUE),
'#description' => t('Append a count of items contained in each term, if the count is greater than zero.'),
- '#required'=>FALSE,
+ '#required'=> FALSE,
);
$form['directory_hide_empty_terms'] = array(
@@ -151,151 +117,269 @@ function directory_admin_settings() {
'#title'=>t('Hide terms with no content'),
'#default_value' => variable_get('directory_hide_empty_terms', FALSE),
'#description' => t('If checked, hide taxonomy terms having no node content.'),
- '#required'=>FALSE,
+ '#required'=> FALSE,
);
-
+
$form['directory_help'] = array(
'#type' => 'textarea',
'#title' => t('Help text for the Directory home'),
'#default_value' => variable_get('directory_help', ''),
'#cols' => 70,
'#rows' => 5,
- '#description' => t('This text will be displayed at the top of the main directory page. It is useful for helping or instructing your users.'),
+ '#description' => t('This text will be displayed at the top of the main directory page. It is useful for helping or instructing your users.'),
);
$form['directory_term_help'] = array(
'#type' => 'textarea',
- '#title' => t('Help text for each Directory term page'),
+ '#title' => t('Help text for each directory term page'),
'#default_value' => variable_get('directory_term_help', ''),
'#cols' => 70,
'#rows' => 5,
- '#description' => t('This text will be displayed at the top of each directory term page. It is useful for helping or instructing your users.'),
+ '#description' => t('This text will be displayed at the top of each directory term page. It is useful for helping or instructing your users.'),
);
return system_settings_form($form);
}
-/********************************************************************
- * Module Specific :: Public Functions
- ********************************************************************/
+function directory_random_page() {
+ $nid = db_result(db_query('SELECT n.nid FROM {node} n WHERE n.status = 1 ORDER BY RAND() LIMIT 1'));
+ drupal_goto("node/$nid");
+}
-/**
- * This is the Controller for directory viewing.
- */
-function directory_page($tid = null, $filter = null, $fid = null) {
+function directory_page($content_type = NULL) {
$output = '';
- if ($tid > 0) { //Display a category view
- if ($help = variable_get('directory_term_help', '')) {
- $output = '
'. $help .'
';
- }
- directory_set_breadcrumb($tid, 'Home');
- $content .= theme('directory_resource', $tid, $filter, $fid); // can return NULL if nothing available
- if (!$content) {
- $output .= t('
There are no items in this category. Please choose another.
';
return $output;
+ }
+ }
+}
+
+/**
+ * Helper function to build a vocabulary tree, that will contain meta
+ * information that will be used at the theme level.
+ *
+ * @param $terms
+ * The terms (the term objects) that will be at the root level of the tree
+ * that will be generated.
+ * @param $content_type
+ * Only the nodes of this content type should be counted.
+ * @return
+ * The generated tree with meta information.
+ */
+function _directory_get_tree($terms, $content_type = NULL) {
+ $show_counts = variable_get('directory_show_child_counts', TRUE);
+ $hide_empty = variable_get('directory_hide_empty_terms', FALSE);
+
+ // Build a list of categories (taxonomy terms) and child counts.
+ foreach ($terms as $term) {
+ $tid = $term->tid;
- default:
- drupal_not_found();
+ // Store the node count.
+ $tree[$tid]['nodecount'] = array('count_own' => 0, 'count_children' => 0);
+ if ($show_counts || $hide_empty) {
+ $tree[$tid]['nodecount'] = _directory_term_count_nodes($term->tid, $content_type);
+ }
+
+ // Store the entire term, this is necessary for theming.
+ $tree[$tid]['term'] = $term;
+ // If desired, exclude empty items.
+ if ((!$hide_empty) || ($tree[$tid]['nodecount']['count_own'] || $tree[$tid]['nodecount']['count_children'])) {
+ $children = taxonomy_get_children($term->tid);
+ if (is_array($children)) {
+ $tree[$tid]['children'] = _directory_get_tree($children, $content_type);
+ }
+ }
}
+
+ // Tree format:
+ // $tree[$tid]['nodecount'] the node count information
+ // $tree[$tid]['term'] the original term object
+ // $tree[$tid]['children'] the tree below the current term
+ return $tree;
+}
+
+/**
+ * This is a replacement function for taxonomy_term_count_nodes.
+ * See: http://drupal.org/node/144969 (drupal issue)
+ * and: http://drupal.org/node/145023 (directory issue).
+ *
+ * Count the number of published nodes classified by a term.
+ *
+ * @param $tid
+ * The term's ID
+ * @param $type
+ * The $node->type. If given, taxonomy_term_count_nodes only counts nodes of
+ * $type that are classified with the term $tid.
+ * @param $save_to_db
+ * This function is recursive, and we don't need to save the result in the DB at each iteration.
+ * $save_to_db is set to FALSE at each nested call, so that the actual saving to DB can happen only
+ * when the function exits the last time.
+ *
+ * @return $array
+ * where:
+ * $array['count_own'] being the number of nodes within the term proper.
+ * $array['count_children'] being the number of nodes in children terms, not counting those which are already counted in the parent term.
+ * $array['own_nodes'] array of nid's within this $tid.
+ * $array['children_nodes'] array of all the descendent nid's from children terms, not including those already set as one's own.
+ *
+ * Results are statically cached.
+ * Also, in order to improve performance accross requests, we cache the serialized array on database, in {cache_page} (this table is flushed each time a node or a taxonomy item is added/updated/deleted).
+ */
+function _directory_term_count_nodes($tid, $type = 0, $save_to_db = TRUE) {
+ static $count = array();
+ $modified = FALSE; // We keep track of modification of $count, to check whether we need to save it to DB.
+
+ if (empty($count)) {
+ $count = cache_get('taxonomy_term_count_nodes', 'cache_page');
+ $count = unserialize($count->data);
+ }
+
+ if (!isset($count[$type])) {
+ $modified = TRUE;
+ $count[$type] = array();
+ // In the queries below, we cannot use 'SELECT t.tid, COUNT(n.nid) AS c FROM ...'
+ // because a node may be assigned more than one term and be counted more than once.
+ // We therefore take note of the nid's and count the number of items in the $count array,
+ // making sure there is no duplicate.
+
+ // $type == 0 always evaluates TRUE if $type is a string
+ if (empty($type) || !is_string($type)) {
+ $result = db_query(db_rewrite_sql('SELECT t.tid, n.nid FROM {term_node} t JOIN {node} n ON t.nid = n.nid WHERE n.status = 1', 't', 'tid'));
+ }
+ else {
+ $result = db_query(db_rewrite_sql("SELECT t.tid, n.nid FROM {term_node} t JOIN {node} n ON t.nid = n.nid WHERE n.status = 1 AND n.type = '%s'", 't', 'tid'), $type);
+ }
+ while ($item = db_fetch_object($result)) {
+ if (!isset($count[$type][$item->tid])) {
+ $count[$type][$item->tid] = array('own_nodes' => array());
+ }
+ $count[$type][$item->tid]['own_nodes'][$item->nid] = 1;
+ }
+ }
+
+ if (!isset($count[$type][$tid]['count_own'])) {
+ $modified = TRUE;
+ $count[$type][$tid]['count_own'] = count($count[$type][$tid]['own_nodes']);
+ $count[$type][$tid]['count_children'] = 0;
+ $count[$type][$tid]['children_nodes'] = array();
+ foreach (_taxonomy_term_children($tid) as $c) {
+ if ($children = _directory_term_count_nodes($c, $type, FALSE)) { // FALSE: we do not need to save $count in the db at this iteration.
+ // Add the children's own nodes:
+ if (is_array($children['own_nodes'])) {
+ foreach ($children['own_nodes'] AS $child_nid => $n) {
+ if (!isset($count[$type][$tid]['own_nodes'][$child_nid])) { // make sure the nid is not already counted for the parent.
+ $count[$type][$tid]['children_nodes'][$child_nid] = 1;
+ }
+ }
+ }
+ // Add the nodes of the children's children.
+ if (is_array($children['children_nodes'])) {
+ foreach ($children['children_nodes'] AS $child_nid => $n) {
+ if (!isset($count[$type][$tid]['own_nodes'][$child_nid])) { // make sure the nid is not already counted for the parent.
+ $count[$type][$tid]['children_nodes'][$child_nid] = 1;
+ }
+ }
+ }
+ }
+ }
+ $count[$type][$tid]['count_children'] = count($count[$type][$tid]['children_nodes']);
+ }
+
+ if ($modified && $save_to_db) {
+ $cache = serialize($count);
+ // the cached data will be used for at least one hour before being flushed.
+ // TODO, make the nb of seconds before this cache is cleared configurable: time() + variable_get();
+ cache_set('taxonomy_term_count_nodes', 'cache_page', $cache, time() + 60 * 60);
+ }
+
+ return $count[$type][$tid];
}
/**
@@ -305,27 +389,16 @@ function directory_term_page($str_tids =
* An array of term IDs to match.
* @param $operator
* How to interpret multiple IDs in the array. Can be "or" or "and".
- * @param $depth
- * How many levels deep to traverse the taxonomy tree. Can be a nonnegative
- * integer or "all".
- * @param $limit
- * The number of results to return.
+ * @param $pager
+ * How many nodes should be displayed per page, zero means no pager.
+ * @param $content_type
+ * Only the nodes of this content type should be retrieved
+ * @param $order
+ * The order clause for the query that retrieve the nodes.
* @return
* A resource identifier pointing to the query results.
*/
-function directory_select_nodes($tids = array(), $operator = 'or', $depth = 0, $limit = 15) {
- $result = directory_select_nodes_query_builder($tids, $operator, $depth, $limit, 'fetch');
- return $result;
-}
-
-function directory_select_count_nodes($tids = array(), $operator = 'or', $depth = 0, $limit = 15) {
- return db_result(directory_select_nodes_query_builder($tids, $operator, $depth, $limit, 'count'));
-}
-
-/**
- * Private function for directory_select_nodes and directory_select_count_nodes
- */
-function directory_select_nodes_query_builder($tids = array(), $operator = 'or', $depth = 0, $limit = 15, $query_type = 'fetch') {
+function _directory_select_nodes($tids = array(), $operator = 'or', $pager = 10, $content_type = NULL, $order = 'n.sticky DESC, n.created DESC') {
if (count($tids) > 0) {
// For each term ID, generate an array of descendant term IDs to the right depth.
$descendant_tids = array();
@@ -338,10 +411,22 @@ function directory_select_nodes_query_bu
$descendant_tids[] = array_merge(array($tid), array_map('_taxonomy_get_tid_from_term', $tree));
}
+ if ($content_type) {
+ $content_type_where = "AND n.type = '". db_escape_string($content_type) ."' ";
+ }
+ else {
+ foreach (variable_get('directory_no_nodes', array()) as $content_type => $hide_nodes) {
+ if (!$hide_nodes) {
+ $enabled[] = "'$content_type'";
+ }
+ }
+ $content_type_where = 'AND n.type IN ('. implode(',', $enabled) .') ';
+ }
+
if ($operator == 'or') {
$str_tids = implode(',', call_user_func_array('array_merge', $descendant_tids));
- $sql_fetch = db_rewrite_sql('SELECT DISTINCT(n.nid), n.* FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN ('. $str_tids .') AND n.status = 1 ORDER BY n.sticky DESC, n.title ASC');
- $sql_count = db_rewrite_sql('SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN ('. $str_tids .') AND n.status = 1 ORDER BY n.sticky DESC, n.title ASC');
+ $sql = 'SELECT DISTINCT(n.nid), n.sticky, n.title, n.created, n.type FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN ('. $str_tids .') AND n.status = 1 '. $content_type_where .'ORDER BY '. $order;
+ $sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN ('. $str_tids .') AND n.status = 1 '. $content_type_where;
}
else {
$joins = '';
@@ -350,276 +435,143 @@ function directory_select_nodes_query_bu
$joins .= ' INNER JOIN {term_node} tn'. $index .' ON n.nid = tn'. $index .'.nid';
$wheres .= ' AND tn'. $index .'.tid IN ('. implode(',', $tids) .')';
}
- $sql_fetch = db_rewrite_sql('SELECT DISTINCT(n.nid), n.* FROM {node} n '. $joins .' WHERE n.status = 1 '. $wheres .' ORDER BY n.sticky DESC, n.title ASC');
- $sql_count = db_rewrite_sql('SELECT COUNT(DISTINCT(n.nid)) FROM {node} n '. $joins .' WHERE n.status = 1 '. $wheres .' ORDER BY n.sticky DESC, n.title ASC');
+ $sql = 'SELECT DISTINCT(n.nid), n.sticky, n.title, n.created, n.type FROM {node} n '. $joins .' WHERE n.status = 1 '. $content_type_where . $wheres .' ORDER BY '. $order;
+ $sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n '. $joins .' WHERE n.status = 1 '. $content_type_where . $wheres;
+ }
+ $sql = db_rewrite_sql($sql);
+ $sql_count = db_rewrite_sql($sql_count);
+ if ($pager > 0) {
+ $result = pager_query($sql, $pager, 0, $sql_count);
+ }
+ else {
+ // If no pager is used, limit to 100 results.
+ $result = db_query_range($sql, 0, 100);
}
-
- $sql = ($query_type == 'count') ? $sql_count : $sql_fetch;
- $result = (is_numeric($limit)) ? db_query_range($sql, 0, $limit) : db_query($sql);
}
return $result;
}
-/**
- * Load and goto a random directory link
- */
-function directory_random() {
- $nid = db_result(db_query('SELECT n.nid FROM {node} n WHERE n.status = 1 ORDER BY RAND() LIMIT 1'));
- drupal_goto("node/$nid");
+function _directory_get_filter_content_types() {
+ $content_type_objects = node_get_types();
+ $var = variable_get('directory_no_nodes', FALSE);
+
+ // Create an array, with the content type names to filter by as keys and
+ // their corresponding full names as values.
+ if (!$var) {
+ foreach ($content_type_objects as $internal_name => $type) {
+ $content_types[$internal_name] = $type->name;
+ }
+ }
+ else {
+ foreach ($var as $content_type => $hide_nodes) {
+ if (!$hide_nodes) {
+ $content_types[$content_type] = $content_type_objects[$content_type]->name;
+ }
+ }
+ }
+ return $content_types;
}
-/********************************************************************
- * Drupal Hooks :: Themeable Functions
- ********************************************************************/
+function _directory_remove_content_type_filter_from_url($url, $content_type) {
+ // Create a base drupal path that will be used in the theming function.
+ if ($url[strlen($url) - 1] == '/') {
+ $url = rtrim($url, '/');
+ }
-/**
- * @addtogroup themeable
- * @{
- */
+ // Remove the current content type from the Drupal path query.
+ if ($content_type) {
+ $url = substr($url, 0, strrpos($url, '/'));
+ }
-function theme_directory_listing($node) {
- $node->teaser = ($node->teaser) ? "- $node->teaser" : $node->teaser;
- return "
\n";
+ return $url;
}
-/** @} End of addtogroup themeable */
-
-/********************************************************************
- * Module Specific :: Private Functions
- ********************************************************************/
-
/**
- * Theme one section of the directory home page, corresponding to one vocabulary.
- * There will be as many sections as there are vocabularies displayed on the home page.
- *
- * @param $vid
- * integer: the vocabulary ID.
+ * Theme a vocabulary section. This typically shows the vocabulary tree,
+ * mentioning the number of nodes per term.
*
- * @param $collapse
- * boolean: say if the vocabulary should follow the collapsed setting.
- * if we are going to print only one vocabulary
- * it would be bad design to have it collapsed.
- *
- * @return $output
- * formatted html.
+ * @param $vocabulary
+ * A vocabulary object.
+ * @param $tree
+ * A tree generated by _directory_get_tree().
+ * @param $collapsed
+ * Whether this vocabulary should be collapsed or not at the theme level.
+ * @param $title
+ * Whether this vocabulary should have a title above its tree or not.
+ * @return
+ * The rendered HTML.
*/
-function theme_directory_home_vocabulary($vid, $collapse = TRUE) {
- $vocabulary = taxonomy_get_vocabulary($vid);
- $terms = taxonomy_get_children(0, $vid);
-
-
- $collapsed_vids = array();
- if ($collapse) {
- $collapsed_vids = variable_get('directory_vocabularies_collapsed', array());
- }
+function theme_directory_vocabulary($vocabulary, $tree = array(), $collapsed = TRUE, $title = TRUE, $content_type = NULL) {
+ static $js_added;
- $collapsed_string = '';
- if (in_array($vid, $collapsed_vids)) {
- $collapsed_string = 'directory-home-vocabulary-collapsed';
- }
- drupal_add_js(drupal_get_path('module', 'directory') .'/directory.js');
- drupal_add_js("var toggleT = ". drupal_to_js(t('show / hide')) .';', 'inline');
-
- $output = '
';
-
- return $output;
-}
-
-/**
- * Load all nodes found in a given tid
- *
- * We don't need static caching at this point since it is only called once per request.
- */
-function directory_get_nodes_by_term($tid, $limit = NULL, $pager = FALSE) {
- global $pager_count;
- if (!is_numeric($pager_count)) $pager_count = 1;
- $nodes = array();
- $where = '';
-
- $skip_type = variable_get('directory_no_nodes', '');
- if (!empty($skip_type)) {
- foreach ($skip_type as $type) {
- $t[] = "'". db_escape_string($type) ."'";
- }
- $where = 'AND n.type NOT IN ('. implode(",", $t) .')';
- }
-
- if ($tid == 'alpha') {
- $sql = db_rewrite_sql('SELECT n.nid FROM {node} n INNER JOIN {term_node} t ON t.nid = n.nid WHERE 1 '. $where .' AND n.status = 1 ORDER BY n.sticky DESC, n.changed DESC');
- }
- elseif ($tid == '0-9') {
- $sql = db_rewrite_sql('SELECT n.nid FROM {node} n INNER JOIN {term_node} t ON t.nid = n.nid WHERE 1 '. $where ." AND n.status = 1 AND n.title REGEXP '^[0-9]' ORDER BY n.sticky DESC, n.changed DESC");
- }
- elseif (preg_match('/^[a-zA-z]$/', $tid)) {
- $sql = db_rewrite_sql('SELECT n.nid FROM {node} n INNER JOIN {term_node} t ON t.nid = n.nid WHERE 1 '. $where ." AND n.status = 1 AND n.title LIKE '". db_escape_string($tid) ."%' ORDER BY n.sticky DESC, n.changed DESC");
- }
- else {
- $sql = db_rewrite_sql('SELECT n.nid FROM {node} n INNER JOIN {term_node} t ON t.nid = n.nid WHERE 1 '. $where .' AND n.status = 1 AND t.tid = '. db_escape_string($tid) .' ORDER BY n.sticky DESC, n.changed DESC');
- }
- if ($pager) {
- $result = pager_query($sql, $limit, $pager_count);
- $pager_count++;
- }
- else {
- $result = $limit ? db_query_range($sql, 0, $limit) : db_query($sql);
+ if (!isset($js_added)) {
+ drupal_add_js(drupal_get_path('module', 'directory') .'/directory.js');
+ drupal_add_js("var toggleT = ". drupal_to_js(t('show / hide')) .';', 'inline');
+ $js_added = TRUE;
}
- while ($data = db_fetch_object($result)) {
- $nodes[$data->nid] = node_load($data->nid);
- $nids[] = $data->nid;
- }
-
- /* Delete this if statement if using the above 'old way' */
- /* A very quick way of gathering taxonomy terms for the collected nodes. */
- if ($nids) {
- $qqq='SELECT t.*, r.nid FROM {term_data} t, {term_node} r WHERE r.tid = t.tid AND r.nid IN ('. implode(', ', $nids) .') ORDER BY weight, name';
- $result = db_query($qqq);
- while ($t = db_fetch_object($result)) {
- $nodes[$t->nid]->taxonomy[$t->tid] = $t;
+ $collapsed_class = '';
+ if ($collapsed) {
+ $collapsed_vids = variable_get('directory_vocabularies_collapsed', array());
+ if (in_array($vocabulary->vid, $collapsed_vids)) {
+ $collapsed_class = 'directory-home-vocabulary-collapsed';
}
}
- return $nodes;
-}
+ $hierarchy_class = ($vocabulary->hierarchy > 0) ? ' hierarchical-vocabulary' : '';
-/**
- * Display the nodes related to a term.
- * This function corresponds to the whole page, and will in turn call theme_directory_resource_section.
- *
- * @param $tid
- * An integer ($term->tid)
- * Or a string. See http://drupal.org/node/144743 and Alphabetical listing code block below.
- *
- * @param $filter
- * either NULL or string 'vid'. If 'vid', terms will be filtered by that vid.
- * See http://drupal.org/node/144743.
- *
- * @param $fid
- * An integer corresponding to the vocabulary ID to filter by.
- *
- * @return $output
- * formatted html.
- */
-function theme_directory_resource($tid, $filter = null, $fid = null) {
- global $pager_total;
- global $pager_count;
- $num_results_per_page = 100;
-
- /* Filters */
- if ($filter == 'vid' && is_numeric($fid)) {
- /* Set the page heading to the term that's being filtered. */
- $term = taxonomy_get_term($tid);
- $vocabulary = taxonomy_get_vocabulary($fid);
- $title = "
$term->name, by $vocabulary->name
\n";
- $nodes = directory_get_nodes_by_term($tid, $num_results_per_page, true);
- /* This is a container for nodes with no term matching the filter. We create an 'Other' category out of this. */
- $nodes_sans_terms = $nodes;
- $taxonomy = taxonomy_get_tree($fid);
- /* Iterate through the filter's terms and display resources that are linked to them */
- foreach ($taxonomy as $term) {
- $node_by_term = null;
- foreach ($nodes as $nid => $node) {
- if ($node->taxonomy[$term->tid]) {
- $node_by_term[$nid] = $node;
- unset($nodes_sans_terms[$nid]);
- }
- }
- $output .= theme('directory_resource_section', $node_by_term, $term);
- }
-
- /* Create the fake 'Other' category */
- $term->tid = -1;
- $term->name = t('General');
- $output .= theme('directory_resource_section', $nodes_sans_terms, $term);
-
- }
- // Alphabetical listing
- elseif (preg_match('/^[a-zA-z]$/', $tid) || $tid == 'alpha' || $tid == '0-9') {
- if ($nodes = directory_get_nodes_by_term($tid, $num_results_per_page, true)) {
- $node = _first($nodes);
- $term = $node->taxonomy[$tid]; // mjc: nodes array is indexed by nid, not 0-based
- $output = directory_toolbar_alpha($tid);
- $output .= theme('directory_resource_section', $nodes, $term);
- if ($pager = theme('pager', NULL, $num_results_per_page, $pager_count - 1)) {
- $output .= $pager;
- }
- }
- }
- // Listing the nodes related to a single term.
- elseif (is_numeric($tid)) {
- $output = theme('directory_resource_sub_section', $tid);
- if ($nodes = directory_get_nodes_by_term($tid, $num_results_per_page, true)) {
- $node = _first($nodes);
- $term = $node->taxonomy[$tid]; // MJC: was $nodes[0] which seems not to exist.. why? get_nodes_by_term uses nid as index into array!
- $output .= theme('directory_resource_section', $nodes, $term);
- }
- else {
- // FIXME: what is the use of this else{} block? We are returning $output, not $term!
- $term = taxonomy_get_term($tid);
- }
+ $path = "directory/vocabulary/$vocabulary->vid";
+ if ($content_type) {
+ $path .= "/$content_type";
}
+ $title_content = (!$title) ? NULL : l(t('!vocabulary-name', array('!vocabulary-name' => $vocabulary->name)), $path);
+ $output = '
';
return $output;
}
/**
- * Display a box with links to the sub-categories
- * This function only displays the shell (title +
elements) where the links will be.
- * It calls theme_directory_list_terms() which will print the content (list of links).
- *
- * @param $tid
- * The term ID whose sub-categories must be displayed.
+ * Theme a tree.
*
+ * @param $tree
+ * A tree generated by _directory_get_tree().
+ * @param $title
+ * The title that will be used for this tree. A tree is typically presented
+ * as nested unordered list, so this title will be placed before the root
+ * unordered list.
+ * @param $content_type
+ * The content type to filter by.
* @return
- * formatted html
+ * The rendered HTML.
*/
-function theme_directory_resource_sub_section($tid) {
- $output = '';
-
- if ($terms = taxonomy_get_children($tid)) {
- $output .= '
'. t('There are currently no posts in this category.') .'
';
}
-
return $output;
}
/**
- * Format a summary of the current pager position, such as "6 through 10 of 52".
+ * Theme the content type filters section.
*
- * @param $limit
- * The number of query results to display per page.
- * @param $element
- * An optional integer to distinguish between multiple pagers on one page.
- * @param $format
- * A printf-style format string for customizing the pager text.
+ * @param $content_type
+ * The content type by which is currently being filtered.
* @return
- * An HTML string that generates this piece of the query pager.
- *
- * @ingroup themeable
+ * The rendered HTML.
*/
-function theme_directory_pager_detail($limit, $element = 0, $format = '%d through %d of %d.') {
- global $pager_from_array, $pager_total;
-
- $output = '
';
-
- return $output;
-}
-
-/**
- * Get the first element of an array
- */
-function &_first(&$array) {
- if (!is_array($array))
- return null;
- if (!count($array))
- return false; // like reset()
- reset($array);
- return $array[key($array)];
-}
-
-/**
- * Get last element of an array
- */
-function &_last(&$array) {
- if (!is_array($array))
- return null;
- if (!count($array))
- return false; // like end()
- end($array);
- return $array[key($array)];
-}
-
-/**
- * This is a replacement function for taxonomy_term_count_nodes.
- * See: http://drupal.org/node/144969 (drupal issue)
- * and: http://drupal.org/node/145023 (directory issue).
- *
- * Count the number of published nodes classified by a term.
- *
- * @param $tid
- * The term's ID
- *
- * @param $type
- * The $node->type. If given, taxonomy_term_count_nodes only counts
- * nodes of $type that are classified with the term $tid.
- *
- * @param $save_to_db
- * This function is recursive, and we don't need to save the result in the DB at each iteration.
- * $save_to_db is set to FALSE at each nested call, so that the actual saving to DB can happen only
- * when the function exits the last time.
- *
- * @return $array
- * where:
- * $array['count_own'] being the number of nodes within the term proper.
- * $array['count_children'] being the number of nodes in children terms, not counting those which are already counted in the parent term.
- * $array['own_nodes'] array of nid's within this $tid.
- * $array['children_nodes'] array of all the descendent nid's from children terms, not including those already set as one's own.
- *
- * Results are statically cached.
- * Also, in order to improve performance accross requests, we cache the serialized array on database, in {cache_page} (this table is flushed each time a node or a taxonomy item is added/updated/deleted).
- */
-function directory_taxonomy_term_count_nodes($tid, $type = 0, $save_to_db = TRUE) {
- static $count = array();
- $modified = FALSE; // We keep track of modification of $count, to check whether we need to save it to DB.
-
- if (empty($count)) {
- $count = cache_get('taxonomy_term_count_nodes', 'cache_page');
- $count = unserialize($count->data);
- }
+function theme_directory_content_type_filters($content_type) {
+ $output = '';
- if (!isset($count[$type])) {
- $modified = TRUE;
- $count[$type] = array();
- // In the queries below, we cannot use 'SELECT t.tid, COUNT(n.nid) AS c FROM ...'
- // because a node may be assigned more than one term and be counted more than once.
- // We therefore take note of the nid's and count the number of items in the $count array,
- // making sure there is no duplicate.
-
- // $type == 0 always evaluates TRUE if $type is a string
- if (is_numeric($type)) {
- $result = db_query(db_rewrite_sql('SELECT t.tid, n.nid FROM {term_node} t JOIN {node} n ON t.nid = n.nid WHERE n.status = 1', 't', 'tid'));
- }
- else {
- $result = db_query(db_rewrite_sql("SELECT t.tid, n.nid FROM {term_node} t JOIN {node} n ON t.nid = n.nid WHERE n.status = 1 AND n.type = '%s'", 't', 'tid'), $type);
- }
- while ($item = db_fetch_object($result)) {
- if (!isset($count[$type][$item->tid])) {
- $count[$type][$item->tid] = array('own_nodes' => array());
- }
- $count[$type][$item->tid]['own_nodes'][$item->nid] = 1;
- }
- }
+ $content_types = _directory_get_filter_content_types();
+ $base_drupal_path = _directory_remove_content_type_filter_from_url($_GET['q'], $content_type);
- if (!isset($count[$type][$tid]['count_own'])) {
- $modified = TRUE;
- $count[$type][$tid]['count_own'] = count($count[$type][$tid]['own_nodes']);
- $count[$type][$tid]['count_children'] = 0;
- $count[$type][$tid]['children_nodes'] = array();
- foreach (_taxonomy_term_children($tid) as $c) {
- if ($children = directory_taxonomy_term_count_nodes($c, $type, FALSE)) { // FALSE: we do not need to save $count in the db at this iteration.
- // Add the children's own nodes:
- if (is_array($children['own_nodes'])) {
- foreach ($children['own_nodes'] AS $child_nid => $n) {
- if (!isset($count[$type][$tid]['own_nodes'][$child_nid])) { // make sure the nid is not already counted for the parent.
- $count[$type][$tid]['children_nodes'][$child_nid] = 1;
- }
- }
- }
- // Add the nodes of the children's children.
- if (is_array($children['children_nodes'])) {
- foreach ($children['children_nodes'] AS $child_nid => $n) {
- if (!isset($count[$type][$tid]['own_nodes'][$child_nid])) { // make sure the nid is not already counted for the parent.
- $count[$type][$tid]['children_nodes'][$child_nid] = 1;
- }
- }
- }
- }
- }
- $count[$type][$tid]['count_children'] = count($count[$type][$tid]['children_nodes']);
- }
+ $output .= '
';
- if ($modified && $save_to_db) {
- $cache = serialize($count);
- // the cached data will be used for at least one hour before being flushed.
- // TODO, make the nb of seconds before this cache is cleared configurable: time() + variable_get();
- cache_set('taxonomy_term_count_nodes', 'cache_page', $cache, time() + 60 * 60);
+ $output .= '
'. t("Filter by content type") .'';
+ $output .= l(t('No filter'), $base_drupal_path, array('class' => 'directory-content-type-filter-link'));
+ foreach ($content_types as $internal_name => $full_name) {
+ $output .= l($full_name, $base_drupal_path .'/'. $internal_name, array('class' => 'directory-content-type-filter-link'));
}
- return $count[$type][$tid];
-}
-
-/**
- * Menu callback for directory/vocabulary.
- *
- * @param $vid
- * the vocabulary ID.
- */
-function directory_vocabulary_page($vid = '') {
- $output = '';
-
- // If we don't have a real vocabulary ID, redirect to the main directory page.
- if (empty($vid) || !is_numeric($vid)) {
- drupal_goto('directory');
+ $output .= '