workspace.module in Workspace 6
Same filename and directory in other branches
Presents a user-centric view of content.
Provides a "My workspace" link in the navigation block. When clicked it brings the user to a table showing the content they have created, with handy links to edit or delete the content, or to create new content.
Optionally provides a link to a user's content on their profile page (viewable if the current user has 'view all workspace' permission.
File
workspace.moduleView source
<?php
/**
* @file
* Presents a user-centric view of content.
*
* Provides a "My workspace" link in the navigation block. When
* clicked it brings the user to a table showing the content
* they have created, with handy links to edit or delete the
* content, or to create new content.
*
* Optionally provides a link to a user's content on their
* profile page (viewable if the current user has 'view all
* workspace' permission.
*/
/**
* Implementation of hook_help().
*/
function workspace_help($path) {
switch ($path) {
case 'admin/help#workspace':
$output = '<p>' . t('The workspace module provides a list of content for each user.') . '</p>';
$output .= '<p>' . t("When enabled, each user will have a 'My workspace' link in the Navigation menu.") . '</p>';
return $output;
}
}
/**
* Implementation of hook_menu().
*/
function workspace_menu() {
$items['workspace/%user_uid_optional'] = array(
'title' => 'My workspace',
'page callback' => 'workspace_list_content',
'page arguments' => array(
1,
),
'access callback' => 'workspace_access',
'access arguments' => array(
1,
),
'weight' => -10,
);
$items['workspace/%user/content'] = array(
'title' => 'Content',
'type' => MENU_DEFAULT_LOCAL_TASK,
'page callback' => 'workspace_list_content',
'page arguments' => array(
1,
),
'access callback' => 'workspace_access',
'access arguments' => array(
1,
),
'weight' => 10,
);
$items['workspace/%user/comments'] = array(
'title' => 'Comments',
'type' => MENU_LOCAL_TASK,
'page callback' => 'workspace_list_comments',
'page arguments' => array(
1,
),
'access callback' => 'workspace_access',
'access arguments' => array(
1,
module_exists('comment'),
),
'weight' => 20,
);
$items['workspace/%user/attachments'] = array(
'title' => 'Attachments',
'type' => MENU_LOCAL_TASK,
'page callback' => 'workspace_list_files',
'page arguments' => array(
1,
),
'access callback' => 'workspace_access',
'access arguments' => array(
1,
module_exists('upload'),
),
'weight' => 30,
);
$items['workspace/%user/configure'] = array(
'title' => 'Configure',
'page callback' => 'workspace_configure',
'page arguments' => array(
1,
),
'access callback' => 'workspace_configure_access',
'access arguments' => array(
1,
),
'type' => MENU_LOCAL_TASK,
'weight' => 50,
);
$items['admin/settings/workspace'] = array(
'title' => 'Workspace',
'description' => 'Customize workspace behavior.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'workspace_settings',
),
'access arguments' => array(
'administer workspaces',
),
);
// In this entry, 'access content' permission may seem liberal
// but since workspace_delete() simply redirects to
// node/*/delete deletion permissions will be applied there.
$items['workspace/delete'] = array(
'title' => 'Delete',
'page callback' => 'workspace_delete',
'access arguments' => array(
'access content',
),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Menu access callback.
*/
function workspace_access($account, $module_enabled = TRUE) {
global $user;
// Let admin see $account
if ($user->uid == 1 && $account->uid > 1) {
return user_access('access content', $account) && user_access('access workspace', $account) && $module_enabled;
}
return user_access('access content', $user) && user_access('access workspace', $user) && (user_access('view all workspaces', $user) || $user->uid == $account->uid && $user->uid != 0) && $module_enabled;
// If, e.g., comment module is disabled, remove comment local task.
}
/**
* Menu access callback.
*/
function workspace_configure_access($account) {
global $user;
if ($user->uid == 1 && $account->uid > 1) {
return user_access('administer workspaces', $account) || user_access('administer own workspace', $account);
}
return $user->uid != 0 && user_access('administer workspaces') || $user->uid == $account->uid && user_access('administer own workspace');
}
/**
* Implementation of hook_perm().
*/
function workspace_perm() {
return array(
'access workspace',
'administer own workspace',
'administer workspaces',
'view all workspaces',
);
}
/**
* Menu callback. The configuration page.
*/
function workspace_configure($account) {
drupal_set_title(t('Workspace: @name', array(
'@name' => $account->name,
)));
$output = drupal_get_form('workspace_configure_form', $account);
return $output;
}
/**
* Form definition for per-user configuration form.
*/
function workspace_configure_form($form_state, $account) {
$form['maxnodes'] = array(
'#type' => 'textfield',
'#title' => t('Number of items'),
'#description' => t('Maximum number of items to display in your workspace.'),
'#default_value' => $account->workspaces ? $account->workspaces['default']['maxnodes'] : 50,
'#size' => 4,
);
$form['maxfilenames'] = array(
'#type' => 'textfield',
'#title' => t('Number of files'),
'#description' => t('Maximum number of filenames to display in your workspace.'),
'#default_value' => $account->workspaces ? $account->workspaces['default']['maxfilenames'] : 50,
'#size' => 4,
);
if (module_exists('comment')) {
$form['maxcomments'] = array(
'#type' => 'textfield',
'#title' => t('Number of comments'),
'#description' => t('Maximum number of comments to display in your workspace.'),
'#default_value' => $account->workspaces['default']['maxcomments'] ? $account->workspaces['default']['maxcomments'] : 50,
'#size' => 4,
);
}
$form['uid'] = array(
'#type' => 'value',
'#value' => $account->uid,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save configuration'),
);
return $form;
}
/**
* Validator for per-user configuration form.
*
* @see workspace_configure_form()
*/
function workspace_configure_form_validate($form, $form_state) {
if (!is_numeric($form_state['values']['maxnodes'])) {
form_set_error('maxnodes', t('Please enter a numeric value.'));
}
if (!is_numeric($form_state['values']['maxfilenames']) && !form_get_errors()) {
form_set_error('maxfilenames', t('Please enter a numeric value.'));
}
if (module_exists('comment')) {
if (!is_numeric($form_state['values']['maxcomments']) && !form_get_errors()) {
form_set_error('maxfilenames', t('Please enter a numeric value.'));
}
}
}
/**
* Submit handler for per-user configuration form.
*
* @see workspace_configure_form()
*/
function workspace_configure_form_submit($form, &$form_state) {
// Must do a full user load to get existing serialized data.
$account = user_load(array(
'uid' => $form_state['values']['uid'],
));
if (!isset($account->workspaces)) {
$account->workspaces = array();
}
$account->workspaces['default']['maxnodes'] = (int) $form_state['values']['maxnodes'];
$account->workspaces['default']['maxfilenames'] = (int) $form_state['values']['maxfilenames'];
user_save($account, array(
'workspaces' => $account->workspaces,
));
drupal_set_message(t('The workspace preferences have been saved.'));
$form_state['redirect'] = 'workspace/' . $form_state['values']['uid'];
}
/**
* Menu callback. Display list of content.
*
* @param $account
* User object representing user whose workspace is being listed.
*/
function workspace_list_content($account) {
global $user;
drupal_set_title(t('Workspace: @name', array(
'@name' => $account->name,
)));
$max = isset($user->workspaces) ? $user->workspaces['default']['maxnodes'] : 50;
$comments_enabled = module_exists('comment');
if ($comments_enabled) {
// If the comment module is enabled, we need to get comment counts too.
$sql = 'SELECT n.nid, n.uid, n.type, 0 as cid, n.title, n.status, n.changed, s.comment_count, 1 as node
FROM {node} n
LEFT JOIN {node_comment_statistics} s ON n.nid = s.nid
WHERE n.uid = %d';
$count_sql = 'SELECT COUNT(n.nid)
FROM {node} n
LEFT JOIN {node_comment_statistics} s ON n.nid = s.nid
WHERE n.uid = %d';
}
else {
// Otherwise we use a simpler query.
$sql = 'SELECT n.nid, n.uid, n.type, 0 as cid, n.title, n.status, n.changed, 1 as node
FROM {node} n
WHERE n.uid = %d';
$count_sql = 'SELECT COUNT(n.nid)
FROM {node} n
WHERE n.uid = %d';
}
$header = array(
array(
'data' => t('Type'),
'field' => 'type',
),
array(
'data' => t('Title'),
'field' => 'title',
),
array(
'data' => t('Owner'),
'field' => 'uid',
),
array(
'data' => t('Published'),
'field' => 'status',
),
array(
'data' => t('Modified'),
'field' => 'changed',
'sort' => 'desc',
),
$comments_enabled ? array(
'data' => t('Replies'),
'field' => 'comment_count',
) : array(
'data' => '',
),
array(
'data' => t('Operations'),
'colspan' => 2,
),
);
$cols = 8;
$result = pager_query(db_rewrite_sql($sql . tablesort_sql($header)), $max, 0, db_rewrite_sql($count_sql), $account->uid);
$rows = workspace_build_rows($result, $account);
$output = '';
// Only add the content add form if the user is viewing his/her own workspace.
if ($user->uid == 1 || user_access('view all workspaces') || $user->uid == $account->uid) {
$output = drupal_get_form('workspace_add_form');
}
$output .= theme_workspace_list($header, $rows, $max, $cols);
return $output;
}
/**
* Menu callback. Display list of comments.
*
* @param $account
* User object representing user whose workspace is being listed.
*/
function workspace_list_comments($account) {
drupal_set_title(t('Workspace: @name', array(
'@name' => $account->name,
)));
$max = isset($account->workspaces) ? $account->workspaces['default']['maxcomments'] : 50;
$sql = 'SELECT c.nid, c.uid, c.cid, c.subject, c.status, c.timestamp, c.pid, 0
FROM {comments} c
WHERE c.uid = %d';
$count_sql = 'SELECT COUNT(cid) FROM {comments} WHERE uid = %d';
// Build the comment listing.
$header = array(
array(
'data' => t('Title'),
'field' => 'title',
),
array(
'data' => t('Published'),
'field' => 'status',
),
array(
'data' => t('Modified'),
'field' => 'timestamp',
'sort' => 'desc',
),
array(
'data' => t('Replies'),
'field' => 'comment_count',
),
array(
'data' => t('Operations'),
'colspan' => 2,
),
);
$cols = 6;
$result = pager_query($sql . tablesort_sql($header), $max, 0, $count_sql, $account->uid);
$rows = workspace_build_rows($result, $account);
return theme_workspace_list($header, $rows, $max, $cols);
}
/**
* Build the query result into a table, respecting access.
*
* @param $result
* A result object as returned from pager_query().
* @param $account
* User object representing user whose workspace is being listed.
*/
function workspace_build_rows($result, $account) {
global $user;
$yes = t('yes');
$no = t('no');
$rows = array();
while ($row = db_fetch_object($result)) {
// It's a node.
if ($row->node == 1) {
// Edit and delete permissions are set by the node type's access hook.
// If no access hook is found, node-level permissions are then used.
// This approach is part of Drupal's core design.
$may_edit = FALSE;
$may_delete = FALSE;
//Check the node type's access hook.
$function = $row->type . '_access';
if ($cck_enabled && strstr($function, 'content_')) {
$function = 'content_access';
}
else {
$function = 'node_access';
}
if (function_exists($function)) {
if (!$function('view', $row, $user)) {
// No view permission means it is not shown in the workspace.
continue;
}
$may_edit = $function('update', $row, $user) ? TRUE : FALSE;
$may_delete = $function('delete', $row, $user) ? TRUE : FALSE;
}
else {
// If we can't find an access function, deny by default.
continue;
}
// The name of the owner of this node.
$name = $user->uid == $row->uid ? $user->name : db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $row->uid));
$rows[] = array(
node_get_types('name', $row->type),
l($row->title, "node/{$row->nid}"),
$name,
$row->status ? $yes : $no,
format_date($row->changed, 'small'),
module_exists('comment') ? array(
'data' => $row->comment_count ? $row->comment_count : 0,
'align' => 'right',
) : array(
'data' => '',
),
$may_edit ? l(t('edit'), "node/{$row->nid}/edit") : '',
$may_delete ? l(t('delete'), "workspace/delete/{$row->nid}") : '',
);
}
else {
// It's a comment.
$num_replies = comment_num_replies($row->cid);
$comment->cid = $row->cid;
$comment->nid = $row->nid;
// Delegate access permission checks and link generation to comment.module.
$comment_links = comment_links($comment, 0);
$link = l(t('edit'), "comment/edit/{$comment->cid}");
$edit_link = $comment_links['comment_edit'] ? $link : '';
$link = l(t('delete'), "comment/delete/{$comment->cid}");
$delete_link = $comment_links['comment_delete'] ? $link : '';
$rows[] = array(
l($row->subject, "node/{$row->nid}", array(), NULL, "comment-{$row->cid}", FALSE, TRUE),
$row->status ? $no : $yes,
format_date($row->timestamp, 'small'),
array(
'data' => $num_replies,
'align' => 'right',
),
$edit_link,
$delete_link,
);
}
}
return $rows;
}
/**
* Menu callback. List file attachments managed by upload.module.
*
* @param $account
* User object representing user whose workspace is being listed.
*/
function workspace_list_files($account) {
global $user;
drupal_set_title(t('Workspace: @name', array(
'@name' => $account->name,
)));
$max = isset($user->workspaces) ? $user->workspaces['default']['maxfilenames'] : 50;
$download = t('download');
$rows = array();
$header = array(
array(
'data' => t('Filename'),
'field' => 'f.filename',
),
array(
'data' => t('Type'),
'field' => 'f.filemime',
),
array(
'data' => t('Modified'),
'field' => 'f.timestamp',
'sort' => 'desc',
),
array(
'data' => t('Size'),
'field' => 'f.filesize',
),
array(
'data' => t('Operations'),
),
);
$cols = 6;
$sql = "SELECT u.nid, f.filemime, f.filename, f.filesize, f.timestamp, f.filepath\n FROM {files} f\n LEFT JOIN {upload} u ON f.fid = u.fid\n WHERE f.uid = %d";
$result = pager_query($sql . tablesort_sql($header), $max, 2, NULL, $account->uid);
while ($row = db_fetch_object($result)) {
$rows[] = array(
l($row->filename, "node/{$row->nid}"),
$row->filemime,
format_date($row->timestamp, 'small'),
format_size($row->filesize),
l($download, file_create_url($row->filepath)),
);
}
return theme('workspace_list', $header, $rows, $max, $cols);
}
/**
* Implementation of hook_theme().
*/
function workspace_theme() {
return array(
'workspace_list' => array(
'arguments' => array(
'header' => array(),
'rows' => array(),
$max = 50,
$cols = 8,
),
),
);
}
/**
* Theme the list of content. Turn the results into a table.
*/
function theme_workspace_list($header, $rows, $max, $cols) {
if ($rows) {
$pager = theme('pager', NULL, $max);
if (!empty($pager)) {
$rows[] = array(
array(
'data' => $pager,
'colspan' => $cols,
),
);
}
$output = theme('table', $header, $rows);
}
else {
$output = t('Your workspace is currently empty.');
}
return $output;
}
/**
* Menu callback. Redirect user to delete node.
*/
function workspace_delete() {
$nid = intval(arg(2));
if (is_numeric($nid)) {
drupal_goto('node/' . $nid . '/delete');
}
}
/**
* Form definition for content addition form.
*/
function workspace_add_form() {
global $user;
$description = t('Choose what kind of content you would like to add.') . ' ' . l(t('Help?'), 'node/add');
$select = t('Select...');
$options = array(
$select => $select,
);
foreach (node_get_types() as $type => $object) {
if (module_invoke(node_get_types('module', $type), 'access', 'create', $type, $user)) {
$options[$type] = $object->name;
}
}
if (count($options) == 1) {
return array();
}
$form['add'] = array(
'#type' => 'fieldset',
'#prefix' => '<div class="container-inline">',
'#suffix' => '</div>',
);
$form['add']['content_type'] = array(
'#type' => 'select',
'#options' => $options,
);
$form['add']['submit'] = array(
'#type' => 'submit',
'#value' => t('Add new item'),
'#suffix' => $description,
);
return $form;
}
/**
* Submit handler for content addition form.
*
* Simply redirects to appropriate node/add/* page.
*
* @see workspace_add_form()
*/
function workspace_add_form_submit($form, $form_state) {
$node_type = $form_state['values']['content_type'];
if ($node_type == t('Select...')) {
drupal_goto('node/add');
}
foreach (node_get_types() as $type => $object) {
if (node_access('create', $type, $user->uid)) {
$options[$type] = $object->name;
}
if (isset($options[$node_type])) {
/* Start hack */
if (stristr($node_type, "_") > -1) {
$node_type = str_replace("_", "-", $node_type);
}
/* End hack */
drupal_goto('node/add/' . $node_type);
}
}
}
/**
* Implementation of hook_settings().
*/
function workspace_settings() {
$roles = user_roles();
// The anonymous user does not have a profile.
unset($roles[DRUPAL_ANONYMOUS_RID]);
$form['info'] = array(
'#value' => t("Select each role for which you want the link to a user's workspace to show up in their user profile."),
);
foreach ($roles as $rid => $name) {
$identifier = 'workspace_user_profile_' . $rid;
$form[$identifier] = array(
'#type' => 'checkbox',
'#title' => $name,
'#default_value' => variable_get($identifier, 0),
);
}
$form['workspace_user_profile_link'] = array(
'#type' => 'textfield',
'#title' => t("Name of link to user's workspace"),
'#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."),
'#default_value' => variable_get('workspace_user_profile_link', t('View recent content created by %username')),
);
return system_settings_form($form);
}
/**
* Implementation of hook_user().
*
* Place link to user's workspace on user's profile page.
*/
function workspace_user($op, &$edit, &$account) {
global $user;
if ($op == 'view') {
if (workspace_access($account)) {
$variables['%username'] = $account->name;
$link_title = variable_get('workspace_user_profile_link', t('View recent content'));
$link = l(strtr($link_title, $variables), 'workspace/' . $account->uid);
$account->content['workspace'] = array(
'#type' => 'user_profile_category',
'#title' => variable_get('workspace_user_profile_title', t('Content')),
'link' => array(
'#value' => $link,
'#type' => 'user_profile_item',
),
'#weight' => -10,
);
}
}
}
Functions
Name | Description |
---|---|
theme_workspace_list | Theme the list of content. Turn the results into a table. |
workspace_access | Menu access callback. |
workspace_add_form | Form definition for content addition form. |
workspace_add_form_submit | Submit handler for content addition form. |
workspace_build_rows | Build the query result into a table, respecting access. |
workspace_configure | Menu callback. The configuration page. |
workspace_configure_access | Menu access callback. |
workspace_configure_form | Form definition for per-user configuration form. |
workspace_configure_form_submit | Submit handler for per-user configuration form. |
workspace_configure_form_validate | Validator for per-user configuration form. |
workspace_delete | Menu callback. Redirect user to delete node. |
workspace_help | Implementation of hook_help(). |
workspace_list_comments | Menu callback. Display list of comments. |
workspace_list_content | Menu callback. Display list of content. |
workspace_list_files | Menu callback. List file attachments managed by upload.module. |
workspace_menu | Implementation of hook_menu(). |
workspace_perm | Implementation of hook_perm(). |
workspace_settings | Implementation of hook_settings(). |
workspace_theme | Implementation of hook_theme(). |
workspace_user | Implementation of hook_user(). |