| 1 |
<?php
|
| 2 |
// $Id: photoblog.module,v 1.2 2006/12/12 01:44:19 davidlesieur Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
*
|
| 7 |
* This module implements photoblog features.
|
| 8 |
*
|
| 9 |
* The main specifications/constraints that guide the design of this module are:
|
| 10 |
*
|
| 11 |
* - Have one node per page.
|
| 12 |
*
|
| 13 |
* - Nodes are in chronological order, with simple previous/next navigation.
|
| 14 |
*
|
| 15 |
* - The previous/next navigation links should be consistent, permanent links
|
| 16 |
* (unlike the standard Drupal pager, which uses relative page numbers).
|
| 17 |
*
|
| 18 |
* - Allow for posting comments in each post's page, and without losing the
|
| 19 |
* navigation context (which precludes both the Drupal pager and Views,
|
| 20 |
* unfortunately).
|
| 21 |
*
|
| 22 |
* - Allow the most recent photoblog post to be used as the site's front page.
|
| 23 |
*
|
| 24 |
* To comply with these specifications, photoblog posts must be displayed as
|
| 25 |
* node pages (node/nid paths). Therefore, the navigation context can only be
|
| 26 |
* inferred from the current node.
|
| 27 |
*
|
| 28 |
* So the resulting compromises are:
|
| 29 |
*
|
| 30 |
* - It is possible to navigate through posts from all users, or from one user
|
| 31 |
* at a time, but only one of these two modes is available site-wide.
|
| 32 |
*
|
| 33 |
* - The previous/next navigation follows a term from the photoblog vocabulary.
|
| 34 |
* The navigation path must be unambiguous, which means that any given node
|
| 35 |
* should use only one term from that vocabulary. Fortunately, terms from other
|
| 36 |
* vocabularies can be used without restraint since they are ignored by the
|
| 37 |
* photoblog navigation logic.
|
| 38 |
*
|
| 39 |
* Suggestions to improve this design are always welcome. ;-)
|
| 40 |
*/
|
| 41 |
|
| 42 |
/**
|
| 43 |
* Implementation of hook_perm().
|
| 44 |
*/
|
| 45 |
function photoblog_perm() {
|
| 46 |
return array('administer photoblogs');
|
| 47 |
}
|
| 48 |
|
| 49 |
/**
|
| 50 |
* Implementation of hook_menu().
|
| 51 |
*/
|
| 52 |
function photoblog_menu($may_cache) {
|
| 53 |
$items = array();
|
| 54 |
if ($may_cache) {
|
| 55 |
$items[] = array(
|
| 56 |
'path' => 'admin/content/photoblog',
|
| 57 |
'title' => t('Photoblogs'),
|
| 58 |
'callback' => 'photoblog_admin',
|
| 59 |
'access' => user_access('administer photoblogs'),
|
| 60 |
'description' => t('Create and manage photoblogs.'),
|
| 61 |
);
|
| 62 |
$items[] = array(
|
| 63 |
'path' => 'admin/content/photoblog/list',
|
| 64 |
'title' => t('List'),
|
| 65 |
'access' => user_access('administer photoblogs'),
|
| 66 |
'type' => MENU_DEFAULT_LOCAL_TASK,
|
| 67 |
'weight' => -10,
|
| 68 |
);
|
| 69 |
$items[] = array(
|
| 70 |
'path' => 'admin/content/photoblog/add',
|
| 71 |
'title' => t('Add photoblog'),
|
| 72 |
'callback' => 'photoblog_admin_add',
|
| 73 |
'access' => user_access('administer photoblogs'),
|
| 74 |
'type' => MENU_LOCAL_TASK,
|
| 75 |
);
|
| 76 |
$items[] = array(
|
| 77 |
'path' => 'photoblog/latest',
|
| 78 |
'callback' => 'photoblog_goto',
|
| 79 |
'callback arguments' => array('latest'),
|
| 80 |
'access' => user_access('access content'),
|
| 81 |
'type' => MENU_CALLBACK,
|
| 82 |
);
|
| 83 |
$items[] = array(
|
| 84 |
'path' => 'photoblog/first',
|
| 85 |
'callback' => 'photoblog_goto',
|
| 86 |
'callback arguments' => array('first'),
|
| 87 |
'access' => user_access('access content'),
|
| 88 |
'type' => MENU_CALLBACK,
|
| 89 |
);
|
| 90 |
$items[] = array(
|
| 91 |
'path' => 'admin/settings/photoblog',
|
| 92 |
'title' => ('Photoblog'),
|
| 93 |
'callback' => 'drupal_get_form',
|
| 94 |
'callback arguments' => array('photoblog_admin_settings'),
|
| 95 |
'access' => user_access('administer site configuration'),
|
| 96 |
'description' => t('Configure photoblog settings.'),
|
| 97 |
'type' => MENU_NORMAL_ITEM,
|
| 98 |
);
|
| 99 |
}
|
| 100 |
elseif (arg(0) == 'admin' && arg(1) == 'content' && arg(2) == 'photoblog' && arg(3) == 'edit' && is_numeric(arg(4))) {
|
| 101 |
$term = taxonomy_get_term((int)arg(4));
|
| 102 |
if ($term) {
|
| 103 |
$items[] = array(
|
| 104 |
'path' => 'admin/content/photoblog/edit',
|
| 105 |
'title' => t('Edit photoblog'),
|
| 106 |
'callback' => 'photoblog_admin_add',
|
| 107 |
'callback arguments' => array((array)$term),
|
| 108 |
'access' => user_access('administer photoblogs'),
|
| 109 |
'type' => MENU_CALLBACK,
|
| 110 |
);
|
| 111 |
}
|
| 112 |
}
|
| 113 |
|
| 114 |
return $items;
|
| 115 |
}
|
| 116 |
|
| 117 |
/**
|
| 118 |
* Implementation of hook_nodeapi().
|
| 119 |
*/
|
| 120 |
function photoblog_nodeapi(&$node, $op, $teaser) {
|
| 121 |
if ($node->type == 'image') {
|
| 122 |
switch ($op) {
|
| 123 |
case 'load':
|
| 124 |
$data['photoblog_next_nid'] = photoblog_get_next($node);
|
| 125 |
$data['photoblog_prev_nid'] = photoblog_get_prev($node);
|
| 126 |
return $data;
|
| 127 |
|
| 128 |
case 'view':
|
| 129 |
// Output navigation links in node content, if appropriate
|
| 130 |
$links_output = _photoblog_get_navigation_links_output();
|
| 131 |
if (isset($links_output['content'])) {
|
| 132 |
$node->content['photoblog-navigation-links'] = array(
|
| 133 |
'#value' => theme('links', photoblog_get_navigation_links($node, 'content'), array('class' => 'links photoblog-navigation-links')),
|
| 134 |
'#weight' => 0,
|
| 135 |
);
|
| 136 |
}
|
| 137 |
break;
|
| 138 |
|
| 139 |
case 'insert':
|
| 140 |
case 'update':
|
| 141 |
// Set front page, if appropriate
|
| 142 |
if (variable_get('photoblog_set_frontpage', FALSE) && $node->status && photoblog_is_photoblog_post($node->nid)) {
|
| 143 |
$args = explode('/', variable_get('site_frontpage', ''));
|
| 144 |
if (($args[0] != 'node' && !is_numeric($args[1])) || $node->nid > $args[1]) {
|
| 145 |
variable_set('site_frontpage', "node/$node->nid");
|
| 146 |
}
|
| 147 |
}
|
| 148 |
break;
|
| 149 |
}
|
| 150 |
}
|
| 151 |
}
|
| 152 |
|
| 153 |
/**
|
| 154 |
* Implementation of hook_link(). Outputs the navigation links as node links.
|
| 155 |
*/
|
| 156 |
function photoblog_link($type, $node = NULL, $teaser = FALSE) {
|
| 157 |
$links = array();
|
| 158 |
$links_output = _photoblog_get_navigation_links_output();
|
| 159 |
if ($type == 'node' && $node && !$teaser && isset($links_output['links'])) {
|
| 160 |
$links = photoblog_get_navigation_links($node, 'links');
|
| 161 |
}
|
| 162 |
return $links;
|
| 163 |
}
|
| 164 |
|
| 165 |
/**
|
| 166 |
* Implementation of hook_block(). Outputs the navigation links in a block.
|
| 167 |
*/
|
| 168 |
function photoblog_block($op = 'list', $delta = 0, $edit = array()) {
|
| 169 |
if ($op == 'list') {
|
| 170 |
$links_output = _photoblog_get_navigation_links_output();
|
| 171 |
if (isset($links_output['block'])) {
|
| 172 |
$blocks[0]['info'] = t('Photoblog navigation');
|
| 173 |
}
|
| 174 |
$blocks[1]['info'] = t('Photoblogs list');
|
| 175 |
return $blocks;
|
| 176 |
}
|
| 177 |
elseif ($op == 'view') {
|
| 178 |
switch ($delta) {
|
| 179 |
case 0:
|
| 180 |
// Find what node is currently displayed
|
| 181 |
if (arg(0) == 'node' && is_numeric(arg(1)) && ($node = node_load(arg(1)))) {
|
| 182 |
// Display the navigation links for the currently displayed node
|
| 183 |
$block['content'] = theme('links', photoblog_get_navigation_links($node, 'block'));
|
| 184 |
}
|
| 185 |
return $block;
|
| 186 |
|
| 187 |
case 1:
|
| 188 |
$block['subject'] = t('Photoblogs');
|
| 189 |
$block['content'] = photoblog_get_start_links();
|
| 190 |
return $block;
|
| 191 |
}
|
| 192 |
}
|
| 193 |
}
|
| 194 |
|
| 195 |
/**
|
| 196 |
* Callback to edit photoblog terms.
|
| 197 |
*/
|
| 198 |
function photoblog_admin() {
|
| 199 |
$header = array(t('Name'), t('Operations'));
|
| 200 |
|
| 201 |
$tree = taxonomy_get_tree(_photoblog_get_vid());
|
| 202 |
if ($tree) {
|
| 203 |
foreach ($tree as $term) {
|
| 204 |
$rows[] = array(str_repeat(' -- ', $term->depth) .' '. _photoblog_format_start_link($term->name, '*', $term->tid), l(t('edit photoblog'), "admin/content/photoblog/edit/$term->tid"));
|
| 205 |
}
|
| 206 |
return theme('table', $header, $rows);
|
| 207 |
}
|
| 208 |
else {
|
| 209 |
return t('No photoblogs available');
|
| 210 |
}
|
| 211 |
}
|
| 212 |
|
| 213 |
function photoblog_admin_add($edit = array()) {
|
| 214 |
if ($_POST['op'] == t('Delete') || $_POST['confirm']) {
|
| 215 |
return drupal_get_form('photoblog_confirm_delete', $edit['tid']);
|
| 216 |
}
|
| 217 |
|
| 218 |
return drupal_get_form('photoblog_admin_form', $edit);
|
| 219 |
}
|
| 220 |
|
| 221 |
function photoblog_admin_form($edit = array()) {
|
| 222 |
if (empty($edit)) {
|
| 223 |
$edit['vid'] = _photoblog_get_vid();
|
| 224 |
}
|
| 225 |
|
| 226 |
$form['name'] = array(
|
| 227 |
'#type' => 'textfield',
|
| 228 |
'#title' => t('Photoblog name'),
|
| 229 |
'#default_value' => $edit['name'],
|
| 230 |
'#size' => 60,
|
| 231 |
'#maxlength' => 64,
|
| 232 |
'#description' => t('The name is used to identify the photoblog.'),
|
| 233 |
'#required' => TRUE,
|
| 234 |
);
|
| 235 |
$form['description'] = array(
|
| 236 |
'#type' => 'textarea',
|
| 237 |
'#title' => t('Description'),
|
| 238 |
'#default_value' => $edit['description'],
|
| 239 |
'#cols' => 60,
|
| 240 |
'#rows' => 5,
|
| 241 |
'#description' => ('The description can be used to provide more information about the photoblog.'),
|
| 242 |
);
|
| 243 |
$form['weight'] = array(
|
| 244 |
'#type' => 'weight',
|
| 245 |
'#title' => t('Weight'),
|
| 246 |
'#default_value' => $edit['weight'],
|
| 247 |
'#delta' => 10,
|
| 248 |
'#description' => t('When listing photoblogs, those with with light (small) weights get listed before photoblogs with heavier (larger) weights. Photoblogs with equal weights are sorted alphabetically.'),
|
| 249 |
);
|
| 250 |
$form['start'] = array(
|
| 251 |
'#type' => 'radios',
|
| 252 |
'#title' => t('Start'),
|
| 253 |
'#description' => t("Select what post to start from whenever a link to this photoblog gets generated (e.g. in the photoblog list block). Photoblogs usually start with the latest post, but linking to the first post might be more appropriate if you need more a slideshow than a photoblog."),
|
| 254 |
'#options' => array(
|
| 255 |
'latest' => t('Start from the latest post'),
|
| 256 |
'first' => t('Start from the first post'),
|
| 257 |
),
|
| 258 |
'#default_value' => variable_get('photoblog_start_'. $edit['tid'], 'latest'),
|
| 259 |
);
|
| 260 |
$form['vid'] = array(
|
| 261 |
'#type' => 'hidden',
|
| 262 |
'#value' => _photoblog_get_vid(),
|
| 263 |
);
|
| 264 |
$form['submit' ] = array(
|
| 265 |
'#type' => 'submit',
|
| 266 |
'#value' => t('Submit'),
|
| 267 |
);
|
| 268 |
if ($edit['tid']) {
|
| 269 |
$form['delete'] = array(
|
| 270 |
'#type' => 'submit',
|
| 271 |
'#value' => t('Delete'),
|
| 272 |
);
|
| 273 |
$form['tid'] = array(
|
| 274 |
'#type' => 'hidden',
|
| 275 |
'#value' => $edit['tid'],
|
| 276 |
);
|
| 277 |
}
|
| 278 |
$form['#base'] = 'photoblog_admin';
|
| 279 |
|
| 280 |
return $form;
|
| 281 |
}
|
| 282 |
|
| 283 |
function photoblog_admin_submit($form_id, $form_values) {
|
| 284 |
$status = taxonomy_save_term($form_values);
|
| 285 |
variable_set('photoblog_start_'. $form_values['tid'], $form_values['start']);
|
| 286 |
switch ($status) {
|
| 287 |
case SAVED_NEW:
|
| 288 |
drupal_set_message(t('Created new photoblog %term.', array('%term' => $form_values['name'])));
|
| 289 |
break;
|
| 290 |
case SAVED_UPDATED:
|
| 291 |
drupal_set_message(t('The photoblog %term has been updated.', array('%term' => $form_values['name'])));
|
| 292 |
break;
|
| 293 |
case SAVED_DELETED:
|
| 294 |
drupal_set_message(t('The photoblog %term has been deleted.', array('%term' => $form_values['name'])));
|
| 295 |
break;
|
| 296 |
}
|
| 297 |
return 'admin/content/photoblog';
|
| 298 |
}
|
| 299 |
|
| 300 |
function photoblog_confirm_delete($tid) {
|
| 301 |
$term = taxonomy_get_term($tid);
|
| 302 |
|
| 303 |
$form['tid'] = array(
|
| 304 |
'#type' => 'value',
|
| 305 |
'#value' => $tid,
|
| 306 |
);
|
| 307 |
$form['name'] = array(
|
| 308 |
'#type' => 'value',
|
| 309 |
'#value' => $term->name,
|
| 310 |
);
|
| 311 |
|
| 312 |
return confirm_form($form, t('Are you sure you want to delete the photoblog %name?', array('%name' => $term->name)), 'admin/content/photoblog', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
|
| 313 |
}
|
| 314 |
|
| 315 |
function photoblog_confirm_delete_submit($form_id, $form_values) {
|
| 316 |
variable_del('photoblog_start_'. $form_values['tid']);
|
| 317 |
taxonomy_del_term($form_values['tid']);
|
| 318 |
drupal_set_message(t('The photoblog %term has been deleted.', array('%term' => $form_values['name'])));
|
| 319 |
|
| 320 |
return 'admin/content/photoblog';
|
| 321 |
}
|
| 322 |
|
| 323 |
/**
|
| 324 |
* Menu callback to redirect to a photoblog post.
|
| 325 |
*
|
| 326 |
* Expects arg(2) for uid, arg(3) for tid, '*' is allowed as a wildcard in both cases.
|
| 327 |
*
|
| 328 |
* @param $dest
|
| 329 |
* Either 'first' to move to the first post of the photoblog, or 'latest' to
|
| 330 |
* move to its latest post.
|
| 331 |
*/
|
| 332 |
function photoblog_goto($dest) {
|
| 333 |
if (!arg(2) || arg(2) == '*') {
|
| 334 |
$uid = 0;
|
| 335 |
}
|
| 336 |
elseif (is_numeric(arg(2))) {
|
| 337 |
$uid = arg(2);
|
| 338 |
}
|
| 339 |
else {
|
| 340 |
drupal_not_found();
|
| 341 |
return;
|
| 342 |
}
|
| 343 |
|
| 344 |
if (!arg(3) || arg(3) == '*') {
|
| 345 |
$tid = 0;
|
| 346 |
}
|
| 347 |
elseif (is_numeric(arg(3))) {
|
| 348 |
$tid = arg(3);
|
| 349 |
}
|
| 350 |
else {
|
| 351 |
drupal_not_found();
|
| 352 |
return;
|
| 353 |
}
|
| 354 |
|
| 355 |
$func = "photoblog_get_$dest";
|
| 356 |
if ($nid = $func($uid, $tid)) {
|
| 357 |
drupal_goto("node/$nid");
|
| 358 |
}
|
| 359 |
else {
|
| 360 |
if ($uid) {
|
| 361 |
$user = user_load(array('uid' => $uid));
|
| 362 |
}
|
| 363 |
if ($tid) {
|
| 364 |
$term = taxonomy_get_term($tid);
|
| 365 |
}
|
| 366 |
if ($user && $term) {
|
| 367 |
drupal_set_message(t('There is no photoblog post in %photoblog by %user.', array('%photoblog' => $term->name, '%user' => $user->name)));
|
| 368 |
drupal_goto();
|
| 369 |
}
|
| 370 |
elseif ($user && !$tid) {
|
| 371 |
drupal_set_message(t('There is no photoblog post by %user.', array('%user' => $user->name)));
|
| 372 |
drupal_goto();
|
| 373 |
}
|
| 374 |
elseif (!$uid && $term) {
|
| 375 |
drupal_set_message(t('There is no photoblog post in %photoblog.', array('%photoblog' => $term->name)));
|
| 376 |
drupal_goto();
|
| 377 |
}
|
| 378 |
elseif (!$uid && !$tid) {
|
| 379 |
drupal_set_message(t('There is no photoblog post.'));
|
| 380 |
drupal_goto();
|
| 381 |
}
|
| 382 |
else {
|
| 383 |
drupal_not_found();
|
| 384 |
}
|
| 385 |
}
|
| 386 |
}
|
| 387 |
|
| 388 |
/**
|
| 389 |
* Admin settings callback.
|
| 390 |
*/
|
| 391 |
function photoblog_admin_settings() {
|
| 392 |
$vocabs = array();
|
| 393 |
if ($vocabularies = taxonomy_get_vocabularies('image')) {
|
| 394 |
foreach ($vocabularies as $vid => $vocabulary) {
|
| 395 |
$vocabs[$vid] = $vocabulary->name;
|
| 396 |
}
|
| 397 |
}
|
| 398 |
$form['photoblog_set_frontpage'] = array(
|
| 399 |
'#type' => 'checkbox',
|
| 400 |
'#title' => t('Automatically set the front page to the latest post.'),
|
| 401 |
'#default_value' => variable_get('photoblog_set_frontpage', FALSE),
|
| 402 |
'#description' => t('Enable this if you wish to update your site\'s front page each time a new photoblog post is made. This will assign the site\'s front page to the new post. This will apply to any new published content belonging to a photoblog, from any author.'),
|
| 403 |
);
|
| 404 |
$form['navigation'] = array(
|
| 405 |
'#type' => 'fieldset',
|
| 406 |
'#title' => t('Navigation'),
|
| 407 |
'#description' => t('Navigation in photoblogs is done through <em>previous</em> and <em>next</em> links.'),
|
| 408 |
);
|
| 409 |
$form['navigation']['photoblog_navigation_mode'] = array(
|
| 410 |
'#type' => 'select',
|
| 411 |
'#title' => t('Navigation mode'),
|
| 412 |
'#options' => array('global' => t('Global'), 'user' => t('Per-user')),
|
| 413 |
'#multiple' => FALSE,
|
| 414 |
'#default_value' => _photoblog_get_navigation_mode(),
|
| 415 |
'#description' => t('What should the destinations of navigation links be? Previous and next image from any author (<em>global</em>), or from the same author as the current image being viewed? In any case, the previous and next images will belong to the same photoblog category as the current image being viewed.'),
|
| 416 |
);
|
| 417 |
$form['navigation']['photoblog_navigation_links_output'] = array(
|
| 418 |
'#type' => 'select',
|
| 419 |
'#title' => t('Output navigation links into'),
|
| 420 |
'#options' => array('block' => t('Block'), 'content' => t('Content'), 'links' => t('Links')),
|
| 421 |
'#multiple' => TRUE,
|
| 422 |
'#default_value' => _photoblog_get_navigation_links_output(),
|
| 423 |
'#description' => t('Where to output the photoblog navigation links? Choose the option(s) that best meet your theming needs. You may select more than one option. If you choose <em>block</em>, you will have to !enable.', array('!enable' => l(t('enable the photoblog navigation block'), 'admin/build/block'))),
|
| 424 |
);
|
| 425 |
return system_settings_form($form);
|
| 426 |
}
|
| 427 |
|
| 428 |
/**
|
| 429 |
* Callback that lists available photoblogs.
|
| 430 |
*/
|
| 431 |
function photoblog_get_start_links() {
|
| 432 |
if (_photoblog_get_navigation_mode() == 'user') {
|
| 433 |
// Find which users have photoblog posts
|
| 434 |
$result = db_query(db_rewrite_sql("SELECT DISTINCT(u.uid), u.name FROM {users} u INNER JOIN {node} n ON u.uid = n.uid INNER JOIN {term_node} tn ON n.nid = tn.nid INNER JOIN {term_data} td ON td.tid = tn.tid WHERE n.type = 'image' AND n.status = 1 AND td.vid = %d ORDER BY u.name", 'u'), _photoblog_get_vid());
|
| 435 |
while ($user = db_fetch_object($result)) {
|
| 436 |
$items = _photoblog_get_start_links($user);
|
| 437 |
if (count($items)) {
|
| 438 |
$content .= theme('item_list', $items, t('@user\'s photoblogs', array('@user' => $user->name)));
|
| 439 |
}
|
| 440 |
}
|
| 441 |
}
|
| 442 |
else {
|
| 443 |
$items = _photoblog_get_start_links();
|
| 444 |
if (count($items)) {
|
| 445 |
$content .= theme('item_list', $items);
|
| 446 |
}
|
| 447 |
}
|
| 448 |
return $content;
|
| 449 |
}
|
| 450 |
|
| 451 |
/**
|
| 452 |
* Return an array with navigation links.
|
| 453 |
*
|
| 454 |
* @node Current node.
|
| 455 |
*
|
| 456 |
* @context Context where the navigation links are to be displayed, either
|
| 457 |
* 'content', 'links', or 'block'.
|
| 458 |
*/
|
| 459 |
function photoblog_get_navigation_links($node, $context) {
|
| 460 |
$links = array();
|
| 461 |
if ($node->photoblog_prev_nid) {
|
| 462 |
$links['photoblog-prev'] = theme('photoblog_prev', $node->photoblog_prev_nid, $context);
|
| 463 |
}
|
| 464 |
if ($node->photoblog_next_nid) {
|
| 465 |
$links['photoblog-next'] = theme('photoblog_next', $node->photoblog_next_nid, $context);
|
| 466 |
}
|
| 467 |
return $links;
|
| 468 |
}
|
| 469 |
|
| 470 |
/**
|
| 471 |
* Return true when the specified node is considered as a photoblog post.
|
| 472 |
*/
|
| 473 |
function photoblog_is_photoblog_post($nid) {
|
| 474 |
static $cache = array();
|
| 475 |
if (!isset($cache[$nid])) {
|
| 476 |
$cache[$nid] = db_result(db_query(db_rewrite_sql("SELECT COUNT(*) FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid INNER JOIN {term_data} td ON tn.tid = td.tid WHERE n.status = 1 AND n.type = 'image' AND td.vid = %d AND tn.nid = %d"), _photoblog_get_vid(), $nid));
|
| 477 |
}
|
| 478 |
return $cache[$nid];
|
| 479 |
}
|
| 480 |
|
| 481 |
/**
|
| 482 |
* Return the nid of the latest image for the specified user and term.
|
| 483 |
*/
|
| 484 |
function photoblog_get_latest($uid, $tid) {
|
| 485 |
return _photoblog_get_post($uid, $tid, 'DESC');
|
| 486 |
}
|
| 487 |
|
| 488 |
/**
|
| 489 |
* Return the nid of the first image for the specified user and term.
|
| 490 |
*/
|
| 491 |
function photoblog_get_first($uid, $tid) {
|
| 492 |
return _photoblog_get_post($uid, $tid, 'ASC');
|
| 493 |
}
|
| 494 |
|
| 495 |
/**
|
| 496 |
* Return the nid of the most recent image older than the given node.
|
| 497 |
*/
|
| 498 |
function photoblog_get_prev($node) {
|
| 499 |
return _photoblog_get_prev_or_next($node, '<', 'DESC');
|
| 500 |
}
|
| 501 |
|
| 502 |
/**
|
| 503 |
* Return the nid of the next image after the given node.
|
| 504 |
*/
|
| 505 |
function photoblog_get_next($node) {
|
| 506 |
return _photoblog_get_prev_or_next($node, '>', 'ASC');
|
| 507 |
}
|
| 508 |
|
| 509 |
/**
|
| 510 |
* Formats a link to a photoblog.
|
| 511 |
*/
|
| 512 |
function _photoblog_format_start_link($name, $uid, $tid) {
|
| 513 |
$dest = variable_get('photoblog_start_'. $tid, 'latest');
|
| 514 |
return l($name, "photoblog/$dest/$uid/$tid");
|
| 515 |
}
|
| 516 |
|
| 517 |
/**
|
| 518 |
* Return the an image by the specified user and with the specified term. The
|
| 519 |
* first or latest image's nid is returned, depending on the given sort option.
|
| 520 |
*/
|
| 521 |
function _photoblog_get_post($uid, $tid, $sort = 'DESC') {
|
| 522 |
$uid_cond = $uid ? "AND n.uid = $uid" : '';
|
| 523 |
$tid_cond = $tid ? "AND tn.tid = $tid" : '';
|
| 524 |
return db_result(db_query(db_rewrite_sql("SELECT n.nid FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid INNER JOIN {term_data} td ON td.tid = tn.tid WHERE n.type = 'image' AND n.status = 1 AND td.vid = %d $tid_cond $uid_cond ORDER BY n.created $sort LIMIT 1"), _photoblog_get_vid()));
|
| 525 |
}
|
| 526 |
|
| 527 |
/**
|
| 528 |
* Return the nid of the previous or next image relative to the given node.
|
| 529 |
*
|
| 530 |
* The previous and next images are images that share a taxonomy term (from the
|
| 531 |
* vocabulary selected in the module's settings) and have the same author with the
|
| 532 |
* given node.
|
| 533 |
*/
|
| 534 |
function _photoblog_get_prev_or_next($node, $op, $order) {
|
| 535 |
$uid_cond = _photoblog_get_navigation_mode() == 'user' ? "AND n.uid = $node->uid" : '';
|
| 536 |
$nid = db_result(db_query(db_rewrite_sql("SELECT n.nid FROM {node} n INNER JOIN {term_node} tn ON tn.nid = n.nid INNER JOIN {term_data} td ON td.vid = %d INNER JOIN {term_node} tn0 ON tn0.tid = tn.tid WHERE n.type = 'image' AND n.status = 1 AND n.created $op %d AND tn0.nid = %d $uid_cond ORDER BY n.created $order LIMIT 1"), _photoblog_get_vid(), $node->created, $node->nid));
|
| 537 |
return $nid;
|
| 538 |
}
|
| 539 |
|
| 540 |
/**
|
| 541 |
* Returns (and possibly creates) a new vocabulary for photoblogs.
|
| 542 |
*/
|
| 543 |
function _photoblog_get_vid() {
|
| 544 |
$vid = variable_get('photoblog_vocabulary', 0);
|
| 545 |
if (!$vid) {
|
| 546 |
// Check to see if a photoblog vocabulary exists
|
| 547 |
$vid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE module='photoblog'"));
|
| 548 |
if (!$vid) {
|
| 549 |
$vocabulary = array(
|
| 550 |
'name' => t('Photoblogs'),
|
| 551 |
'multiple' => 0,
|
| 552 |
'required' => 0,
|
| 553 |
'hierarchy' => 0,
|
| 554 |
'relations' => 0,
|
| 555 |
'module' => 'photoblog',
|
| 556 |
'nodes' => array('image' => 1),
|
| 557 |
);
|
| 558 |
taxonomy_save_vocabulary($vocabulary);
|
| 559 |
$vid = $vocabulary['vid'];
|
| 560 |
}
|
| 561 |
variable_set('photoblog_vocabulary', $vid);
|
| 562 |
}
|
| 563 |
|
| 564 |
return $vid;
|
| 565 |
}
|
| 566 |
|
| 567 |
/**
|
| 568 |
* Returns an array containing the output target for navigation links. Possible values are 'links', 'block', or 'content'.
|
| 569 |
*/
|
| 570 |
function _photoblog_get_navigation_links_output() {
|
| 571 |
return variable_get('photoblog_navigation_links_output', array('links'));
|
| 572 |
}
|
| 573 |
|
| 574 |
/**
|
| 575 |
* Returns the navigation mode, either 'global' or 'user'.
|
| 576 |
*/
|
| 577 |
function _photoblog_get_navigation_mode() {
|
| 578 |
return variable_get('photoblog_navigation_mode', 'global');
|
| 579 |
}
|
| 580 |
|
| 581 |
/**
|
| 582 |
* Returns an array with links to the photoblogs for the given user that have at least one post.
|
| 583 |
*/
|
| 584 |
function _photoblog_get_start_links($user = NULL) {
|
| 585 |
$uid_cond = isset($user) ? "AND n.uid = $user->uid" : '';
|
| 586 |
$uid_arg = isset($user) ? $user->uid : '*';
|
| 587 |
$items = array();
|
| 588 |
|
| 589 |
// Build links to each photoblog
|
| 590 |
$tree = taxonomy_get_tree(_photoblog_get_vid());
|
| 591 |
foreach ($tree as $term) {
|
| 592 |
$count = db_result(db_query(db_rewrite_sql("SELECT COUNT(*) FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE n.type = 'image' AND n.status = 1 AND tn.tid = %d $uid_cond"), $term->tid));
|
| 593 |
if ($count > 0) {
|
| 594 |
$items[] = _photoblog_format_start_link($term->name, $uid_arg, $term->tid);
|
| 595 |
}
|
| 596 |
}
|
| 597 |
|
| 598 |
return $items;
|
| 599 |
}
|
| 600 |
|
| 601 |
/**
|
| 602 |
* Theme the title of the navigation link for the previous image.
|
| 603 |
* Returns an array in hook_links() fashion.
|
| 604 |
*/
|
| 605 |
function theme_photoblog_prev($nid, $context) {
|
| 606 |
return array(
|
| 607 |
'title' => t('Previous'),
|
| 608 |
'href' => "node/$nid",
|
| 609 |
);
|
| 610 |
}
|
| 611 |
|
| 612 |
/**
|
| 613 |
* Theme the title of the navigation link for the next image.
|
| 614 |
* Returns an array in hook_links() fashion.
|
| 615 |
*/
|
| 616 |
function theme_photoblog_next($nid, $context) {
|
| 617 |
return array(
|
| 618 |
'title' => t('Next'),
|
| 619 |
'href' => "node/$nid",
|
| 620 |
);
|
| 621 |
}
|