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

Contents of /contributions/modules/nf_handshake/nf_handshake.module

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


Revision 1.8 - (show annotations) (download) (as text)
Thu Nov 29 07:21:32 2007 UTC (2 years ago) by rconstantine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +324 -107 lines
File MIME type: text/x-php
#193325 fixed it so user 1 and other admins can engage in handshakes - i.e. the checkboxes work correctly now

also we now react to user deletion and remove handshakes from our tables - you may need to clean your tables by hand as I didn't include a retroactive cleaning function

added css IDs to inbox and outbox and included a css file

added ability to include email address and picture from standard user profile as exchangable data - this was a pain in the butt! so if anyone wants to add other items from the users table, be my guest to roll a patch.
1 <?php
2 /**
3 * This is the nf_handshake module. The nodeprofile module is required as the handshakes involve the CCK fields from the content types
4 * so designated by nodeprofile as lonely nodes.
5 *
6 * @version $Id$;
7 * @package Handshake
8 * @category NeighborForge
9 * @author Ryan Constantine
10 * @filesource
11 * @license http://www.gnu.org/licenses/gpl.txt GNU_GENERAL_PUBLIC_LICENSE
12 * @link none yet
13 * TODO fix date presentation
14 * TODO remove all handshake menu items/user profile items from user 1 and other 'administer handshake' people if the settings match
15 * TODO allow admin to designate some fields as always viewable (handshake not needed); display above handshake/contact option if have permission to view this
16 * TODO allow users to designate some fields as always viewable (handshake not needed); display above handshake/contact option
17 * TODO user search - by address, by ???; allow admin to specify fields that are searchable; make as a separate,
18 * companion module like nf_handshake_user_search.module; if search field is 'always viewable' then results would include everyone who meets
19 * the criteria, otherwise, only those where a handshake exists and that data is exposed.
20 * TODO Add tab in admin UI so admin can selectively place sub-fields of complex CCK fields into either a separate effective field
21 * (for info trade purposes only) or make that sub-field out-of-bounds. For example, people may wish to share their birth year
22 * separate from their birth month and day.
23 * TODO ??? flag admin: make a block for this?
24 * TODO ??? CRON Although users can see their initiated handshakes' status, add a cron job for sending emails/private messages upon update of status(?)
25 */
26
27 /**
28 * Constants to define the status of the handshake transaction
29 */
30 define('NFHANDSHAKE_REJECTED', 0);
31 define('NFHANDSHAKE_ACCEPTED', 1);
32 define('NFHANDSHAKE_PENDING', 2);
33 define('NFHANDSHAKE_REVIEWED', 3);
34 define('NFHANDSHAKE_FLAGGED', 4);
35 define('NFHANDSHAKE_EXPIRED', 5);
36 define('NFHANDSHAKE_EXTENSION_REQUESTED', 6);
37 define('NFHANDSHAKE_UPGRADE_REQUESTED', 7);
38
39 /**
40 * Constants to define user flags that fit into a 3 digit int
41 */
42 define('NFHANDSHAKE_NONE', 0);
43 define('NFHANDSHAKE_AGE_INAPPROPRIATE', 1);
44 define('NFHANDSHAKE_SPAM', 2);
45 define('NFHANDSHAKE_HARASSMENT', 3);
46 define('NFHANDSHAKE_QUESTIONABLE_PURPOSE', 4);
47 define('NFHANDSHAKE_OTHER', 5);
48
49 /**
50 * Constants to define admin flags that fit into a 3 digit int
51 */
52 define('NFHANDSHAKE_NONE', 0);
53 define('NFHANDSHAKE_FURTHER_REVIEW', 10);
54 define('NFHANDSHAKE_VIOLATION_OF_TS', 20);
55 define('NFHANDSHAKE_WARNING_1', 30);
56 define('NFHANDSHAKE_WARNING_2', 40);
57 define('NFHANDSHAKE_SUSPEND_USER', 50);
58 define('NFHANDSHAKE_ALERT_PARENTS', 60);
59 define('NFHANDSHAKE_IUID_COMMENT', 70);
60 define('NFHANDSHAKE_AUID_COMMENT', 80);
61
62 //-----------------------------------------Various Drupal Hooks-----------------------------------------
63 //-----------------------------------------Various Drupal Hooks-----------------------------------------
64 //-----------------------------------------Various Drupal Hooks-----------------------------------------
65
66 /**
67 * Implementation of hook_help
68 *
69 * Display help and module information
70 * @param string $section Which section of the site we're displaying help
71 * @return string $output Help text.
72 */
73 function nf_handshake_help($section='') {
74 $output = '';
75 switch ($section) {
76 case "admin/help#nf_handshake":
77 $output = '<p>' . t("Changes the way users contact each other and what they can know about each other.
78 Implements a handshake routine where one user offers to expose certain profile fields to another in exchange
79 for the same consideration."). '</p>';
80 break;
81 }
82
83 return $output;
84 } // function nf_handshake_help()
85
86 /**
87 * Implementation of hook_perm
88 *
89 * Why is there separate 'initiate handshake' and 'accept handshake' permissions? In the case where you've used another module of mine
90 * that allows sub-accounts and you want to allow sub-accounts to initiate handshakes but only the main account holder to accept them.
91 * This would be the case where a parent is the primary account holder and a child is a sub-account holder. 'View own handshakes' is a
92 * separate permission for the same reason. The admin may wish for children to see that someone is trying to shake hands so that they
93 * can pester their parent to look into it. 'View handshakes' may or may not be used in the future.
94 *
95 * Valid permissions for this module
96 * @return array $items An array of menu items
97 */
98 function nf_handshake_perm() {
99 return array('administer handshakes', 'intitiate handshake', 'accept handshake', 'view own handshakes', 'view handshakes', 'bypass handshakes');
100 } // function nf_handshake_perm()
101
102 /**
103 * Implementation of hook_menu
104 *
105 * @return array An array of arrays, to add menu entries to the system menu.
106 */
107 function nf_handshake_menu($may_cache) {
108 $items = array();
109 global $user;
110 if ($may_cache) {
111 //-----------------------admin ui menu items----------------------------------
112 $items[] = array( //setup which data can be exchanged in the handshake process
113 'path' => 'admin/user/nf_handshake',
114 'title' => t('Handshake setup'),
115 'callback' => 'nf_handshake_main',
116 'access' => user_access('administer handshakes'),
117 'description' => t('This is how you organize your nodeprofile CCK field types for user sharing. To begin, go to <em>
118 Choose CCK Fields</em>, then move on to <em>Make groupings</em>. Those in groups are
119 considered equivalent so that if a user has one field type in the group, but not another, they can still share that info with
120 someone that has another field type in the same group.'),
121 'type' => MENU_NORMAL_ITEM,
122 );
123
124 $items[] = array( //tab to take us to main administer page
125 'path' => 'admin/user/nf_handshake/overview',
126 'title' => t('Overview'),
127 'access' => user_access('administer handshakes'),
128 'type' => MENU_DEFAULT_LOCAL_TASK,
129 'weight' => -10,
130 );
131
132 $items[] = array(
133 'path' => 'admin/user/nf_handshake/edit',
134 'title' => t('Edit'),
135 'callback' => 'drupal_get_form',
136 'callback arguments' => array('nf_handshake_edit'),
137 'access' => user_access('administer handshakes'),
138 'type' => MENU_CALLBACK,
139 );
140
141 $items[] = array(
142 'path' => 'admin/user/nf_handshake/delete',
143 'title' => t('Delete'),
144 'callback' => 'drupal_get_form',
145 'callback arguments' => array('nf_handshake_confirm_delete'),
146 'access' => user_access('administer handshakes'),
147 'type' => MENU_CALLBACK,
148 );
149
150 $items[] = array(
151 'path' => 'admin/user/nf_handshake/choose_cck_fields',
152 'title' => t('Choose CCK fields'),
153 'callback' => 'drupal_get_form',
154 'callback arguments' => array('nf_handshake_choose_cck_fields'),
155 'access' => user_access('administer handshakes'),
156 'type' => MENU_LOCAL_TASK,
157 'weight' => -8,
158 );
159
160 $items[] = array(
161 'path' => 'admin/user/nf_handshake/delete_cck_fields',
162 'title' => t('Delete CCK field'),
163 'callback' => 'drupal_get_form',
164 'callback arguments' => array('nf_handshake_confirm_cck_fields_delete'),
165 'access' => user_access('administer handshakes'),
166 'type' => MENU_CALLBACK,
167 );
168
169 $items[] = array(
170 'path' => 'admin/user/nf_handshake/make_grouping',
171 'title' => t('Make groupings'),
172 'callback' => 'drupal_get_form',
173 'callback arguments' => array('nf_handshake_make_groupings'),
174 'access' => user_access('administer handshakes'),
175 'type' => MENU_LOCAL_TASK,
176 'weight' => -4,
177 );
178
179 $items[] = array(
180 'path' => 'admin/user/nf_handshake/edit_group',
181 'title' => t('Edit group'),
182 'callback' => 'drupal_get_form',
183 'callback arguments' => array('nf_handshake_group_edit'),
184 'access' => user_access('administer handshakes'),
185 'type' => MENU_CALLBACK,
186 );
187
188 $items[] = array(
189 'path' => 'admin/user/nf_handshake/delete_group',
190 'title' => t('Delete group'),
191 'callback' => 'drupal_get_form',
192 'callback arguments' => array('nf_handshake_confirm_group_delete'),
193 'access' => user_access('administer handshakes'),
194 'type' => MENU_CALLBACK,
195 );
196
197 $items[] = array(
198 'path' => 'admin/user/nf_handshake/settings',
199 'title' => t('Misc settings'),
200 'callback' => 'drupal_get_form',
201 'callback arguments' => array('nf_handshake_settings'),
202 'access' => user_access('administer handshakes'),
203 'type' => MENU_LOCAL_TASK,
204 'weight' => -2,
205 );
206
207 $items[] = array( //administer flags set by the users
208 'path' => 'admin/user/nf_handshake_flags',
209 'title' => t('Handshake flag admin'),
210 'callback' => 'nf_handshake_flags',
211 'access' => user_access('administer handshakes'),
212 'description' => t('Users can flag handshake requests as SPAM and other things. The admin can mediate these instances here.'),
213 'type' => MENU_NORMAL_ITEM,
214 );
215
216 $items[] = array( //tab to take us to main flag administer page
217 'path' => 'admin/user/nf_handshake_flags/overview',
218 'title' => t('Overview'),
219 'access' => user_access('administer handshakes'),
220 'type' => MENU_DEFAULT_LOCAL_TASK,
221 'weight' => -10,
222 );
223
224 $items[] = array( //tab to take us to main flag administer page
225 'path' => 'admin/user/nf_handshake_flags/decisions',
226 'title' => t('Decisions'),
227 'callback' => 'nf_handshake_flag_decisions',
228 'access' => user_access('administer handshakes'),
229 'type' => MENU_LOCAL_TASK,
230 'weight' => -8,
231 );
232
233 $items[] = array(
234 'path' => 'admin/user/nf_handshake_flags/view',
235 'title' => t('Administer flag'),
236 'callback' => 'drupal_get_form',
237 'callback arguments' => array('nf_handshake_view_flag'),
238 'access' => user_access('administer handshakes'),
239 'type' => MENU_CALLBACK,
240 );
241
242 $items[] = array(
243 'path' => 'user/nf_handshake/initiate',
244 'title' => t('Initiate handshake'),
245 'callback' => 'drupal_get_form',
246 'callback arguments' => array('nf_handshake_initiate'),
247 'access' => user_access('intitiate handshake'),
248 'type' => MENU_CALLBACK,
249 );
250
251 $items[] = array(
252 'path' => 'user/nf_handshake/revoke_confirm',
253 'title' => t('Confirm handshake revoke'),
254 'callback' => 'drupal_get_form',
255 'callback arguments' => array('nf_handshake_revoke_confirm'),
256 'access' => user_access('view own handshakes'),
257 'type' => MENU_CALLBACK,
258 );
259
260 $items[] = array(
261 'path' => 'user/nf_handshake/extend_duration',
262 'title' => t('Extend handshake duration'),
263 'callback' => 'drupal_get_form',
264 'callback arguments' => array('nf_handshake_extend_duration'),
265 'access' => user_access('accept handshake'),
266 'type' => MENU_CALLBACK,
267 );
268
269 $items[] = array(
270 'path' => 'user/nf_handshake/request_extension',
271 'title' => t('Extend handshake duration'),
272 'callback' => 'nf_handshake_request_extention',
273 'access' => user_access('intitiate handshake'),
274 'type' => MENU_CALLBACK,
275 );
276
277 $items[] = array(
278 'path' => 'user/nf_handshake/flag_reply',
279 'title' => t('Respond to flagging'),
280 'callback' => 'drupal_get_form',
281 'callback arguments' => array('nf_handshake_flag_reply'),
282 'access' => user_access('intitiate handshake')|| user_access('accept handshake'),
283 'type' => MENU_CALLBACK,
284 );
285 }
286 else {
287 //-----------------------user-viewable menu itmes----------------------------------
288 $admin_access = user_access('administer users');
289 $access_access = user_access('administer access control');
290 $view_access = user_access('access user profiles');
291 if (arg(0) == 'user' && is_numeric(arg(1)) && arg(1) > 0) {
292 $account = user_load(array('uid' => arg(1)));
293 if ($user !== FALSE) {
294 // Always let a user view their own account
295 $view_access |= $user->uid == arg(1);
296 // Only admins can view blocked accounts
297 $view_access &= $account->status || $admin_access;
298
299 $items[] = array( //reroute users away from standard user profile page
300 'path' => 'user/' .arg(1),
301 'title' => t('View a user'),
302 'callback' => 'nf_handshake_view_user',
303 'callback arguments' => array(arg(1)),
304 'access' => $view_access,
305 'type' => MENU_CALLBACK,
306 );
307
308 $items[] = array(
309 'path' => 'user/' .arg(1). '/view',
310 'title' => t('View'),
311 'access' => $view_access,
312 'type' => MENU_DEFAULT_LOCAL_TASK,
313 'weight' => -10
314 );
315 }
316 }
317
318 //additions to user's own admin pages
319 $new_handshakes = nf_handshake_get_new_handshake_requests($user->uid);
320 $unanswered_handshakes = nf_handshake_get_read_handshake_requests($user->uid);
321 $flags_to_attend = nf_handshake_get_read_handshake_flags_iuid($user->uid);
322 $flags_to_attend += nf_handshake_get_read_handshake_flags_auid($user->uid);
323 $new = $new_handshakes + $flags_to_attend;
324 $items[] = array(
325 'path' => 'user/' .$user->uid. '/nf_handshake',
326 'title' => t('Handshakes'),
327 'callback' => 'drupal_get_form',
328 'callback arguments' => array('nf_handshake_view_contacts'),
329 'access' => user_access('view own handshakes'),
330 'type' => MENU_LOCAL_TASK,
331 );
332 //view handshake list
333 $items[] = array(
334 'path' => 'user/' .$user->uid. '/nf_handshake/view_contacts',
335 'title' => t('Contacts'),
336 'access' => user_access('view own handshakes'),
337 'type' => MENU_DEFAULT_LOCAL_TASK,
338 'weight' => -10,
339 );
340 $items[] = array(
341 'path' => 'user/' .$user->uid. '/nf_handshake/inbox',
342 'title' => t('Handshake inbox'). ($new ? ' (' .$new. ')' : ' -') . ($unanswered_handshakes ? ' (' .$unanswered_handshakes. ')' : ' -'),
343 'callback' => 'drupal_get_form',
344 'callback arguments' => array('nf_handshake_inbox'),
345 'access' => user_access('accept handshake'),
346 'type' => MENU_LOCAL_TASK,
347 'weight' => -6,
348 );
349 $items[] = array(
350 'path' => 'user/' .$user->uid. '/nf_handshake/search',
351 'title' => t('User search'),
352 'callback' => 'nf_handshake_search_view',
353 'access' => user_access('access user profiles'),
354 'type' => MENU_LOCAL_TASK,
355 'weight' => -4,
356 );
357
358 //view a handshake request
359 $items[] = array(
360 'path' => 'user/' .$user->uid. '/nf_handshake/view_hsr',
361 'title' => t('View request'),
362 'callback' => 'drupal_get_form',
363 'callback arguments' => array('nf_handshake_view_hsr'),
364 'access' => user_access('view own handshakes'),
365 'type' => MENU_CALLBACK,
366 );
367 }
368 return $items;
369 } // function nf_handshake_menu()
370
371 /**
372 * CRON to reject requests automatically if the user doesn't respond within a week (or a set time by the admin).
373 * CRON to expire old rejected requests; this will allow people to reinitiate handshakes with those that have rejected them.
374 */
375 function nf_handshake_cron() {
376 $settings = variable_get('nf_handshake_settings', array('initiate_expire_unit' => 'Weeks', 'initiate_expire_number' => 1, 'reject_expire_unit' => 'Months', 'reject_expire_number' => 6));
377 //Set unanswered handshake requests to rejected after the expiration date
378 $number = $settings['reject_expire_number'];
379 $unit = $settings['reject_expire_unit'];
380 switch ($unit) {
381 case 'Days':
382 $unit = 60*60*24;
383 break;
384 case 'Weeks':
385 $unit = 60*60*24*7;
386 break;
387 case 'Months':
388 $unit = 60*60*24*30;
389 break;
390 case 'Years':
391 $unit = 60*60*24*365;
392 break;
393 }
394
395 $sql = "SELECT auid, iuid, datestamp, duration FROM {nf_handshake} WHERE (hstatus = %d OR hstatus = %d) AND duration < %d";
396 $results = db_query($sql, NFHANDSHAKE_PENDING, NFHANDSHAKE_REVIEWED, time());
397 while ($result = db_fetch_object($results)) {
398 $entries['auid'][] = $result->auid;
399 $entries['iuid'][] = $result->iuid;
400 $entries['datestamp'][] = $result->datestamp;
401 }
402 $sql1 = "UPDATE {nf_handshake} SET duration = %d, hstatus = %d WHERE iuid= %d AND auid = %d";
403 $sql2 = "DELETE FROM {nf_handshake_manage} WHERE iuid= %d AND auid = %d";
404 if (!empty($entries['auid'])) {
405 foreach ($entries['auid'] as $key => $value) {
406 $duration = $entries['datestamp'][$key] + ($unit*$number);
407 $success1 = db_query($sql1, $duration, NFHANDSHAKE_REJECTED, $entries['iuid'][$key], $entries['auid'][$key]);
408 $success2 = db_query($sql2, $entries['iuid'][$key], $entries['auid'][$key]);
409 }
410 }
411 //Expire rejected handshakes NFHANDSHAKE_EXPIRED
412 $sql3 = "UPDATE {nf_handshake} SET hstatus = %d WHERE duration < %d AND hstatus = %d";
413 $success3 = db_query($sql3, NFHANDSHAKE_EXPIRED, time(), NFHANDSHAKE_REJECTED);
414 } // function nf_handshake_cron()
415
416 /**
417 * Implementation of hook_form_alter.
418 *
419 * Intercept the removal of a CCK field from a content type and make sure we get a change to react to it.
420 *
421 * @param string $form_id The ID of the form we need to adjust.
422 * @param array &$form A reference to the form to adjust so that we change the actual form.
423 */
424 function nf_handshake_form_alter($form_id, &$form) {
425 if ($form_id == '_content_admin_field_remove') {
426 $form['#submit'] = array('nf_handshake_remove_field_submit' => array(), '_content_admin_field_remove_submit' => array());
427 }
428 } // function nf_handshake_form_alter()
429
430 /**
431 * Our submit function so we can deal with removal of CCK fields from content types.
432 *
433 * @param sting $form_id The ID of the form to process.
434 * @param array $form_values The fields to process.
435 */
436 function nf_handshake_remove_field_submit($form_id, $form_values) {
437 if ($form_id == '_content_admin_field_remove') {
438 //first update references in the handshakes themselves
439 $sql = "SELECT * FROM {nf_handshake} ORDER BY iuid";
440 $results = db_query($sql);
441 while ($result = db_fetch_object($results)) {
442 $sql2 = "UPDATE {nf_handshake} SET hfields = '%s' WHERE iuid = %d and auid = %d";
443 $hfields = unserialize($result->hfields);
444 foreach ($hfields as $field => $val) {//test to see if this entry is from the affected content type
445 $exp_val = explode('::', $field);
446 $type_name = $exp_val[0];
447 $field_name = $exp_val[1];
448 if ($type_name == $form_values['type_name'] && $field_name == $form_values['field_name']) {
449 unset($hfields[$field]);
450 }
451 }
452 ksort($hefields);
453 $hfields = serialize($hfields);
454 $success = db_query($sql2, $hfields, $result->iuid, $result->auid);
455 }
456 //then update the variables stored in the variables table
457 $field_names_var = _nf_handshake_get_cckfieldnames();
458 $group_names_var = _nf_handshake_get_groupnames();
459 foreach ($field_names_var as $type => $the_rest) {
460 if ($type == $form_values['type_name']) {
461 foreach ($the_rest as $key => $value) {
462 if ($key == $form_values['field_name']) {
463 unset($field_names_var[$type][$key]);
464 }
465 }
466 }
467 }
468 ksort($field_names_var);
469 variable_set('nf_handshake_cckfieldnames', $field_names_var);
470 foreach ($group_names_var as $group => $the_rest) {
471 foreach ($the_rest as $type_field1 => $type_field2) {
472 $exp_val = explode('::', $type_field1);
473 $type = $exp_val[0];
474 $field = $exp_val[1];
475 if ($type == $form_values['type_name'] && $field == $form_values['field_name']) {
476 unset($group_names_var[$group][$type_field1]);
477 }
478 }
479 }
480 ksort($group_names_var);
481 variable_set('nf_handshake_groupnames', $group_names_var);
482 drupal_set_message(t('Handshake module has updated its references to the content type you changed.'));
483 }
484 return;
485 }
486
487 /**
488 * Respond to changes in content types.
489 *
490 * We don't do anything upon insertion of a new content type as we don't know if the user will turn it into a nodeprofile type or not.
491 * We must delete references to fields in content types that are deleted. We must update fields we use from content types we use if they
492 * are changed. Since we add a capital 'X' to the end of fieldnames that are part of an upgrade request, leave them intact.
493 *
494 * @param string $op The operation on the node type. Possibilities are 'insert', 'delete', and 'update'.
495 * @param object The node type object on which $op is being performed.
496 */
497 function nf_handshake_node_type($op, $info) {
498 switch ($op){
499 case 'delete':
500 //first update references in the handshakes themselves
501 $sql = "SELECT * FROM {nf_handshake} ORDER BY iuid";
502 $results = db_query($sql);
503 while ($result = db_fetch_object($results)) {
504 $hfields = array();
505 $sql2 = "UPDATE {nf_handshake} SET hfields = '%s' WHERE iuid = %d and auid = %d";
506 $hfields = unserialize($result->hfields);
507 foreach ($hfields as $field => $val) {//test to see if this entry is from the affected content type
508 $exp_val = explode('::', $field);
509 $type_name = $exp_val[0];
510 $field_name = $exp_val[1];
511 if ($type_name == $info->type) {
512 unset($hfields[$field]);
513 }
514 }
515 ksort($hfields);
516 $hfields = serialize($hfields);
517 $success = db_query($sql2, $hfields, $result->iuid, $result->auid);
518 }
519 //then update the variables stored in the variables table
520 $field_names_var = _nf_handshake_get_cckfieldnames();
521 $group_names_var = _nf_handshake_get_groupnames();
522 foreach ($field_names_var as $type => $the_rest) {
523 if ($type == $info->type) {
524 unset($field_names_var[$type]);
525 }
526 }
527 ksort($field_names_var);
528 variable_set('nf_handshake_cckfieldnames', $field_names_var);
529 foreach ($group_names_var as $group => $the_rest) {
530 foreach ($the_rest as $type_field1 => $type_field2) {
531 $exp_val = explode('::', $type_field1);
532 $type = $exp_val[0];
533 $field = $exp_val[1];
534 if ($type == $info->type) {
535 unset($group_names_var[$group][$type_field1]);
536 }
537 }
538 }
539 ksort($group_names_var);
540 variable_set('nf_handshake_groupnames', $group_names_var);
541 drupal_set_message(t('Handshake module has updated its references to the content type you changed.'));
542 break;
543 case 'update':
544 if (!empty($info->old_type) && $info->old_type != $info->type) {
545 //first update references in the handshakes themselves
546 $sql = "SELECT * FROM {nf_handshake} ORDER BY iuid";
547 $results = db_query($sql);
548 while ($result = db_fetch_object($results)) {
549 $sql2 = "UPDATE {nf_handshake} SET hfields = '%s' WHERE iuid = %d and auid = %d";
550 $hfields = unserialize($result->hfields);
551 foreach ($hfields as $field => $val) {//test to see if this entry is from the affected content type
552 $exp_val = explode('::', $field);
553 $type_name = $exp_val[0];
554 $field_name = $exp_val[1];
555 if ($type_name == $info->old_type) {//switch out the old name with the new
556 $old_type_field = $info->old_type. '::' .$field_name;
557 $new_type_field = $info->type. '::' .$field_name;
558 $temp_val = $hfields[$old_type_field];
559 unset($hfields[$old_type_field]);
560 if ($temp_val !== 0) {//leave any 'X' values intact.
561 $exp_val2 = explode('::', $temp_val);
562 $hfields[$new_type_field] = $info->type. '::' .$exp_val2[1];
563 }
564 else {
565 $hfields[$new_type_field] = 0;
566 }
567 }
568 }
569 ksort($hefields);
570 $hfields = serialize($hfields);
571 $success = db_query($sql2, $hfields, $result->iuid, $result->auid);
572 }
573 //then update the variables stored in the variables table
574 $field_names_var = _nf_handshake_get_cckfieldnames();
575 $group_names_var = _nf_handshake_get_groupnames();
576 foreach ($field_names_var as $type => $the_rest) {
577 if ($type == $info->old_type) {
578 $temp_data = $field_names_var[$type];
579 unset($field_names_var[$type]);
580 $field_names_var[$info->type] = $temp_data;
581 }
582 }
583 ksort($field_names_var);
584 variable_set('nf_handshake_cckfieldnames', $field_names_var);
585 foreach ($group_names_var as $group => $the_rest) {
586 foreach ($the_rest as $type_field1 => $type_field2) {
587 $exp_val = explode('::', $type_field1);
588 $type = $exp_val[0];
589 $field = $exp_val[1];
590 if ($type == $info->old_type) {
591 unset($group_names_var[$group][$type_field1]);
592 $group_names_var[$group][$info->type. '::' .$field] = $info->type. '::' .$field;
593 }
594 }
595 }
596 ksort($group_names_var);
597 variable_set('nf_handshake_groupnames', $group_names_var);
598 drupal_set_message(t('Handshake module has updated its references to the content type you changed.'));
599 }
600 break;
601 }
602 }
603
604 /**
605 * Implementation of hook_user. We need to respond to users being deleted and delete their entries from our tables
606 * in order to prevent orphan handshakes.
607 *
608 * @param string $op What kind of action is being performed.
609 * @param array $edit The array of form values submitted by the user.
610 * @param array $account The user object on which the operation is being performed.
611 * @param string $category The active category of user information being edited.
612 */
613 function nf_handshake_user($op, &$edit, &$account, $category = NULL) {
614 switch($op) {
615 case 'delete':
616 $uid = $account->uid;
617 $sql = "DELETE FROM {nf_handshake} WHERE auid = %d OR iuid = %d";
618 $sql2 = "DELETE FROM {nf_handshake_manage} WHERE auid = %d OR iuid = %d";
619 dq_query($sql, $uid);
620 dq_query($sql2, $uid);
621 break;
622 }
623 }
624 //-----------------------------------------Administrative Hooks and Functions-----------------------------------------
625 //-----------------------------------------Administrative Hooks and Functions-----------------------------------------
626 //-----------------------------------------Administrative Hooks and Functions-----------------------------------------
627
628 /**
629 * Callback function: Add options for the .
630 *
631 * @return string $output The HTML to be displayed.
632 */
633 function nf_handshake_main() {
634 $all_nodeprofiles = nodeprofile_get_types('names');
635 $all_groups = _nf_handshake_get_groupnames();
636 $selected_cck_fields = _nf_handshake_get_cckfieldnames();
637 ksort($selected_cck_fields);
638 ksort($all_groups);
639 $output = '';
640 $header = array(t('Content type'), t('Selected CCK fields'));
641 if (!empty($selected_cck_fields)) {
642 if (!empty($all_groups)) {
643 foreach ($all_groups as $key => $val) {
644 $rows = array();
645 foreach ($val as $set => $value) {
646 $split_value = explode('::', $value);
647 $type = $split_value[0];
648 $type_name = $all_nodeprofiles[$type];
649 $field_name = $split_value[1];
650 if ($type == 'Users table') {
651 $rows[] = array('<strong><em>' .$type. '</em><strong>', $field_name);
652 unset($selected_cck_fields['Users_table'][$field_name]);
653 }
654 else {
655 $rows[] = array('<em>' .$type_name. '</em>', $field_name);
656 unset($selected_cck_fields[$type][$field_name]);
657 }
658 if (empty($selected_cck_fields[$type])) {
659 unset($selected_cck_fields[$type]);
660 }
661 }
662 $fieldset = array(
663 '#type' => 'fieldset',
664 '#value' => theme('table', $header, $rows),
665 '#title' => t('Group: ') .$key,
666 '#description' => t('Fields that can be exchanged as equivalent.'),
667 '#collapsible' => TRUE,
668 '#collapsed' => FALSE,
669 '#weight' => 0,
670 );
671 $output .= theme('fieldset', $fieldset);
672 }
673 if (!empty($selected_cck_fields)) {
674 $rows = array();
675 foreach ($selected_cck_fields as $type => $set) {
676 if ($type == 'Users_table') {
677 foreach ($set as $key => $value) {
678 $rows[] = array('<strong><em>Users table</em></strong>', $value);
679 }
680 }
681 else {
682 $type_name = $all_nodeprofiles[$type];
683 foreach ($set as $key => $value) {
684 $rows[] = array('<em>' .$type_name. '</em>', $value);
685 }
686 }
687 }
688 $output .= theme('table', $header, $rows);
689 }
690 }
691 else {
692 $rows = array();
693 foreach ($selected_cck_fields as $type => $set) {
694 if ($type == 'Users_table') {
695 foreach ($set as $key => $value) {
696 $rows[] = array('<strong><em>Users table</em></strong>', $value);
697 }
698 }
699 else {
700 $type_name = $all_nodeprofiles[$type];
701 foreach ($set as $key => $value) {
702 $rows[] = array('<em>' .$type_name. '</em>', $value);
703 }
704 }
705 }
706 $output .= theme('table', $header, $rows);
707 }
708 }
709 else {
710 $output = t('You first need to select CCK fields that users can share, then make groups of those fields if you wish.');
711 }
712 return $output;
713 } // function nf_handshake_main()
714
715 /**
716 * Present the admin with a drop down of nodeprofile-related cck fields and allow him/her to select those that users may share.
717 *
718 * @return array $form The form to be rendered.
719 */
720 function nf_handshake_choose_cck_fields() {
721 $all_cck_fields = array();
722 $all_nodeprofiles = nodeprofile_get_types('names');
723 ksort($all_nodeprofiles);
724 $added_cck_fields = _nf_handshake_get_cckfieldnames();
725 $sql = "SELECT type_name, field_name FROM {node_field_instance} WHERE type_name = '%s' ORDER BY field_name";
726 foreach ($all_nodeprofiles as $key => $value) {
727 $results = db_query($sql, $key);
728 while ($result = db_fetch_object($results)) {
729 if (!(key_exists($result->type_name, $added_cck_fields) && key_exists($result->field_name, $added_cck_fields[$result->type_name]))) {
730 $all_cck_fields[$value][$result->type_name. '::' .$result->field_name] = $result->field_name;
731 }
732 }
733 }
734 //add user photo and email address from users table to $all_cck_fields
735 if (!(key_exists('Users_table', $added_cck_fields) && key_exists('mail', $added_cck_fields['Users_table']))) {
736 $all_cck_fields['Users_table']['mail'] = 'mail';
737 }
738 if (!(key_exists('Users_table', $added_cck_fields) && key_exists('picture', $added_cck_fields['Users_table']))) {
739 $all_cck_fields['Users_table']['picture'] = 'picture';
740 }
741 $form['cck_fields'] = array(
742 '#type' => 'select',
743 '#title' => t('Add profile-related CCK fields'),
744 '#options' => $all_cck_fields,
745 );
746 $form['submit'] = array(
747 '#type' => 'submit',
748 '#value' => t('Add CCK field'),
749 );
750 $form['options'] = array(
751 '#type' => 'value',
752 '#value' => $all_cck_fields,
753 );
754 $form['info'] = array(
755 '#type' => 'item',
756 '#value' => t('Select the CCK fields that you would like to allow users to share with each other.'),
757 );
758 return $form;
759 } // function nf_handshake_choose_cck_fields()
760
761 /**
762 * Submit the table name to be saved to the table list.
763 *
764 * @param string $form_id
765 * @param mixed $form_values
766 * @return string The path to send the user to.
767 */
768 function nf_handshake_choose_cck_fields_submit($form_id, $form_values) {
769 if ($form_values['op'] == t('Add CCK field')) {
770 $selection = explode('::', $form_values['cck_fields']);
771 $added_cck_fields = _nf_handshake_get_cckfieldnames();
772 if (isset($selection[1])) {
773 $added_cck_fields[$selection[0]][$selection[1]] = $selection[1];
774 }
775 else {
776 $added_cck_fields['Users_table'][$selection[0]] = $selection[0];
777 }
778 variable_set('nf_handshake_cckfieldnames', $added_cck_fields);
779 drupal_set_message(t('The CCK field list has been updated.'));
780 }
781 return 'admin/user/nf_handshake/choose_cck_fields';
782 } // function nf_handshake_choose_cck_fields_submit()
783
784 /**
785 * Theme for the cck field chooser.
786 *
787 * @param array $form The form to render.
788 * @return string $output The HTML to be displayed.
789 */
790 function theme_nf_handshake_choose_cck_fields($form) {
791 $all_nodeprofiles = nodeprofile_get_types('names');
792 $header = array(t('Content type'), array('data' => t('Selected CCK fields'), 'colspan' => 2));
793 $selected_cck_fields = _nf_handshake_get_cckfieldnames();
794 ksort($selected_cck_fields);
795 $rows = array();
796 if (!empty($selected_cck_fields)) {
797 foreach ($selected_cck_fields as $type => $set) {
798 if ($type == 'Users_table') {
799 foreach ($set as $key => $value) {
800 $delete = l(t('delete'), 'admin/user/nf_handshake/delete_cck_fields/' .$type. '::' .$value);
801 $rows[] = array('<strong><em>Users table</em></strong>', $value, $delete);
802 }
803 }
804 else {
805 $type_name = $all_nodeprofiles[$type];
806 foreach ($set as $key => $value) {
807 $delete = l(t('delete'), 'admin/user/nf_handshake/delete_cck_fields/' .$type. '::' .$value);
808 $rows[] = array('<em>' .$type_name. '</em>', $value, $delete);
809 }
810 }
811 }
812 }
813 $rows[] = array(drupal_render($form['cck_fields']), drupal_render($form['submit']), '');
814 $output = drupal_render($form['info']);
815 $output .= theme('table', $header, $rows);
816 $output .= drupal_render($form);
817
818 return $output;
819 } //function theme_nf_handshake_choose_cck_fields()
820
821 /**
822 * Returns a confirmation page for deleting a cck field from the list (not the actual field).
823 *
824 * @param integer $name Name of cck field to be deleted; passed in from path.
825 * @return array $form The name is passed to the submit.
826 */
827 function nf_handshake_confirm_cck_fields_delete($name = NULL) {
828 if ($name == NULL) {
829 drupal_goto('admin/user/nf_handshake/choose_cck_fields');
830 return;
831 }
832 if ($admin = user_access('administer handshakes')) {
833 $type_and_field = explode('::', $name);
834 $form['type'] = array(
835 '#type' => 'value',
836 '#value' => $type_and_field[0],
837 );
838 $form['name'] = array(
839 '#type' => 'value',
840 '#value' => $type_and_field[1],
841 );
842 $return_address = 'admin/user/nf_handshake/choose_cck_fields';
843 $form = confirm_form($form, t('Are you sure you want to delete the CCK field %name from the admin list?',
844 array('%name' => $type_and_field[1])), $return_address,
845 t('Deleting a CCK field from the list here will not delete the actual field. This action cannot be undone.'), t('Delete'), t('Cancel'));
846 return $form;
847 }
848 } // function nf_handshake_confirm_cck_fields_delete()
849
850 /**
851 * Implementation of forms api _submit call. Deletes a cck field from the variable list after confirmation.
852 *
853 * @param string $form_id
854 * @param mixed $form_values
855 * @return string $return_address The path to return to after we've deleted the table.
856 */
857 function nf_handshake_confirm_cck_fields_delete_submit($form_id, $form_values) {
858 $added_cck_fields = _nf_handshake_get_cckfieldnames();
859 unset($added_cck_fields[$form_values['type']][$form_values['name']]);
860 if (empty($added_cck_fields[$form_values['type']])) {
861 unset($added_cck_fields[$form_values['type']]);
862 }
863 variable_set('nf_handshake_cckfieldnames', $added_cck_fields);
864 if (!isset($added_cck_fields[$form_values['name']][$form_values['name']])) {
865 drupal_set_message(t('The cck field %name has been removed from the administration list.', array('%name' => $form_values['name'])));
866 watchdog('nf_handshake', t('nf_handshake: deleted %name from nf_handshake_cckfieldnames list.', array('%name' => $form_values['name'])));
867 }
868 $return_address = 'admin/user/nf_handshake/choose_cck_fields';
869 return $return_address;
870 } // function nf_handshake_confirm_cck_fields_delete_submit()
871
872 /**
873 * Allow the admin to group fields together.
874 *
875 * If there are two fields that are related that may
876 * not be in common between two nodeprofile sets, but which users should be able to share, they can be grouped together. For example, say
877 * that nodeprofile A is set up for businesses and nodeprofile B is set up for customers and they each have addresses in their profile nodes,
878 * but in a different format; without groupings, you would have to name one address field with one name and the other address field with another name.
879 * Users would check the box stating they want to share their address with the other user, but would be unable to because the second user's field
880 * had a different name. By grouping them together, an association is made such that this problem is overcome.
881 *
882 * @return array $form The form to be rendered.
883 */
884 function nf_handshake_make_groupings() {
885 $all_groups = _nf_handshake_get_groupnames();
886 $added_cck_fields = _nf_handshake_get_cckfieldnames();
887 $form['note'] = array(
888 '#type' => 'item',
889 '#title' => t('Group similar fields together'),
890 '#description' => t('This allows you to group logical fields together for exchange as a group. See the README for details.'),
891 );
892 $not_field_options = array();
893 $field_options = array();
894 foreach ($all_groups as $group => $types) {
895 if (!empty($types)) {
896 foreach ($types as $type => $field) {
897 $not_field_options[$type] = $field;
898 }
899 }
900 }
901 $all_nodeprofiles = nodeprofile_get_types('names');
902 foreach ($added_cck_fields as $type => $the_rest) {
903 if (!empty($the_rest)) {
904 foreach ($the_rest as $field => $val) {
905 if (!key_exists($type. '::' .$val, $not_field_options)) {
906 if ($type == 'Users_table') {
907 $field_options[$type. '::' .$val] = 'Users table::' .$val;
908 }
909 else {
910 $field_options[$type. '::' .$val] = $all_nodeprofiles[$type]. '::' .$val;
911 }
912 }
913 }
914 }
915 }
916 foreach ($all_groups as $group => $types) {
917 $form[$group] = array(
918 '#tree' => TRUE,
919 );
920 $form[$group]['new_field'] = array(
921 '#type' => 'select',
922 '#title' => t('fields'),
923 '#options' => $field_options,
924 '#default' => NULL,
925 );
926 $form[$group]['submit'] = array(
927 '#type' => 'submit',
928 '#value' => t('Add fieldname to ') .$group,
929 );
930 }
931 $form['groupname'] = array(
932 '#type' => 'textfield',
933 '#size' => 20,
934 '#maxlength' => 64,
935 );
936 $form['gsubmit'] = array(
937 '#type' => 'submit',
938 '#value' => t('Add group'),
939 );
940 return $form;
941 } // function nf_handshake_make_groupings()
942
943 /**
944 * Submit the group name and any field associations.
945 *
946 * @param string $form_id
947 * @param mixed $form_values
948 * @return string The path to send the user to.
949 */
950 function nf_handshake_make_groupings_submit($form_id, $form_values) {
951 if ($form_values['op'] == t('Add group')) {
952 $all_groups = _nf_handshake_get_groupnames();
953 $all_groups[$form_values['groupname']] = array();
954 variable_set('nf_handshake_groupnames', $all_groups);
955 drupal_set_message(t('The group name has been added.'));
956 }
957 else {
958 $op = substr($form_values['op'], 17);
959 $all_groups = _nf_handshake_get_groupnames();
960 if (!in_array($form_values[$op]['new_field'], $all_groups[$op])) {
961 $all_groups[$op][$form_values[$op]['new_field']] = $form_values[$op]['new_field'];
962 }
963 ksort($all_groups[$op]);
964 variable_set('nf_handshake_groupnames', $all_groups);
965 drupal_set_message(t('The group list has been updated.'));
966 }
967
968 return 'admin/user/nf_handshake/make_grouping';
969 } // function nf_handshake_make_groupings_submit()
970
971 /**
972 * Theme for the group maker.
973 *
974 * <p>The purpose of groups was explained elsewhere. Here we add new groups via a textfield and associated button. Groups are presented as fieldsets
975 * and fields can be added to them. Also, the groups can be deleted. Fields not in a group are in the 'no_group' group.</p>
976 * @param array $form The form to render.
977 * @return string $output The HTML to render the page.
978 */
979 function theme_nf_handshake_make_groupings($form) {
980 $output = '';
981 $output_array = array();
982 $all_groups = _nf_handshake_get_groupnames();
983 $all_nodeprofiles = nodeprofile_get_types('names');
984 $header = array(array('data' => t('Selected fieldnames'), 'colspan' => 2));
985 $output .= drupal_render($form['note']);
986 if (!empty($all_groups)) {
987 foreach ($all_groups as $group => $name) {
988 $rows = array();
989 if (!empty($name)) {
990 foreach ($name as $key => $value) {
991 $exp_val = explode('::', $value);
992 $type = $exp_val[0];
993 $val = $exp_val[1];
994 if ($exp_val[0] == 'Users table') {
995 $delete = l(t('delete'), 'admin/user/nf_handshake/delete_group/' .$group. '/Users_table::' .$val);
996 $rows[] = array('Users table::' .$val, $delete);
997 }
998 else {
999 $delete = l(t('delete'), 'admin/user/nf_handshake/delete_group/' .$group. '/' .$value);
1000 $rows[] = array($all_nodeprofiles[$type]. '::' .$val, $delete);
1001 }
1002 }
1003 }
1004 $edit = l(t('edit group'), 'admin/user/nf_handshake/edit_group/' .$group);
1005 $delete = l(t('delete group'), 'admin/user/nf_handshake/delete_group/' .$group);
1006 $rows[] = array($edit, $delete);
1007 if ($form[$group]['new_field']['#options'] == array()) {
1008 unset($form[$group]['new_field']);
1009 unset($form[$group]['submit']);
1010 }
1011 else {
1012 $rows[] = array(drupal_render($form[$group]['new_field']), drupal_render($form[$group]['submit']));
1013 }
1014 $fieldset = array(
1015 '#type' => 'fieldset',
1016 '#value' => theme('table', $header, $rows),
1017 '#title' => t('Group: ') .$group,
1018 '#description' => t('Place fields into this group that should be exchanged together.'),
1019 '#collapsible' => TRUE,
1020 '#collapsed' => TRUE,
1021 '#weight' => 0,
1022 );
1023 $output_array[] = theme('fieldset', $fieldset);
1024 }
1025 ksort($output_array);
1026 foreach ($output_array as $out) {
1027 $output .= $out;
1028 }
1029 }
1030 $last_row[] = array(drupal_render($form['groupname']), drupal_render($form['gsubmit']));
1031 $output .= theme('table', array(), $last_row);
1032 $output .= drupal_render($form);
1033 return $output;
1034 } //function theme_nf_handshake_make_groupings()
1035
1036 /**
1037 * Edit the group name
1038 *
1039 * @param string $name The group to edit
1040 * @return mixed Blank if no group name specified, $form if specified
1041 */
1042 function nf_handshake_group_edit($name = NULL) {
1043 if ($name == NULL) {
1044 drupal_goto('admin/user/nf_handshake/make_grouping');
1045 return;
1046 }
1047 if ($admin = user_access('administer handshakes')) {
1048 $added_groups = _nf_handshake_get_groupnames();
1049 $form['name'] = array(
1050 '#type' => 'textfield',
1051 '#title' => t('Group name'),
1052 '#default_value' => $name,
1053 '#size' => 20,
1054 '#required' => TRUE,
1055 '#maxlength' => 64,
1056 );
1057 $form['old_name'] = array(
1058 '#type' => 'value',
1059 '#value' => $name,
1060 );
1061 $form['submit'] = array(
1062 '#type' => 'submit',
1063 '#value' => t('Save group name'),
1064 );
1065 return $form;
1066 }
1067 } // function nf_handshake_group_edit()
1068
1069 /**
1070 * Validate the group name before saving it
1071 *
1072 * @param string $form_id
1073 * @param mixed $form_values
1074 */
1075 function nf_handshake_group_edit_validate($form_id, $form_values) {
1076 if ($form_values['name']) {
1077 if ($form_values['op'] == t('Save group name')) {
1078 if (!$form_values['name']) {
1079 form_set_error('name', t('You must specify a valid group name.'));
1080 }
1081 }
1082 }
1083 else {
1084 form_set_error('name', t('You must specify a valid group name.'));
1085 }
1086 } // function nf_handshake_group_edit_validate()
1087
1088 /**
1089 * Submit the group name to be saved, to the variable.
1090 *
1091 * @param string $form_id
1092 * @param mixed $form_values
1093 * @return string The path to se