Handle node/add/case?gids[]=$pid use case in a way that works
[drupal_ctog.git] / ctog.module
blob56d1ba1b61c41759eae714e315fd8a192ed9ea39
1 <?php
2 // $Id$
4 /**
5  * @file
6  * Keeps CT projects in sync with OG groups.
7  */
9 /**
10  * Implementation of hook_help().
11  */
12 function ctog_help($path, $arg) {
13   $output = '';
14   switch ($path) {
15   case 'admin/help#ctog':
16     $output = '<p>'. t('Keeps CT projects in sync with OG groups.') .'</p>';
17     break;
18   }
19   return $output;
22 /**
23  * Implementation of hook_menu().
24  */
25 function ctog_menu() {
26   $items = array();
27   $items['ctog/ahah'] = array(
28     'page callback' => 'ctog_ahah',
29     'access callback' => 'ctog_access_ahah',
30     'type' => MENU_CALLBACK,
31   );
32   return $items;
35 /**
36  * Decides if one is eligible for the AHAH callback.
37  */
38 function ctog_access_ahah() {
39   global $user;
40   if (isset($user->og_groups) && !empty($user->og_groups)) {
41     return TRUE;
42   }
43   return FALSE;
46 /**
47  * AHAH callback to update the list of assignees.
48  *
49  * @param $_POST['casetracker']['pid']
50  *   ID of the Case Tracker project the assignees are needed.
51  * @param $_POST['form_build_id']
52  *   Build ID of the form to be updated in cache.
53  * @param $_POST['form_id']
54  *   ID of the form to be updated in cache.
55  */
56 function ctog_ahah() {
57   $assignees = array(t('Unassigned') => t('Unassigned'));
58   $result = db_query('SELECT name FROM {users} u INNER JOIN {og_uid} USING (uid) WHERE nid = %d AND is_active = 1 AND status <> 0 ORDER BY name', $_POST['casetracker']['pid']);
59   while ($name = db_result($result)) {
60     $assignees[$name] = $name;
61   }
62   // Update the cached form (if it's found).
63   $form_state = array('submitted' => FALSE);
64   $form_build_id = $_POST['form_build_id'];
65   if (!$form = form_get_cache($form_build_id, $form_state)) {
66     // Probably hacking attempt, do nothing (for now).
67     drupal_json(FALSE);
68     return;
69   }
70   $form['casetracker']['assign_to']['#options'] = $assignees;
71   form_set_cache($form_build_id, $form, $form_state, TRUE);
72   $form += array(
73     '#post' => $_POST,
74     '#programmed' => FALSE,
75   );
76   // Rebuild the form.
77   $form = form_builder($_POST['form_id'], $form, $form_state);
78   $subform = $form['casetracker']['assign_to'];
79   unset($subform['#prefix'], $subform['#suffix']); // Prevent duplicate wrappers.
80   $subform['#attributes']['class'] = empty($subform['#attributes']['class']) ? 'ahah-new-content' : $subform['#attributes']['class'] .' ahah-new-content';
81   $output = drupal_render($subform);
82   drupal_json(array('status' => TRUE, 'data' => $output));
85 /**
86  * Implementation of hook_form_alter().
87  */
88 function ctog_form_alter(&$form, $form_state, $form_id) {
89   // Make sure that CT case nodes are posted only into one OG group: the one
90   // which is the CT project.
91   // If we want to completely hide the group selection fieldset, we must be
92   // sure that ctog.module has greater weight than og_access.module (see
93   // ctog.install), so this module's hook_form_alter() is triggered AFTER
94   // og_access.module's one.
95   if (isset($form['#node']) && $form_id == $form['#node']->type .'_node_form') {
96     $node = $form['#node'];
97     if (casetracker_is_case($node->type) && og_is_group_post_type($node->type)) {
98       _ctog_form_alter($form);
99       // The OG group membership is governed only by ctog_node_form_submit()
100       // based on the CT project membership. If we 'hide' the OG 'Groups'
101       // fieldset by this line, this is easily done.
102       $form['og_nodeapi']['#type'] = 'value';
103       // Additionally, we have to trick OG a little bit: tell it that the
104       // first OG group/CT project is selected, and reset it in our own submit
105       // handler.
106       if ($form['casetracker']['pid']['#default_value']) {
107         // If CT ships a #default_value (eg. we are on a node/%/edit page),
108         // use that one as CT project / OG group ID - as a rule of thumb.
109         $pid = $form['casetracker']['pid']['#default_value'];
110       }
111       else if (!empty($form['og_nodeapi']['visible']['og_groups']['#default_value'])) {
112         // If CT has not set a project ID for us yet (eg. submitting a new
113         // CT issue / OG group node), but OG set a default (eg. submitting a
114         // new OG group node to a/some specific OG group), use that/first one
115         // as CT project / OG group ID - as a rule of index finger.
116         reset($form['og_nodeapi']['visible']['og_groups']['#default_value']);
117         $pid = each($form['og_nodeapi']['visible']['og_groups']['#default_value']);
118         $pid = $pid['value'];
119         $form['casetracker']['pid']['#default_value'] = $pid;
120       }
121       else {
122         // If there is no sensible default, just use the first OG group listed
123         // as CT project / OG group ID - as the last resort.
124         if (isset($form['casetracker']['pid']['#options'])) {
125           reset($form['casetracker']['pid']['#options']);
126           $pid = each($form['casetracker']['pid']['#options']);
127           $pid = $pid['key'];
128         }
129         else {
130           $pid = $form['casetracker']['pid']['#value'];
131         }
132       }
133       $form['og_nodeapi']['visible']['og_groups']['#default_value'] = array($pid => $pid);
134       $form['og_nodeapi']['visible']['og_groups']['#type'] = 'value';
135       $form['#validate'][] = 'ctog_ctog_form_validate';
136       $form['#submit'][] = 'ctog_node_form_submit';
137     }
138   }
139   if (($form_id == 'comment_form') && isset($form['casetracker'])) {
140     // This one cannot go to hook_form_FORM_ID_alter(), as that one is called
141     // too early, and casetracker.module would overwrite the stuff we are
142     // altering here.
143     _ctog_form_alter($form);
144   }
148  * Additional validate handler for CT & OG (case && group post) node and
149  * comment forms.
150  */
151 function ctog_ctog_form_validate($form, &$form_state) {
152   if ($uid = db_result(db_query("SELECT uid FROM {users} WHERE name = '%s' AND status <> 0", $form_state['values']['casetracker']['assign_to']))) {
153     if (!og_is_group_member($form_state['values']['casetracker']['pid'], TRUE, $uid)) {
154       // Ensure that the (new) assignee (if any) is a member of the (new)
155       // project.
156       form_set_error('casetracker][assign_to', t('This user is not a member of the selected group.'));
157     }
158   }
162  * Additional submit handler for CT & OG (case && group post) node.
163  */
164 function ctog_node_form_submit($form, &$form_state) {
165   // The OG group selection part of the case/group post node submit form has
166   // been removed by setting it's #type to 'value'. Now we are dealing with
167   // the group selection part of that form by setting the OG group id of the
168   // new node _only_ to it's CT project id, _and_ making it private.
169   foreach ($form_state['values']['og_groups'] as $key => $value) {
170     $form_state['values']['og_groups'][$key] = 0;
171   }
172   $pid = $form_state['values']['casetracker']['pid'];
173   $form_state['values']['og_groups'][$pid] = $pid;
174   $form_state['values']['og_public'] = 0;
175   $to = node_load($pid);
176   watchdog('ctog', '%title has been submitted to %to.', array('%title' => $node->title, '%to' => $to->title));
180  * Implementation of hook_form_comment_form_alter().
181  */
182 function ctog_form_comment_form_alter(&$form, $form_state) {
183   $node = isset($form['nid']['#value']) ? node_load($form['nid']['#value']) : NULL;
184   if (!$node) {
185     // Hopefully there is no comment form without a corresponding node, but
186     // bail out early if it's the case. ;)
187     return;
188   }
189   if (casetracker_is_case($node->type) && og_is_group_post_type($node->type)) {
190     $form['#validate'][] = 'ctog_ctog_form_validate';
191     $form['#submit'][] = 'ctog_comment_form_submit';
192   }
196  * Additional submit handler for CT & OG (case && group post) comment.
197  */
198 function ctog_comment_form_submit($form, &$form_state) {
199   // $form['casetracker']['pid']['#default_value'] is the old OG group id.
200   // $form_state['values']['casetracker']['pid'] is the new CT project id.
201   // If they differ (ie. CT project id has been changed by this comment), set
202   // the OG group id of the node accordingly.
203   if ($form['casetracker']['pid']['#default_value'] != $form_state['values']['casetracker']['pid']) {
204     $node = $form['#node'];
205     $node->og_groups = array($form_state['values']['casetracker']['pid']);
206     og_save_ancestry($node);
207     $from = node_load($form['casetracker']['pid']['#default_value']);
208     $to = node_load($form_state['values']['casetracker']['pid']);
209     watchdog('ctog', '%title has been moved from %from to %to.', array('%title' => $node->title, '%from' => $from->title, '%to' => $to->title));
210   }
214  * Helper function for form_alters.
215  */
216 function _ctog_form_alter(&$form) {
217   if (isset($form['casetracker'])) {
218     // Assignee should be select instead of radios.
219     $form['casetracker']['assign_to']['#type'] = 'select';
220     if (!empty($form['og_nodeapi']['visible']['og_groups']['#default_value'])) {
221       // If OG has set a default (eg. submitting a new OG group node to a/some
222       // specific OG group), use that/first one as CT project / OG group ID -
223       // as a rule of thumb.
224       // Add the AHAH magic.
225       $form['casetracker']['pid']['#ahah'] = array(
226         'event' => 'change',
227         'path' => 'ctog/ahah',
228         'wrapper' => 'edit-casetracker-assign-to-wrapper',
229         'method' => 'replace',
230       );
231       reset($form['og_nodeapi']['visible']['og_groups']['#default_value']);
232       $pid = each($form['og_nodeapi']['visible']['og_groups']['#default_value']);
233       $pid = $pid['value'];
234       $form['casetracker']['pid']['#default_value'] = $pid;
235     }
236     else if (isset($form['casetracker']['pid']['#options'])) {
237       // Add the AHAH magic.
238       $form['casetracker']['pid']['#ahah'] = array(
239         'event' => 'change',
240         'path' => 'ctog/ahah',
241         'wrapper' => 'edit-casetracker-assign-to-wrapper',
242         'method' => 'replace',
243       );
244       reset($form['casetracker']['pid']['#options']);
245       $pid = each($form['casetracker']['pid']['#options']);
246       $pid = $pid['key'];
247     }
248     else {
249       $pid = $form['casetracker']['pid']['#value'];
250     }
251     $pid = !empty($form['casetracker']['pid']['#default_value']) ? $form['casetracker']['pid']['#default_value'] : $pid;
252     // Reset the list of available assignees to members of the selected
253     // project (basically this is what the AHAH callback does, anyway).
254     $assignees = array(t('Unassigned') => t('Unassigned'));
255     $result = db_query('SELECT name FROM {users} u INNER JOIN {og_uid} USING (uid) WHERE nid = %d AND is_active = 1 AND status <> 0 ORDER BY name', $pid);
256     while ($name = db_result($result)) {
257       $assignees[$name] = $name;
258     }
259     $form['casetracker']['assign_to']['#options'] = $assignees;
260   }