| 1 |
<?php |
<?php |
| 2 |
// $Id: indexpage.module,v 1.7 2006/04/13 15:49:31 unconed Exp $ |
// $Id$ |
| 3 |
|
|
| 4 |
/** |
/** |
| 5 |
* indexpage module |
* @file |
| 6 |
* |
* This module displays customizable index pages for each node type, with |
| 7 |
* This module displays customizables index pages for each node type, with |
* alphabetical, taxonomy, and user filters. |
| 8 |
* alphabetical and taxonomy filters. |
* |
|
* |
|
| 9 |
* Licensed under the terms of the GNU General Public License: |
* Licensed under the terms of the GNU General Public License: |
| 10 |
* http://www.opensource.org/licenses/gpl-license.php |
* http://www.opensource.org/licenses/gpl-license.php |
| 11 |
* |
* |
| 12 |
* @version 1.0 |
* @version 1.0 |
| 13 |
* @author Carlos A. Paramio (carlos.paramio@interactors.coop) |
* @author Carlos A. Paramio (carlos.paramio@interactors.coop) |
| 14 |
* |
* |
| 15 |
* @version 1.2 |
* @version 1.2 |
| 16 |
* Updated for 4.7 forms, node list, and plugged SQL injection holes |
* Updated for 4.7 forms, node list, and plugged SQL injection holes |
| 17 |
* @author Khalid Baheyeldin http://2bits.com |
* @author Khalid Baheyeldin http://2bits.com |
| 18 |
* |
* |
| 19 |
|
* @version 1.3 |
| 20 |
|
* Updated for 5.x, 6.x. |
| 21 |
|
* @author Nancy Wichmann http://nanwich.info |
| 22 |
|
* |
| 23 |
|
* @version 1.4 |
| 24 |
|
* Updated for 5.x, 6.x - added user filters, faster page build. |
| 25 |
|
* @author Nancy Wichmann http://nanwich.info |
| 26 |
*/ |
*/ |
| 27 |
|
|
| 28 |
function indexpage_help($section = null) { |
/** |
| 29 |
switch ($section) { |
* Implementation of hook_help(). |
| 30 |
|
*/ |
| 31 |
|
function indexpage_help($path, $args) { |
| 32 |
|
switch ($path) { |
| 33 |
case 'admin/help#indexpage': |
case 'admin/help#indexpage': |
| 34 |
return t('Displays index pages for each node type, with alphabetical and taxonomy filters.'); |
return t('Displays index pages for each node type, with alphabetical, taxonomy, and user filters.'); |
| 35 |
break; |
break; |
| 36 |
} |
} |
| 37 |
} |
} |
| 38 |
|
|
| 39 |
function indexpage_admin_settings() { |
/** |
| 40 |
$form['general'] = array( |
* Implementation of hook_theme(). |
| 41 |
'#type' => 'fieldset', |
*/ |
| 42 |
'#title' => t('General settings'), |
function indexpage_theme($path, $args) { |
| 43 |
'#collapsible' => true, |
return array( |
| 44 |
'#collapsed' => false, |
'indexpage_term' => array( |
| 45 |
); |
'arguments' => array('term', 'type'), |
| 46 |
|
), |
|
$form['general']['indexpage_description'] = array( |
|
|
'#type' => 'textarea', |
|
|
'#title' => t('Description text for main index page'), |
|
|
'#default_value' => variable_get('indexpage_description', ''), |
|
|
'#cols' => 60, |
|
|
'#rows' => 5, |
|
|
); |
|
|
|
|
|
$form['general']['indexpage_maxresults'] = array( |
|
|
'#type' => 'textfield', |
|
|
'#title' => t('Max number of results per page'), |
|
|
'#default_value' => variable_get('indexpage_maxresults', 10), |
|
|
'#size' => 2, |
|
|
'#maxlength' => 2, |
|
|
); |
|
|
|
|
|
$form['general']['indexpage_suppress_unused'] = array( |
|
|
'#type' => 'checkbox', |
|
|
'#title' => t('Suppress unused taxonomy terms'), |
|
|
'#default_value' => variable_get('indexpage_suppress_unused', false), |
|
|
'#description' => t('If this option is selected, terms with no associated nodes will not be shown.'), |
|
|
); |
|
|
|
|
|
$form['general']['indexpage_teaser_tooltip'] = array( |
|
|
'#type' => 'checkbox', |
|
|
'#title' => t("Use the node's teaser as the link title"), |
|
|
'#default_value' => variable_get('indexpage_teaser_tooltip', true), |
|
|
'#description' => t('If this option is selected, the teaser for the node will be used for the link title (tooltip).'), |
|
| 47 |
); |
); |
|
|
|
|
// Do a fieldset for each content type. |
|
|
$type_list = node_get_types('names'); |
|
|
foreach ($type_list as $type => $name) { |
|
|
$set = $type; |
|
|
$form[$set] = array( |
|
|
'#type' => 'fieldset', |
|
|
'#title' => t('Index page settings for !s', array('!s' => $type)), |
|
|
'#collapsible' => true, |
|
|
'#collapsed' => false, |
|
|
); |
|
|
|
|
|
$var_prefix = 'indexpage_'. $type; |
|
|
|
|
|
$form[$set][$var_prefix .'_name'] = array( |
|
|
'#type' => 'textfield', |
|
|
'#title' => t('Name to show for this node type'), |
|
|
'#default_value' => variable_get($var_prefix .'_name', $name), |
|
|
'#size' => 20, |
|
|
'#maxlength' => 50, |
|
|
); |
|
|
|
|
|
$form[$set][$var_prefix .'_enable'] = array( |
|
|
'#type' => 'checkbox', |
|
|
'#title' => t('Enable index page for this node type'), |
|
|
'#return_value' => 1, |
|
|
'#default_value' => variable_get($var_prefix .'_enable', 1), |
|
|
); |
|
|
|
|
|
$form[$set][$var_prefix .'_alphaindex'] = array( |
|
|
'#type' => 'checkbox', |
|
|
'#title' => t('Show alphabetical index for this node type'), |
|
|
'#return_value' => 1, |
|
|
'#default_value' => variable_get($var_prefix .'_alphaindex', 1), |
|
|
); |
|
|
|
|
|
$form[$set][$var_prefix .'_vocfilter'] = array( |
|
|
'#type' => 'checkbox', |
|
|
'#title' => t('Show vocabulary filters for this node type'), |
|
|
'#return_value' => 1, |
|
|
'#default_value' => variable_get($var_prefix .'_vocfilter', 1), |
|
|
); |
|
|
} |
|
|
return system_settings_form($form); |
|
| 48 |
} |
} |
| 49 |
|
|
| 50 |
|
/** |
| 51 |
|
* Implementation of hook_perm(). |
| 52 |
|
*/ |
| 53 |
function indexpage_perm() { |
function indexpage_perm() { |
| 54 |
return array('access indexpage'); |
return array('access indexpage'); |
| 55 |
} |
} |
| 56 |
|
|
| 57 |
function indexpage_menu($may_cache) { |
/** |
| 58 |
|
* Implementation of hook_menu(). |
| 59 |
|
*/ |
| 60 |
|
function indexpage_menu() { |
| 61 |
global $user; |
global $user; |
| 62 |
$items = array(); |
$items = array(); |
| 63 |
if ($may_cache) { |
$items['indexpage'] = array( |
| 64 |
$items[] = array( |
'title' => 'Index page', |
| 65 |
'path' => 'indexpage', |
'page callback' => 'indexpage_page', |
| 66 |
'title' => t('Index page'), |
'page arguments' => array(1, 2, 3), |
| 67 |
'callback' => 'indexpage_page', |
'access arguments' => array('access indexpage'), |
|
'access' => user_access('access indexpage'), |
|
| 68 |
'type' => MENU_NORMAL_ITEM, |
'type' => MENU_NORMAL_ITEM, |
| 69 |
); |
); |
| 70 |
|
|
| 71 |
$items[] = array( |
$items['admin/settings/indexpage'] = array( |
| 72 |
'path' => 'admin/settings/indexpage', |
'title' => 'IndexPage', |
| 73 |
'title' => t('IndexPage'), |
'description' => 'IndexPage settings.', |
| 74 |
'description' => t('IndexPage settings.'), |
'page callback' => 'drupal_get_form', |
| 75 |
'callback' => 'drupal_get_form', |
'page arguments' => array('indexpage_admin_settings'), |
| 76 |
'callback arguments' => array('indexpage_admin_settings'), |
'access arguments' => array('administer site configuration'), |
|
'access' => user_access('administer site configuration'), |
|
| 77 |
'type' => MENU_NORMAL_ITEM, |
'type' => MENU_NORMAL_ITEM, |
| 78 |
|
'file' => 'indexpage.admin.inc', |
| 79 |
); |
); |
| 80 |
|
|
| 81 |
} |
|
|
else { |
|
|
$types = node_get_types('names'); |
|
|
foreach ($types as $type => $name) { |
|
|
if (variable_get('indexpage_'. $type .'_enable', 1)) { |
|
|
$items[] = array( |
|
|
'path' => 'indexpage/'. $type, |
|
|
'title' => t('Index page for !s', array('!s' => variable_get('indexpage_'. $type .'_name', $name))), |
|
|
'description' => t('Index page for !s', array('!s' => $name)), |
|
|
'access' => user_access('access indexpage'), |
|
|
'type' => MENU_NORMAL_ITEM, |
|
|
); |
|
|
} |
|
|
} |
|
|
} |
|
| 82 |
return $items; |
return $items; |
| 83 |
} |
} |
| 84 |
|
|
| 85 |
function indexpage_page() { |
function indexpage_page($type, $op = NULL, $uid = NULL) { |
| 86 |
|
drupal_add_css(drupal_get_path('module', 'indexpage') . '/indexpage.css'); |
| 87 |
|
|
| 88 |
|
global $user; |
| 89 |
|
$output = NULL; |
| 90 |
|
|
| 91 |
// Is this the overview index? |
// Is this the overview index? |
| 92 |
if (!arg(1)) { |
if (!$type) { |
| 93 |
$output .= '<div class="content">'; |
$output .= '<div class="content">'; |
| 94 |
$output .= nl2br(variable_get('indexpage_description', '')); |
$output .= nl2br(variable_get('indexpage_description', '')); |
| 95 |
$output .= '<ul>'; |
$output .= '<ul>'; |
| 96 |
$types = node_get_types('names'); |
$types = node_get_types('names'); |
| 97 |
foreach ($types as $type => $name) { |
foreach ($types as $type => $name) { |
| 98 |
if (variable_get('indexpage_'. $type .'_enable', 1)) { |
if (variable_get('indexpage_' . $type . '_enable', 1)) { |
| 99 |
$output .= '<li>'. l(t('Index page for !s', array('!s' => variable_get('indexpage_'. $type .'_name', $type))), 'indexpage/'. $type) .'</li>'; |
$output .= '<li>' . l(t('Index page for !s', array('!s' => check_plain(variable_get('indexpage_' . $type . '_name', $type)))), drupal_get_path_alias('indexpage/' . $type)) . '</li>'; |
| 100 |
} |
} |
| 101 |
} |
} |
|
$output .= '</ul></div>'; |
|
| 102 |
|
|
| 103 |
if (user_access('administer site configuration')) { |
$output .= '</ul></div>'; |
|
$output .= '<p>'. l(t('Indexpage settings'), 'admin/settings/indexpage', array(), drupal_get_destination()) .'</p>'; |
|
|
} |
|
| 104 |
|
|
| 105 |
return $output; |
return $output; |
| 106 |
} |
} |
| 107 |
else { |
else { |
| 108 |
// Do the index for a specific type. |
// Do the index for a specific type. |
| 109 |
$access = _node_access_where_sql(); |
// $sql = _indexpage_check_status("SELECT COUNT(n.nid) FROM {node} n WHERE n.type = ':type'"); |
| 110 |
$exist_type = @db_result(db_query("SELECT COUNT(n.type) FROM {node} n, {node_access} na WHERE n.type = '%s'". ($access ? ' AND '. $access : ''), arg(1))); |
$sql = _indexpage_check_status("SELECT COUNT(n.nid) FROM {node} n WHERE n.type = '$type'"); |
| 111 |
if ($exist_type && variable_get('indexpage_'. arg(1) .'_enable', 1)) { |
$exist_type = db_result(db_query($sql, array(':type' => $type))); |
| 112 |
if (!arg(2)) { |
if ($exist_type && variable_get('indexpage_' . $type . '_enable', 1)) { |
| 113 |
return indexpage_page_index(arg(1)); |
if (empty($op) && $op !== '0') { |
| 114 |
|
$unpublished = @db_result(db_query("SELECT COUNT(DISTINCT(n.nid)) FROM {node} n WHERE n.type = ':type' AND n.status = 0", array(':type' => $type))); |
| 115 |
|
return indexpage_page_index($type, $exist_type, $unpublished); |
| 116 |
} |
} |
| 117 |
else { |
else { |
| 118 |
return indexpage_page_list(arg(1), arg(2)); |
return indexpage_page_list($type, $op, $uid); |
| 119 |
} |
} |
| 120 |
} |
} |
| 121 |
else { |
else { |
| 122 |
return t('ERROR: That node type does not exist, there are no entries, or the index page for this node type is disabled.'); |
return t('ERROR: That content type does not exist, there are no entries, or the index page for that type is disabled.'); |
| 123 |
} |
} |
| 124 |
} |
} |
| 125 |
} |
} |
| 126 |
|
|
| 127 |
function indexpage_page_index($type) { |
function indexpage_page_index($type, $count = 0, $unpub_count = 0) { |
| 128 |
$name = variable_get('indexpage_'. $type .'_name', $type); |
$stuff = explode('-', $type); |
| 129 |
|
$type = $stuff[0]; |
| 130 |
|
|
| 131 |
|
$name = check_plain(variable_get('indexpage_' . $type . '_name', $type)); |
| 132 |
|
$show_count = variable_get('indexpage_show_count', TRUE); |
| 133 |
|
$show_users = variable_get('indexpage_show_users', FALSE); |
| 134 |
|
$show_untagged = variable_get('indexpage_show_untagged', TRUE); |
| 135 |
|
$suppress_unused = variable_get('indexpage_suppress_unused', FALSE); |
| 136 |
|
$show_description = variable_get('indexpage_show_description', FALSE); |
| 137 |
|
$list_format = variable_get('indexpage_list_format', 'list'); |
| 138 |
$links = array(); |
$links = array(); |
| 139 |
|
|
| 140 |
/* Index by letter block */ |
drupal_set_title(t('Index Page for !type', array('!type' => $name))); |
| 141 |
if (variable_get('indexpage_'. $type .'_alphaindex', 1)) { |
|
| 142 |
$output .= '<div class="filter">'; |
$output = '<div class="indexpage_index indexpage_' . $type . '">'; |
| 143 |
$output .= '<h3>'. t('Alphabetical index') .'</h3>'; |
|
| 144 |
|
// Get node info. |
| 145 |
|
$node_opts = variable_get('node_options_' . $type, array()); |
| 146 |
|
if (($where = array_search(t('status'), $node_opts)) !== FALSE) { |
| 147 |
|
$node_opts[$where] = t('published'); |
| 148 |
|
} |
| 149 |
|
|
| 150 |
|
if ($description = variable_get('indexpage_' . $type . '_page_text', NULL)) { |
| 151 |
|
$output .= '<div class="indexpage_description">' . $description . '</div>'; |
| 152 |
|
} |
| 153 |
|
|
| 154 |
|
if ($show_count) { |
| 155 |
|
$count_msg = format_plural($count, 'There is one !type node', 'There are @count !type nodes', |
| 156 |
|
array('!type' => $name)); |
| 157 |
|
if ($unpub_count) { |
| 158 |
|
$count_msg .= format_plural($unpub_count, ', of which one is unpublished.', ', of which @count are unpublished.'); |
| 159 |
|
} |
| 160 |
|
else { |
| 161 |
|
$count_msg .= '.'; |
| 162 |
|
} |
| 163 |
|
$output .= '<p>' . $count_msg . ' ' . t('This content type uses these options: !opts.', array('!opts' => implode(', ', $node_opts))) . '</p>'; |
| 164 |
|
} |
| 165 |
|
|
| 166 |
|
// Index by letter block. |
| 167 |
|
if (variable_get('indexpage_' . $type . '_alphaindex', 1)) { |
| 168 |
|
$output .= '<div class="indexpage-node-index">'; |
| 169 |
|
$output .= '<h3>' . t('Alphabetical index') . '</h3>'; |
| 170 |
|
$output .= '<p><em>' . t('Click a letter to see the titles of content beginning with that letter.') . '</em></p>'; |
| 171 |
$output .= '<p>'; |
$output .= '<p>'; |
| 172 |
|
// Note: this doesn't work well with non-English. |
| 173 |
$range = drupal_map_assoc(range('A', 'Z')); |
$range = drupal_map_assoc(range('A', 'Z')); |
| 174 |
foreach ($range as $letter) { |
foreach ($range as $letter) { |
| 175 |
$sql = "SELECT COUNT(n.nid) FROM {node} n INNER JOIN {node_revisions} r USING (nid, vid) WHERE n.type='%s' AND (r.title LIKE '%s%%' OR r.title LIKE '%s%%')"; |
$sql = _indexpage_check_status("SELECT COUNT(n.nid) FROM {node} n WHERE n.type=':type' AND LOWER(n.title) LIKE ':letter%'"); |
| 176 |
if (db_result(db_query($sql, $type, $letter, strtolower($letter))) > 0) { |
if (db_result(db_query($sql, array(':type' => $type, ':letter' => drupal_strtolower($letter)))) > 0) { |
| 177 |
$range[$letter] = l($letter, "indexpage/$type/$letter"); |
$range[$letter] = l($letter, drupal_get_path_alias("indexpage/$type/$letter"), array('attributes' => array('title' => "$name content beginning with '$letter'"))); |
| 178 |
} |
} |
| 179 |
} |
} |
| 180 |
|
|
| 181 |
$sql = "SELECT COUNT(n.nid) FROM {node} n INNER JOIN {node_revisions} r USING (nid, vid) WHERE n.type='%s' AND (r.title REGEXP '^[^[:alpha:]].*$')"; |
$sql = _indexpage_check_status("SELECT COUNT(n.nid) FROM {node} n WHERE n.type=':type' AND (n.title REGEXP '^[^[:alpha:]].*$')"); |
| 182 |
if (db_result(db_query($sql, $type)) > 0) { |
if (db_result(db_query($sql, array(':type' => $type))) > 0) { |
| 183 |
$range['#'] = l('#', "indexpage/$type/_"); |
$range['#'] = l('#', drupal_get_path_alias("indexpage/$type/_"), array('attributes' => array('title' => "$name content beginning with a non-alphabetic character"))); |
| 184 |
} |
} |
| 185 |
|
|
| 186 |
$range['all'] = l('all', "indexpage/$type/all"); |
$range['all'] = l(t('all'), drupal_get_path_alias("indexpage/$type/all"), array('attributes' => array('title' => "All $name content"))); |
| 187 |
|
|
| 188 |
|
$output .= implode(' | ', $range) . '</p></div>'; |
| 189 |
|
} |
| 190 |
|
|
| 191 |
$output .= implode(' | ', $range) .'</p></div>'; |
// Index by users section. |
| 192 |
|
$rows = array(); |
| 193 |
|
$sql = _indexpage_check_status("SELECT n.uid, COUNT(n.uid) as count FROM {node} n WHERE n.type=':type'") . ' GROUP BY n.uid'; |
| 194 |
|
$users = db_query($sql, $type); |
| 195 |
|
while ($u = db_fetch_object($users)) { |
| 196 |
|
$account = user_load($u->uid); |
| 197 |
|
$rows[] = array( |
| 198 |
|
theme('username', $account, array('picture' => TRUE, 'homepage' => FALSE)), |
| 199 |
|
l($u->count, "indexpage/$type/user/$u->uid", array('attributes' => array('title' => t('Show the content this user contributed')))), |
| 200 |
|
); |
| 201 |
|
} |
| 202 |
|
if ($rows) { |
| 203 |
|
$header = array(t('User Name'), t('Count')); |
| 204 |
|
$fieldset = array( |
| 205 |
|
'#title' => t('Users who have created !name content', array('!name' => $name)), |
| 206 |
|
'#description' => t('User names link to the user profile; the counts link to a list of titles by that user.'), |
| 207 |
|
'#collapsible' => TRUE, |
| 208 |
|
'#collapsed' => (count($rows) > variable_get('indexpage_maxresults', 10)), |
| 209 |
|
'#value' => theme('table', $header, $rows), |
| 210 |
|
); |
| 211 |
|
$output .= '<div class="indexpage-users">' . theme('fieldset', $fieldset) . '</div>'; |
| 212 |
} |
} |
| 213 |
|
|
| 214 |
// Index by taxonomy terms block. |
// Index by taxonomy terms section. |
| 215 |
$voc_list = array(); |
$voc_list = array(); |
| 216 |
$suppress_unused = variable_get('indexpage_suppress_unused', false); |
if (variable_get('indexpage_' . $type . '_vocfilter', 1)) { |
| 217 |
if (variable_get('indexpage_'. $type .'_vocfilter', 1)) { |
$vocs = db_query("SELECT v.name, v.vid FROM {taxonomy_vocabulary} v LEFT JOIN {taxonomy_vocabulary_node_type} t ON t.vid=v.vid WHERE t.type=':type'", $type); |
|
$vocs = db_query("SELECT name, v.vid FROM {vocabulary} v LEFT JOIN {vocabulary_node_types} vnt on v.vid=vnt.vid WHERE type LIKE '%%%s%%'", $type); |
|
| 218 |
while ($voc = db_fetch_array($vocs)) { |
while ($voc = db_fetch_array($vocs)) { |
| 219 |
$term_list = array(); |
$term_list = array(); |
| 220 |
$voc_list[$voc['vid']] = $voc['name']; |
$voc_list[$voc['vid']] = check_plain($voc['name']); |
| 221 |
$output .= '<div class="indexpage-filter">'; |
$output .= '<div class="indexpage-filter-' . $voc['vid'] . '">'; |
| 222 |
$output .= '<h3>'. t('List by !s terms', array('!s' => $voc['name'])) .'</h3>'; |
$voc_count = 0; |
| 223 |
|
|
| 224 |
$terms = db_query('SELECT name, tid FROM {term_data} WHERE vid=%s', $voc['vid']); |
$terms = taxonomy_get_tree($voc['vid']); |
| 225 |
while ($term = db_fetch_object($terms)) { |
foreach ($terms as $term) { |
| 226 |
$sql = "SELECT COUNT(n.nid) FROM {node} n LEFT JOIN {term_node} t on n.nid=t.nid WHERE type='%s' AND t.tid=%d"; |
$sql = _indexpage_check_status("SELECT COUNT(n.nid) FROM {node} n LEFT JOIN {taxonomy_term_node} t on t.nid=n.nid AND t.vid=n.vid WHERE type=':type' AND t.tid=:tid"); |
| 227 |
if (db_result(db_query($sql, $type, $term->tid))) { |
$term->node_count = $how_many = db_result(db_query($sql, array(':type' => $type, ':tid' => $term->tid))); |
| 228 |
$term_list[] = l($term->name, "indexpage/$type/$term->tid"); |
$voc_count += $how_many; |
| 229 |
|
if ($how_many || !$suppress_unused) { |
| 230 |
|
$term_list[] = theme('indexpage_term', $term, $type); |
| 231 |
|
} |
| 232 |
|
} |
| 233 |
|
|
| 234 |
|
if ($term_list) { |
| 235 |
|
if ($list_format == 'list') { |
| 236 |
|
$stuff = theme('item_list', $term_list, NULL, 'ul', array('class' => 'indexpage_term_list')); |
| 237 |
} |
} |
| 238 |
else { |
else { |
| 239 |
if (!$suppress_unused) { |
$header = array(); |
| 240 |
$term_list[] = $term->name; |
if ($show_description) { |
| 241 |
|
$header = array( |
| 242 |
|
t('Category'), |
| 243 |
|
t('Description'), |
| 244 |
|
); |
| 245 |
} |
} |
| 246 |
|
$stuff = theme('table', $header, $term_list, array('class' => 'indexpage_term_list')); |
| 247 |
} |
} |
| 248 |
} |
} |
| 249 |
$output .= '<p>'. implode(' | ', $term_list) .'</p></div>'; |
else { |
| 250 |
|
$stuff = '<p>' . t('None found') . '</p>'; |
| 251 |
|
} |
| 252 |
|
$fieldset = array( |
| 253 |
|
'#title' => t('List by !s Categories', array('!s' => $voc['name'])) . ($show_count ? ' (' . $voc_count . ')' : NULL), |
| 254 |
|
'#description' => t('Terms (categories) that have content will link to a list of titles tagged with that term.'), |
| 255 |
|
'#collapsible' => TRUE, |
| 256 |
|
'#collapsed' => (count($term_list) > variable_get('indexpage_maxresults', 10)), |
| 257 |
|
'#value' => $stuff, |
| 258 |
|
'#attributes' => array('class' => 'indexpage_category indexpage_category_' . $voc['vid']), |
| 259 |
|
); |
| 260 |
|
$output .= theme('fieldset', $fieldset) . '</div>'; |
| 261 |
|
} |
| 262 |
|
|
| 263 |
|
// Handle unclassified. |
| 264 |
|
if ($show_untagged) { |
| 265 |
|
$sql = _indexpage_check_status("SELECT COUNT(n.nid) FROM {node} n LEFT JOIN {taxonomy_term_node} t on n.nid=t.nid WHERE type=':type' AND t.tid IS NULL"); |
| 266 |
|
$how_many = db_result(db_query($sql, array(':type' => $type))); |
| 267 |
|
if ($how_many > 0) { |
| 268 |
|
$title = format_plural($how_many, 'There is one unclassified !type node.', 'There are @count unclassified !type nodes.', |
| 269 |
|
array('!type' => $name)); |
| 270 |
|
$output .= '<p>' . l($title, drupal_get_path_alias("indexpage/$type/0")) . '</p>'; |
| 271 |
|
} |
| 272 |
|
$sql = _indexpage_check_status("SELECT n.nid, v.name FROM {node} n JOIN {taxonomy_term_node} tn ON tn.nid=n.nid JOIN {taxonomy_term_data} td ON td.tid=tn.tid JOIN {taxonomy_vocabulary} v ON v.vid=td.vid LEFT JOIN {taxonomy_vocabulary_node_type} nt ON nt.vid=v.vid AND nt.type=n.type WHERE n.type=':type' AND nt.type IS NULL"); |
| 273 |
|
$misclassed = db_query($sql, array(':type' => $type)); |
| 274 |
|
$voc_names = array(); |
| 275 |
|
$how_many = 0; |
| 276 |
|
while ($row = db_fetch_array($misclassed)) { |
| 277 |
|
$voc_names[] = decode_entities(check_plain($row['name'])); |
| 278 |
|
++$how_many; |
| 279 |
|
} |
| 280 |
|
if ($voc_names) { |
| 281 |
|
$voc_names = array_unique($voc_names); |
| 282 |
|
$output .= '<p>' . t('There are !count !type nodes improperly classified in %vocs.', array('!count' => $how_many, '!type' => $type_name, '%vocs' => implode(', ', $voc_names))) . '</p>'; |
| 283 |
|
} |
| 284 |
} |
} |
| 285 |
} |
} |
| 286 |
|
|
| 287 |
// Operations for this node type. |
// Operations for this node type. |
| 288 |
$output .= '<h3>'. t('Operations') .'</h3>'; |
$output .= '<h3>' . t('Operations') . '</h3>'; |
| 289 |
$dest = drupal_get_destination(); |
$dest = drupal_get_destination(); |
| 290 |
|
|
| 291 |
$links['indexpage-create'] = array( |
if (user_access("create $type") || user_access("create $type content")) { |
| 292 |
'title' => t('Create a new entry'), |
$links['indexpage-create'] = array( |
| 293 |
'href' => 'node/add/'. $type, |
'title' => t('Create a new entry'), |
| 294 |
'attributes' => array('title' => t('Create a new !type node.', array('!type' => $type))), |
'href' => 'node/add/' . $type, |
| 295 |
'query' => $dest, |
'attributes' => array('title' => t('Create a new !type node.', array('!type' => $type)), 'rel' => 'nofollow'), |
| 296 |
); |
'query' => $dest, |
| 297 |
|
); |
| 298 |
|
} |
| 299 |
|
|
| 300 |
if (user_access('administer content types')) { |
if (user_access('administer content types')) { |
| 301 |
$links['indexpage-content-type'] = array( |
$links['indexpage-content-type'] = array( |
| 302 |
'title' => t('Edit !type', array('!type' => $type)), |
'title' => t('Edit !type', array('!type' => $type)), |
| 303 |
'href' => 'admin/content/types/'. $type, |
'href' => 'admin/content/types/' . $type, |
| 304 |
'attributes' => array('title' => t('Edit the !type content type', array('!type' => $type))), |
'attributes' => array('title' => t('Edit the !type content type', array('!type' => $type)), 'rel' => 'nofollow'), |
| 305 |
'query' => $dest, |
'query' => $dest, |
| 306 |
); |
); |
| 307 |
} |
} |
| 308 |
|
|
| 309 |
if (user_access('administer taxonomy')) { |
if (user_access('administer taxonomy')) { |
| 310 |
foreach ($voc_list as $vid => $name) { |
foreach ($voc_list as $vid => $name) { |
| 311 |
$links['indexpage-vocabulary-'. $vid] = array( |
$links['indexpage-vocabulary-' . $vid] = array( |
| 312 |
'title' => t('Edit !type vocabulary', array('!type' => $name)), |
'title' => t('Edit !type vocabulary', array('!type' => $name)), |
| 313 |
'href' => 'admin/content/taxonomy/edit/vocabulary/'. $vid, |
'href' => 'admin/content/taxonomy/edit/vocabulary/' . $vid, |
| 314 |
'attributes' => array('title' => t('Edit the !type vocabulary.', array('!type' => $name))), |
'attributes' => array('title' => t('Edit the !type vocabulary.', array('!type' => $name)), 'rel' => 'nofollow'), |
| 315 |
'query' => $dest, |
'query' => $dest, |
| 316 |
); |
); |
| 317 |
} |
} |
| 318 |
} |
} |
| 319 |
|
|
| 320 |
|
if (user_access('administer site configuration')) { |
| 321 |
|
$links['indexpage-settings'] = array( |
| 322 |
|
'title' => t('Indexpage settings'), |
| 323 |
|
'href' => 'admin/settings/indexpage', |
| 324 |
|
'attributes' => array('title' => t('Change the Indexpage settings'), 'rel' => 'nofollow'), |
| 325 |
|
'query' => $dest, |
| 326 |
|
); |
| 327 |
|
} |
| 328 |
|
|
| 329 |
$output .= theme('links', $links, array('class' => 'links inline')); |
$output .= theme('links', $links, array('class' => 'links inline')); |
| 330 |
|
|
| 331 |
return $output; |
return $output . '</div>'; |
| 332 |
} |
} |
| 333 |
|
|
| 334 |
function indexpage_page_list($type, $filter) { |
function theme_indexpage_term($term, $type) { |
| 335 |
$name = variable_get('indexpage_'. $type .'_name', $type); |
static $show_count, $show_description, $list_format; |
| 336 |
$output = null; |
if (!isset($show_count)) { |
| 337 |
if ($term = intval($filter)) { |
$show_count = variable_get('indexpage_show_count', TRUE); |
| 338 |
// Filter by vocabulary term. |
$show_description = variable_get('indexpage_show_description', FALSE); |
| 339 |
$sql = "SELECT r.title, n.nid, r.teaser FROM {node} n LEFT JOIN {term_node} t USING (nid) INNER JOIN {node_revisions} r USING (nid, vid) WHERE type='%s' AND t.tid=%d"; |
$list_format = variable_get('indexpage_list_format', 'list'); |
| 340 |
$args = array($type, $term); |
} |
| 341 |
|
$item = str_repeat('– ', $term->depth); |
| 342 |
|
if ($term->node_count) { |
| 343 |
|
$item .= l($term->name, drupal_get_path_alias("indexpage/$type/$term->tid")) . ($show_count ? ' (' . $term->node_count . ')' : NULL); |
| 344 |
} |
} |
| 345 |
else { |
else { |
| 346 |
// Check if all nodes of this type wanted. |
$item .= check_plain($term->name); |
| 347 |
if ($filter == 'all') { |
} |
| 348 |
$sql = "SELECT r.title, n.nid, r.teaser FROM {node} n INNER JOIN {node_revisions} r USING (nid, vid) WHERE n.type='%s'"; |
switch ($list_format) { |
| 349 |
$args = array($type); |
case 'list': |
| 350 |
|
$item .= $show_description ? (' — ' . $term->description) : NULL; |
| 351 |
|
break; |
| 352 |
|
|
| 353 |
|
case 'table': |
| 354 |
|
$item = array($item); |
| 355 |
|
if ($show_description) { |
| 356 |
|
$item[] = $term->description; |
| 357 |
|
} |
| 358 |
|
break; |
| 359 |
|
} |
| 360 |
|
return $item; |
| 361 |
|
} |
| 362 |
|
|
| 363 |
|
function _indexpage_check_status($query) { |
| 364 |
|
// Must have 'admin nodes' permission to see unpublished. |
| 365 |
|
if (!user_access('administer nodes')) { |
| 366 |
|
$query .= ' AND n.status = 1'; |
| 367 |
|
} |
| 368 |
|
return db_rewrite_sql($query); |
| 369 |
|
} |
| 370 |
|
|
| 371 |
|
function indexpage_page_list($type, $filter, $uid = NULL) { |
| 372 |
|
static $acct = array(); |
| 373 |
|
$name = check_plain(variable_get('indexpage_' . $type . '_name', $type)); |
| 374 |
|
|
| 375 |
|
$breadcrumb = drupal_get_breadcrumb(); |
| 376 |
|
$breadcrumb[] = l(t('Index page for !s', array('!s' => $name)), drupal_get_path_alias('indexpage/' . $type)); |
| 377 |
|
drupal_set_breadcrumb($breadcrumb); |
| 378 |
|
|
| 379 |
|
$output = '<div class="indexpage_results">'; |
| 380 |
|
$args = array(':type' => $type); |
| 381 |
|
if (is_numeric($filter)) { |
| 382 |
|
// Filter by vocabulary term. |
| 383 |
|
$sql = "SELECT n.*, r.teaser FROM {node} n LEFT JOIN {taxonomy_term_node} t ON t.nid=n.nid AND t.vid=n.vid INNER JOIN {node_revision} r ON r.nid=n.nid AND r.vid=n.vid WHERE type=':type' AND t.tid :filter "; |
| 384 |
|
$args[':filter'] = $filter == 0 ? 'IS NULL' : '=' . $filter; |
| 385 |
|
|
| 386 |
|
if ($filter) { |
| 387 |
|
$term = taxonomy_get_term($filter); |
| 388 |
|
$term_name = check_plain($term->name); |
| 389 |
} |
} |
| 390 |
else { |
else { |
| 391 |
// Filter by letter. |
$term_name = t('no terms'); |
| 392 |
if ($filter == '_') { |
} |
| 393 |
$sql = "SELECT r.title, n.nid, r.teaser FROM {node} n INNER JOIN {node_revisions} r USING (nid, vid) WHERE n.type='%s' AND (r.title REGEXP '^[^[:alpha:]].*$')"; |
drupal_set_title(t('!type nodes classified with !term', array('!type' => $name, '!term' => $term_name))); |
| 394 |
$args = array($type); |
} |
| 395 |
} |
else { |
| 396 |
else { |
switch ($filter) { |
| 397 |
$sql = "SELECT r.title, n.nid, r.teaser FROM {node} n INNER JOIN {node_revisions} r USING (nid, vid) WHERE n.type='%s' AND (r.title LIKE '%s%%' OR r.title LIKE '%s%%')"; |
case 'all': |
| 398 |
$args = array($type, $filter, strtolower($filter)); |
// All nodes of this type wanted. |
| 399 |
} |
$sql = "SELECT n.*, r.teaser FROM {node} n INNER JOIN {node_revision} r ON r.nid=n.nid AND r.vid=n.vid WHERE n.type=':type'"; |
| 400 |
|
drupal_set_title(t('All !type nodes', array('!type' => $name))); |
| 401 |
|
break; |
| 402 |
|
|
| 403 |
|
case '_': |
| 404 |
|
// Filter by non_alpha. |
| 405 |
|
$sql = "SELECT n.*, r.teaser FROM {node} n INNER JOIN {node_revision} r ON r.nid=n.nid AND r.vid=n.vid WHERE n.type=':type' AND (n.title REGEXP '^[^[:alpha:]].*$')"; |
| 406 |
|
drupal_set_title(t('!type nodes beginning with non-alphabetical', array('!type' => $name))); |
| 407 |
|
break; |
| 408 |
|
|
| 409 |
|
case 'user': |
| 410 |
|
// Filter by user. |
| 411 |
|
$sql = "SELECT n.*, r.teaser FROM {node} n INNER JOIN {node_revision} r ON r.nid=n.nid AND r.vid=n.vid WHERE n.type=':type' AND n.uid = :uid"; |
| 412 |
|
$args[':uid'] = $uid; |
| 413 |
|
$account = user_load($uid); |
| 414 |
|
drupal_set_title(t('!type nodes created by %user', array('!type' => $name, '%user' => theme('username', $account, array('plain' => TRUE))))); |
| 415 |
|
break; |
| 416 |
|
|
| 417 |
|
default: |
| 418 |
|
// Filter by letter. |
| 419 |
|
$sql = "SELECT n.*, r.teaser FROM {node} n INNER JOIN {node_revision} r ON r.nid=n.nid AND r.vid=n.vid WHERE n.type=':type' AND LOWER(n.title) LIKE ':letter%'"; |
| 420 |
|
$args[':letter'] = drupal_strtolower($filter); |
| 421 |
|
drupal_set_title(t('!type nodes beginning with "!term"', array('!type' => $name, '!term' => $filter))); |
| 422 |
|
break; |
| 423 |
} |
} |
| 424 |
} |
} |
| 425 |
|
|
| 426 |
$header = array( |
$sql = _indexpage_check_status($sql); |
| 427 |
array('data' => t('title'), 'field' => 'title', 'sort' => 'asc'), |
|
| 428 |
|
$show_fields = array_merge(array('title' => 1), variable_get('indexpage_fields', array())); |
| 429 |
|
$show_fields = array_filter($show_fields); |
| 430 |
|
$weight_avail = module_exists('weight'); |
| 431 |
|
|
| 432 |
|
$fields = array( |
| 433 |
|
'title' => array('data' => t('Title'), 'field' => 'title', 'sort' => 'asc', 'class' => 'left'), |
| 434 |
|
'type' => array('data' => t('Type'), 'field' => 'type', 'class' => 'center'), |
| 435 |
|
'language' => array('data' => t('Language'), 'field' => 'language', 'class' => 'center'), |
| 436 |
|
'uid' => array('data' => t('Author'), 'field' => 'uid', 'class' => 'left'), |
| 437 |
|
'authors' => array('data' => t('Authors / Editors'), 'field' => 'uid', 'class' => 'left'), |
| 438 |
|
'terms' => array('data' => t('Terms'), /*'field' => 'taxonomy',*/ 'class' => 'left'), |
| 439 |
|
'created' => array('data' => t('Created'), 'field' => 'created', 'class' => 'center'), |
| 440 |
|
'changed' => array('data' => t('Updated'), 'field' => 'changed', 'class' => 'center'), |
| 441 |
|
'status' => array('data' => t('Published'), 'field' => 'status', 'class' => 'center'), |
| 442 |
|
'promote' => array('data' => t('Promoted'), 'field' => 'promote', 'class' => 'center'), |
| 443 |
|
'sticky' => array('data' => t('Sticky'), 'field' => 'sticky', 'class' => 'center'), |
| 444 |
); |
); |
| 445 |
$sql .= tablesort_sql($header); |
if ($weight_avail) { |
| 446 |
|
$fields['weight'] = array('data' => t('Weight'), /*'field' => 'node_weight',*/ 'class' => 'center'); |
| 447 |
|
} |
| 448 |
|
|
| 449 |
$max_results = variable_get('indexpage_maxresults', 10); |
$max_results = variable_get('indexpage_maxresults', 10); |
| 450 |
$result = pager_query($sql, $max_results, 0, null, $args); |
$tooltip = variable_get('indexpage_teaser_tooltip', TRUE); |
| 451 |
if (db_num_rows(db_query($sql, $args))) { |
|
| 452 |
while ($n = db_fetch_object($result)) { |
$header = array(); |
| 453 |
if (variable_get('indexpage_teaser_tooltip', true)) { |
foreach ($show_fields as $key => $value) { |
| 454 |
$title = strip_tags($n->teaser); |
$header[] = $fields[$key]; |
| 455 |
|
} |
| 456 |
|
$rows = array(); |
| 457 |
|
|
| 458 |
|
$sql .= tablesort_sql($header); |
| 459 |
|
// Have to do this crap until they update pager_query. |
| 460 |
|
$search = array_keys($args); |
| 461 |
|
$replace = array_values($args); |
| 462 |
|
$sql = str_replace($search, $replace, $sql); |
| 463 |
|
$result = pager_query($sql, $max_results, 0, NULL, $args); |
| 464 |
|
|
| 465 |
|
while ($node = db_fetch_object($result)) { |
| 466 |
|
$line = array(); |
| 467 |
|
if ($weight_avail) { |
| 468 |
|
_weight_decode($node); |
| 469 |
|
} |
| 470 |
|
|
| 471 |
|
foreach ($show_fields as $key => $value) { |
| 472 |
|
switch ($key) { |
| 473 |
|
case 'terms': |
| 474 |
|
// $field_value = $node->taxonomy; |
| 475 |
|
break; |
| 476 |
|
case 'weight': |
| 477 |
|
$field_value = $node->node_weight; |
| 478 |
|
break; |
| 479 |
|
default: |
| 480 |
|
$field_value = $node->{$fields[$key]['field']}; |
| 481 |
} |
} |
| 482 |
else { |
$field_align = $fields[$key]['class']; |
| 483 |
$title = check_plain($n->title); |
switch ($key) { |
| 484 |
|
case 'title': |
| 485 |
|
if ($tooltip) { |
| 486 |
|
$title = strip_tags($node->teaser); |
| 487 |
|
} |
| 488 |
|
else { |
| 489 |
|
$title = check_plain($field_value); |
| 490 |
|
} |
| 491 |
|
$field_value = l($node->title, drupal_get_path_alias('node/' . $node->nid), array('attributes' => array('title' => $title))); |
| 492 |
|
break; |
| 493 |
|
|
| 494 |
|
case 'changed': |
| 495 |
|
case 'created': |
| 496 |
|
$field_value = format_date($field_value, 'custom', variable_get('date_format_short', 'm/d/Y - H:i')); |
| 497 |
|
break; |
| 498 |
|
|
| 499 |
|
case 'promote': |
| 500 |
|
case 'status': |
| 501 |
|
case 'sticky': |
| 502 |
|
$field_value = $field_value > 0 ? t('Yes') : t('No'); |
| 503 |
|
break; |
| 504 |
|
|
| 505 |
|
case 'uid': |
| 506 |
|
$account = user_load($node->uid); |
| 507 |
|
$field_value = theme('username', $account); |
| 508 |
|
break; |
| 509 |
|
|
| 510 |
|
case 'terms': |
| 511 |
|
$items = array(); |
| 512 |
|
$terms = db_query("SELECT td.name FROM {taxonomy_term_node} tn JOIN {taxonomy_term_data} td ON td.tid=tn.tid WHERE tn.nid=:nid ORDER BY td.name", array(':nid' => $node->nid)); |
| 513 |
|
while ($name = db_result($terms)) { |
| 514 |
|
$items[] = check_plain($name); |
| 515 |
|
} |
| 516 |
|
if ($items) { |
| 517 |
|
$items = array_unique($items); |
| 518 |
|
} |
| 519 |
|
else { |
| 520 |
|
$items[] = t('- none -'); |
| 521 |
|
} |
| 522 |
|
if (count($items) > 1) { |
| 523 |
|
$field_value = decode_entities(theme('item_list', $items)); |
| 524 |
|
} |
| 525 |
|
else { |
| 526 |
|
$field_value = $items[0]; |
| 527 |
|
} |
| 528 |
|
break; |
| 529 |
|
|
| 530 |
|
case 'authors': |
| 531 |
|
$items = array(); |
| 532 |
|
$uids = array($node->uid); |
| 533 |
|
$revs = db_query("SELECT DISTINCT(r.uid) FROM {node_revision} r WHERE r.nid=:nid ORDER by r.vid DESC", array(':nid' => $node->nid)); |
| 534 |
|
while ($rev_uid = db_result($revs)) { |
| 535 |
|
$uids[] = $rev_uid; |
| 536 |
|
} |
| 537 |
|
$uids = array_unique($uids); |
| 538 |
|
foreach ($uids as $uid) { |
| 539 |
|
if (!isset($acct[$uid])) { |
| 540 |
|
$acct[$uid] = user_load($uid); |
| 541 |
|
} |
| 542 |
|
$items[] = theme('username', $acct[$uid]); |
| 543 |
|
} |
| 544 |
|
$field_value = theme('item_list', $items); |
| 545 |
|
break; |
| 546 |
} |
} |
| 547 |
$rows[] = array( |
$line[] = array('data' => $field_value, 'align' => $field_align); |
|
// l(htmlspecialchars($n->title), 'node/'. $n->nid, array('title' => strip_tags($n->teaser))), |
|
|
l($n->title, 'node/'. $n->nid, array('title' => $title)), |
|
|
); |
|
|
} |
|
|
if ($pager = theme('pager', NULL, $max_results, 0)) { |
|
|
$rows[] = array(array('data' => $pager, 'colspan' => 2)); |
|
| 548 |
} |
} |
| 549 |
$output .= theme('table', $header, $rows); |
$rows[] = $line; |
| 550 |
} |
} |
| 551 |
else { |
|
| 552 |
$output .= t('There are no results'); |
if (!$rows) { |
| 553 |
|
$rows[] = array(array('data' => t('There are no results.'), 'colspan' => 20)); |
| 554 |
} |
} |
| 555 |
$output .= '<p>'. l(t('Return to index page for !s', array('!s' => $name)), 'indexpage/'. $type) .'</p>'; |
|
| 556 |
return $output; |
$output .= theme('table', $header, $rows) . theme('pager'); |
| 557 |
|
return $output . '</div>'; |
| 558 |
} |
} |