class HeartbeatActivity in Heartbeat 6.4
Same name and namespace in other branches
- 6.3 includes/heartbeatactivity.inc \HeartbeatActivity
- 7 includes/heartbeatactivity.inc \HeartbeatActivity
Class defines an activity message object
Hierarchy
- class \HeartbeatActivity
Expanded class hierarchy of HeartbeatActivity
1 string reference to 'HeartbeatActivity'
File
- includes/
heartbeatactivity.inc, line 12 - HeartbeatActivity object Defines one heartbeat activity object.
View source
class HeartbeatActivity {
// DB fields
public $uaid = 0;
public $tuaid = 0;
public $message_id = '';
public $nid_info = '';
public $nid_target_info = '';
public $uid = 0;
public $uid_access = TRUE;
public $uid_target = 0;
public $nid = 0;
public $nid_access = TRUE;
public $nid_target = 0;
public $nid_target_access = TRUE;
public $timestamp = 0;
public $language = 'en';
public $message = '';
public $message_concat = '';
public $access = HEARTBEAT_PUBLIC_TO_ALL;
public $variables = array();
public $additions = NULL;
public $classes = '';
// User object of the uid, being the actor of activity.
public $actor = NULL;
// Array of associated user activity ID's.
public $uaids = array();
// Template composite
public $template = '';
// Global properties on message base.
public $display_time = TRUE;
public $count = 0;
// count for same instance
public $target_count = 0;
// count for same instance that is merged by target
public $time_info_grouped = 0;
public $delete_access = FALSE;
public $actor_access = FALSE;
// Template variables
public $name = 'heartbeatactivity';
public $type = 'heartbeatactivity';
public $build_mode = 'none';
public $content = array();
/**
* constructor
* @param $data Array or Object with fields that can match this object
* Data for the message, some are converted.
* It's possible to give a sql-result set as data which will
* adapt to a heartbeatActivity object.
* @param $template HeartbeatMessageTemplate
* holds the template data.
*/
function __construct($data, HeartbeatMessageTemplate $template) {
$this->template = $template;
$this->additions = new stdClass();
$this->message_id = $this->template->message_id;
if (is_object($data)) {
$data = (array) $data;
}
if (isset($data['uaid'])) {
$this->uaid = $data['uaid'];
}
if (isset($data['count'])) {
$this->count = $data['count'];
}
// Only load the user if it's needed.
if (empty($data['mail'])) {
$this->actor = heartbeat_user_load($data['uid']);
}
else {
$account = new stdClass();
$message_actor_data = unserialize($data['data']);
unset($data['data']);
$account->data = $message_actor_data;
$account->heartbeat_activity_settings = isset($message_actor_data['heartbeat_activity_settings']) ? $message_actor_data['heartbeat_activity_settings'] : array();
foreach (user_fields() as $field) {
if (isset($data[$field])) {
$account->{$field} = $data[$field];
}
}
$this->actor = $account;
}
$this->uid = $data['uid'];
$this->uid_target = $data['uid_target'];
$this->nid = $data['nid'];
$this->nid_info = !empty($data['nid_info']) ? unserialize($data['nid_info']) : array();
$this->nid_target = isset($data['nid_target']) ? (int) $data['nid_target'] : 0;
$this->nid_target_info = !empty($data['nid_target_info']) ? unserialize($data['nid_target_info']) : array();
$this->timestamp = !empty($data['timestamp']) ? $data['timestamp'] : $_SERVER['REQUEST_TIME'];
// For performance reasons, one activity has knowlegde of the comment count.
$this->additions->comment_count = isset($data['uaid_comments']) ? $data['uaid_comments'] : 0;
$this->access = (int) $data['access'];
if (isset($data['message'])) {
$this->message = $data['message'];
}
else {
$this->message = $this->template->message;
}
if (!empty($data['message_concat'])) {
$this->message_concat = $data['message_concat'];
}
else {
$this->message_concat = $this->template->message_concat;
}
$this
->set_variables($data['variables']);
if (isset($data['extra']['duplicate'])) {
$this->variables['duplicate'] = $data['extra']['duplicate'];
}
}
/**
* Method gets a heartbeat_activity variable
*
* @desc The magic getter method fetches a variable
* in members. If not found there, it will always
* check the content holder as well
*/
public function __get($variable) {
return $this->variables[$variable];
}
/**
* Method sets a heartbeat_activity property
*
* @desc The magic setter method sets a variable to member
* If not found, just stash in the content array
*/
public function __set($variable, $value) {
$this->variables[$variable] = $value;
}
/*
* Rebuild the message with given candidate variables
*/
public function rebuild_message($concat = FALSE) {
if (count($this->variables) > 0) {
$variables = array();
foreach ($this->variables as $key => $value) {
$key[0] = '!';
$variables[$key] = $value;
}
}
if ($concat) {
return t($this->template->message_concat, $variables);
}
return t($this->template->message, $variables);
}
/**
* Create the link for a delete button.
*/
public function delete_button($args = array()) {
$attributes = array(
'query' => drupal_get_destination(),
'alias' => TRUE,
);
if (count($this->uaids) > 1) {
$attributes['attributes'] = array(
'onclick' => 'javascript:Drupal.heartbeat.splitGroupedMessage(' . $this->uaid . ', new Array(' . implode(",", $this->uaids) . ')); return false;',
);
}
$attributes += $args;
return '<span class="hover-delete">' . l(t('Delete'), 'heartbeat/delete/' . $this->uaid, $attributes) . '</span>';
}
/*
* Rebuild the message with given candidate variables
*/
public function create_grouped_message($candidates, $max_items_to_group = 5) {
global $base_url;
$message_template = $this
->rebuild_message(TRUE);
$message_extension = '';
$message_template = str_replace("%times%", $this->target_count, $message_template);
$message_template = str_replace("%count%", $this->target_count, $message_template);
// Prepare the merged factors from the stored messages
$merged_string = '';
$remains = array();
$target = $this->template->concat_args['group_target'];
$beat = 'beat-item-' . $this->uaid;
$unique = $candidates['variables'];
$count = $candidates['count'];
//count($candidates['variables']);
// Limit the number of displayed (grouped) messages by message
// or left as default global configuration
if (!empty($this->template->concat_args['group_num_max'])) {
$max_items_to_group = $this->template->concat_args['group_num_max'];
}
// Reduce the variables for substitution to the maximum
// Add the remains by keeping the others plus the last one,
// in case the total exceeds the max group setting.
if ($count > $max_items_to_group) {
$count = $max_items_to_group;
$unique = array_slice($unique, 0, $count);
$remains = array_slice($candidates['variables'], $count);
}
// Replacement of placeholder with group targets
// If there is a match for %variable%
// Try to replace the variable with the group_target variables
if (preg_match_all("|\\%(.*)\\%(.*)|U", $message_template, $matches)) {
if ($this->template->concat_args['show_remaining_items']) {
$hidden_remains = theme('heartbeat_activity_remaining', $beat, $target, $remains);
}
// TODO Make a decision on how to handle the target on merged groups
// This code in comment is/was a attempt to have more grouping words
// The difficult and almost impossible part is the fact that you always
// have to target something to group on (for the same node or same user)
//foreach ($matches[1] as $target) {
$placeholder = $matches[1][0];
$i = 1;
foreach ($unique as $stored_variables) {
// limit them to the value given by the group variable setting
if (isset($stored_variables["@" . $target])) {
if ($i == 1) {
$merged_string .= ' ' . $stored_variables["@" . $target];
}
elseif ($i < $count && $count > 2) {
if (isset($this->template->concat_args['merge_separator_t']) && strlen(strip_tags($this->template->concat_args['merge_separator_t'])) > 0) {
$merged_string .= ' ' . t($this->template->concat_args['merge_separator']);
}
else {
$merged_string .= ' ' . $this->template->concat_args['merge_separator'];
}
$merged_string .= ' ' . $stored_variables["@" . $target];
}
elseif ($i == $count || $count == 2) {
if (isset($this->template->concat_args['merge_end_separator_t']) && strlen(strip_tags($this->template->concat_args['merge_end_separator_t'])) > 0) {
$merged_string .= ' ' . t($this->template->concat_args['merge_end_separator']);
}
else {
$merged_string .= ' ' . $this->template->concat_args['merge_end_separator'];
}
if (count($remains) >= 1 && $hidden_remains != '') {
// Add the last item.
$merged_string .= ' ' . $stored_variables["@" . $target];
if ($this->template->concat_args['show_remaining_items']) {
// Add the remains.
$message_extension .= $hidden_remains;
// Add the link to the remaining items.
$merged_string .= theme('hearbeat_activity_remain_link', $beat, count($remains));
}
}
else {
$merged_string .= ' ' . $stored_variables["@" . $target];
}
}
}
$i++;
}
$message_template = str_replace("%" . $placeholder . "%", $merged_string, $message_template);
if (isset($message_extension)) {
$message_template .= $message_extension;
}
//}
}
$this->message = $message_template;
}
/**
* Public function to save activity to database
* @param array raw argument to enforce as is (pre-renderd)
*/
public function save($raw_args = array()) {
$locale = module_exists('locale');
if (!empty($this->nid)) {
$node = node_load($this->nid);
// Add extra node access information for nid.
if (empty($this->nid_info)) {
// Add extra node access information for nid.
$this->nid_info = array(
'uid' => $node->uid,
'type' => $node->type,
'format' => $node->format,
);
}
}
if (!empty($this->nid_target)) {
$node_target = node_load($this->nid_target);
// Add extra node access information for nid_target.
$this->nid_target_info = array(
'uid' => $node_target->uid,
'type' => $node_target->type,
'format' => $node_target->format,
);
}
// if a user selected a language, then we follow i19n.
if (isset($node) && !empty($node->language)) {
return $this
->_save($raw_args, $node->language);
}
if ($locale) {
return $this
->save_locale($raw_args);
}
else {
return $this
->_save($raw_args);
}
}
/**
* Sets the variables array
* Data variables are stored in an array to use them to build real variables.
* this means that when activity message objects get merged, the variables
* will be filled with variables components from all instances.
*/
private function set_variables($variables = NULL) {
if (!empty($variables)) {
if (is_string($variables)) {
$this->variables = heartbeat_decode_message_variables($variables);
}
elseif (is_array($variables)) {
$this->variables = $variables;
}
}
}
/**
* Save activity log with multilingual content
* and multilingual parts to pre-translate
*
* @param array $raw_args
*/
private function save_locale($raw_args = array()) {
$logged = FALSE;
$args = $this
->rebuild_arguments($raw_args, TRUE);
$locale = $args['locale'];
unset($args['locale']);
// Save activity by logging a row for each active language
// Translations only when locale exists
$languages = locale_language_list();
$tuaid = NULL;
foreach ($languages as $language => $human_language) {
// preprocess multilingual message "parts"
// for all flagged token replacements
foreach ($this->variables as $key => $value) {
if (isset($locale[$key])) {
$amp_token = str_replace("#", "!", $key);
$args[$amp_token] = locale($locale[$key], $language);
}
}
$uaid = $this
->log_message($args, $language);
// Each language has the first uaid (user activity id) as
// tuaid (translated user activity id)
if ($uaid && !isset($tuaid)) {
$tuaid = $uaid;
}
db_query("INSERT INTO {heartbeat_translations} SET tuaid=%d, uaid=%d", $tuaid, $uaid);
}
$this->uaid = $tuaid;
return $tuaid;
}
/**
* Save activity log
*
* @param array $raw_args
*/
private function _save($raw_args = array(), $lang = '') {
// Rebuild arguments with tokens
$args = $this
->rebuild_arguments($raw_args);
$this->uaid = $this
->log_message($args, $lang);
return $this->uaid;
}
/**
* Logs a heartbeat message
* @param string language optional
*
*/
private function log_message($args, $lang = '') {
if (empty($lang)) {
global $language;
$lang = $language->language;
}
$message = t($this->message, $args, $lang);
$message_concat = t($this->message_concat, $args, $lang);
// Checks if there should be logging what so ever
if (empty($message)) {
watchdog('heartbeat', 'Error in logging user activity: it is not possible to log empty message', array(), WATCHDOG_ERROR);
return FALSE;
}
// Log relational message to user activity
$logged = db_query("INSERT INTO {heartbeat_activity}\n SET uid=%d, uid_target=%d, nid=%d, nid_target=%d, message_id='%s', language='%s',\n access = %d, message ='%s',message_concat ='%s', timestamp=%d\n , nid_info='%s', nid_target_info='%s', uaid_comments=%d, variables='%s'", $this->uid, $this->uid_target, $this->nid, $this->nid_target, $this->message_id, $lang, $this->access, $message, $message_concat, $this->timestamp, serialize($this->nid_info), serialize($this->nid_target_info), 0, heartbeat_encode_message_variables($this->variables));
if (!$logged) {
return 0;
}
$uaid = db_last_insert_id('heartbeat_activity', 'uaid');
$this->uaids[] = $uaid;
return $uaid;
}
/**
* Rebuild the arguments for variables
* to share within this object
*
* @param array $raw_input of arguments
*/
private function rebuild_arguments($raw_input, $locale = FALSE) {
$args = array();
if ($locale) {
// Variables that need to be pre-translated go here
$args['locale'] = array();
}
$tags = heartbeat_allowed_tags();
// Rebuild arguments with language tokens
foreach ($this->variables as $key => $value) {
$value = filter_xss($value, $tags);
// Leave $key[0] == "!" asis
if ($key[0] != "@" && $key[0] != "#") {
//continue; // bad argument
}
$oldkey = $key;
// Reset the key of the arguments to ! to parse the next
// tokenization asis.
if ($key[0] == "@") {
$key[0] = "!";
}
// # and @ token replacement prefixes are kept,
// but set a flag for it in the raw_arguments
if ($key[0] == "#") {
// if it has to be translated ...
if ($locale) {
$args['locale'][$key] = $value;
}
// Now reset the key
$key[0] = "!";
}
// if argument is prefilled, override
if (isset($raw_input[$oldkey])) {
$args[$key] = $raw_input[$oldkey];
continue;
}
// Argument gets the value as in variables
$args[$key] = $value;
}
return $args;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | property | ||
HeartbeatActivity:: |
public | function | ||
HeartbeatActivity:: |
public | function | Create the link for a delete button. | |
HeartbeatActivity:: |
private | function | Logs a heartbeat message | |
HeartbeatActivity:: |
private | function | Rebuild the arguments for variables to share within this object | |
HeartbeatActivity:: |
public | function | ||
HeartbeatActivity:: |
public | function | Public function to save activity to database | |
HeartbeatActivity:: |
private | function | Save activity log with multilingual content and multilingual parts to pre-translate | |
HeartbeatActivity:: |
private | function | Sets the variables array Data variables are stored in an array to use them to build real variables. this means that when activity message objects get merged, the variables will be filled with variables components from all instances. | |
HeartbeatActivity:: |
private | function | Save activity log | |
HeartbeatActivity:: |
function | constructor | ||
HeartbeatActivity:: |
public | function | Method gets a heartbeat_activity variable | |
HeartbeatActivity:: |
public | function | Method sets a heartbeat_activity property |