1 |
85ad3d82
|
Assos Assos
|
<?php
|
2 |
|
|
|
3 |
|
|
/**
|
4 |
|
|
* @file
|
5 |
|
|
* User menu callbacks for Privatemsg.
|
6 |
|
|
*/
|
7 |
|
|
|
8 |
|
|
|
9 |
|
|
/**
|
10 |
|
|
* Returns a form which handles and displays thread actions.
|
11 |
|
|
*
|
12 |
|
|
* Additional actions can be added with the privatemsg_thread_operations hook.
|
13 |
|
|
* It is also possible to extend this form with additional buttons or other
|
14 |
|
|
* elements, in that case, the definitions in the above hook need no label tag,
|
15 |
|
|
* instead, the submit button key needs to match with the key of the operation.
|
16 |
|
|
*
|
17 |
|
|
* @see hook_privatemsg_thread_operations()
|
18 |
|
|
*
|
19 |
|
|
* @return
|
20 |
|
|
* The FAPI definitions for the thread action form.
|
21 |
|
|
*/
|
22 |
|
|
function _privatemsg_action_form($type) {
|
23 |
|
|
$form = array(
|
24 |
|
|
'#prefix' => '<div class="container-inline">',
|
25 |
|
|
'#suffix' => '</div>',
|
26 |
|
|
'#weight' => -5,
|
27 |
|
|
);
|
28 |
|
|
// Display all operations which have a label.
|
29 |
|
|
$operations = module_invoke_all('privatemsg_thread_operations', $type);
|
30 |
|
|
drupal_alter('privatemsg_thread_operations', $operations, $type);
|
31 |
|
|
foreach ($operations as $operation => $array) {
|
32 |
|
|
if (!empty($array['button'])) {
|
33 |
|
|
$form[$operation] = array(
|
34 |
|
|
'#type' => 'submit',
|
35 |
|
|
'#value' => $array['label'],
|
36 |
|
|
'#ajax' => array(
|
37 |
|
|
'callback' => 'privatemsg_list_js',
|
38 |
|
|
'wrapper' => 'privatemsg-list-form',
|
39 |
|
|
'effect' => 'fade',
|
40 |
|
|
),
|
41 |
|
|
);
|
42 |
|
|
}
|
43 |
|
|
elseif (isset($array['label'])) {
|
44 |
|
|
$options[$operation] = $array['label'];
|
45 |
|
|
}
|
46 |
|
|
}
|
47 |
|
|
if (!empty($options)) {
|
48 |
|
|
array_unshift($options, t('Actions...'));
|
49 |
|
|
$form['operation'] = array(
|
50 |
|
|
'#type' => 'select',
|
51 |
|
|
'#options' => $options,
|
52 |
|
|
'#ajax' => array(
|
53 |
|
|
'callback' => 'privatemsg_list_js',
|
54 |
|
|
'wrapper' => 'privatemsg-list-form',
|
55 |
|
|
'effect' => 'fade',
|
56 |
|
|
),
|
57 |
|
|
'#executes_submit_callback' => TRUE,
|
58 |
|
|
);
|
59 |
|
|
$form['submit'] = array(
|
60 |
|
|
'#type' => 'submit',
|
61 |
|
|
'#value' => t('Execute'),
|
62 |
|
|
'#attributes' => array('class' => array('form-item')),
|
63 |
|
|
'#states' => array(
|
64 |
|
|
'visible' => array(
|
65 |
|
|
// This is never true, button is always hidden when JS is enabled.
|
66 |
|
|
':input[name=operation]' => array('value' => 'fake'),
|
67 |
|
|
),
|
68 |
|
|
),
|
69 |
|
|
);
|
70 |
|
|
}
|
71 |
|
|
return $form;
|
72 |
|
|
}
|
73 |
|
|
|
74 |
|
|
/**
|
75 |
|
|
* AJAX callback to return the form again.
|
76 |
|
|
*/
|
77 |
|
|
function privatemsg_list_js($form, $form_state) {
|
78 |
|
|
return $form['updated'];
|
79 |
|
|
}
|
80 |
|
|
|
81 |
|
|
function privatemsg_delete($form, $form_state, $thread, $message) {
|
82 |
|
|
$form['pmid'] = array(
|
83 |
|
|
'#type' => 'value',
|
84 |
|
|
'#value' => $message->mid,
|
85 |
|
|
);
|
86 |
|
|
$form['delete_destination'] = array(
|
87 |
|
|
'#type' => 'value',
|
88 |
|
|
'#value' => count($thread['messages']) > 1 ? 'messages/view/' . $message->thread_id : 'messages',
|
89 |
|
|
);
|
90 |
|
|
|
91 |
|
|
if (privatemsg_user_access('read all private messages')) {
|
92 |
|
|
$form['delete_options'] = array(
|
93 |
|
|
'#type' => 'checkbox',
|
94 |
|
|
'#title' => t('Delete this message for all users?'),
|
95 |
|
|
'#description' => t('Tick the box to delete the message for all users.'),
|
96 |
|
|
'#default_value' => FALSE,
|
97 |
|
|
);
|
98 |
|
|
}
|
99 |
|
|
return confirm_form($form,
|
100 |
|
|
t('Are you sure you want to delete this message?'),
|
101 |
|
|
isset($_GET['destination']) ? $_GET['destination'] : 'messages/view/' . $message->thread_id,
|
102 |
|
|
t('This action cannot be undone.'),
|
103 |
|
|
t('Delete'),
|
104 |
|
|
t('Cancel')
|
105 |
|
|
);
|
106 |
|
|
}
|
107 |
|
|
|
108 |
|
|
function privatemsg_delete_submit($form, &$form_state) {
|
109 |
|
|
global $user;
|
110 |
|
|
$account = clone $user;
|
111 |
|
|
|
112 |
|
|
if ($form_state['values']['confirm']) {
|
113 |
|
|
if (isset($form_state['values']['delete_options']) && $form_state['values']['delete_options']) {
|
114 |
|
|
privatemsg_message_change_delete($form_state['values']['pmid'], 1);
|
115 |
|
|
drupal_set_message(t('Message has been deleted for all users.'));
|
116 |
|
|
}
|
117 |
|
|
else {
|
118 |
|
|
privatemsg_message_change_delete($form_state['values']['pmid'], 1, $account);
|
119 |
|
|
drupal_set_message(t('Message has been deleted.'));
|
120 |
|
|
}
|
121 |
|
|
}
|
122 |
|
|
$form_state['redirect'] = $form_state['values']['delete_destination'];
|
123 |
|
|
}
|
124 |
|
|
|
125 |
|
|
/**
|
126 |
|
|
* List messages.
|
127 |
|
|
*
|
128 |
|
|
* @param $argument
|
129 |
|
|
* An argument to pass through to the query builder.
|
130 |
|
|
* @param $uid
|
131 |
|
|
* User id messages of another user should be displayed
|
132 |
|
|
*
|
133 |
|
|
* @return
|
134 |
|
|
* Form array
|
135 |
|
|
*/
|
136 |
|
|
function privatemsg_list_page($argument = 'list', $uid = NULL) {
|
137 |
|
|
global $user;
|
138 |
|
|
|
139 |
|
|
// Setting default behavior...
|
140 |
|
|
$account = $user;
|
141 |
|
|
// Because uid is submitted by the menu system, it's a string not a integer.
|
142 |
|
|
if ((int)$uid > 0 && $uid != $user->uid) {
|
143 |
|
|
// Trying to view someone else's messages...
|
144 |
|
|
if (!$account_check = user_load($uid)) {
|
145 |
|
|
return MENU_NOT_FOUND;
|
146 |
|
|
}
|
147 |
|
|
if (!privatemsg_user_access('read all private messages')) {
|
148 |
|
|
return MENU_ACCESS_DENIED;
|
149 |
|
|
}
|
150 |
|
|
// Has rights and user_load return an array so user does exist
|
151 |
|
|
$account = $account_check;
|
152 |
|
|
}
|
153 |
|
|
|
154 |
|
|
return drupal_get_form('privatemsg_list', $argument, $account);
|
155 |
|
|
}
|
156 |
|
|
|
157 |
|
|
function privatemsg_list($form, &$form_state, $argument, $account) {
|
158 |
|
|
drupal_add_css(drupal_get_path('module', 'privatemsg') . '/styles/privatemsg-list.css');
|
159 |
|
|
|
160 |
|
|
// If this is an AJAX request, update $_GET['q'] so that table sorting and
|
161 |
|
|
// similar links are using the correct base path.
|
162 |
|
|
if ($_GET['q'] == 'system/ajax') {
|
163 |
|
|
$q = 'messages';
|
164 |
|
|
if (!empty($argument)) {
|
165 |
|
|
$q .= '/' . $argument;
|
166 |
|
|
}
|
167 |
|
|
$_GET['q'] = $q;
|
168 |
|
|
}
|
169 |
|
|
|
170 |
|
|
// Load the table columns.
|
171 |
|
|
$columns = array_merge(array('subject', 'last_updated'), array_filter(variable_get('privatemsg_display_fields', array('participants'))));
|
172 |
|
|
|
173 |
|
|
// Load the themed list headers based on the available data.
|
174 |
|
|
$headers = _privatemsg_list_headers($columns);
|
175 |
|
|
|
176 |
|
|
$form = array(
|
177 |
|
|
'#list_argument' => $argument,
|
178 |
|
|
'#submit' => array('privatemsg_list_submit'),
|
179 |
|
|
'updated' => array(
|
180 |
|
|
'#prefix' => '<div id="privatemsg-list-form">',
|
181 |
|
|
'#suffix' => '</div>',
|
182 |
|
|
),
|
183 |
|
|
);
|
184 |
|
|
$form['updated']['list'] = array(
|
185 |
|
|
'#type' => 'tableselect',
|
186 |
|
|
'#header' => $headers,
|
187 |
|
|
'#options' => array(),
|
188 |
|
|
'#attributes' => array('class' => array('privatemsg-list')),
|
189 |
|
|
'#empty' => t('No messages available.'),
|
190 |
|
|
'#weight' => 5,
|
191 |
|
|
'#pre_render' => array('_privatemsg_list_thread'),
|
192 |
|
|
);
|
193 |
|
|
|
194 |
|
|
$query = _privatemsg_assemble_query('list', $account, $argument);
|
195 |
|
|
$i = 0;
|
196 |
|
|
foreach ($query->execute() as $row) {
|
197 |
|
|
// Store the raw row data.
|
198 |
|
|
$form['updated']['list']['#options'][$row->thread_id] = (array)$row;
|
199 |
|
|
// Tableselect sorts the options, set a weight so that the order doesn't get
|
200 |
|
|
// changed.
|
201 |
|
|
$form['updated']['list']['#options'][$row->thread_id]['#weight'] = $i++;
|
202 |
|
|
}
|
203 |
|
|
|
204 |
|
|
if (!empty($form['updated']['list']['#options'])) {
|
205 |
|
|
$form['updated']['actions'] = _privatemsg_action_form($argument);
|
206 |
|
|
}
|
207 |
|
|
|
208 |
|
|
// Save the currently active account, used for actions.
|
209 |
|
|
$form['account'] = array('#type' => 'value', '#value' => $account);
|
210 |
|
|
|
211 |
|
|
// Define checkboxes, pager and theme
|
212 |
|
|
$form['updated']['pager'] = array('#markup' => theme('pager'), '#weight' => 20);
|
213 |
|
|
return $form;
|
214 |
|
|
}
|
215 |
|
|
|
216 |
|
|
/**
|
217 |
|
|
* Process privatemsg_list form submissions.
|
218 |
|
|
*
|
219 |
|
|
* Execute the chosen action on the selected messages. This function is
|
220 |
|
|
* based on node_admin_nodes_submit().
|
221 |
|
|
*/
|
222 |
|
|
function privatemsg_list_submit($form, &$form_state) {
|
223 |
|
|
// Load all available operation definitions.
|
224 |
|
|
$operations = module_invoke_all('privatemsg_thread_operations', $form['#list_argument']);
|
225 |
|
|
drupal_alter('privatemsg_thread_operations', $operations, $form['#list_argument']);
|
226 |
|
|
|
227 |
|
|
// Default "default" operation, which won't do anything.
|
228 |
|
|
$operation = array('callback' => 0);
|
229 |
|
|
|
230 |
|
|
// Check if a valid operation has been submitted.
|
231 |
|
|
if (isset($form_state['values']['operation']) && isset($operations[$form_state['values']['operation']])) {
|
232 |
|
|
$operation = $operations[$form_state['values']['operation']];
|
233 |
|
|
}
|
234 |
|
|
|
235 |
|
|
if (!empty($form_state['values']['op'])) {
|
236 |
|
|
// Load all keys where the value is the current op.
|
237 |
|
|
$keys = array_keys($form_state['values'], $form_state['values']['op']);
|
238 |
|
|
|
239 |
|
|
// Loop over them and detect if a matching button was pressed.
|
240 |
|
|
foreach ($keys as $key) {
|
241 |
|
|
if ($key != 'op' && isset($operations[$key])) {
|
242 |
|
|
$operation = $operations[$key];
|
243 |
|
|
}
|
244 |
|
|
}
|
245 |
|
|
}
|
246 |
|
|
|
247 |
|
|
// Only execute something if we have a valid callback and at least one checked thread.
|
248 |
|
|
if (!empty($operation['callback'])) {
|
249 |
|
|
// Hack to fix destination during ajax requests.
|
250 |
|
|
if (isset($form_state['input']['ajax_page_state'])) {
|
251 |
|
|
$destination = 'messages';
|
252 |
|
|
if (!empty($form['#list_argument'])) {
|
253 |
|
|
$destination .= '/' . $form['#list_argument'];
|
254 |
|
|
}
|
255 |
|
|
$_GET['destination'] = $destination;
|
256 |
|
|
}
|
257 |
|
|
privatemsg_operation_execute($operation, $form_state['values']['list'], $form_state['values']['account']);
|
258 |
|
|
}
|
259 |
|
|
|
260 |
|
|
$form_state['rebuild'] = TRUE;
|
261 |
|
|
$form_state['input'] = array();
|
262 |
|
|
}
|
263 |
|
|
|
264 |
|
|
|
265 |
|
|
function privatemsg_new($form, &$form_state, $recipients = array(), $subject = '', $thread_id = NULL, $read_all = FALSE) {
|
266 |
|
|
global $user;
|
267 |
|
|
|
268 |
|
|
$recipients_plain = '';
|
269 |
|
|
$body = '';
|
270 |
|
|
|
271 |
|
|
// convert recipients to array of user objects
|
272 |
|
|
$unique = FALSE;
|
273 |
|
|
if (!empty($recipients) && is_string($recipients) || is_int($recipients)) {
|
274 |
|
|
$unique = TRUE;
|
275 |
|
|
$recipients = _privatemsg_generate_user_array($recipients);
|
276 |
|
|
}
|
277 |
|
|
elseif (is_object($recipients)) {
|
278 |
|
|
$recipients = array($recipients);
|
279 |
|
|
}
|
280 |
|
|
elseif (empty($recipients) && is_string($recipients)) {
|
281 |
|
|
$recipients = array();
|
282 |
|
|
}
|
283 |
|
|
|
284 |
|
|
$usercount = 0;
|
285 |
|
|
$to = array();
|
286 |
|
|
$to_plain = array();
|
287 |
|
|
$blocked_messages = array();
|
288 |
|
|
foreach ($recipients as $recipient) {
|
289 |
|
|
// Allow to pass in normal user objects.
|
290 |
|
|
if (empty($recipient->type)) {
|
291 |
|
|
$recipient->type = 'user';
|
292 |
|
|
$recipient->recipient = $recipient->uid;
|
293 |
|
|
}
|
294 |
|
|
if ($recipient->type == 'hidden') {
|
295 |
|
|
continue;
|
296 |
|
|
}
|
297 |
|
|
if (isset($to[privatemsg_recipient_key($recipient)])) {
|
298 |
|
|
// We already added the recipient to the list, skip him.
|
299 |
|
|
continue;
|
300 |
|
|
}
|
301 |
|
|
if (!privatemsg_recipient_access($recipient->type, 'write', $recipient)) {
|
302 |
|
|
// User does not have access to write to this recipient, continue.
|
303 |
|
|
continue;
|
304 |
|
|
}
|
305 |
|
|
|
306 |
|
|
// Check if another module is blocking the sending of messages to the recipient by current user.
|
307 |
|
|
$user_blocked = module_invoke_all('privatemsg_block_message', $user, array(privatemsg_recipient_key($recipient) => $recipient), array('thread_id' => $thread_id));
|
308 |
|
|
if (!count($user_blocked) <> 0 && $recipient->recipient) {
|
309 |
|
|
if ($recipient->type == 'user' && $recipient->recipient == $user->uid) {
|
310 |
|
|
$usercount++;
|
311 |
|
|
// Skip putting author in the recipients list for now.
|
312 |
|
|
continue;
|
313 |
|
|
}
|
314 |
|
|
$to[privatemsg_recipient_key($recipient)] = privatemsg_recipient_format($recipient);
|
315 |
|
|
$to_plain[privatemsg_recipient_key($recipient)] = privatemsg_recipient_format($recipient, array('plain' => TRUE, 'unique' => $unique));
|
316 |
|
|
}
|
317 |
|
|
else {
|
318 |
|
|
// Store blocked messages. These are only displayed if all recipients
|
319 |
|
|
// are blocked.
|
320 |
|
|
$first_reason = reset($user_blocked);
|
321 |
|
|
$blocked_messages[] = $first_reason['message'];
|
322 |
|
|
}
|
323 |
|
|
}
|
324 |
|
|
|
325 |
|
|
if (empty($to) && $usercount >= 1 && empty($blocked_messages)) {
|
326 |
|
|
// Assume the user sent message to own account as if the usercount is one or less, then the user sent a message but not to self.
|
327 |
|
|
$to['user_' . $user->uid] = privatemsg_recipient_format($user);
|
328 |
|
|
$to_plain['user_' . $user->uid] = privatemsg_recipient_format($user, array('plain' => TRUE));
|
329 |
|
|
}
|
330 |
|
|
|
331 |
|
|
// Subject has / encoded twice if clean urls are enabled to get it through
|
332 |
|
|
// mod_rewrite and the menu system. Decode it once more.
|
333 |
|
|
$subject = str_replace('%2F', '/', $subject);
|
334 |
|
|
|
335 |
|
|
if (!empty($to)) {
|
336 |
|
|
$recipients_plain = implode(', ', $to_plain);
|
337 |
|
|
}
|
338 |
|
|
if (isset($form_state['values'])) {
|
339 |
|
|
if (isset($form_state['values']['recipient'])) {
|
340 |
|
|
$recipients_plain = $form_state['values']['recipient'];
|
341 |
|
|
}
|
342 |
|
|
if (isset($form_state['values']['subject'])) {
|
343 |
|
|
$subject = $form_state['values']['subject'];
|
344 |
|
|
}
|
345 |
|
|
if (isset($form_state['values']['body'])) {
|
346 |
|
|
$body = $form_state['values']['body'];
|
347 |
|
|
}
|
348 |
|
|
}
|
349 |
|
|
if (!$thread_id && !empty($recipients_plain)) {
|
350 |
|
|
drupal_set_title(t('Write new message to @recipient', array('@recipient' => $recipients_plain)));
|
351 |
|
|
}
|
352 |
|
|
elseif (!$thread_id) {
|
353 |
|
|
drupal_set_title(t('Write new message'));
|
354 |
|
|
}
|
355 |
|
|
|
356 |
|
|
$form = array(
|
357 |
|
|
'#access' => (privatemsg_user_access('write privatemsg') || privatemsg_user_access('reply only privatemsg')),
|
358 |
|
|
);
|
359 |
|
|
if (isset($form_state['privatemsg_preview'])) {
|
360 |
|
|
|
361 |
|
|
$preview_subject = '';
|
362 |
|
|
// Only display subject on preview for new messages.
|
363 |
|
|
if (empty($form_state['validate_built_message']->thread_id)) {
|
364 |
|
|
$preview_subject = check_plain($form_state['validate_built_message']->subject);
|
365 |
|
|
// If message has tokens, replace them.
|
366 |
|
|
if ($form_state['validate_built_message']->has_tokens) {
|
367 |
|
|
$preview_subject = privatemsg_token_replace($preview_subject, array('privatemsg_message' => $form_state['validate_built_message']), array('sanitize' => TRUE, 'privatemsg-show-span' => FALSE));
|
368 |
|
|
}
|
369 |
|
|
}
|
370 |
|
|
|
371 |
|
|
$form['message_header'] = array(
|
372 |
|
|
'#type' => 'fieldset',
|
373 |
|
|
'#title' => !empty($preview_subject) ? $preview_subject : t('Preview'),
|
374 |
|
|
'#attributes' => array('class' => array('preview')),
|
375 |
|
|
'#weight' => -20,
|
376 |
|
|
);
|
377 |
|
|
$form['message_header']['message_preview'] = $form_state['privatemsg_preview'];
|
378 |
|
|
}
|
379 |
|
|
$form['author'] = array(
|
380 |
|
|
'#type' => 'value',
|
381 |
|
|
'#value' => $user,
|
382 |
|
|
);
|
383 |
|
|
if (is_null($thread_id)) {
|
384 |
|
|
$description_array = array();
|
385 |
|
|
foreach (privatemsg_recipient_get_types() as $name => $type) {
|
386 |
|
|
if (privatemsg_recipient_access($name, 'write')) {
|
387 |
|
|
$description_array[] = $type['description'];
|
388 |
|
|
}
|
389 |
|
|
}
|
390 |
|
|
$description = t('Enter the recipient, separate recipients with commas.');
|
391 |
|
|
$description .= theme('item_list', array('items' => $description_array));
|
392 |
|
|
|
393 |
|
|
$form['recipient'] = array(
|
394 |
|
|
'#type' => 'textfield',
|
395 |
|
|
'#title' => t('To'),
|
396 |
|
|
'#description' => $description,
|
397 |
|
|
'#default_value' => $recipients_plain,
|
398 |
|
|
'#required' => TRUE,
|
399 |
|
|
'#weight' => -10,
|
400 |
|
|
'#size' => 50,
|
401 |
|
|
'#autocomplete_path' => 'messages/autocomplete',
|
402 |
|
|
// Do not hardcode #maxlength, make it configurable by number of recipients, not their name length.
|
403 |
|
|
);
|
404 |
|
|
}
|
405 |
|
|
$form['subject'] = array(
|
406 |
|
|
'#type' => 'textfield',
|
407 |
|
|
'#title' => t('Subject'),
|
408 |
|
|
'#size' => 50,
|
409 |
|
|
'#maxlength' => 255,
|
410 |
|
|
'#default_value' => $subject,
|
411 |
|
|
'#weight' => -5,
|
412 |
|
|
);
|
413 |
|
|
|
414 |
|
|
// The input filter widget looses the format during preview, specify it
|
415 |
|
|
// explicitly.
|
416 |
|
|
if (isset($form_state['values']) && array_key_exists('format', $form_state['values'])) {
|
417 |
|
|
$format = $form_state['values']['format'];
|
418 |
|
|
}
|
419 |
|
|
$form['body'] = array(
|
420 |
|
|
'#type' => 'text_format',
|
421 |
|
|
'#title' => t('Message'),
|
422 |
|
|
'#rows' => 6,
|
423 |
|
|
'#weight' => -3,
|
424 |
|
|
'#default_value' => $body,
|
425 |
|
|
'#resizable' => TRUE,
|
426 |
|
|
'#format' => isset($format) ? $format : NULL,
|
427 |
|
|
'#after_build' => array('privatemsg_check_format_access'),
|
428 |
|
|
);
|
429 |
|
|
if (privatemsg_user_access('use tokens in privatemsg') && module_exists('token')) {
|
430 |
|
|
$form['token'] = array(
|
431 |
|
|
'#type' => 'fieldset',
|
432 |
|
|
'#title' => t('Token browser'),
|
433 |
|
|
'#weight' => -1,
|
434 |
|
|
'#collapsible' => TRUE,
|
435 |
|
|
'#collapsed' => TRUE,
|
436 |
|
|
);
|
437 |
|
|
$form['token']['browser'] = array(
|
438 |
|
|
'#theme' => 'token_tree',
|
439 |
|
|
'#token_types' => array('privatemsg_message'),
|
440 |
|
|
);
|
441 |
|
|
}
|
442 |
|
|
$form['actions'] = array('#type' => 'actions');
|
443 |
|
|
if (variable_get('privatemsg_display_preview_button', FALSE)) {
|
444 |
|
|
$form['actions']['preview'] = array(
|
445 |
|
|
'#type' => 'submit',
|
446 |
|
|
'#value' => t('Preview message'),
|
447 |
|
|
'#submit' => array('privatemsg_new_preview'),
|
448 |
|
|
'#weight' => 48,
|
449 |
|
|
);
|
450 |
|
|
}
|
451 |
|
|
$form['actions']['submit'] = array(
|
452 |
|
|
'#type' => 'submit',
|
453 |
|
|
'#value' => t('Send message'),
|
454 |
|
|
'#weight' => 49,
|
455 |
|
|
);
|
456 |
|
|
$url = 'messages';
|
457 |
|
|
$title = t('Cancel');
|
458 |
|
|
if (isset($_REQUEST['destination'])) {
|
459 |
|
|
$url = $_REQUEST['destination'];
|
460 |
|
|
}
|
461 |
|
|
elseif (!is_null($thread_id)) {
|
462 |
|
|
$url = $_GET['q'];
|
463 |
|
|
$title = t('Clear');
|
464 |
|
|
}
|
465 |
|
|
|
466 |
|
|
$form['actions']['cancel'] = array(
|
467 |
|
|
'#markup' => l($title, $url, array('attributes' => array('id' => 'edit-cancel'))),
|
468 |
|
|
'#weight' => 50,
|
469 |
|
|
);
|
470 |
|
|
|
471 |
|
|
if (!is_null($thread_id)) {
|
472 |
|
|
$form['thread_id'] = array(
|
473 |
|
|
'#type' => 'value',
|
474 |
|
|
'#value' => $thread_id,
|
475 |
|
|
);
|
476 |
|
|
$form['subject'] = array(
|
477 |
|
|
'#type' => 'value',
|
478 |
|
|
'#default_value' => $subject,
|
479 |
|
|
);
|
480 |
|
|
$form['reply'] = array(
|
481 |
|
|
'#markup' => '<h2 class="privatemsg-reply">' . t('Reply') . '</h2>',
|
482 |
|
|
'#weight' => -10,
|
483 |
|
|
);
|
484 |
|
|
if (empty($to)) {
|
485 |
|
|
// If there are no valid recipients, hide all visible parts of the form.
|
486 |
|
|
foreach (element_children($form) as $element) {
|
487 |
|
|
$form[$element]['#access'] = FALSE;
|
488 |
|
|
}
|
489 |
|
|
|
490 |
|
|
// Display a message if some users are blocked.
|
491 |
|
|
if (!empty($blocked_messages)) {
|
492 |
|
|
$form['blocked'] = array(
|
493 |
|
|
'#theme' => 'item_list',
|
494 |
|
|
'#items' => $blocked_messages,
|
495 |
|
|
'#title' => t('You can not reply to this conversation because all recipients are blocked.'),
|
496 |
|
|
);
|
497 |
|
|
}
|
498 |
|
|
}
|
499 |
|
|
}
|
500 |
|
|
// Only set read all if it is a boolean TRUE. It might also be an integer set
|
501 |
|
|
// through the URL.
|
502 |
|
|
$form['read_all'] = array(
|
503 |
|
|
'#type' => 'value',
|
504 |
|
|
'#value' => $read_all === TRUE,
|
505 |
|
|
);
|
506 |
|
|
// Attach field widgets.
|
507 |
|
|
$message = (object) array();
|
508 |
|
|
if (isset($form_state['validate_built_message'])) {
|
509 |
|
|
$message = $form_state['validate_built_message'];
|
510 |
|
|
}
|
511 |
|
|
|
512 |
|
|
// If a module (e.g. OG) adds a validate or submit callback to the form in
|
513 |
|
|
// field_attach_form, the form system will not add ours automatically
|
514 |
|
|
// anymore. Therefore, explicitly adding them here.
|
515 |
|
|
$form['#submit'] = array('privatemsg_new_submit');
|
516 |
|
|
$form['#validate'] = array('privatemsg_new_validate');
|
517 |
|
|
|
518 |
|
|
field_attach_form('privatemsg_message', $message, $form, $form_state);
|
519 |
|
|
return $form;
|
520 |
|
|
}
|
521 |
|
|
|
522 |
|
|
/**
|
523 |
|
|
* After build callback; Hide format widget if user doesn't have permission.
|
524 |
|
|
*/
|
525 |
|
|
function privatemsg_check_format_access($element) {
|
526 |
|
|
if (isset($element['format'])) {
|
527 |
|
|
$element['format']['#access'] = privatemsg_user_access('select text format for privatemsg');
|
528 |
|
|
}
|
529 |
|
|
return $element;
|
530 |
|
|
}
|
531 |
|
|
|
532 |
|
|
function privatemsg_new_validate($form, &$form_state) {
|
533 |
|
|
// The actual message that is being sent, we create this during validation and
|
534 |
|
|
// pass to submit to send out.
|
535 |
|
|
$message = (object)$form_state['values'];
|
536 |
|
|
$message->mid = 0;
|
537 |
|
|
$message->format = $message->body['format'];
|
538 |
|
|
$message->body = $message->body['value'];
|
539 |
|
|
$message->timestamp = REQUEST_TIME;
|
540 |
|
|
// Avoid subjects which only consist of a space as these can not be clicked.
|
541 |
|
|
$message->subject = trim($message->subject);
|
542 |
|
|
|
543 |
|
|
$trimmed_body = trim(truncate_utf8(strip_tags($message->body), 50, TRUE, TRUE));
|
544 |
|
|
if (empty($message->subject) && !empty($trimmed_body)) {
|
545 |
|
|
$message->subject = $trimmed_body;
|
546 |
|
|
}
|
547 |
|
|
// Only parse the user string for a new thread.
|
548 |
|
|
if (!isset($message->thread_id)) {
|
549 |
|
|
list($message->recipients, $invalid, $duplicates, $denieds) = _privatemsg_parse_userstring($message->recipient);
|
550 |
|
|
}
|
551 |
|
|
else {
|
552 |
|
|
// Load participants. Limit recipients to visible unless read_all is TRUE.
|
553 |
|
|
$message->recipients = _privatemsg_load_thread_participants($message->thread_id, $message->read_all ? FALSE : $message->author);
|
554 |
|
|
}
|
555 |
|
|
|
556 |
|
|
if (!empty($invalid)) {
|
557 |
|
|
// Display information about invalid recipients.
|
558 |
|
|
drupal_set_message(t('The following users will not receive this private message: @invalid.', array('@invalid' => implode(", ", $invalid))), 'error');
|
559 |
|
|
}
|
560 |
|
|
if (!empty($denieds)) {
|
561 |
|
|
// Display information about denied recipients.
|
562 |
|
|
drupal_set_message(t('You do not have access to write these recipients: @denieds.', array('@denieds' => implode(", ", $denieds))), 'error');
|
563 |
|
|
}
|
564 |
|
|
|
565 |
|
|
if (!empty($duplicates)) {
|
566 |
|
|
// Add JS and CSS to allow choosing the recipient.
|
567 |
|
|
drupal_add_js(drupal_get_path('module', 'privatemsg') . '/privatemsg-alternatives.js');
|
568 |
|
|
|
569 |
|
|
// Display information about recipients that couldn't be identified
|
570 |
|
|
// uniquely.
|
571 |
|
|
$js_duplicates = array();
|
572 |
|
|
foreach ($duplicates as $string => $duplicate) {
|
573 |
|
|
$alternatives = array();
|
574 |
|
|
foreach ($duplicate as $match) {
|
575 |
|
|
$formatted_match = privatemsg_recipient_format($match, array('plain' => TRUE, 'unique' => TRUE));
|
576 |
|
|
$js_duplicates[$formatted_match] = $string;
|
577 |
|
|
$alternatives[] = '<span class="privatemsg-recipient-alternative">' . $formatted_match . '</span>';
|
578 |
|
|
}
|
579 |
|
|
// Build a formatted list of possible recipients.
|
580 |
|
|
$alternatives = theme('item_list', array('items' => $alternatives, 'attributes' => array('class' => array('action-links'))));
|
581 |
|
|
form_set_error('recipient', '<span class="privatemsg-alternative-description">' . t('The site has multiple recipients named %string. Please choose your intended recipient: !list', array('%string' => $string, '!list' => $alternatives)) . '</span>');
|
582 |
|
|
}
|
583 |
|
|
|
584 |
|
|
// Also make that information available to the javascript replacement code.
|
585 |
|
|
drupal_add_js(array('privatemsg_duplicates' => $js_duplicates), 'setting');
|
586 |
|
|
}
|
587 |
|
|
|
588 |
|
|
$validated = _privatemsg_validate_message($message, TRUE);
|
589 |
|
|
foreach ($validated['messages'] as $type => $texts) {
|
590 |
|
|
foreach ($texts as $text) {
|
591 |
|
|
drupal_set_message($text, $type);
|
592 |
|
|
}
|
593 |
|
|
}
|
594 |
|
|
$form_state['validate_built_message'] = $message;
|
595 |
|
|
}
|
596 |
|
|
|
597 |
|
|
function privatemsg_new_preview($form, &$form_state) {
|
598 |
|
|
$message = $form_state['validate_built_message'];
|
599 |
|
|
// Execute submit hook, removes empty fields.
|
600 |
|
|
field_attach_submit('privatemsg_message', $message, $form, $form_state);
|
601 |
|
|
// Load information attached to the message. Use an internal function
|
602 |
|
|
// to avoid the internal field cache.
|
603 |
|
|
_field_invoke_multiple('load', 'privatemsg_message', array($message->mid => $message));
|
604 |
|
|
$form_state['privatemsg_preview'] = array(
|
605 |
|
|
'#markup' => theme('privatemsg_view', array('message' => $message)),
|
606 |
|
|
);
|
607 |
|
|
// This forces the form to be rebuilt instead of being submitted.
|
608 |
|
|
$form_state['rebuild'] = TRUE;
|
609 |
|
|
}
|
610 |
|
|
|
611 |
|
|
|
612 |
|
|
/**
|
613 |
|
|
* Submit callback for the privatemsg_new form.
|
614 |
|
|
*/
|
615 |
|
|
function privatemsg_new_submit($form, &$form_state) {
|
616 |
|
|
$message = $form_state['validate_built_message'];
|
617 |
|
|
field_attach_submit('privatemsg_message', $message, $form, $form_state);
|
618 |
|
|
|
619 |
|
|
// Format each recipient.
|
620 |
|
|
$recipient_names = array();
|
621 |
|
|
foreach ($message->recipients as $recipient) {
|
622 |
|
|
$recipient_names[] = privatemsg_recipient_format($recipient);
|
623 |
|
|
}
|
624 |
|
|
try {
|
625 |
|
|
$message = _privatemsg_send($message);
|
626 |
|
|
_privatemsg_handle_recipients($message->mid, $message->recipients);
|
627 |
|
|
drupal_set_message(t('A message has been sent to !recipients.', array('!recipients' => implode(', ', $recipient_names))));
|
628 |
|
|
// Only redirect on new threads.
|
629 |
|
|
if ($message->mid == $message->thread_id || variable_get('privatemsg_default_redirect_reply', FALSE)) {
|
630 |
|
|
$redirect = variable_get('privatemsg_default_redirect', '<new-message>');
|
631 |
|
|
if ($redirect == '<new-message>' || (!empty($_REQUEST['destination']) && $_REQUEST['destination'] == '[new-message]')) {
|
632 |
|
|
if (!empty($_REQUEST['destination']) && $_REQUEST['destination'] == '[new-message]') {
|
633 |
|
|
// Remove GET param so that drupal_goto() uses the redirect from
|
634 |
|
|
// $form_state.
|
635 |
|
|
unset($_GET['destination']);
|
636 |
|
|
}
|
637 |
|
|
// Forward to the new message in the thread.
|
638 |
|
|
$form_state['redirect'] = array('messages/view/' . $message->thread_id, array('fragment' => 'privatemsg-mid-' . $message->mid));
|
639 |
|
|
}
|
640 |
|
|
elseif (!empty($redirect)) {
|
641 |
|
|
$form_state['redirect'] = $redirect;
|
642 |
|
|
}
|
643 |
|
|
}
|
644 |
|
|
}
|
645 |
|
|
catch (Exception $e) {
|
646 |
|
|
if (error_displayable()) {
|
647 |
|
|
require_once DRUPAL_ROOT . '/includes/errors.inc';
|
648 |
|
|
$variables = _drupal_decode_exception($e);
|
649 |
|
|
drupal_set_message(t('Failed to send a message to !recipients. %type: !message in %function (line %line of %file).', array('!recipients' => implode(', ', $recipient_names)) + $variables), 'error');
|
650 |
|
|
}
|
651 |
|
|
else {
|
652 |
|
|
drupal_set_message(t('Failed to send a message to !recipients. Contact your site administrator.', array('!recipients' => implode(', ', $recipient_names))), 'error');
|
653 |
|
|
}
|
654 |
|
|
}
|
655 |
|
|
}
|
656 |
|
|
|
657 |
|
|
|
658 |
|
|
/**
|
659 |
|
|
* Menu callback for messages/undo/action.
|
660 |
|
|
*
|
661 |
|
|
* This function will test if an undo callback is stored in SESSION and execute it.
|
662 |
|
|
*/
|
663 |
|
|
function privatemsg_undo_action() {
|
664 |
|
|
// Check if a undo callback for that user exists.
|
665 |
|
|
if (isset($_SESSION['privatemsg']['undo callback']) && is_array($_SESSION['privatemsg']['undo callback'])) {
|
666 |
|
|
$undo = $_SESSION['privatemsg']['undo callback'];
|
667 |
|
|
// If the defined undo callback exists, execute it
|
668 |
|
|
if (isset($undo['function']) && isset($undo['args'])) {
|
669 |
|
|
// Load the user object.
|
670 |
|
|
if (isset($undo['args']['account']) && $undo['args']['account'] > 0) {
|
671 |
|
|
$undo['args']['account'] = user_load((int)$undo['args']['account']);
|
672 |
|
|
}
|
673 |
|
|
call_user_func_array($undo['function'], $undo['args']);
|
674 |
|
|
}
|
675 |
|
|
}
|
676 |
|
|
// Return back to the site defined by the destination GET param.
|
677 |
|
|
drupal_goto();
|
678 |
|
|
}
|
679 |
|
|
|
680 |
|
|
|
681 |
|
|
/**
|
682 |
|
|
* Return autocomplete results for usernames.
|
683 |
|
|
*
|
684 |
|
|
* Prevents usernames from being used and/or suggested twice.
|
685 |
|
|
*/
|
686 |
|
|
function privatemsg_autocomplete($string) {
|
687 |
|
|
$names = array();
|
688 |
|
|
// 1: Parse $string and build list of valid user names.
|
689 |
|
|
$fragments = explode(',', $string);
|
690 |
|
|
foreach ($fragments as $name) {
|
691 |
|
|
if ($name = trim($name)) {
|
692 |
|
|
$names[$name] = $name;
|
693 |
|
|
}
|
694 |
|
|
}
|
695 |
|
|
// 2: Find the next user name suggestion.
|
696 |
|
|
$fragment = array_pop($names);
|
697 |
|
|
$matches = array();
|
698 |
|
|
if (!empty($fragment)) {
|
699 |
|
|
$remaining = 10;
|
700 |
|
|
$types = privatemsg_recipient_get_types();
|
701 |
|
|
foreach ($types as $name => $type) {
|
702 |
|
|
if (isset($type['autocomplete']) && is_callable($type['autocomplete']) && privatemsg_recipient_access($name, 'write')) {
|
703 |
|
|
$function = $type['autocomplete'];
|
704 |
|
|
$return = $function($fragment, $names, $remaining);
|
705 |
|
|
if (is_array($return) && !empty($return)) {
|
706 |
|
|
$matches = array_merge($matches, $return);
|
707 |
|
|
}
|
708 |
|
|
$remaining = 10 - count($matches);
|
709 |
|
|
if ($remaining <= 0) {
|
710 |
|
|
break;
|
711 |
|
|
}
|
712 |
|
|
}
|
713 |
|
|
}
|
714 |
|
|
}
|
715 |
|
|
// Allow modules to alter the autocomplete list.
|
716 |
|
|
drupal_alter('privatemsg_autocomplete', $matches, $names, $fragment);
|
717 |
|
|
|
718 |
|
|
// Format the suggestions.
|
719 |
|
|
$themed_matches = array();
|
720 |
|
|
foreach ($matches as $key => $match) {
|
721 |
|
|
$themed_matches[$key] = privatemsg_recipient_format($match, array('plain' => TRUE));
|
722 |
|
|
}
|
723 |
|
|
|
724 |
|
|
// Check if there are any duplicates.
|
725 |
|
|
if (count(array_unique($themed_matches)) != count($themed_matches)) {
|
726 |
|
|
// Loop over matches, look for duplicates of each one.
|
727 |
|
|
foreach ($themed_matches as $themed_match) {
|
728 |
|
|
$duplicate_keys = array_keys($themed_matches, $themed_match);
|
729 |
|
|
if (count($duplicate_keys) > 1) {
|
730 |
|
|
// There are duplicates, make them unique.
|
731 |
|
|
foreach ($duplicate_keys as $duplicate_key) {
|
732 |
|
|
// Reformat them with unique argument.
|
733 |
|
|
$themed_matches[$duplicate_key] = privatemsg_recipient_format($matches[$duplicate_key], array('plain' => TRUE, 'unique' => TRUE));
|
734 |
|
|
}
|
735 |
|
|
}
|
736 |
|
|
}
|
737 |
|
|
}
|
738 |
|
|
|
739 |
|
|
// Prefix the matches and convert them to the correct form for the
|
740 |
|
|
// autocomplete.
|
741 |
|
|
$prefix = count($names) ? implode(", ", $names) . ", " : '';
|
742 |
|
|
$suggestions = array();
|
743 |
|
|
foreach ($themed_matches as $match) {
|
744 |
|
|
$suggestions[$prefix . $match . ', '] = $match;
|
745 |
|
|
}
|
746 |
|
|
|
747 |
|
|
// convert to object to prevent drupal bug, see http://drupal.org/node/175361
|
748 |
|
|
drupal_json_output((object)$suggestions);
|
749 |
|
|
}
|
750 |
|
|
|
751 |
|
|
|
752 |
|
|
/**
|
753 |
|
|
* Menu callback for viewing a thread.
|
754 |
|
|
*
|
755 |
|
|
* @param $thread
|
756 |
|
|
* A array containing all information about a specific thread, generated by
|
757 |
|
|
* privatemsg_thread_load().
|
758 |
|
|
* @return
|
759 |
|
|
* The page content.
|
760 |
|
|
*
|
761 |
|
|
* @see privatemsg_thread_load()
|
762 |
|
|
*/
|
763 |
|
|
function privatemsg_view($thread) {
|
764 |
|
|
drupal_set_title($thread['subject']);
|
765 |
|
|
|
766 |
|
|
$content = array(
|
767 |
|
|
'#thread' => $thread,
|
768 |
|
|
);
|
769 |
|
|
|
770 |
|
|
if ($thread['to'] != $thread['message_count'] || !empty($thread['start'])) {
|
771 |
|
|
// Generate paging links.
|
772 |
|
|
$older = '';
|
773 |
|
|
if (isset($thread['older_start'])) {
|
774 |
|
|
$options = array(
|
775 |
|
|
'query' => array('start' => $thread['older_start']),
|
776 |
|
|
'title' => t('Display older messages'),
|
777 |
|
|
);
|
778 |
|
|
$older = l(t('<<'), 'messages/view/' . $thread['thread_id'], $options);
|
779 |
|
|
}
|
780 |
|
|
$newer = '';
|
781 |
|
|
if (isset($thread['newer_start'])) {
|
782 |
|
|
$options = array(
|
783 |
|
|
'query' => array('start' => $thread['newer_start']),
|
784 |
|
|
'title' => t('Display newer messages'),
|
785 |
|
|
);
|
786 |
|
|
$newer = l(t('>>'), 'messages/view/' . $thread['thread_id'], $options);
|
787 |
|
|
}
|
788 |
|
|
$substitutions = array('@from' => $thread['from'], '@to' => $thread['to'], '@total' => $thread['message_count'], '!previous_link' => $older, '!newer_link' => $newer);
|
789 |
|
|
$title = t('!previous_link Displaying messages @from - @to of @total !newer_link', $substitutions);
|
790 |
|
|
$content['pager'] = array(
|
791 |
|
|
'#markup' => trim($title),
|
792 |
|
|
'#prefix' => '<div class="privatemsg-view-pager">',
|
793 |
|
|
'#suffix' => '</div>',
|
794 |
|
|
'#weight' => 3,
|
795 |
|
|
);
|
796 |
|
|
}
|
797 |
|
|
|
798 |
|
|
// Render the participants.
|
799 |
|
|
$content['participants'] = array(
|
800 |
|
|
'#markup' => theme('privatemsg_recipients', array('thread' => $thread)),
|
801 |
|
|
'#weight' => -5
|
802 |
|
|
);
|
803 |
|
|
|
804 |
|
|
// Render the messages.
|
805 |
|
|
$content['messages']['#weight'] = 0;
|
806 |
|
|
$i = 1;
|
807 |
|
|
$count = count($thread['messages']);
|
808 |
|
|
foreach ($thread['messages'] as $pmid => $message) {
|
809 |
|
|
// Set message as read and theme it.
|
810 |
|
|
// Add CSS classes.
|
811 |
|
|
$message->classes = array('privatemsg-message', 'privatemsg-message-' . $i, $i % 2 == 1 ? 'privatemsg-message-even' : 'privatemsg-message-odd');
|
812 |
|
|
if (!empty($message->is_new)) {
|
813 |
|
|
// Mark message as read.
|
814 |
|
|
privatemsg_message_change_status($pmid, PRIVATEMSG_READ, $thread['user']);
|
815 |
|
|
$message->classes[] = 'privatemsg-message-new';
|
816 |
|
|
}
|
817 |
|
|
|
818 |
|
|
if ($i == 1) {
|
819 |
|
|
$message->classes[] = 'privatemsg-message-first';
|
820 |
|
|
}
|
821 |
|
|
if ($i == $count) {
|
822 |
|
|
$message->classes[] = 'privatemsg-message-last';
|
823 |
|
|
}
|
824 |
|
|
$i++;
|
825 |
|
|
$content['messages'][$pmid] = array(
|
826 |
|
|
'#markup' => theme('privatemsg_view', array('message' => $message)),
|
827 |
|
|
);
|
828 |
|
|
}
|
829 |
|
|
|
830 |
|
|
// Display the reply form if user is allowed to use it.
|
831 |
|
|
if (privatemsg_user_access('write privatemsg') || privatemsg_user_access('reply only privatemsg')) {
|
832 |
|
|
$content['reply'] = drupal_get_form('privatemsg_new', $thread['participants'], $thread['subject-original'], $thread['thread_id'], $thread['read_all']);
|
833 |
|
|
$content['reply']['#weight'] = 5;
|
834 |
|
|
}
|
835 |
|
|
// Check after calling the privatemsg_new form so that this message is only
|
836 |
|
|
// displayed when we are not sending a message.
|
837 |
|
|
if ($thread['read_all']) {
|
838 |
|
|
// User has permission to read all messages AND is not a participant of the current thread.
|
839 |
|
|
drupal_set_message(t('This conversation is being viewed with escalated privileges and may not be the same as shown to normal users.'), 'warning');
|
840 |
|
|
}
|
841 |
|
|
|
842 |
|
|
drupal_alter('privatemsg_view', $content);
|
843 |
|
|
|
844 |
|
|
return $content;
|
845 |
|
|
}
|
846 |
|
|
|
847 |
|
|
/**
|
848 |
|
|
* Batch processing function for rebuilding the index.
|
849 |
|
|
*/
|
850 |
|
|
function privatemsg_load_recipients($mid, $recipient, &$context) {
|
851 |
|
|
// Get type information.
|
852 |
|
|
$type = privatemsg_recipient_get_type($recipient->type);
|
853 |
|
|
|
854 |
|
|
// First run, initialize sandbox.
|
855 |
|
|
if (!isset($context['sandbox']['current_offset'])) {
|
856 |
|
|
$context['sandbox']['current_offset'] = 0;
|
857 |
|
|
$count_function = $type['count'];
|
858 |
|
|
$context['sandbox']['count'] = $count_function($recipient);
|
859 |
|
|
}
|
860 |
|
|
|
861 |
|
|
// Fetch the 10 next recipients.
|
862 |
|
|
$load_function = $type['generate recipients'];
|
863 |
|
|
$uids = $load_function($recipient, 10, $context['sandbox']['current_offset']);
|
864 |
|
|
|
865 |
|
|
if (!empty($uids)) {
|
866 |
|
|
foreach ($uids as $uid) {
|
867 |
|
|
privatemsg_message_change_recipient($mid, $uid, 'hidden');
|
868 |
|
|
}
|
869 |
|
|
|
870 |
|
|
$context['sandbox']['current_offset'] += 10;
|
871 |
|
|
// Set finished based on sandbox.
|
872 |
|
|
$context['finished'] = empty($context['sandbox']['count']) ? 1 : ($context['sandbox']['current_offset'] / $context['sandbox']['count']);
|
873 |
|
|
}
|
874 |
|
|
else {
|
875 |
|
|
// If no recipients were returned, mark as finished too.
|
876 |
|
|
$context['sandbox']['finished'] = 1;
|
877 |
|
|
}
|
878 |
|
|
|
879 |
|
|
// If we are finished, mark the recipient as read.
|
880 |
|
|
if ($context['finished'] >= 1) {
|
881 |
|
|
db_update('pm_index')
|
882 |
|
|
->fields(array('is_new' => PRIVATEMSG_READ))
|
883 |
|
|
->condition('mid', $mid)
|
884 |
|
|
->condition('recipient', $recipient->recipient)
|
885 |
|
|
->condition('type', $recipient->type)
|
886 |
|
|
->execute();
|
887 |
|
|
}
|
888 |
|
|
} |