/[drupal]/contributions/modules/workspace/workspace.module
ViewVC logotype

Contents of /contributions/modules/workspace/workspace.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.37 - (show annotations) (download) (as text)
Tue Jul 21 18:03:23 2009 UTC (4 months, 1 week ago) by frankralf
Branch: MAIN
CVS Tags: HEAD
Changes since 1.36: +18 -4 lines
File MIME type: text/x-php
#441532 - Applied cumulative patch no. 3 by hutch
1 <?php
2 // $Id: workspace.module,v 1.36 2009/07/13 17:17:17 frankralf Exp $
3
4 /**
5 * @file
6 * Presents a user-centric view of content.
7 *
8 * Provides a "My workspace" link in the navigation block. When
9 * clicked it brings the user to a table showing the content
10 * they have created, with handy links to edit or delete the
11 * content, or to create new content.
12 *
13 * Optionally provides a link to a user's content on their
14 * profile page (viewable if the current user has 'view all
15 * workspace' permission.
16 */
17
18 /**
19 * Implementation of hook_help().
20 */
21 function workspace_help($path) {
22 switch ($path) {
23 case 'admin/help#workspace':
24 $output = '<p>'. t('The workspace module provides a list of content for each user.') .'</p>';
25 $output .= '<p>'. t("When enabled, each user will have a 'My workspace' link in the Navigation menu.") .'</p>';
26 return $output;
27 }
28 }
29
30 /**
31 * Implementation of hook_menu().
32 */
33 function workspace_menu() {
34 $items['workspace/%user_uid_optional'] = array(
35 'title' => 'My workspace',
36 'page callback' => 'workspace_list_content',
37 'page arguments' => array(1),
38 'access callback' => 'workspace_access',
39 'access arguments' => array(1),
40 'weight' => -10,
41 );
42 $items['workspace/%user/content'] = array(
43 'title' => 'Content',
44 'type' => MENU_DEFAULT_LOCAL_TASK,
45 'page callback' => 'workspace_list_content',
46 'page arguments' => array(1),
47 'access callback' => 'workspace_access',
48 'access arguments' => array(1),
49 'weight' => 10,
50 );
51 $items['workspace/%user/comments'] = array(
52 'title' => 'Comments',
53 'type' => MENU_LOCAL_TASK,
54 'page callback' => 'workspace_list_comments',
55 'page arguments' => array(1),
56 'access callback' => 'workspace_access',
57 'access arguments' => array(1, module_exists('comment')),
58 'weight' => 20,
59 );
60 $items['workspace/%user/attachments'] = array(
61 'title' => 'Attachments',
62 'type' => MENU_LOCAL_TASK,
63 'page callback' => 'workspace_list_files',
64 'page arguments' => array(1),
65 'access callback' => 'workspace_access',
66 'access arguments' => array(1, module_exists('upload')),
67 'weight' => 30,
68 );
69 $items['workspace/%user/configure'] = array(
70 'title' => 'Configure',
71 'page callback' => 'workspace_configure',
72 'page arguments' => array(1),
73 'access callback' => 'workspace_configure_access',
74 'access arguments' => array(1),
75 'type' => MENU_LOCAL_TASK,
76 'weight' => 50,
77 );
78 $items['admin/settings/workspace'] = array(
79 'title' => 'Workspace',
80 'description' => 'Customize workspace behavior.',
81 'page callback' => 'drupal_get_form',
82 'page arguments' => array('workspace_settings'),
83 'access arguments' => array('administer workspaces'),
84 );
85 // In this entry, 'access content' permission may seem liberal
86 // but since workspace_delete() simply redirects to
87 // node/*/delete deletion permissions will be applied there.
88 $items['workspace/delete'] = array(
89 'title' => 'Delete',
90 'page callback' => 'workspace_delete',
91 'access arguments' => array('access content'),
92 'type' => MENU_CALLBACK,
93 );
94
95 return $items;
96 }
97
98 /**
99 * Menu access callback.
100 */
101 function workspace_access($account, $module_enabled = TRUE) {
102 global $user;
103 // Let admin see $account
104 if ($user->uid == 1 && $account->uid > 1) {
105 return user_access('access content', $account)
106 && user_access('access workspace', $account)
107 && $module_enabled;
108 }
109 return user_access('access content', $user) // If you may not see content, you may not see workspaces.
110 && user_access('access workspace', $user) // Allowed to see own workspace
111 && (user_access('view all workspaces', $user) // Must either have permission to see all workspaces
112 || (($user->uid == $account->uid) // or must be your workspace
113 && ($user->uid != 0))) // and you must not be an anonymous user
114 && $module_enabled; // If, e.g., comment module is disabled, remove comment local task.
115 }
116
117 /**
118 * Menu access callback.
119 */
120 function workspace_configure_access($account) {
121 global $user;
122 if ($user->uid == 1 && $account->uid > 1) {
123 return user_access('administer workspaces', $account)
124 || user_access('administer own workspace', $account);
125 }
126 return ($user->uid != 0) // May not be anonymous user.
127 && user_access('administer workspaces') // Must either have permission to administer all workspaces
128 || ($user->uid == $account->uid // Or if this is your workspace
129 && user_access('administer own workspace') // you must have 'administer own workspace' permission
130 );
131 }
132
133 /**
134 * Implementation of hook_perm().
135 */
136 function workspace_perm() {
137 return array('access workspace', 'administer own workspace', 'administer workspaces', 'view all workspaces');
138 }
139
140 /**
141 * Menu callback. The configuration page.
142 */
143 function workspace_configure($account) {
144 drupal_set_title(t('Workspace: @name', array('@name' => $account->name)));
145 $output = drupal_get_form('workspace_configure_form', $account);
146 return $output;
147 }
148
149 /**
150 * Form definition for per-user configuration form.
151 */
152 function workspace_configure_form($form_state, $account) {
153 $form['maxnodes'] = array(
154 '#type' => 'textfield',
155 '#title' => t('Number of items'),
156 '#description' => t('Maximum number of items to display in your workspace.'),
157 '#default_value' => $account->workspaces ? $account->workspaces['default']['maxnodes'] : 50,
158 '#size' => 4
159 );
160 $form['maxfilenames'] = array(
161 '#type' => 'textfield',
162 '#title' => t('Number of files'),
163 '#description' => t('Maximum number of filenames to display in your workspace.'),
164 '#default_value' => $account->workspaces ? $account->workspaces['default']['maxfilenames'] : 50,
165 '#size' => 4
166 );
167 if ( module_exists('comment') ) {
168 $form['maxcomments'] = array(
169 '#type' => 'textfield',
170 '#title' => t('Number of comments'),
171 '#description' => t('Maximum number of comments to display in your workspace.'),
172 '#default_value' => $account->workspaces['default']['maxcomments'] ? $account->workspaces['default']['maxcomments'] : 50,
173 '#size' => 4
174 );
175 }
176 $form['uid'] = array(
177 '#type' => 'value',
178 '#value' => $account->uid,
179 );
180 $form['submit'] = array(
181 '#type' => 'submit',
182 '#value' => t('Save configuration')
183 );
184 return $form;
185 }
186
187 /**
188 * Validator for per-user configuration form.
189 *
190 * @see workspace_configure_form()
191 */
192 function workspace_configure_form_validate($form, $form_state) {
193 if (!is_numeric($form_state['values']['maxnodes'])) {
194 form_set_error('maxnodes', t('Please enter a numeric value.'));
195 }
196 if (!is_numeric($form_state['values']['maxfilenames']) && !form_get_errors()) {
197 form_set_error('maxfilenames', t('Please enter a numeric value.'));
198 }
199 if ( module_exists('comment') ) {
200 if (!is_numeric($form_state['values']['maxcomments']) && !form_get_errors()) {
201 form_set_error('maxfilenames', t('Please enter a numeric value.'));
202 }
203 }
204 }
205
206 /**
207 * Submit handler for per-user configuration form.
208 *
209 * @see workspace_configure_form()
210 */
211 function workspace_configure_form_submit($form, &$form_state) {
212 // Must do a full user load to get existing serialized data.
213 $account = user_load(array('uid' => $form_state['values']['uid']));
214 if (!isset($account->workspaces)) {
215 $account->workspaces = array();
216 }
217 $account->workspaces['default']['maxnodes'] = (int)$form_state['values']['maxnodes'];
218 $account->workspaces['default']['maxfilenames'] = (int)$form_state['values']['maxfilenames'];
219 user_save($account, array('workspaces' => $account->workspaces));
220 drupal_set_message(t('The workspace preferences have been saved.'));
221 $form_state['redirect'] = 'workspace/'. $form_state['values']['uid'];
222 }
223
224 /**
225 * Menu callback. Display list of content.
226 *
227 * @param $account
228 * User object representing user whose workspace is being listed.
229 */
230 function workspace_list_content($account) {
231 global $user;
232 drupal_set_title(t('Workspace: @name', array('@name' => $account->name)));
233 $max = isset($user->workspaces) ? $user->workspaces['default']['maxnodes'] : 50;
234 $comments_enabled = module_exists('comment');
235 if ($comments_enabled) {
236 // If the comment module is enabled, we need to get comment counts too.
237 $sql = 'SELECT n.nid, n.uid, n.type, 0 as cid, n.title, n.status, n.changed, s.comment_count, 1 as node
238 FROM {node} n
239 LEFT JOIN {node_comment_statistics} s ON n.nid = s.nid
240 WHERE n.uid = %d';
241 $count_sql = 'SELECT COUNT(n.nid)
242 FROM {node} n
243 LEFT JOIN {node_comment_statistics} s ON n.nid = s.nid
244 WHERE n.uid = %d';
245 }
246 else {
247 // Otherwise we use a simpler query.
248 $sql = 'SELECT n.nid, n.uid, n.type, 0 as cid, n.title, n.status, n.changed, 1 as node
249 FROM {node} n
250 WHERE n.uid = %d';
251 $count_sql = 'SELECT COUNT(n.nid)
252 FROM {node} n
253 WHERE n.uid = %d';
254 }
255
256 $header = array(
257 array('data' => t('Type'), 'field' => 'type'),
258 array('data' => t('Title'), 'field' => 'title'),
259 array('data' => t('Owner'), 'field' => 'uid'),
260 array('data' => t('Published'), 'field' => 'status'),
261 array('data' => t('Modified'), 'field' => 'changed', 'sort' => 'desc'),
262 $comments_enabled ? array('data' => t('Replies'), 'field' => 'comment_count') : array('data' => ''),
263 array('data' => t('Operations'), 'colspan' => 2)
264 );
265 $cols = 8;
266 $result = pager_query(db_rewrite_sql($sql . tablesort_sql($header)), $max, 0, db_rewrite_sql($count_sql), $account->uid);
267 $rows = workspace_build_rows($result, $account);
268 $output = '';
269 // Only add the content add form if the user is viewing his/her own workspace.
270 if ($user->uid == 1 || user_access('view all workspaces') || $user->uid == $account->uid) {
271 $output = drupal_get_form('workspace_add_form');
272 }
273
274 $output .= theme_workspace_list($header, $rows, $max, $cols);
275 return $output;
276 }
277
278 /**
279 * Menu callback. Display list of comments.
280 *
281 * @param $account
282 * User object representing user whose workspace is being listed.
283 */
284 function workspace_list_comments($account) {
285 drupal_set_title(t('Workspace: @name', array('@name' => $account->name)));
286 $max = isset($account->workspaces) ? $account->workspaces['default']['maxcomments'] : 50;
287
288 $sql = 'SELECT c.nid, c.uid, c.cid, c.subject, c.status, c.timestamp, c.pid, 0
289 FROM {comments} c
290 WHERE c.uid = %d';
291
292 $count_sql = 'SELECT COUNT(cid) FROM {comments} WHERE uid = %d';
293
294 // Build the comment listing.
295 $header = array(
296 array('data' => t('Title'), 'field' => 'title'),
297 array('data' => t('Published'), 'field' => 'status'),
298 array('data' => t('Modified'), 'field' => 'timestamp', 'sort' => 'desc'),
299 array('data' => t('Replies'), 'field' => 'comment_count'),
300 array('data' => t('Operations'), 'colspan' => 2)
301 );
302 $cols = 6;
303 $result = pager_query($sql . tablesort_sql($header), $max, 0, $count_sql, $account->uid);
304 $rows = workspace_build_rows($result, $account);
305 return theme_workspace_list($header, $rows, $max, $cols);
306 }
307
308 /**
309 * Build the query result into a table, respecting access.
310 *
311 * @param $result
312 * A result object as returned from pager_query().
313 * @param $account
314 * User object representing user whose workspace is being listed.
315 */
316 function workspace_build_rows($result, $account) {
317 global $user;
318 $yes = t('yes');
319 $no = t('no');
320 $rows = array();
321 while ($row = db_fetch_object($result)) {
322 // It's a node.
323 if ($row->node == 1) {
324 // Edit and delete permissions are set by the node type's access hook.
325 // If no access hook is found, node-level permissions are then used.
326 // This approach is part of Drupal's core design.
327 $may_edit = FALSE;
328 $may_delete = FALSE;
329
330 //Check the node type's access hook.
331 $function = $row->type .'_access';
332 if ($cck_enabled && strstr($function, 'content_')) {
333 $function = 'content_access';
334 }
335 else {
336 $function = 'node_access';
337 }
338
339 if (function_exists($function)) {
340 if (!$function('view', $row, $user)) {
341 // No view permission means it is not shown in the workspace.
342 continue;
343 }
344 $may_edit = $function('update', $row, $user) ? TRUE : FALSE;
345 $may_delete = $function('delete', $row, $user) ? TRUE : FALSE;
346 }
347 else {
348 // If we can't find an access function, deny by default.
349 continue;
350 }
351
352 // The name of the owner of this node.
353 $name = ($user->uid == $row->uid) ? $user->name : db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $row->uid));
354 $rows[] = array(
355 node_get_types('name', $row->type),
356 l($row->title, "node/$row->nid"),
357 $name,
358 $row->status ? $yes : $no,
359 format_date($row->changed, 'small'),
360 module_exists('comment') ? array('data' => $row->comment_count ? $row->comment_count : 0, 'align' => 'right') : array('data' => ''),
361 $may_edit ? l(t('edit'), "node/$row->nid/edit") : '',
362 $may_delete ? l(t('delete'), "workspace/delete/$row->nid") : ''
363 );
364 }
365 else {
366 // It's a comment.
367 $num_replies = comment_num_replies($row->cid);
368 $comment->cid = $row->cid;
369 $comment->nid = $row->nid;
370
371 // Delegate access permission checks and link generation to comment.module.
372 $comment_links = comment_links($comment, 0);
373 $link = l(t('edit'), "comment/edit/$comment->cid");
374 $edit_link = $comment_links['comment_edit'] ? $link : '';
375
376 $link = l(t('delete'), "comment/delete/$comment->cid");
377 $delete_link = $comment_links['comment_delete'] ? $link : '';
378
379 $rows[] = array(
380 l($row->subject, "node/$row->nid", array(), NULL, "comment-$row->cid", FALSE, TRUE),
381 $row->status ? $no : $yes,
382 format_date($row->timestamp, 'small'),
383 array('data' => $num_replies, 'align' => 'right'),
384 $edit_link,
385 $delete_link,
386 );
387 }
388 }
389 return $rows;
390 }
391
392 /**
393 * Menu callback. List file attachments managed by upload.module.
394 *
395 * @param $account
396 * User object representing user whose workspace is being listed.
397 */
398 function workspace_list_files($account) {
399 global $user;
400 drupal_set_title(t('Workspace: @name', array('@name' => $account->name)));
401 $max = isset($user->workspaces) ? $user->workspaces['default']['maxfilenames'] : 50;
402 $download = t('download');
403 $rows = array();
404 $header = array(
405 array('data' => t('Filename'), 'field' => 'f.filename'),
406 array('data' => t('Type'), 'field' => 'f.filemime'),
407 array('data' => t('Modified'), 'field' => 'f.timestamp', 'sort' => 'desc'),
408 array('data' => t('Size'), 'field' => 'f.filesize'),
409 array('data' => t('Operations')),
410 );
411 $cols = 6;
412 $sql = "SELECT u.nid, f.filemime, f.filename, f.filesize, f.timestamp, f.filepath
413 FROM {files} f
414 LEFT JOIN {upload} u ON f.fid = u.fid
415 WHERE f.uid = %d";
416 $result = pager_query($sql . tablesort_sql($header), $max, 2, NULL, $account->uid);
417
418 while ($row = db_fetch_object($result)) {
419 $rows[] = array(
420 l($row->filename, "node/$row->nid"),
421 $row->filemime,
422 format_date($row->timestamp, 'small'),
423 format_size($row->filesize),
424 l($download, file_create_url($row->filepath)),
425 );
426 }
427
428 return theme('workspace_list', $header, $rows, $max, $cols);
429 }
430
431 /**
432 * Implementation of hook_theme().
433 */
434 function workspace_theme() {
435 return array(
436 'workspace_list' => array(
437 'arguments' => array('header' => array(), 'rows' => array(), $max = 50, $cols = 8),
438 ),
439 );
440 }
441
442 /**
443 * Theme the list of content. Turn the results into a table.
444 */
445 function theme_workspace_list($header, $rows, $max, $cols) {
446 if ($rows) {
447 $pager = theme('pager', NULL, $max);
448 if (!empty($pager)) {
449 $rows[] = array(array('data' => $pager, 'colspan' => $cols));
450 }
451 $output = theme('table', $header, $rows);
452 }
453 else {
454 $output = t('Your workspace is currently empty.');
455 }
456 return $output;
457 }
458
459 /**
460 * Menu callback. Redirect user to delete node.
461 */
462 function workspace_delete() {
463 $nid = intval(arg(2));
464 if (is_numeric($nid)) {
465 drupal_goto('node/'. $nid .'/delete');
466 }
467 }
468
469 /**
470 * Form definition for content addition form.
471 */
472 function workspace_add_form() {
473 global $user;
474 $description = t('Choose what kind of content you would like to add.') .' '. l(t('Help?'), 'node/add');
475 $select = t('Select...');
476 $options = array($select => $select);
477 foreach (node_get_types() as $type => $object) {
478 if (module_invoke(node_get_types('module', $type), 'access', 'create', $type, $user)) {
479 $options[$type] = $object->name;
480 }
481 }
482 if (count($options) == 1) {
483 return array();
484 }
485 $form['add'] = array(
486 '#type' => 'fieldset',
487 '#prefix' => '<div class="container-inline">',
488 '#suffix' => '</div>',
489 );
490 $form['add']['content_type'] = array(
491 '#type' => 'select',
492 '#options' => $options,
493 );
494 $form['add']['submit'] = array(
495 '#type' => 'submit',
496 '#value' => t('Add new item'),
497 '#suffix' => $description,
498 );
499 return $form;
500 }
501
502 /**
503 * Submit handler for content addition form.
504 *
505 * Simply redirects to appropriate node/add/* page.
506 *
507 * @see workspace_add_form()
508 */
509 function workspace_add_form_submit($form, $form_state) {
510 $node_type = $form_state['values']['content_type'];
511 if ($node_type == t('Select...')) {
512 drupal_goto('node/add');
513 }
514
515 foreach (node_get_types() as $type => $object) {
516 if (node_access('create', $type, $user->uid)) {
517 $options[$type] = $object->name;
518 }
519 if (isset($options[$node_type])) {
520 /* Start hack */
521 if (stristr($node_type, "_") > -1) {
522 $node_type = str_replace("_", "-", $node_type);
523 }
524 /* End hack */
525 drupal_goto('node/add/'. $node_type);
526 }
527 }
528 }
529
530 /**
531 * Implementation of hook_settings().
532 */
533 function workspace_settings() {
534 $roles = user_roles();
535 // The anonymous user does not have a profile.
536 unset($roles[DRUPAL_ANONYMOUS_RID]);
537 $form['info'] = array(
538 '#value' => t("Select each role for which you want the link to a user's workspace to show up in their user profile."),
539 );
540 foreach ($roles as $rid => $name) {
541 $identifier = 'workspace_user_profile_'. $rid;
542 $form[$identifier] = array(
543 '#type' => 'checkbox',
544 '#title' => $name,
545 '#default_value' => variable_get($identifier, 0),
546 );
547 }
548 $form['workspace_user_profile_link'] = array(
549 '#type' => 'textfield',
550 '#title' => t("Name of link to user's workspace"),
551 '#description' => t("This will be used to display the link to a user's workspace on his or her profile page. The %username token will be replaced by the username of the user whose profile is being shown."),
552 '#default_value' => variable_get('workspace_user_profile_link', t('View recent content created by %username')),
553 );
554
555 return system_settings_form($form);
556 }
557
558 /**
559 * Implementation of hook_user().
560 *
561 * Place link to user's workspace on user's profile page.
562 */
563 function workspace_user($op, &$edit, &$account) {
564 global $user;
565 if ($op == 'view') {
566 if (workspace_access($account)) {
567 $variables['%username'] = $account->name;
568 $link_title = variable_get('workspace_user_profile_link', t('View recent content'));
569 $link = l(strtr($link_title, $variables), 'workspace/'. $account->uid);
570 $account->content['workspace'] = array(
571 '#type' => 'user_profile_category',
572 '#title' => variable_get('workspace_user_profile_title', t('Content')),
573 'link' => array(
574 '#value' => $link,
575 '#type' => 'user_profile_item',
576 ),
577 '#weight' => -10,
578 );
579 }
580 }
581 }

  ViewVC Help
Powered by ViewVC 1.1.2