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

Contents of /contributions/modules/og_content_type_admin/og_content_type_admin.module

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


Revision 1.16 - (show annotations) (download) (as text)
Mon Oct 6 14:53:32 2008 UTC (13 months, 3 weeks ago) by paulbooker
Branch: MAIN
CVS Tags: HEAD
Changes since 1.15: +38 -45 lines
File MIME type: text/x-php
further changes to development release but there are still problems with applying access level privileges
1 <?php
2 /**
3 * This is the og_content_type_admin module for use with Organic Groups.
4 *
5 * <p>This file contains information on the og_content_type_admin module. This module adds
6 * to OG the ability to restrict which content types can be used by each group.</p>
7 * <p>In the site admin interface, the admin can select which content types are available
8 * outside of groups. The admin can also set the default content types that are available
9 * to new user-created groups. The admin can set which content types are available to individual
10 * groups as well. Lastly, the admin can set content types as 'required' - see below for more on
11 * that.</p>
12 * <p>So far as the OG owner is concerned, (s)he will see a listing of content types that have
13 * been made available to the group. The types can be individually (de)activated so that the group
14 * doesn't have to use types the owner doesn't feel the group needs. However, the owner can always
15 * create content of these deactivated types, and users can view that content. Those types that
16 * were marked as 'required' by the site admin will always be usable by the group members and
17 * cannot be deactivated by the group owner.</p>
18 *
19 * @version $Id: og_content_type_admin.module,v 1.15 2008/10/01 22:33:38 paulbooker Exp $;
20 * @package OG_CTA
21 * @category NeighborForge
22 * @author Ryan Constantine
23 * @filesource
24 * @license http://www.gnu.org/licenses/gpl.txt GNU_GENERAL_PUBLIC_LICENSE
25 * @link none yet
26 * TODO it seems that changing the title of the Create content menu item changes in the menu table,
27 * but doesn't change the text displayed; why?
28 * TODO add a button on the site-wide portion of assignment page to delete an entry from node_type
29 * since our list of available content_types comes from there (node_get_types) and it isn't accurate.
30 * only show the button if the "module_invoke_all('node_info');" doesn't have a matching entry in
31 * the result from "node_get_types". this will also place buttons next to user-created content types,
32 * but I don't see how to differentiate. this will still leave "content_type_XX" tables that probably
33 * shouldn't be there.
34 */
35
36 /**
37 * Constants to indicate whether a content type is assigned to a group.
38 */
39 define('NOT_ASSIGNED_TO_GROUP', 0);
40 define('ASSIGNED_TO_GROUP', 1);
41
42 /**
43 * Constants to indicats whether a content type is activated/deactivated/required.
44 */
45 define('DEACTIVATED', 0);
46 define('ACTIVATED', 1);
47 define('REQUIRED', 2);
48
49 /**
50 * Implementation of hook_help
51 *
52 * Display help and module information
53 * @param string section which section of the site we're displaying help
54 * @return help text for section
55 */
56 function og_content_type_admin_help($path, $arg) {
57
58 $output = '';
59 switch ($path) {
60 case "admin/help#og_content_type_admin":
61 $output = '<p>' . t("Allows the restriction of the use of content types by organic groups.
62 Site admins can setup which content types are available site-wide (outside groups), to new groups, and can assign types to individual groups.
63 Group owners can then activate or deactivate the types for use in their group."). '</p>';
64 break;
65 }
66
67 return $output;
68 } // function og_content_type_admin_help()
69
70 /**
71 * Implementation of hook_perm
72 *
73 * Valid permissions for this module
74 * @return array An array of valid permissions for the onthisdate module
75 */
76 function og_content_type_admin_perm() {
77
78 return array('administer og content types');
79 } // function og_content_type_admin_perm()
80
81 /**
82 * Implementation of hook_menu
83 *
84 * The menu item(s) for this module.
85 * @param boolean $may_cache Whether the menu item can be cached or not
86 * @return array An array of arrays, to add menu entries to the system menu.
87 */
88 function og_content_type_admin_menu() {
89 global $user, $_menu;
90 $items = array();
91
92 $items['admin/og/og_content_types'] = array( //adminster which content types are assigned to which groups and the site in general
93 'title' => t('OG Content Types'),
94 'page callback' => 'drupal_get_form',
95 'page arguments' => array('og_content_type_admin_main'),
96 'access arguments' => array('administer og content types'),
97 'description' => t('Administer which content types can be used by site-wide and by each Organic Group.'),
98 'type' => MENU_NORMAL_ITEM,
99 );
100
101 $items['admin/og/og_content_types/overview'] = array( //tab to take us to main administer page
102 'title' => t('Overview'),
103 'access arguments' => array('administer og content types'),
104 'type' => MENU_DEFAULT_LOCAL_TASK,
105 'weight' => -10,
106 );
107
108 $items['admin/og/og_content_types/admin'] = array( //assign and/or make required content types for each group under administration
109 'title' => t('Assign Content Types'),
110 'page callback' => 'drupal_get_form',
111 'page arguments' => array('og_content_type_admin_admin'),
112 'access arguments' => array('administer og content types'),
113 'type' => MENU_LOCAL_TASK,
114 );
115
116 $items['admin/og/og_content_types/delete'] = array( //delete a group from separate content type management and revert to defaults
117 'title' => t('Delete'),
118 'page callback' => 'drupal_get_form',
119 'page arguments' => array('og_content_type_admin_confirm_delete'),
120 'access arguments' => array('administer og content types'),
121 'type' => MENU_CALLBACK,
122 );
123
124 $items['node/%/ogct'] = array(
125 'title' => t('Content Types'),
126 'page callback' => 'drupal_get_form',
127 'page arguments' => array('og_content_type_admin_owner', 1),
128 'access callback' => '_og_content_type_admin_is_admin_access_callback',
129 'access arguments' => array(1),
130 'weight' => 6,
131 'type' => MENU_LOCAL_TASK
132 );
133 return $items;
134 } // function og_content_type_admin_menu()
135
136 function _og_content_type_admin_is_admin_access_callback($nid){
137 $group = node_load($nid);
138 //$return = (isset($group->og_selective) && _og_content_type_admin_is_admin($group)) ? TRUE : FALSE;
139 return TRUE;
140 return $return;
141 }
142
143 /**
144 * Implementation of hook_theme().
145 */
146 function og_content_type_admin_theme() {
147 return array(
148 'og_content_type_admin_main' => array(
149 'arguments' => array('form' => NULL),
150 ),
151 'og_content_type_admin_admin' => array(
152 'arguments' => array('form' => NULL),
153 ),
154 'og_content_type_admin_owner' => array(
155 'arguments' => array('form' => NULL),
156 ),
157 );
158 }
159
160 /**
161 * Implementation of hook_og_create_links().
162 */
163 function og_content_type_admin_og_create_links($group) {
164 global $user;
165 $links = array();
166 if ($group) {
167 if ((_og_content_type_admin_is_admin($group) && !variable_get('og_content_type_admin_no_change', 0)) || $user->uid == 1) {
168 $links[] = l(t('Manage group content types'), "node/$group->nid/ogct", array('title' => t('Lets you decide which content types your group\'s users can create.')));
169 }
170 }
171 return $links;
172 } // function og_content_type_admin_og_create_links()
173
174 //Site administration section---------------------------------------------------------------------------------
175 //This section is only for administration forms and form processing
176
177 /**
178 * Callback function: Add groups to administer the content types for.
179 *
180 * @param integer $gid
181 * The GID of the group.
182 * @return mixed
183 */
184 function og_content_type_admin_main($gid = NULL) {
185 if ($admin = user_access('administer og content types')) {
186 $options = og_all_groups_options();
187 $added = _og_content_type_admin_get_added();
188 foreach ($added as $group_id => $name) {//remove from the select, groups we're already working with
189 if (array_key_exists($group_id, $options)) {
190 unset($options[$group_id]);
191 }
192 }
193 if (count($options)) {
194 $form['group'] = array(
195 '#type' => 'select',
196 '#title' => t('Groups'),
197 '#options' => $options,
198 );
199 $form['submit'] = array(
200 '#type' => 'submit',
201 '#value' => t('Add group'),
202 );
203 }
204 }
205 return $form;
206 } // function og_content_type_admin_main()
207
208 /**
209 * Validate the group name before adding or saving it
210 *
211 * @param string $form
212 * @param mixed $form_state
213 * @return string
214 */
215 function og_content_type_admin_main_validate($form, &$form_state) {
216 $form_values = $form_state['values'];
217 if ($form_values['group']) {
218 //make sure the user isn't injecting something not on the list.
219 $check_options = _og_content_type_admin_get_added();
220 if ($form_values['op'] == t('Add group')) {
221 if (array_key_exists($form_values['group'], $check_options)) {
222 form_set_error('group', t('The group name %name is already added. Please choose another group name.', array('%name' => $form_values['group']['name'])));
223 }
224 }
225 }
226 else {
227 form_set_error('name', t('You must specify a valid group name.'));
228 }
229 }//function og_content_type_admin_main_validate()
230
231 /**
232 * Submit the group name and id to be added to the database.
233 *
234 * @param string $form
235 * @param mixed $form_state
236 * @return string
237 */
238 function og_content_type_admin_main_submit($form, &$form_state) {
239 $form_values = $form_state['values'];
240 if ($form_values['op'] == t('Add group')) {
241 $all_groups = og_all_groups_options();
242 db_query("INSERT INTO {og_content_type_admin} (gid, name) VALUES (%d, '%s')", $form_values['group'], $all_groups[$form_values['group']]);
243 drupal_set_message(t('The group has been added.'));
244 }
245 $form_state['redirect'] = 'admin/og/og_content_types';
246 } //function og_content_type_admin_main_submit()
247
248 /**
249 * Theme for the add page of the main function.
250 *
251 * <p>This lists all of the current account types with links to edit them or their assigned roles, followed with
252 * a field and button to add a new account type name to the list.</p>
253 * @param mixed $form
254 * @return mixed
255 */
256 function theme_og_content_type_admin_main($form) {
257 $header = array(t('Group'), array('data' => t('Operations'), 'colspan' => 2));
258 $added_groups = _og_content_type_admin_get_added();
259 //keep the sitewide settings at the top...
260 $name = $added_groups[-1];
261 $admin = l(t('assign content types'), 'admin/og/og_content_types/admin/' . -1);
262 $rows[] = array($name, $admin, NULL);
263 //...with the default group settings next...
264 $name = $added_groups[0];
265 $admin = l(t('assign content types'), 'admin/og/og_content_types/admin/' . 0);
266 $rows[] = array($name, $admin, NULL);
267 //...then finish the rest in alphabetical order
268 foreach ($added_groups as $gid => $name) {
269 if ($gid != -1 && $gid != 0) {
270 $admin = l(t('assign content types'), 'admin/og/og_content_types/admin/' .$gid);
271 $delete = l(t('delete'), 'admin/og/og_content_types/delete/' .$gid);
272 $rows[] = array($name, $admin, $delete);
273 }
274 }
275 $rows[] = array(drupal_render($form['group']), array('data' => drupal_render($form['submit']), colspan => 2));
276
277 $output = drupal_render($form);
278 $output .= theme('table', $header, $rows);
279
280 return $output;
281 } //function theme_og_content_type_admin_main()
282
283 /**
284 * Returns a confirmation page for deleting a group from the content type admin table.
285 *
286 * @param integer $gid Value of group to be deleted; passed in from path.
287 * @return array $form The GID is passed to the submit.
288 */
289 function og_content_type_admin_confirm_delete(&$form_state, $gid= NULL) {
290 if ($gid == NULL) {
291 drupal_goto('admin/og/og_content_types');
292 return;
293 }
294 $sql = "SELECT octa.gid, octa.name FROM {og_content_type_admin} octa WHERE octa.gid = %d";
295 $result = db_fetch_object(db_query($sql, $gid));
296 $form['name'] = array('#type' => 'value', '#value' => $result->name);
297 $form['gid'] = array('#type' => 'value', '#value' => $gid);
298 $return_address = 'admin/og/og_content_types';
299 $form = confirm_form($form, t('Are you sure you want to delete the group %name from the content type manager?',
300 array('%name' => $result->name)), $return_address,
301 t('Deleting a group here will revert the content types associated with it to the defaults. This action cannot be undone.'), t('Delete'), t('Cancel'));
302 return $form;
303 } // function og_content_type_admin_confirm_delete()
304
305 /**
306 * Implementation of forms api _submit call. Deletes a group from the og_content_type_admin table after confirmation.
307 *
308 * @param string $form
309 * @param mixed $form_state
310 * @return string $return_address The path to return to after we've deleted the record.
311 */
312 function og_content_type_admin_confirm_delete_submit($form, &$form_state) {
313 $form_values = $form_state['values'];
314 $dbquery = db_query('DELETE FROM {og_content_type_admin} WHERE gid = %d', $form_values['gid']);
315 if ($dbquery) {
316 drupal_set_message(t('The group %gid has been removed from the content type admin table.', array('%gid' => $form_values['name'])));
317 watchdog('content', t('og_content_type_admin: deleted %gid.', array('%gid' => $form_values['name'])));
318 }
319 $form_state['redirect'] = 'admin/og/og_content_types';
320 } // function og_content_type_admin_confirm_delete_submit()
321
322 /**
323 * Callback function: Assign or Require content types to groups.
324 *
325 * @param
326 * @return array $form
327 */
328 function og_content_type_admin_admin(&$form_state, $gid = NULL) {
329 if ($gid == NULL) {
330 $sql = "SELECT octa.gid, octa.name, octa.types_allowed, octa.types_active FROM {og_content_type_admin} octa ORDER BY octa.name ASC";
331 $results = db_query($sql);
332 $coll = 1;
333 }
334 else {
335 $sql = "SELECT octa.gid, octa.name, octa.types_allowed, octa.types_active FROM {og_content_type_admin} octa WHERE octa.gid = %d";
336 $results = db_query($sql, $gid);
337 $coll = 0;
338 }
339 //these are the master lists, used when we haven't filled in any values for a particular $gid
340 $node_types_types = node_get_types();
341 if (module_exists('nf_registration_mod')) {
342 $pageroute_types = _nf_registration_mod_menu_status();
343 foreach ($pageroute_types as $typea => $nums) {
344 if ($nums[1] == 48) {
345 if (isset($node_types_types[$typea])) {
346 unset($node_types_types[$typea]);
347 }
348 }
349 }
350 }
351
352 $form['groups'] = array('#tree' => TRUE);
353 while ($result = db_fetch_object($results)) { //grab a group that we're monitoring
354 $form['groups'][$result->name] = array(
355 '#tree' => TRUE,
356 );
357 $form['groups'][$result->name]['coll'] = array('#value' => $coll);
358 $form['groups'][$result->name]['gid'] = array('#value' => $result->gid, '#type' => 'hidden');
359 if ($result->gid != -1) {//default group
360 $assigned_status = unserialize($result->types_allowed);
361 $required_status = unserialize($result->types_active);
362 foreach ($node_types_types as $type) {
363 if (!og_is_omitted_type($type->type) && !og_is_group_type($type->type)) {
364 $form['groups'][$result->name][$type->type]['name'] = array('#value' => t($type->name));
365 $form['groups'][$result->name][$type->type]['name2'] = array(
366 '#type' => 'value',
367 '#value' => t($type->name)
368 );
369 $form['groups'][$result->name][$type->type]['allowed'] = array(
370 '#type' => 'checkbox',
371 '#return_value' => ASSIGNED_TO_GROUP,
372 );
373 if ($assigned_status[$type->type] != ASSIGNED_TO_GROUP) {
374 $form['groups'][$result->name][$type->type]['allowed']['#default_value'] = NOT_ASSIGNED_TO_GROUP;
375 }
376 else {
377 $form['groups'][$result->name][$type->type]['allowed']['#default_value'] = ASSIGNED_TO_GROUP;
378 }
379 $form['groups'][$result->name][$type->type]['required'] = array(
380 '#type' => 'checkbox',
381 '#return_value' => REQUIRED,
382 );
383 //although here we only use the values 0 & 2, since we use 1 elsewhere (the group owner settings), take care at submission
384 //to not DEACTIVATE already-ACTIVATED types; i.e. if we're not setting it to two, respect that it might already be a 1;
385 //see og_content_type_admin_admin_submit
386 if ($required_status[$type->type] != REQUIRED) {
387 $form['groups'][$result->name][$type->type]['required']['#default_value'] = DEACTIVATED;
388 }
389 else {
390 $form['groups'][$result->name][$type->type]['required']['#default_value'] = REQUIRED;
391 }
392 if ($result->name == 'Default') {
393 $form['groups'][$result->name][$type->type]['propagate']['submit'] = array(
394 '#type' => 'submit',
395 '#value' => t('Allow "' .$type->name. '" in all groups'),
396 );
397 }
398 }
399 }
400 }
401 else { //repeat of above, but since we're looking at site-wide use of content types, don't throw out group-exempt types
402 $assigned_status = unserialize($result->types_allowed);
403 $required_status = unserialize($result->types_active);
404 foreach ($node_types_types as $type) {
405 $form['groups'][$result->name][$type->type]['name'] = array('#value' => t($type->name));
406 $form['groups'][$result->name][$type->type]['allowed'] = array(
407 '#type' => 'checkbox',
408 '#disabled' => TRUE,
409 '#value' => ASSIGNED_TO_GROUP,
410 );
411 /*if ($assigned_status[$type->type] != ASSIGNED_TO_GROUP) {
412 $form['groups'][$result->name][$type->type]['allowed']['#default_value'] = NOT_ASSIGNED_TO_GROUP;
413 } else {
414 $form['groups'][$result->name][$type->type]['allowed']['#default_value'] = ASSIGNED_TO_GROUP;
415 }*/
416 $form['groups'][$result->name][$type->type]['required'] = array(
417 '#type' => 'checkbox',
418 '#default_value' => $required_status[$type->type],
419 '#return_value' => REQUIRED,
420 );
421 if ($required_status[$type->type] != REQUIRED) {
422 $form['groups'][$result->name][$type->type]['required']['#default_value'] = DEACTIVATED;
423 }
424 else {
425 $form['groups'][$result->name][$type->type]['required']['#default_value'] = REQUIRED;
426 }
427 }
428 }
429 //TODO add a checkbox for each monitored group - place result in a new field in the DB table called 'hide', as in 'hide UI from group owner';
430 // this will allow us to restrict changes for each group, rather than globally
431 $form['no_change'] = array(
432 '#type' => 'checkbox',
433 '#default_value' => variable_get('og_content_type_admin_no_change', 0),
434 '#title' => 'Disallow changes by all group owners',
435 '#description' => 'Hide the group owner interface so they can\'t change their group\'s settings.
436 This has the effect of setting all <em>ALLOWED</em> content types to <em>ACTIVATED</em> since the group owner will no longer be able to set them.
437 This affects all groups. Once checked and saved, unchecking (and saving) will not <em>DEACTIVATE</em> any type.',
438 );
439 }
440 //create a submit button
441 $form['submit'] = array('#type' => 'submit', '#value' => t('Save assignments'));
442
443 return $form;
444 } //function og_content_type_admin_admin()
445
446 /**
447 * Submit the group/content-type associations for storage
448 *
449 * @param string $form_id
450 * @param mixed $form_values
451 */
452 function og_content_type_admin_admin_submit($form, &$form_state) {
453 $form_values = $form_state['values'];
454 $propagate_type = NULL;
455 if (strstr($form_values['op'], 'Allow')) {
456 $startpos = strpos($form_values['op'], '"');
457 $endpos = strrpos($form_values['op'], '"');
458 $length = $endpos - $startpos - 1;
459 $propagate_type = substr($form_values['op'], ($startpos + 1), $length);
460 foreach (element_children($form_values['groups']) as $group) {
461 foreach (element_children($form_values['groups'][$group]) as $type) {
462 if ($form_values['groups'][$group][$type]['name2'] == $propagate_type) {
463 if ($form_values['groups'][$group] != 'Site Wide') {
464 $form_values['groups'][$group][$type]['allowed'] = ASSIGNED_TO_GROUP;
465 }
466 }
467 }
468 }
469 }
470 //if the required value of a particular content type is DEACTIVATED (0) and not REQUIRED (2),
471 //make sure it isn't already set to ACTIVATED(1) before saving it as DEACTIVATED(0) unless we're looking at site-wide
472 $error = FALSE;
473 foreach (element_children($form_values['groups']) as $group) {
474 //grab the stored 'required/activated' data for comparison
475 $sql = "SELECT octa.types_active FROM {og_content_type_admin} octa WHERE octa.name = '%s'";
476 $results = db_fetch_object(db_query($sql, $group));
477 $required_status = unserialize($results->types_active);
478
479 //isolate the submitted values per group and ready them for storage
480 foreach (element_children($form_values['groups'][$group]) as $type) {
481 if ($type != 'gid') {
482 if ($form_values['groups'][$group][$type]['required'] == REQUIRED) { //required is king, so base other decisions on it
483 $required[$group][$type] = REQUIRED;
484 $assigned[$group][$type] = ASSIGNED_TO_GROUP; // it can't be required and not assigned to the group!!!
485 }
486 elseif ($required_status[$type] == ACTIVATED) { //check stored value here since this form can't set this to ACTIVATED
487 if (($form_values['groups'][$group][$type]['allowed'] == ASSIGNED_TO_GROUP) && ($form_values['groups'][$group]['gid'] == -1)) {
488 $required[$group][$type] = DEACTIVATED; //We can't set this to ACTIVATED in any way for site-wide, so if it isn't REQUIRED...
489 $assigned[$group][$type] = ASSIGNED_TO_GROUP; //then it must be DEACTIVATED
490 }
491 elseif ($form_values['groups'][$group][$type]['allowed'] == ASSIGNED_TO_GROUP) {
492 $required[$group][$type] = ACTIVATED; //since we've assigned it to the group and the group owner activated it...
493 $assigned[$group][$type] = ASSIGNED_TO_GROUP; //go ahead and store the values as such
494 }
495 else {
496 $required[$group][$type] = DEACTIVATED; //we haven't assigned it to the group, or we just unassigned it, so...
497 $assigned[$group][$type] = NOT_ASSIGNED_TO_GROUP; //make sure to deactivate it
498 }
499 }
500 else { //it's currently deactivated; make sure assigned groups are enabled if we don't allow the group owner to make changes
501 //drupal_set_message('<pre>Form values: ' .print_r($form_values, TRUE). '</pre>');
502 if ((($form_values['no_change'] == 1) && ($form_values['groups'][$group][$type]['allowed'] == ASSIGNED_TO_GROUP)) || (($form_values['groups'][$group]['gid'] == 0) && ($form_values['groups'][$group][$type]['allowed'] == ASSIGNED_TO_GROUP))) {
503 $required[$group][$type] = ACTIVATED;
504 $assigned[$group][$type] = ASSIGNED_TO_GROUP;
505 }
506 else {
507 $required[$group][$type] = DEACTIVATED; //it's not required, and the group owner hasn't activated it, so save it's...
508 $assigned[$group][$type] = $form_values['groups'][$group][$type]['allowed']; //deactivated state and whatever we set 'Assigned' to
509 }
510 }
511 }
512 }
513 $query = db_query("UPDATE {og_content_type_admin} SET types_allowed = '%s', types_active = '%s' WHERE name = '%s'",
514 serialize($assigned[$group]), serialize($required[$group]), $group);
515 if (!$query) {
516 $error = TRUE;
517 }
518 }
519 if (isset($form_values['no_change'])) {
520 variable_set('og_content_type_admin_no_change', $form_values['no_change']);
521 }
522 else {
523 variable_set('og_content_type_admin_no_change', 0);
524 }
525
526 if ($error) {
527 drupal_set_message(t('There was an error processing the data. Try again, or contact your site administrator.'), 'error');
528 }
529 else {
530 drupal_set_message(t('The changes have been saved. The group owner must now activate content types for them to be used in that group.'));
531 }
532 } //function og_content_type_admin_admin_submit()
533
534 /**
535 * Theme function to display the group/content-type association grid
536 *
537 * @param $form The form for the table.
538 * @return string An HTML string representing the table.
539 */
540 function theme_og_content_type_admin_admin($form) {
541 //header is common for each group we work with
542
543 $output = '';
544 $output_array = array();
545 foreach (element_children($form['groups']) as $key) { //grab a group
546 $rows = array();
547 if (is_array($form['groups'][$key])) {
548 foreach (element_children($form['groups'][$key]) as $type) { //grab a content type
549 if (($type != 'coll') && ($type != 'gid')) {
550 $row = array();
551 $row[] = array('data' => drupal_render($form['groups'][$key][$type]['name']), 'class' => 'role'); //re-use the role CSS style
552 $row[] = array('data' => drupal_render($form['groups'][$key][$type]['allowed']), 'align' => 'left', 'title' => t($type));
553 $row[] = array('data' => drupal_render($form['groups'][$key][$type]['required']), 'align' => 'left', 'title' => t($type));
554 if ($key == 'Default') {
555 $row[] = array('data' => drupal_render($form['groups'][$key][$type]['propagate']), 'align' => 'left');
556 }
557 $rows[] = $row;
558 }
559 }
560 }
561 if ($key == 'Default') {
562 $header = array();
563 $header[] = t('Content Types');
564 $header[] = t('Allow');
565 $header[] = t('Require');
566 $header[] = t('Propagate');
567 }
568 else {
569 $header = array();
570 $header[] = t('Content Types');
571 $header[] = t('Allow');
572 $header[] = t('Require');
573 }
574 $fieldset = array(
575 '#type' => 'fieldset',
576 '#value' => theme('table', $header, $rows, array('id' => 'roles')),// re-use the roles CSS style
577 '#title' => $key,
578 '#description' => t('If you <em>REQUIRE</em> that a group use a content type, it will automatically be allowed;
579 no need to check the <em>ALLOW</em> boxes too.'),
580 '#collapsible' => TRUE,
581 '#collapsed' => ($form['groups'][$key]['coll']['#value'] == 1) ? TRUE : FALSE,
582 '#weight' => 0,
583 );
584 //$fieldset['gid'] = $form['groups'][$key]['gid'];
585 if ($key == 'Site Wide') {
586 $fieldset['#weight'] = -10;
587 $fieldset['#description'] = t('Since you are the group owner of the entire site, it doesn\'t make sense to have more than one control.
588 <em>REQUIRE</em> the content types you would like to have activated at the site-wide level.');
589 $output_array[$fieldset['#weight']] = theme('fieldset', $fieldset);
590 }
591 elseif ($key == 'Default') {
592 $fieldset['#weight'] = -8;
593 $fieldset['#description'] .= t(' For the <em>Default</em> group, all <em>ALLOWED</em> content types will also be <em>ACTIVATED</em>.
594 Additionally, clicking any of the <em>Allow TYPE in all groups</em> buttons will submit the form and check all <em>ALLOWED</em> boxes in every group except <em>Site Wide</em>.
595 This is particularly useful if you\'ve added a content type after many group admins have customized their type usage.');
596 $output_array[$fieldset['#weight']] = theme('fieldset', $fieldset);
597 }
598 else {
599 $output_array[] = theme('fieldset', $fieldset);
600 }
601 unset ($form['groups'][$key]['coll']);//if we don't unset these, drupal_render lists 1's at the end of the page
602 }
603
604 ksort($output_array);
605 foreach ($output_array as $out) {
606 $output .= $out;
607 }
608
609 $output .= drupal_render($form);
610 return $output;
611 } //function theme_og_content_type_admin_admin()
612
613 //Group owner administration section----------------------------------------------------------------------
614 //This section is only for the group content type administration form and its processing
615
616 /**
617 * Let the group owner decide which content types his members can use.
618 *
619 * @param object $group
620 * @return array $form
621 */
622 function og_content_type_admin_owner(&$form_state, $nid) { //print "nid = ".$nid;
623 global $user;
624 $group = node_load($nid); //print_r($group);
625 og_set_theme($group->nid);
626 og_set_group_context($group);
627
628 $sql = "SELECT octa.gid, octa.name, octa.types_allowed, octa.types_active FROM {og_content_type_admin} octa WHERE octa.gid = %d";
629 if (!$result = db_fetch_object(db_query($sql, $group->nid))) { //if the group isn't one we're monitoring yet, get the defaults
630 $result = db_fetch_object(db_query($sql, 0));
631 }
632 $form['group'] = array(
633 '#tree' => TRUE,
634 );
635 $assigned = unserialize($result->types_allowed);
636 $activated_status = unserialize($result->types_active);
637 foreach ($assigned as $type => $value) {
638 if ($value) {
639 $form['group'][$type] = array(
640 '#type' => 'checkbox',
641 );
642 if ($activated_status[$type] != REQUIRED) {
643 $form['group'][$type]['#default_value'] = $activated_status[$type];
644 $form['group'][$type]['#return_value'] = ACTIVATED;
645 }
646 else {
647 $form['group'][$type]['#value'] = REQUIRED;
648 $form['group'][$type]['#return_value'] = REQUIRED;
649 $form['group'][$type]['#disabled'] = TRUE;
650 $form['group'][$type]['#title'] = t('This is required by the site admin.');
651 }
652 }
653 else {
654 $form['group'][$type] = array(
655 '#type' => 'hidden',
656 '#value' => DEACTIVATED,
657 );
658 }
659 }
660 //create a submit button
661 $form['submit'] = array('#type' => 'submit', '#value' => t('Save assignments'));
662
663 // Breadcrumb navigation:
664 $breadcrumb[] = l(t('Home'), NULL);
665 $breadcrumb[] = l(t('Groups'), 'og');
666 $breadcrumb[] = l(t("@title", array('@title' => $group->title)), 'node/'.$group->nid);
667 drupal_set_breadcrumb($breadcrumb);
668 return $form;
669 } // function og_content_type_admin_owner()
670
671 /**
672 * Submit the group/content-type associations for storage
673 *
674 * @param string $form_id
675 * @param mixed $form_values
676 */
677 function og_content_type_admin_owner_submit($form, &$form_state) {
678 $form_values = $form_state['values'];
679 //check if the group is already monitored, if not INSERT it; if so, UPDATE it.
680 if (is_numeric(arg(1))) {
681 $group = node_load(arg(1));
682 if ($group) {
683 if (db_fetch_object(db_query("SELECT octa.gid FROM {og_content_type_admin} octa WHERE octa.gid = %d", $group->nid))) {
684 $query = db_query("UPDATE {og_content_type_admin} SET types_active = '%s' WHERE name = '%s'", serialize($form_values['group']), $group->title);
685 }
686 else {
687 $allowed = db_fetch_object(db_query("SELECT octa.types_allowed FROM {og_content_type_admin} octa WHERE octa.gid = %d", 0));
688 $query = db_query("INSERT INTO {og_content_type_admin} (gid, name, types_allowed, types_active) VALUES (%d, '%s', '%s', '%s')",
689 $group->nid, $group->title, $allowed->types_allowed, serialize($form_values['group']));
690 }
691 if (!$query) {
692 drupal_set_message(t('There was an error processing the data. Try again, or contact your site administrator.'), 'error');
693 }
694 else {
695 drupal_set_message(t('The changes have been saved.'));
696 }
697 }
698 }
699 } //function og_content_type_admin_owner_submit()
700
701 /**
702 * Theme function to display the group/content-type association grid
703 *
704 * @param $form The form for the table.
705 * @return string An HTML string representing the table.
706 */
707 function theme_og_content_type_admin_owner($form) {
708 //header is common for each group we work with
709 $header[] = (t('Content Types'));
710 $header[] = (t('Active'));
711 $output = '';
712 $rows = array();
713 if (is_array($form['group'])) {
714 foreach (element_children($form['group']) as $type) { //grab a content type
715 if ($form['group'][$type]['#type'] != 'hidden') {
716 $row = array();
717 $node_type = node_get_types('type', $type);
718 $row[] = array('data' => $node_type->name, 'class' => 'role'); //re-use the role CSS style
719 $row[] = array('data' => drupal_render($form['group'][$type]), 'align' => 'left', 'title' => t($type));
720 $rows[] = $row;
721 }
722 }
723 }
724 $fieldset = array(
725 '#type' => 'fieldset',
726 '#value' => theme('table', $header, $rows, array('id' => 'roles')),// re-use the roles CSS style
727 '#title' => 'Group Content Types',
728 '#description' => t('As group owner, you can limit the kinds of content that your group members create in this group by deactivating content types.
729 <h3><strong>You will still be able to use the deactivated content types yourself, even though your group members won\'t.</strong></h3>
730 Your site admin may give you recommendations.
731 Disabled items are <em>required</em> by the site admin.'),
732 );
733 $output .= theme('fieldset', $fieldset);
734 $output .= drupal_render($form);
735 return $output;
736 } //function theme_og_content_type_admin_owner()
737
738 //Nuts and bolts, Meat and potatoes section---------------------------------------------------------------
739 //This section contains all processing to make sure that only the authorized content types are useable in
740 //each situation that may come up
741
742 /**
743 * Remove content menu items based on the 'site-wide' settings set in og_content_type_admin_admin.
744 *
745 * This function removes from the 'Create content' menu any types which should not be available site-wide.
746 * This has the effect of requiring that the removed types, if used at all, be associated with groups; i.e.
747 * those content types cannot be publicly viewable as they will have a group context. This of course, depends
748 * on how the admin sets the audience settings. If only admins can cross-post and mark group postings as public,
749 * then this will all work as designed. This function does not remove illegal content types from the node/add
750 * page's listing, nor does it remove the menu items within the OG 'group detail' menu. It also doesn't account
751 * for directly entering in an illegal url. Other functions handle these problems.
752 */
753 function og_content_type_admin_menu_alter(&$callbacks) {
754 global $user;
755
756 $sql = "SELECT octa.types_active FROM {og_content_type_admin} octa WHERE octa.gid = -1";
757 $holder = db_fetch_object(db_query($sql));
758 $activated_types = unserialize($holder->types_active);
759
760 foreach ($activated_types as $type => $value) {
761 if (($value == DEACTIVATED) && ($user->uid != 1)) {
762 $url = str_replace('_', '-', $type);
763 $type_path = "node/add/$url";
764 $callbacks[$type_path]['access callback'] = FALSE;
765 }
766 }
767 $callbacks['node/add']['page callback'] = 'og_content_type_admin_node_add';
768 }
769
770 /**
771 * Interception of the node module's node_add function.
772 *
773 * Present a node submission form or a set of links to such forms.
774 */
775 function og_content_type_admin_node_add($type = NULL) {
776 global $user, $_GET;
777
778 $gid = NULL;
779 drupal_flush_all_caches();
780
781 //if there is a group context, get the active types for the group, otherwise, use the site-wide list
782 if (is_array($_GET[gids])) {
783 $gid = $_GET[gids][0];
784 $sql = "SELECT octa.types_active, octa.types_allowed FROM {og_content_type_admin} octa WHERE octa.gid = %d";
785 //if we're keeping track of this group, get it's active types, otherwise, get the defaults
786 if (!$result = db_fetch_object(db_query($sql, $_GET[gids][0]))) {
787 $result = db_fetch_object(db_query($sql, 0));
788 }
789 $activated_types = unserialize($result->types_active);
790 $allowed_types = unserialize($result->types_allowed);
791 $look_at_allowed = 1;
792 }
793 else {
794 $sql = "SELECT octa.types_active FROM {og_content_type_admin} octa WHERE octa.gid = -1";
795 $holder = db_fetch_object(db_query($sql));
796 $activated_types = unserialize($holder->types_active);
797 $look_at_allowed = 0;
798 }
799
800 $types = node_get_types();
801 if (module_exists('nf_registration_mod')) {
802 $pageroute_types = _nf_registration_mod_menu_status();
803 foreach ($pageroute_types as $typea => $nums) {
804 if ($nums[1] == 48) {
805 if (isset($types[$typea])) {
806 unset($types[$typea]);
807 }
808 }
809 }
810 }
811 $type = isset($type) ? str_replace('-', '_', $type) : NULL;
812 $allowed_for_group_admins = (($allowed_types[$type] != NOT_ASSIGNED_TO_GROUP) && (_og_content_type_admin_is_admin_content_access_nid($gid)));
813 $allowed_for_users = (($activated_types[$type] != DEACTIVATED) && (!_og_content_type_admin_is_admin_content_access_nid($gid)));
814
815 // If a node type has been specified, validate its existence and output the form if authorized.
816 // If the user is site admin, allow all content types.
817 if (($user->uid == 1) && isset($types[$type])) {
818 // Initialize settings:
819 $node = array('uid' => $user->uid, 'name' => $user->name, 'type' => $type);
820 drupal_set_title(t('Submit @name', array('@name' => $types[$type]->name)));
821 $output = drupal_get_form($type. '_node_form', $node);
822 }// If we don't know the gid, then use site-wide types. Only allow types that aren't DEACTIVATED.
823 elseif (($look_at_allowed == 0) && isset($types[$type]) && node_access('create', $type) && ($activated_types[$type] != DEACTIVATED)) {
824 // Initialize settings:
825 $node = array('uid' => $user->uid, 'name' => $user->name, 'type' => $type);
826 drupal_set_title(t('Submit @name', array('@name' => $types[$type]->name)));
827 $output = drupal_get_form($type. '_node_form', $node);
828 }// If we have the gid, check if the user is a group admin. If so, allow them to create ALLOWED types that are not activated for their group members.
829 // Otherwise, if the user is not a group admin, they can only create types that are not DEACTIVATED.
830 elseif (($look_at_allowed == 1) && isset($types[$type]) && node_access('create', $type) && ($allowed_for_group_admins || $allowed_for_users)) {
831 // Initialize settings:
832 $node = array('uid' => $user->uid, 'name' => $user->name, 'type' => $type);
833 drupal_set_title(t('Submit @name', array('@name' => $types[$type]->name)));
834 $output = drupal_get_form($type. '_node_form', $node);
835 }
836 else {
837 // If no (valid) node type has been provided, display a node type overview.
838 // Make sure to use the site-wide settings since we're on the node/add page in this case.
839 drupal_set_title(t('Create content'));
840 foreach ($types as $type) {
841 if (function_exists($type->module. '_form') && node_access('create', $type->type) && (($activated_types[$type->type] != DEACTIVATED) || ($user->uid == 1))) {
842 $type_url_str = str_replace('_', '-', $type->type);
843 $title = t('Add a new @s.', array('@s' => $type->name));
844 if ($gid != NULL) {
845 $out = '<dt>' .l(drupal_ucfirst($type->name), "node/add/$type_url_str", array('title' => $title), "gids[]=$gid"). '</dt>';
846 }
847 else {
848 $out = '<dt>' .l(drupal_ucfirst($type->name), "node/add/$type_url_str", array('title' => $title)). '</dt>';
849 }
850 $out .= '<dd>' .filter_xss_admin($type->description). '</dd>';
851 $item[$type->type] = $out;
852 }
853 }
854
855 if (isset($item)) {
856 uksort($item, 'strnatcasecmp');
857 $output = t('Choose the appropriate item from the list:'). '<dl>' .implode('', $item). '</dl>';
858 }
859 else {
860 drupal_set_title(t('Invalid Content Type'));
861 $output = t('Either the content type you are trying to create does not exist,
862 or you are not authorized to access the content type you have tried to create in the current context.
863 \'Create\' a content type by selecting from either the group menu or the \'Create content\' menu instead.');
864 }
865 }
866
867 return $output;
868 } // function og_content_type_admin_node_add()
869
870 /**
871 * Implementation of hook_block(). See og_content_type_admin_block_details.
872 */
873 function og_content_type_admin_block($op = 'list', $delta = 0, $edit = array()) {
874 if ($op == 'list') {
875 $blocks[0]['info'] = t('Group details override by OG Content Type Admin');
876
877 // Auto-enable the group blocks for fresh installations.
878 $blocks[0]['status'] = 1;
879 $blocks[0]['weight'] = -2;
880
881 return $blocks;
882 }
883 elseif ($op == 'view') {
884 switch ($delta) {
885 case 0:
886 return og_content_type_admin_block_details();
887 }
888 }
889 } // function og_content_type_admin_block()
890
891 /**
892 * We want admins to use this instead of og_block_details().
893 *
894 * Upon installation, we read og_block_details' settings, disable it, and assign those settings to this block.
895 * Upon uninstallation, we reverse the process.
896 */
897 function og_content_type_admin_block_details() {
898 global $user;
899
900 if ($node = og_get_group_context()) {
901 $cntall = db_result(db_query(og_list_users_sql(0, 0, 'u.name ASC', TRUE), $node->nid));
902 $result = db_query(og_list_users_sql(0), $node->nid);
903 $cntpending = 0;
904 while ($row = db_fetch_object($result)) {
905 if ($row->is_active == 0) {
906 $cntpending++;
907 }
908 if ($row->uid == $user->uid) {
909 if ($row->is_active) {
910 $subscription = 'active';
911 }
912 else {
913 $subscription = 'requested';
914 }
915 }
916 }
917
918 $links[] = l(t('Group home'), "node/$node->nid");
919
920 if ($subscription == 'active' || user_access('administer nodes')) {
921 $links2 = module_invoke_all('og_create_links', $node);
922 $links = array_merge($links, $links2);
923 $sql = "SELECT octa.types_active, octa.types_allowed FROM {og_content_type_admin} octa WHERE octa.gid = %d";
924 //if we're keeping track of this group, get it's active types, otherwise, get the defaults
925 if (!$result = db_fetch_object(db_query($sql, $node->nid))) {
926 $result = db_fetch_object(db_query($sql, 0));
927 }
928 $activated_types = unserialize($result->types_active);
929 $allowed_types = unserialize($result->types_allowed);
930 $types = node_get_types();
931 //sift through the links returned and remove the restricted content types
932 foreach ($types as $type) {
933 foreach ($links as $link => $value) {
934 $link_test_text = t('Create !type', array('!type' => $type->name));
935 if (strstr($value, $link_test_text) && ($activated_types[$type->type] == DEACTIVATED) && (!_og_content_type_admin_is_admin_content_access_nid($node->nid))) {
936 unset($links[$link]);
937 }
938 if (strstr($value, $link_test_text) && ($allowed_types[$type->type] == NOT_ASSIGNED_TO_GROUP) && ($user->uid != 1)) {
939 unset($links[$link]);
940 }
941 }
942 }
943
944 if ($node->og_selective < OG_INVITE_ONLY) {
945 $links[] = l(t('Invite friend'), "og/invite/$node->nid");
946 }
947 $txt = format_plural($cntall-$cntpending, '1 subscriber', '@count subscribers');
948 $txt = og_is_picture() ? l($txt, "og/users/$node->nid/faces") : l($txt, "og/users/$node->nid");
949 $txt .= $cntpending ? " ($cntpending)" : '';
950 $links[] = $txt;
951 $links[] = t('Manager: '). theme('username', $node);
952 $links[] = isset($subscription) ? l(t('My subscription'), "og/manage/$node->nid") : og_subscribe_link($node);
953 if (isset($node->og_website) && !empty($node->og_website)) {
954 $links[] = l(t('website'), $node->og_website);
955 }
956 if (module_exists('search') && user_access('search content')) {
957 $post = drupal_get_form('og_content_type_admin_search_form', $node);
958 }
959 }
960 elseif ($subscription == 'requested') {
961 $links[] = t('Your subscription request awaits approval.');
962 $links[] = l(t('delete request'), "og/unsubscribe/$node->nid", array(), 'destination=og');
963 }
964 elseif (!$user->uid) {
965 $dest = drupal_get_destination();
966 $links[] = t('You must <a href="!register">register</a>/<a href="!login">login</a> in order to post into this group.', array('!register' => url("user/register", $dest), '!login' => url("user/login", $dest)));
967 }
968 elseif ($node->og_selective < OG_INVITE_ONLY) {
969 $links[] = og_subscribe_link($node);
970 }
971 else {
972 $links[] = t('This is a @closed group. The group administrators add/remove subscribers as needed.', array('@closed' => t('closed')));
973 }
974 $block['content'] = theme('item_list', $links). $post;
975 $block['subject'] = $node->title;
976 return $block;
977 }
978 } // function og_content_type_admin_block_details()
979
980 /**
981 * Replacement for og_search_form; make it prettier
982 *
983 * @param object $group
984 * @return array
985 */
986 function og_content_type_admin_search_form($group) {
987 $form['filter0'] = array(
988 '#type' => 'textfield',
989 '#title' => '',
990 '#description' => '',
991 '#size' => 19,
992 '#maxlength' => 255,
993 '#attributes' => array('class' => 'group_search'),
994 );
995 $form['submit'] = array(
996 '#type' => 'submit',
997 '#value' => t('Search this group'),
998 '#attributes' => array('class' => 'group_search_button'),
999 );
1000 $form['#process'] = array('views_filters_process' => array());
1001 $form['#method'] = 'get';
1002 $form['#action'] = url("og/search/$group->nid");
1003 return $form;
1004 } // function og_content_type_admin_search_form
1005
1006 /**
1007 * Implementation of hook_nodeapi
1008 *
1009 * We need to update group name changes.
1010 * We need to remove from our table any reference to a deleted group.
1011 *
1012 */
1013 function og_content_type_admin_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
1014 switch ($op) {
1015 case 'update':
1016 if ($group = db_fetch_object(db_query("SELECT nid FROM {og} WHERE nid = %d", $node->nid))) {
1017 if (db_query("SELECT * FROM {og_content_type_admin} WHERE gid = %d", $group->nid)) {
1018 $sql = "UPDATE {og_content_type_admin} SET name = '%s' WHERE gid = %d";
1019 $result = db_query($sql, $node->title, $group->nid);
1020 if (!$result) {
1021 drupal_set_message('Problem updating the group name for the OG Content Type Admin table.', 'error');
1022 }
1023 }
1024 }
1025 break;
1026 case 'delete':
1027 if ($group = db_fetch_object(db_query("SELECT nid FROM {og} WHERE nid = %d", $node->nid))) {
1028 if (db_query("SELECT * FROM {og_content_type_admin} WHERE gid = %d", $group->nid)) {
1029 $sql = "DELETE FROM {og_content_type_admin} WHERE gid = %d";
1030 $result = db_query($sql, $group->nid);
1031 if (!$result) {
1032 drupal_set_message('Problem removing a reference to the deleted group from the OG Content Type Admin table.', 'error');
1033 }
1034 }
1035 }
1036 break;
1037 }
1038 } // function og_content_type_admin_nodeapi()
1039
1040 /**
1041 * Implementation of hook_node_type.
1042 *
1043 * Intercept creation or deletion of node types and add/delete references to them in our DB table.
1044 * @param string $op The operation being performed on $info.
1045 * @param object $info The node type object on which $op is being performed.
1046 */
1047 function og_content_type_admin_node_type($op, $info) {
1048