'. t('Shoutbox') .'';
$help .= '
'. t('The shoutbox gives your team a space to microblog.') .'
';
$help .= '';
$help .= '- '. t('Shouts can be used to tell others what you\'re up to, link to websites of interest, or cover other random stuff that comes up during the day.') .'
';
$help .= '- '. t('Keep your shouts short and to the point. If a shout starts getting long, consider using a blog post or document to capture your thoughts.') .'
';
$help .= '- '. t('URLs will automatically be linked in your posts.') .'
';
$help .= '
';
return $help;
}
}
/**
* Implementation of hook_menu()
*/
function atrium_shoutbox_menu() {
$items = array();
$items['shoutbox'] = array(
'title' => 'Shoutbox',
'title callback' => 'atrium_shoutbox_title',
'page callback' => 'atrium_shoutbox_page',
'access callback' => module_exists('spaces') ? 'spaces_access_feature' : 'user_access',
'access arguments' => module_exists('spaces') ? array('view', 'atrium_shoutbox') : array('access comments'),
'type' => MENU_NORMAL_ITEM,
'menu_name' => 'features',
'options' => array(
'fragment' => 'block-atrium_shoutbox-shoutbox',
'attributes' => array(
'id' => 'atrium-shoutbox-launcher',
'class' => 'palette-toggle'
),
),
);
$items['shoutbox/js'] = array(
'description' => 'Shoutbox AJAX submission callback.',
'page callback' => 'atrium_shoutbox_ajax',
'access arguments' => array('post comments'),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Implementation of hook_menu_alter().
*/
function atrium_shoutbox_menu_alter(&$items) {
// Remove shoutbox node add page.
if (isset($items['node/add/shoutbox'])) {
unset($items['node/add/shoutbox']);
}
}
/**
* Shoutbox menu item title callback.
*/
function atrium_shoutbox_title($title) {
$title = t($title);
if (($shoutbox = atrium_shoutbox_get_shoutbox()) && !empty($shoutbox['count'])) {
$title .= " ({$shoutbox['count']})";
}
return $title;
}
/**
* Implementation of hook_block()
*/
function atrium_shoutbox_block($op = 'list', $delta = 0) {
switch ($op) {
case 'list':
return array('shoutbox' => array('info' => t('Shoutbox')));
case 'view':
$access = module_exists('spaces') ? spaces_access_feature('view', 'atrium_shoutbox') : user_access('access comments');
if ($delta == 'shoutbox' && $access && !context_isset('context', 'shoutbox_og')) {
if ($shoutbox = atrium_shoutbox_get_shoutbox()) {
$space = module_exists('spaces') ? spaces_get_space() : FALSE;
if (($space && $space->type === 'og') || !module_exists('spaces_og')) {
$link = l(t('Full view'), 'shoutbox');
$output = drupal_get_form('atrium_shoutbox_shoutform', $shoutbox['node'], $shoutbox['view'], $shoutbox['rendered']);
$output .= "$link
";
return array(
'subject' => !empty($space->group) ? filter_xss_admin($space->group->title) : t('Shoutbox'),
'content' => $output
);
}
else {
return array(
'subject' => t('Shoutbox'),
'content' => $shoutbox['rendered']
);
}
}
}
break;
}
}
/**
* Implementation of hook_nodeapi().
*/
function atrium_shoutbox_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
if ($node->type == 'shoutbox') {
switch ($op) {
case 'load':
$node->shoutbox = $node->nid;
unset($node->comment);
break;
case 'view':
$node->content = array('shoutbox' => array('#value' => atrium_shoutbox_page()));
break;
}
}
}
/**
* Implementation of hook_context_links_alter().
* Yank out button for creating new shoutboxes.
*/
function atrium_shoutbox_context_links_alter(&$links) {
if (isset($links['shoutbox'])) {
unset($links['shoutbox']);
}
}
/**
* Page callback for spaces shoutbox feature.
*/
function atrium_shoutbox_page() {
$shoutbox = atrium_shoutbox_get_shoutbox();
if ($shoutbox && $shoutbox['node']) {
$view = views_get_view('shoutbox_shouts');
$rendered = $view->execute_display('page_1');
return drupal_get_form('atrium_shoutbox_shoutform', $shoutbox['node'], $view, $rendered);
}
return $shoutbox ? $shoutbox['rendered'] : '';
}
/**
* Generate the shoutbox for the current space and/or situation along with user
* unread count calculations. This behaves as a singleton for the page load so
* that it can be used at several points (menu title callback, block, etc.).
*/
function atrium_shoutbox_get_shoutbox($reset = FALSE) {
// Admin killswitch.
if (arg(0) === 'admin') {
return FALSE;
}
static $shoutbox;
if (!isset($shoutbox) || $reset) {
// Add shoutbox js and current server timestamp. Note that we don't
// use the client side timestamp (via JS) because the cookie timestamp
// is compared with shout times. We avoid bad client clocks and
// inconsistencies using this method.
drupal_add_js(drupal_get_path('module', 'admin') . '/includes/jquery.cookie.js');
drupal_add_js(drupal_get_path('module', 'atrium_shoutbox') . '/atrium_shoutbox.js');
drupal_add_js(array('atrium_shoutbox' => array('timestamp' => time())), 'setting');
$shoutbox = array();
$space = module_exists('spaces') ? spaces_get_space() : FALSE;
if (($space && $space->type === 'og') || !module_exists('spaces_og')) {
if ($view = views_get_view('shoutbox_shoutboxes')) {
$view->execute_display('default');
// Shoutboxes exist for our current request, use the first.
if (is_array($view->result) && count($view->result)) {
$node = node_load($view->result[0]->nid);
}
// No shoutboxes exist yet. Lazy instantiate one.
else {
global $user;
$node = (object) array(
'title' => isset($space->group) ? $space->group->title : t('Shoutbox'),
'body' => '',
'name' => isset($space->group) ? $space->group->name : $user->name,
'type' => 'shoutbox',
);
node_save($node);
}
// Get the view and pass it to the form, as we will want access to the
// raw view resultset ourselves.
if (node_access('view', $node) && $view = views_get_view('shoutbox_shouts')) {
$shoutbox['node'] = $node;
$shoutbox['view'] = $view;
}
}
}
else {
$view = views_get_view('shoutbox_shouts');
$shoutbox['node'] = FALSE;
$shoutbox['view'] = $view;
}
// Execute/render shoutbox & count unread shouts for the current user.
if (!empty($shoutbox)) {
global $user;
$shoutbox['count'] = 0;
$shoutbox['rendered'] = $shoutbox['view']->execute_display('default');
if (!empty($shoutbox['view']->result) && !empty($_REQUEST['AtriumShoutbox'])) {
$user_last_viewed = $_REQUEST['AtriumShoutbox'];
foreach ($shoutbox['view']->result as $row) {
// Only tally shouts that occurred after this user's last view.
// The user's shouts don't count.
if (
isset($row->comments_timestamp, $row->comments_uid) &&
$row->comments_timestamp >= $user_last_viewed &&
$row->comments_uid !== $user->uid
) {
$shoutbox['count']++;
}
}
}
}
}
return $shoutbox;
}
/**
* Shoutbox AJAX callback
*/
function atrium_shoutbox_ajax($op = 'shout') {
// Disable any devel output
global $user, $devel_shutdown;
$devel_shutdown = FALSE;
switch ($op) {
case 'full': // Requested full comment
case 'shout': // Submitted shout
default:
$form_state = array('values' => $_POST);
$text = trim($form_state['values']['shout']);
$nid = $form_state['values']['nid'];
if (!empty($nid) && !empty($text)) {
atrium_shoutbox_shout($nid, array('text' => $text, 'uid' => $user->uid));
}
// Update the shout view.
list($view_name, $view_display) = explode(':', $form_state['values']['view']);
$output = views_embed_view($view_name, $view_display);
print drupal_to_js(array('status' => TRUE, 'data' => $output));
break;
}
exit();
}
/**
* Save shoutbox as comment
*
* Store the whole comment but trim the subject to a shorter text
*/
function atrium_shoutbox_shout($nid, $shout) {
$comment = $shout;
$comment['nid'] = $nid;
// See comment_save() for the thread building code.
$max = db_result(db_query('SELECT MAX(thread) FROM {comments} WHERE nid = %d', $nid));
$max = rtrim($max, '/');
$thread = int2vancode(vancode2int($max) + 1) .'/';
$comment += array(
'nid' => $nid,
'comment' => $shout['text'],
'timestamp' => time(),
'uid' => 0, // Defaults to anonymous
'status' => COMMENT_NOT_PUBLISHED,
'thread' => $thread,
);
// Retrieve the username to store with the comment
if (!empty($comment['uid']) && ($account = user_load(array('uid' => $comment['uid'])))) {
$comment['name'] = $account->name;
}
// The body may be in any format, so we:
// 1) Filter it into HTML
// 2) Strip out all HTML tags
// 3) Convert entities back to plain-text.
// Note: format is checked by check_markup().
if (trim($shout['subject']) == '') {
$subject = decode_entities(strip_tags(filter_xss($shout['text'], array())));
$subject = truncate_utf8($subject, 63, TRUE, FALSE);
$comment['subject'] = $subject;
}
drupal_write_record('comments', $comment);
// Invoke hooks.
comment_invoke_comment($comment, 'insert');
}
/**
* New shoutbox form.
*
* @param $form_state
* The FAPI form state array.
* @param $shoutbox
* The shoutbox node object to which shouts will be related.
* @param $view
* The view for rendered shouts. Needed to AJAX update the view in question.
* @param $rendered
* A rendered list of shouts to display.
*/
function atrium_shoutbox_shoutform($form_state, $shoutbox, $view, $rendered) {
$wrapper = 'atrium-shoutbox-wrapper-'. $shoutbox->nid;
$form = array(
'#attributes' => array('class' => 'shoutform'),
'#theme' => 'atrium_shoutbox_shoutform'
);
$form['nid'] = array(
'#type' => 'hidden',
'#value' => $shoutbox->nid
);
$form['view'] = array(
'#type' => 'hidden',
'#value' => "{$view->name}:{$view->current_display}",
'#attributes' => array('class' => 'atrium-shoutbox-shoutform-view')
);
$form['shout'] = array(
'#type' => 'textarea',
'#resizable' => FALSE,
'#rows' => 2,
'#access' => user_access('post comments'),
);
$form['shoutbox_submit'] = array(
'#type' => 'submit',
'#value' => t('Shout'),
'#ahah' => array(
'path' => 'shoutbox/js/shout',
'wrapper' => $wrapper,
'method' => 'replace',
'effect' => 'none',
),
'#access' => user_access('post comments'),
);
$form['wrapper'] = array(
'#type' => 'markup',
'#value' => "",
);
return $form;
}
/**
* Form submission, in case there's no js
*/
function atrium_shoutbox_shoutform_submit($form, $form_state) {
global $user;
$text = trim($form_state['values']['shout']);
$nid = $form_state['values']['nid'];
if (!empty($nid) && !empty($text)) {
atrium_shoutbox_shout($nid, array('text' => $text, 'uid' => $user->uid));
}
}
/**
* Implementation of hook_theme().
*/
function atrium_shoutbox_theme() {
return array('atrium_shoutbox_shoutform' => array());
}
/**
* Shoutbox form theme function.
*/
function theme_atrium_shoutbox_shoutform($form) {
drupal_add_js(drupal_get_path('module', 'atrium_shoutbox') .'/atrium_shoutbox.js');
$input = drupal_render($form['shout']) . drupal_render($form['shoutbox_submit']);
$output = "";
$output .= drupal_render($form);
return $output;
}