Parent Directory
|
Revision Log
|
Revision Graph
small tweaks and optimizations. ready for initial release
| 1 | <?php |
| 2 | // $Id: og_collections.module,v 1.1 2008/03/13 20:12:56 sdboyer Exp $ |
| 3 | |
| 4 | /** |
| 5 | * @file |
| 6 | * The og_collections.module file, which manages the creation and deployment of |
| 7 | * 'Collections' of 'Pre-Configured Panels' in conjunction with Organic Groups. |
| 8 | * |
| 9 | * Collections are sets of panels (as in the Panels and OG Panels modules) that |
| 10 | * can be paired with group types. Once a collection of panels has been paired |
| 11 | * with a group type, every new group of that type will automatically be granted |
| 12 | * their own duplicate set of the panels in the collection. |
| 13 | * |
| 14 | */ |
| 15 | |
| 16 | /** |
| 17 | * Implementation of hook_help() |
| 18 | */ |
| 19 | function og_collections_help($section) { |
| 20 | switch ($section) { |
| 21 | case 'admin/help#og_collections': // TODO write up quite a |
| 22 | } |
| 23 | } |
| 24 | |
| 25 | /** |
| 26 | * Implementation of hook_menu() |
| 27 | */ |
| 28 | function og_collections_menu($may_cache) { |
| 29 | if ($group_types = og_collections_group_types()) { |
| 30 | $multgrps = count($group_types) > 1 ? TRUE : FALSE; |
| 31 | } |
| 32 | $collectionsetting = variable_get('og_collections_settings', FALSE); |
| 33 | if ($may_cache) { |
| 34 | $items[] = array( |
| 35 | 'path' => 'admin/og/og_collections', |
| 36 | 'title' => t('OG Collections'), |
| 37 | 'description' => t('Set up OG Panels to automatically generate associated sets of panels when new groups are created.'), |
| 38 | 'callback' => 'drupal_get_form', |
| 39 | 'callback arguments' => array('og_collections_admin'), |
| 40 | 'access' => user_access('administer organic groups'), |
| 41 | 'weight' => 0, |
| 42 | ); |
| 43 | $items[] = array( |
| 44 | 'path' => 'admin/og/og_collections/settings', |
| 45 | 'title' => t('Collections Settings'), |
| 46 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 47 | 'weight' => -10, |
| 48 | ); |
| 49 | if ($group_types && $collectionsetting) { // at least one group type must have already been set, and collections must be enabled |
| 50 | if ($collectionsetting == 1) { |
| 51 | $pcpanels = FALSE; |
| 52 | } |
| 53 | else if ($collectionsetting == 2) { |
| 54 | $pcpanels = TRUE; |
| 55 | } |
| 56 | // sets up the pre-configured panel types selection tab |
| 57 | $items[] = array( |
| 58 | 'path' => 'admin/og/og_collections/collectioncfg', |
| 59 | 'title' => t('Collections'), |
| 60 | 'description' => $pcpanels ? t('Select which pre-configured panels are to be used for each of your group type bundles.') : t('Select which pre-configured panels are to be used in your group bundle.'), |
| 61 | 'callback' => 'og_collections_admin_collectioncfg', |
| 62 | 'callback arguments' => array('default'), |
| 63 | 'type' => MENU_LOCAL_TASK, |
| 64 | 'access' => user_access('administer organic groups'), |
| 65 | 'weight' => -4, |
| 66 | ); |
| 67 | if ($collectionsetting == 2) { |
| 68 | $items[] = array( |
| 69 | 'path' => 'admin/og/og_collections/collectioncfg/default', |
| 70 | 'title' => t('Default'), |
| 71 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 72 | 'access' => user_access('administer organic groups'), |
| 73 | ); |
| 74 | $i = 1; |
| 75 | foreach ($group_types as $type => $name) { |
| 76 | $items[] = array( |
| 77 | 'path' => 'admin/og/og_collections/collectioncfg/'. $type, |
| 78 | 'title' => t($name), |
| 79 | 'callback' => 'og_collections_admin_collectioncfg', |
| 80 | 'callback arguments' => array($type), // for some reason, this argument isn't being passed. currently sporking it using arg() in the callback |
| 81 | 'type' => MENU_LOCAL_TASK, |
| 82 | 'access' => user_access('administer organic groups'), |
| 83 | 'weight' => $i, |
| 84 | ); |
| 85 | $i++; |
| 86 | } |
| 87 | } |
| 88 | // sets up the pre-configured panels configuration tab |
| 89 | $items[] = array( |
| 90 | 'path' => 'admin/og/og_collections/pcpanelsetup', |
| 91 | 'title' => t('Pre-Configured Panels'), |
| 92 | 'description' => t('Configure the panels that make up your collection.'), |
| 93 | 'callback' => 'og_collections_admin_pcpanelsetup', |
| 94 | 'callback arguments' => array('default'), |
| 95 | 'type' => MENU_LOCAL_TASK, |
| 96 | 'access' => user_access('administer organic groups'), |
| 97 | 'weight' => -2, |
| 98 | ); |
| 99 | if ($collectionsetting == 2) { |
| 100 | $items[] = array( |
| 101 | 'path' => 'admin/og/og_collections/pcpanelsetup/default', |
| 102 | 'title' => t('Default'), |
| 103 | 'description' => t('Configure the panels that make up your collection.'), |
| 104 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 105 | 'access' => user_access('administer organic groups'), |
| 106 | ); |
| 107 | $i = 1; |
| 108 | foreach ($group_types as $type => $name) { |
| 109 | $items[] = array( |
| 110 | 'path' => 'admin/og/og_collections/pcpanelsetup/'. $type, |
| 111 | 'title' => t($name), |
| 112 | 'callback' => 'og_collections_admin_pcpanelsetup', |
| 113 | 'callback arguments' => array($type), |
| 114 | 'type' => MENU_LOCAL_TASK, |
| 115 | 'access' => user_access('administer organic groups'), |
| 116 | 'weight' => $i, |
| 117 | ); |
| 118 | $i++; |
| 119 | } |
| 120 | } |
| 121 | $items[] = array( |
| 122 | 'path' => 'admin/og/og_collections/pcpanel', |
| 123 | 'callback' => 'og_collections_pcpanel_manage', |
| 124 | 'type' => MENU_CALLBACK, |
| 125 | 'access' => user_access('admnister organic groups'), |
| 126 | ); |
| 127 | } |
| 128 | } |
| 129 | return $items; |
| 130 | } |
| 131 | |
| 132 | /** |
| 133 | * Return the list of node types that have been classified by og as groups. |
| 134 | * |
| 135 | * Because of the omnipresent 'Default' collection, it's sometimes helpful to add a 'Default' |
| 136 | * value to the beginning of this array. That's what the first parameter is for. |
| 137 | * |
| 138 | * @param boolean $default, default FALSE |
| 139 | * indicates whether a 'Default' type should be added at the beginning of the array. |
| 140 | * @return array $group_types |
| 141 | * An associative array of the form [systemtypename] => [publicfacingntypeame] for all group types. |
| 142 | * Also can return FALSE if no groups have been defined. |
| 143 | */ |
| 144 | function og_collections_group_types($default = FALSE) { |
| 145 | if ($group_types = variable_get('og_node_types', FALSE)) { |
| 146 | asort($group_types); |
| 147 | foreach ($group_types as $type) { |
| 148 | $group_types[$type] = node_get_types('name', $type); |
| 149 | } |
| 150 | if ($default) { // defaults to not, but if the caller requests it, the 'default' group is inserted at the beginning of the array |
| 151 | $group_types = array_merge(array('default' => 'Default'), $group_types); |
| 152 | } |
| 153 | } |
| 154 | return $group_types; |
| 155 | } |
| 156 | |
| 157 | /** |
| 158 | * Renders the form for group collections settings |
| 159 | */ |
| 160 | function og_collections_admin_collectioncfg($type) { |
| 161 | $group_types = og_collections_group_types(TRUE); |
| 162 | drupal_set_title("'". $group_types[$type] ."' Collection"); |
| 163 | if (mysql_num_fields(db_query("SELECT * FROM {og_collections} WHERE grouptype = 'default'")) == 1) { |
| 164 | drupal_set_message("You need to create at least one pre-configured panel for OG Collections to operate properly. Use this form to create your first one."); |
| 165 | drupal_get_destination(); |
| 166 | drupal_goto('admin/og/og_collections/pcpanel/form'); |
| 167 | } |
| 168 | $collectionsetting = variable_get('og_collections_settings', FALSE); |
| 169 | // TODO Need to improve helptext considerably |
| 170 | if ($collectionsetting == 1) { |
| 171 | $helptext = '<p>This form allows you to control the overall configuration for your collection. You can also !link to the list below.'; |
| 172 | } |
| 173 | elseif ($collectionsetting == 2) { |
| 174 | $helptext = "<p>This form allows you to control the overall configuration for each group type's pre-configured panel. You can also !link to the list below."; |
| 175 | } |
| 176 | $output = t($helptext, array('!link' => l(t('add a new pre-configured panel'), 'admin/og/og_collections/pcpanel/form', array(), drupal_get_destination()))); |
| 177 | $output .= drupal_get_form('og_collections_collectioncfg_table', $type); |
| 178 | return $output; |
| 179 | } |
| 180 | |
| 181 | /** |
| 182 | * FAPI definition for the configure overall collection settings form. |
| 183 | * |
| 184 | * @ingroup forms |
| 185 | * @param string $type |
| 186 | * The group type for which the collection settings are being edited. |
| 187 | * |
| 188 | */ |
| 189 | function og_collections_collectioncfg_table($type) { |
| 190 | $collectioncfg = og_collections_load_collectioncfg($type); |
| 191 | $form['typevar'] = array('#type' => 'hidden', '#value' => $type); |
| 192 | // $form['#action'] = arg(3) ? url('admin/og/og_collections/'. $theme_key) : url('admin/build/block'); |
| 193 | $form['#tree'] = TRUE; |
| 194 | // TODO add a default tab as a means of allowing people to add/remove panel pre-configured panels? |
| 195 | foreach ($collectioncfg as $pcpid => $pcpanel) { |
| 196 | $pcpanel = og_collections_load_pcpanel($pcpanel['did'], FALSE, $type); |
| 197 | $form[$pcpid]['page_title'] = array('#value' => '#'. $pcpid .': '. $pcpanel->page_title); |
| 198 | $form[$pcpid]['weight'] = array('#type' => 'weight', '#default_value' => $pcpanel->weight ? $pcpanel->weight : 0); |
| 199 | $form[$pcpid]['edit'] = array('#value' => l(t('Edit'), "admin/og/og_collections/pcpanel/form/$type/$pcpid", array(), drupal_get_destination())); |
| 200 | if ($type == 'default') { |
| 201 | $form[$pcpid]['delete'] = array('#value' => l(t('Delete'), "admin/og/og_collections/pcpanel/delete/$pcpid", array(), drupal_get_destination())); |
| 202 | } |
| 203 | if ($pcpanel->default_page == 1) { |
| 204 | $default_page = $pcpid; |
| 205 | } |
| 206 | if ($pcpanel->active == 1) { |
| 207 | $activelist[] = $pcpid; |
| 208 | } |
| 209 | if ($pcpanel->published == 1) { |
| 210 | $publist[] = $pcpid; |
| 211 | } |
| 212 | if ($pcpanel->show_blocks == 1) { |
| 213 | $blklist[] = $pcpid; |
| 214 | } |
| 215 | $optionshome[$pcpid] = ''; |
| 216 | } |
| 217 | |
| 218 | $options = $optionshome; |
| 219 | $optionshome[0] = t('<em>(Do not replace the group homepage with a pre-configured panel)</em>'); |
| 220 | // $form[0]; // need to add something here that allows people to DESELECT something as the homepage |
| 221 | $form['active'] = array( |
| 222 | '#type' => 'checkboxes', |
| 223 | '#options' => $options, |
| 224 | '#default_value' => $activelist ? $activelist : NULL, |
| 225 | ); |
| 226 | $form['default_page'] = array( |
| 227 | '#type' => 'radios', |
| 228 | '#options' => $optionshome, |
| 229 | '#default_value' => $default_page ? $default_page : 0, |
| 230 | ); |
| 231 | $form['published'] = array( |
| 232 | '#type' => 'checkboxes', |
| 233 | '#options' => $options, |
| 234 | '#default_value' => $publist ? $publist : NULL, |
| 235 | ); |
| 236 | $form['show_blocks'] = array( |
| 237 | '#type' => 'checkboxes', |
| 238 | '#options' => $options, |
| 239 | '#default_value' => $blklist ? $blklist : NULL, |
| 240 | ); |
| 241 | $form['submit'] = array( |
| 242 | '#type' => 'submit', |
| 243 | '#value' => t('Save Collection'), |
| 244 | ); |
| 245 | return $form; |
| 246 | } |
| 247 | |
| 248 | /** |
| 249 | * Theme the collection settings form into a table. |
| 250 | * |
| 251 | * @ingroup themeable |
| 252 | */ |
| 253 | function theme_og_collections_collectioncfg_table($form) { |
| 254 | $isdefault = $form['typevar']['#value'] == 'default' ? TRUE : FALSE; |
| 255 | foreach (element_children($form) as $pcpid) { |
| 256 | if (is_numeric($pcpid)) { |
| 257 | $rows[] = array( |
| 258 | drupal_render($form[$pcpid]['page_title']), |
| 259 | drupal_render($form['default_page'][$pcpid]), |
| 260 | drupal_render($form['active'][$pcpid]), |
| 261 | drupal_render($form['published'][$pcpid]), |
| 262 | drupal_render($form['show_blocks'][$pcpid]), |
| 263 | drupal_render($form[$pcpid]['weight']), |
| 264 | drupal_render($form[$pcpid]['edit']), |
| 265 | drupal_render($form[$pcpid]['delete']), // TODO figure out a way to get rid of this if !$isdefault |
| 266 | ); |
| 267 | } |
| 268 | } |
| 269 | |
| 270 | $output = drupal_render($form); |
| 271 | $oper = $isdefault ? array('data' => t('Operations'), 'align' => 'center', 'colspan' => 2) : array('data' => t('Operations'), 'align' => 'center', 'colspan' => 1); |
| 272 | $header = array(t('Panel Name'), t('Home Page'), t('Enabled'), t('Published'), t('Show Blocks'), t('Weight'), $oper); |
| 273 | return theme('table', $header, $rows). $output; |
| 274 | } |
| 275 | |
| 276 | function og_collections_collectioncfg_table_validate($form_id, $form_values, $form) { |
| 277 | // what kind of validation actually needs to be done here? any? |
| 278 | } |
| 279 | |
| 280 | function og_collections_collectioncfg_table_submit($form_id, $form_values) { |
| 281 | $type = $form_values['typevar']; |
| 282 | $collectioncfg = og_collections_load_collectioncfg($type); |
| 283 | foreach (array_keys($collectioncfg) as $pcpid) { |
| 284 | $collectioncfg[$pcpid]['active'] = (int) $form_values['default_page'] == $pcpid ? 1 : $form_values['active'][$pcpid] ? 1 : 0; // ensures that pcpanels set to be home pages are also active |
| 285 | $collectioncfg[$pcpid]['default_page'] = (int) $form_values['default_page'] == $pcpid ? 1 : 0; |
| 286 | $collectioncfg[$pcpid]['weight'] = (int) $form_values[$pcpid]['weight']; |
| 287 | $collectioncfg[$pcpid]['published'] = (int) $form_values['default_page'] == $pcpid ? 1 : ($form_values['published'][$pcpid]) == $pcpid ? 1 : 0; // ensures that pcpanels set to be home pages are also published |
| 288 | $collectioncfg[$pcpid]['show_blocks'] = (int) ($form_values['show_blocks'][$pcpid]) == $pcpid ? 1 : 0; |
| 289 | } |
| 290 | if (og_collections_save_collectioncfg($type, $collectioncfg, array_keys($collectioncfg))) { |
| 291 | drupal_set_message(t("Updated '$type' Collection.")); |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | /** |
| 296 | * Render the page containing pcpanel-specific configuration links. |
| 297 | * |
| 298 | * @ingroup themeable |
| 299 | * @param string $type |
| 300 | * The group type for which the collection settings are being edited. |
| 301 | * @return string $output |
| 302 | * String of HTML that has (already) been rendered by the theme('page') function... TODO split this into a separate function so it can be themed |
| 303 | */ |
| 304 | function og_collections_admin_pcpanelsetup($type) { |
| 305 | $group_types = og_collections_group_types(TRUE); |
| 306 | drupal_set_title("'". $group_types[$type] ."' Panels Collection"); |
| 307 | if (count(db_fetch_array(db_query("SELECT * FROM {og_collections} WHERE grouptype = 'default'"))) == 1) { |
| 308 | drupal_set_message("You need to create at least one group panel pre-configured panel before you can start configuring them! Use this form to create one."); |
| 309 | drupal_get_destination(); |
| 310 | drupal_goto('admin/og/og_collections/pcpanel/form'); |
| 311 | } |
| 312 | $collectionsetting = variable_get('og_collections_settings', FALSE); |
| 313 | if ($collectionsetting == 1) { |
| 314 | $helptext = '<p>This form allows you to control the panel content and setup for each pre-configured panel. You can !link here, if desired.</p>'; |
| 315 | $linktext = 'add a new pre-configured panel'; |
| 316 | } |
| 317 | elseif ($collectionsetting == 2) { |
| 318 | $helptext = "<p>Because you have selected to allow every group type to maintain its own independent collection, this page will allow you to configure content and layout settings for pre-configured panels that are specific to each collection. However, !link will not immediately result in pre-configured panels that are specific to each collection.</p> |
| 319 | <p>Instead, OG Collections creates only one version for each pre-configured panel initially - the 'Default' version. Creating a collection-specific version for one of these panels is easy: simply select the group type from the secondary tabs list and click on any of the modification links that correspond to the pre-configured panel in the table below. The group type-specific pre-configured panel will be created automatically if you save your changes on that form.</p> |
| 320 | <p>However, it is strongly recommended that you set up your panel pre-configured panels in the Default type first. Until a version of a pre-configured panel is created for a given group type, that group type will utilize the default pre-configured panel loadout, but when you create the type-specific version, it will be an exact copy of all the settings pre-configured panel's Default settings. Consequently, it is to your advantage to load your Default pre-configured panel configurations out with as much common content as possible, THEN begin working on the type-specific pre-configured panels.</p> |
| 321 | <p>These are just guidelines. At any time, you can remove a type-specific pre-configured panel and cause the group type to begin using Default again instead. You can also copy panel pre-configured panel settings from one group type to another, if you want. But, NOTE that <strong>both of these options are completely irreversible</strong> short of restoring your database from a <a href=\"http://drupal.org/project/backup_migrate\">backup</a>.</p>"; |
| 322 | $linktext = 'adding a new pre-configured panel'; |
| 323 | } |
| 324 | $output = t($helptext, array('!link' => l(t($linktext), 'admin/og/og_collections/pcpanel/form', array(), drupal_get_destination()))); |
| 325 | |
| 326 | // looks like we may not need a form, as no data gets submitted or changed directly on this page...begin form substitution! |
| 327 | $collectioncfg = og_collections_load_collectioncfg($type); |
| 328 | $multi = $collectionsetting == 2 ? TRUE : FALSE; |
| 329 | $isdefault = strtolower($type) == 'default' ? TRUE : FALSE; |
| 330 | |
| 331 | if (!$isdefault) { |
| 332 | foreach ($collectioncfg as $pcpid => $pcpanel) { |
| 333 | $pcpanel = og_collections_load_pcpanel($pcpanel['did'], FALSE, $type); |
| 334 | if ($pcpanel->active) { |
| 335 | $row = array(); |
| 336 | $row['page_title'] = $pcpanel->page_title; |
| 337 | $row['usedef'] = $pcpanel->usedef ? 'Yes' : 'No'; |
| 338 | $row['default_page'] = $pcpanel->default_page ? 'Yes' : 'No'; |
| 339 | $row['content'] = l(t('Content'), "admin/og/og_collections/pcpanel/content/$type/$pcpid", array(), drupal_get_destination()); |
| 340 | $row['layout'] = l(t('Layout'), "admin/og/og_collections/pcpanel/layout/$type/$pcpid", array(), drupal_get_destination()); |
| 341 | $row['layset'] = l(t('Layout Settings'), "admin/og/og_collections/pcpanel/layset/$type/$pcpid", array(), drupal_get_destination()); |
| 342 | $row['revert'] = $pcpanel->usedef ? 'Already Tied' : l(t('Revert'), "admin/og/og_collections/pcpanel/revert/$type/$pcpid", array(), drupal_get_destination()); |
| 343 | $row['mirror'] = 'Coming Soon'; |
| 344 | |
| 345 | $rows[] = $row; |
| 346 | } |
| 347 | } |
| 348 | } |
| 349 | else { |
| 350 | foreach ($collectioncfg as $pcpid => $pcpanel) { |
| 351 | $pcpanel = og_collections_load_pcpanel($pcpanel['did'], FALSE); |
| 352 | if ($pcpanel->active) { |
| 353 | $row = array(); |
| 354 | $row['page_title'] = $pcpanel->page_title; |
| 355 | $row['default_page'] = $pcpanel->default_page ? 'Yes' : 'No'; |
| 356 | $row['content'] = l(t('Content'), "admin/og/og_collections/pcpanel/content/$pcpid", array(), drupal_get_destination()); |
| 357 | $row['layout'] = l(t('Layout'), "admin/og/og_collections/pcpanel/layout/$pcpid", array(), drupal_get_destination()); |
| 358 | $row['layset'] = l(t('Layout Settings'), "admin/og/og_collections/pcpanel/layset/$pcpid", array(), drupal_get_destination()); |
| 359 | $row['mirror'] = 'Coming Soon'; |
| 360 | |
| 361 | $rows[] = $row; // any utility in making the rows array associative? |
| 362 | } |
| 363 | } |
| 364 | } |
| 365 | |
| 366 | if ($isdefault) { |
| 367 | $header = array(t('Panel Name'), t('Home Page?'), t('Edit Content'), t('Edit Layout'), t('Edit Layout Settings'), t('Import Template')); |
| 368 | } |
| 369 | else { |
| 370 | $header = array(t('Panel Name'), t('Tied to Default'), t('Home Page?'), t('Edit Content'), t('Edit Layout'), t('Edit Layout Settings'), t('Revert to Default'), t('Import Template')); |
| 371 | } |
| 372 | $linktext = "admin/og/og_collections/collectioncfg"; |
| 373 | $linktext .= $isdefault ? "" : "/$type"; |
| 374 | $output .= theme('table', $header, $rows); |
| 375 | $output .= t('<p>Pre-configured panels that have been disabled in !panpcpanel will not appear in the above list. You must enable them before you can edit them here.</p>', array('!panpcpanel' => l(t('Panel Templates'), $linktext))); |
| 376 | return $output; |
| 377 | } |
| 378 | |
| 379 | /* |
| 380 | * Form to add/edit a pre-configured panel. if a $did is passed in, it edits that pcpanel. if there's no $did, it creates a new pcpanel. |
| 381 | */ |
| 382 | function og_collections_pcpanel_form($did = NULL) { |
| 383 | if ($did) { |
| 384 | $pcpanel = og_collections_load_pcpanel($did, FALSE); |
| 385 | } |
| 386 | drupal_set_title($did ? "Configure $pcpanel->page_title Template" : "Add New Pre-Configured Panel"); |
| 387 | |
| 388 | $form['page_title'] = array( |
| 389 | '#title' => t('Panel Name Title'), |
| 390 | '#type' => 'textfield', |
| 391 | '#required' => TRUE, |
| 392 | '#default_value' => $did ? $pcpanel->page_title : NULL, |
| 393 | '#disabled' => $pcpanel->default_page ? TRUE : FALSE, |
| 394 | '#description' => t('The title for the page and of the tab that will be used by default when this pre-configured panel is instantiated.'), |
| 395 | '#size' => 32, |
| 396 | ); |
| 397 | $form['path'] = array( |
| 398 | '#title' => t('Default Path'), |
| 399 | '#type' => 'textfield', |
| 400 | '#default_value' => $pcpanel->default_page ? '' : $pcpanel->path, |
| 401 | '#required' => $pcpanel->default_page ? FALSE : TRUE, |
| 402 | '#description' => $pcpanel->default_page ? t('This pre-configured panel is currently set to act as the group home page and therefore cannot be assigned a default path.') : t('The sub-path (appearing after the root group path) this pre-configured panel will appear at upon instantiation.'), |
| 403 | '#disabled' => $pcpanel->default_page ? TRUE : FALSE, |
| 404 | '#size' => 32, |
| 405 | ); |
| 406 | $form['show_blocks'] = array( |
| 407 | '#title' => t('Show blocks'), |
| 408 | '#type' => 'checkbox', |
| 409 | '#default_value' => $did ? $pcpanel->show_blocks : TRUE, |
| 410 | '#description' => t('If unchecked, unmodified instantiations of this pre-configured panel will NOT show the standard group blocks.'), |
| 411 | ); |
| 412 | $form['published'] = array( |
| 413 | '#type' => 'checkbox', |
| 414 | '#title' => t('Published'), |
| 415 | '#default_value' => $did ? $pcpanel->published : FALSE, |
| 416 | '#description' => t('If unchecked, instantiations of this pre-configured panel will initially be unpublished and viewable only by site or group administrators. Keeping this unchecked is wise if the page contains information that is not automatically present on group creation, and having this page accessible but empty would reflect poorly on the group.'), |
| 417 | ); |
| 418 | |
| 419 | $form['submit'] = array( |
| 420 | '#type' => 'submit', |
| 421 | '#value' => $did ? t('Update Pre-configured Panel') : t('Create Pre-configured Panel'), |
| 422 | ); |
| 423 | $form['did'] = array('#type' => 'value', '#value' => $did); |
| 424 | return $form; |
| 425 | } |
| 426 | |
| 427 | // FIXME NEED a validation function to ensure that paths entered are valid. |
| 428 | function og_collections_pcpanel_form_validate($form_id, $form_values, $form) { |
| 429 | |
| 430 | } |
| 431 | |
| 432 | /** |
| 433 | * Creates a new panel pre-configured panel, or modifies an existing one. Also ensures that all relevant |
| 434 | * collectioncfgs are updated with the new panel information. |
| 435 | **/ |
| 436 | function og_collections_pcpanel_form_submit($form_id, $form_values) { |
| 437 | if ($form_values['did']) { |
| 438 | $pcpanel = og_collections_load_pcpanel($form_values['did'], FALSE); |
| 439 | $pcpanel->page_title = $form_values['page_title']; |
| 440 | $pcpanel->path = $form_values['path']; |
| 441 | $pcpanel->show_blocks = $form_values['show_blocks']; |
| 442 | $pcpanel->published = $form_values['published']; |
| 443 | og_collections_save_pcpanel($pcpanel); |
| 444 | drupal_set_message(t('Pre-configured panel "'. $pcpanel->panel_title .'" has successfully been updated.')); |
| 445 | return 'admin/og/og_collections/collectioncfg'; // TODO return to the page that the edit was called from? |
| 446 | } |
| 447 | else { |
| 448 | // Create a new display in the default grouptype |
| 449 | $display = panels_new_display(); |
| 450 | panels_save_display($display); |
| 451 | // grouptype doesn't need to be included; column defaults to 'default', and new panel pcpanels are always in the default grouptype |
| 452 | $pcpid = db_next_id("{og_collections_pcpanel}_pcpid"); |
| 453 | og_collections_manage_db('pcpid_'. $pcpid, 'add'); |
| 454 | db_query("INSERT INTO {og_collections_pcpanel} (did, pcpid) VALUES (%d, %d)", $display->did, $pcpid); |
| 455 | drupal_set_message(t("The pre-configured panel '%title' created, and has been added to the Default collection. You must now select a default layout.", array('%title' => $form_values['page_title']))); |
| 456 | // Update all collectioncfgs to reflect new pre-configured panel. might be worth turning this into a hook at some point, at least in the generalized module. |
| 457 | // if this mass-update method is useful somewhere else, split it out into some separate function |
| 458 | $conf = array( |
| 459 | 'active' => 0, |
| 460 | 'default_page' => 0, |
| 461 | 'weight' => 0, |
| 462 | 'did' => $display->did, |
| 463 | 'usedef' => 1, |
| 464 | 'page_title' => $form_values['page_title'], |
| 465 | 'path' => $form_values['path'], |
| 466 | 'published' => $form_values['published'], |
| 467 | 'show_blocks' => $form_values['show_blocks'], |
| 468 | 'grouptype' => 'default', |
| 469 | ); |
| 470 | $group_types = og_collections_group_types(TRUE); |
| 471 | foreach (array_keys($group_types) as $type) { |
| 472 | $collectioncfg = og_collections_load_collectioncfg($type); |
| 473 | $collectioncfg[$pcpid] = $conf; |
| 474 | og_collections_save_collectioncfg($type, $collectioncfg, array($pcpid)); |
| 475 | } |
| 476 | drupal_get_destination(); |
| 477 | return 'admin/og/og_collections/pcpanel/layout/'. $pcpid; // redirect to layout selection |
| 478 | } |
| 479 | } |
| 480 | |
| 481 | /** |
| 482 | * Central pre-configured panel management function, redirects requests based on supplemental args; takes any number of args that can be passed to the |
| 483 | * 'admin/og/og_collections/pcpanel' URL and dispatches them appropriately |
| 484 | */ |
| 485 | function og_collections_pcpanel_manage() { |
| 486 | $args = func_get_args(); |
| 487 | $op = array_shift($args); |
| 488 | $dest = drupal_get_destination(); |
| 489 | $error = $success = ''; |
| 490 | $collectionsetting = variable_get('og_collections_settings', FALSE); |
| 491 | $multi = $collectionsetting == 1 ? FALSE : TRUE; |
| 492 | |
| 493 | switch ($op) { |
| 494 | case 'form': |
| 495 | if (!empty($args[0]) && !empty($args[1])) { |
| 496 | if (is_string($args[0]) && is_numeric($args[1])) { |
| 497 | if ($pcpanel = og_collections_load_pcpanel(array($args[0], $args[1]))) { |
| 498 | $output = drupal_get_form('og_collections_pcpanel_form', $pcpanel->did); |
| 499 | } |
| 500 | else { |
| 501 | $error = 'No pre-configured panel was loaded with the arguments provided.'; |
| 502 | break; |
| 503 | } |
| 504 | } |
| 505 | else { |
| 506 | $error = 'The arguments provided were in an invalid format.'; |
| 507 | break; |
| 508 | } |
| 509 | } |
| 510 | else { |
| 511 | $output = drupal_get_form('og_collections_pcpanel_form'); |
| 512 | } |
| 513 | return $output; |
| 514 | |
| 515 | case 'layout': |
| 516 | case 'content': // FIXME display_edit.inc in Panels needs to be updated with a different return value if the form is cancelled. Or something. |
| 517 | case 'layset': |
| 518 | if (is_numeric($args[0])) { // editing the default version of a pre-configured panel |
| 519 | list($pcpid) = $args; |
| 520 | $result = og_collections_pcpanel_edit($op, $pcpid, $error, $success); |
| 521 | } |
| 522 | elseif (is_string($args[0])) { // editing a group type specific version of a pre-configured panel |
| 523 | list($type, $pcpid) = $args; |
| 524 | $result = og_collections_pcpanel_edit($op, $pcpid, $error, $success, $type); |
| 525 | } |
| 526 | if ($result) { |
| 527 | return $result; // only anything is returned into result is when the form strings need to be returned for processing |
| 528 | } |
| 529 | // all other situations (errors, success, whatever), result in a break |
| 530 | break; |
| 531 | |
| 532 | case 'revert': // reverting a given page pcpanel to default and re-linking it |
| 533 | if (!$multi) { |
| 534 | $error = 'Reversion is pointless if you are using only one collection for all your group types. How did you even GET here!?!'; // =) |
| 535 | break; |
| 536 | } |
| 537 | if (isset($args[0], $args[1])) { |
| 538 | if (is_string($args[0]) && is_numeric($args[1])) { |
| 539 | $pcpanel = og_collections_load_pcpanel(array($args[0], $args[1]), FALSE); |
| 540 | return drupal_get_form('og_collections_pcpanel_revert_confirm', $pcpanel); |
| 541 | } |
| 542 | } |
| 543 | break; |
| 544 | |
| 545 | case 'delete': // delete a given pcpanel |
| 546 | if (!isset($args[0]) || !is_numeric($args[0])) { |
| 547 | $error = 'A valid pcpid must be supplied if you want to delete a pre-configured panel.'; |
| 548 | break; |
| 549 | } |
| 550 | if ($multi) { |
| 551 | $dids = db_num_rows(db_query("SELECT * FROM {og_collections_pcpanel} WHERE pcpid = %d", $args[0])); |
| 552 | drupal_set_message(t('WARNING: Deleting this pre-configured panel will remove it for ALL group types. This will result in the automatic, irreversible deletion of the <strong>%dids</strong> uniquely configured display(s) that correspond to this pre-configured panel. If you just want the pre-configured panel to not be instantiated for a particular group type, simply disable it on the !link', array('%dids' => $dids, '!link' => l(t('Panel Templates'), 'admin/og/og_collections/collectioncfg')))); |
| 553 | } |
| 554 | return drupal_get_form('og_collections_pcpanel_delete_confirm', $args[0], $multi); |
| 555 | break; |
| 556 | |
| 557 | } |
| 558 | if (!empty($error)) { |
| 559 | drupal_set_message($error, 'error'); |
| 560 | drupal_goto(); |
| 561 | } |
| 562 | elseif (!empty($success)) { |
| 563 | drupal_set_message($success); |
| 564 | drupal_goto(); |
| 565 | } |
| 566 | } |
| 567 | |
| 568 | function og_collections_pcpanel_revert_confirm($pcpanel) { |
| 569 | $form['pcpid'] = array('#type' => 'value', '#value' => $pcpanel->pcpid); |
| 570 | $form['type'] = array('#type' => 'value', '#value' => $pcpanel->grouptype); |
| 571 | $form['page_title'] = array('#type' => 'value', '#value' => $pcpanel->page_title); |
| 572 | |
| 573 | return confirm_form($form, |
| 574 | t('Are you sure you want to revert the type-specific pre-configured panel %title back to the Default type?', array('%title' => $pcpanel->page_title)), |
| 575 | "admin/og/og_collections/pcpanelsetup/$pcpanel->grouptype", |
| 576 | t('This action CANNOT be undone; any custom type-specific changes you have made to this pre-configured panel will be PERMANENTLY lost.'), |
| 577 | t('Revert'), t('Cancel') |
| 578 | ); |
| 579 | } |
| 580 | |
| 581 | function og_collections_pcpanel_revert_confirm_submit($form_id, $form_values) { |
| 582 | $pcpanel = og_collections_load_pcpanel(array($form_values['type'], $form_values['pcpid']), FALSE); |
| 583 | $defcollectioncfg = og_collections_load_collectioncfg(); |
| 584 | $collectioncfg = og_collections_load_collectioncfg($pcpanel->grouptype); |
| 585 | $collectioncfg[$pcpanel->pcpid]['usedef'] = 1; |
| 586 | $collectioncfg[$pcpanel->pcpid]['did'] = $defcollectioncfg[$pcpanel->pcpid]['did']; |
| 587 | panels_delete_display($pcpanel->did); |
| 588 | db_query("DELETE FROM {og_collections_pcpanel} WHERE pcpid = %d AND grouptype = '%s'", $pcpanel->pcpid, $pcpanel->grouptype); |
| 589 | og_collections_save_collectioncfg($pcpanel->grouptype, $collectioncfg, array($pcpanel->pcpid)); |
| 590 | } |
| 591 | |
| 592 | |
| 593 | function og_collections_pcpanel_delete_confirm($pcpid) { |
| 594 | $collectioncfg = og_collections_load_collectioncfg(); |
| 595 | $form['pcpid'] = array('#type' => 'value', '#value' => $pcpid); |
| 596 | $form['page_title'] = array('#type' => 'value', '#value' => $collectioncfg[$pcpid]['page_title'] ? $collectioncfg[$pcpid]['page_title'] : ''); |
| 597 | |
| 598 | return confirm_form($form, |
| 599 | t('Are you sure you want to delete the %title pre-configured panel?', array('%title' => $collectioncfg[$pcpid]['page_title'] ? $collectioncfg[$pcpid]['page_title'] : '')), |
| 600 | isset($_GET['destination']) ? $_GET['destination'] : 'admin/og/og_collections/collectioncfg', |
| 601 | t('This action CANNOT be undone.'), |
| 602 | t('Delete'), t('Cancel') |
| 603 | ); |
| 604 | } |
| 605 | |
| 606 | function og_collections_pcpanel_delete_confirm_submit($form_id, $form_values) { |
| 607 | og_collections_pcpanel_delete($form_values['pcpid']); |
| 608 | drupal_set_message(t('%title has been deleted.', array('%title' => $form_values['page_title']))); |
| 609 | } |
| 610 | |
| 611 | // very dangerous function. validate thoroughly before calling. |
| 612 | function og_collections_pcpanel_delete($pcpid) { |
| 613 | $result = db_query("SELECT did FROM {og_collections_pcpanel} WHERE pcpid = %d", $pcpid); |
| 614 | while ($row = db_fetch_array($result)) { |
| 615 | panels_delete_display($row['did']); |
| 616 | } |
| 617 | db_query("DELETE FROM {og_collections_pcpanel} WHERE pcpid = %d", $pcpid); |
| 618 | og_collections_manage_db('pcpid_'. $pcpid, 'drop'); |
| 619 | } |
| 620 | |
| 621 | /* |
| 622 | * Function that handles the panels API editing for all three panels |
| 623 | * editing types - display editing (i.e., content), layout, and layout settings. |
| 624 | */ |
| 625 | function og_collections_pcpanel_edit($op, $pcpid, &$error, &$success, $type = 'default') { |
| 626 | if (!$pcpanel = og_collections_load_pcpanel(array($type, $pcpid), TRUE)) { |
| 627 | if (!$pcpanel = og_collections_load_pcpanel(array('default', $pcpid), TRUE, $type)) { // only way this happens is with a bad pcpid. error out. |
| 628 | $error .= 'ERROR: Bad pcpid provided. The pre-configured panel you are attempting to edit does not exist.'; |
| 629 | return FALSE; |
| 630 | } |
| 631 | $isnew = TRUE; |
| 632 | if (isset($_POST['op'])) { |
| 633 | if ($_POST['op'] == 'Save') { // this is the second passthrough, and the user has chosen to save the panel; we slip the exported panel w/the 'new' $did so the submit function operates on that one instead |
| 634 | og_collections_export_display($pcpanel->display); |
| 635 | } |
| 636 | elseif ($_POST['op'] == 'Cancel') { |
| 637 | $success = t('Operation cancelled. A collection-specific panel has NOT been created; your pre-configured panel is still tied to the Default.'); |
| 638 | return $success; |
| 639 | } |
| 640 | } |
| 641 | else { |
| 642 | $group_types = og_collections_group_types(); |
| 643 | $newdisplay = 'NOTE: The !grouptype collection is currently tied to the Default type for this panel. If you save changes on this page, a version of this pre-configured panel specific to the !grouptype collection will be generated, and this panel\'s link to the Default pre-configured panel will be broken.'; |
| 644 | drupal_set_message(t($newdisplay, array('!grouptype' => $group_types[$type]))); |
| 645 | } |
| 646 | } |
| 647 | switch ($op) { |
| 648 | case 'content': |
| 649 | $saved = panels_edit($pcpanel->display, NULL, $pcpanel->display->content_types); |
| 650 | break; |
| 651 | case 'layout': |
| 652 | $saved = panels_edit_layout($pcpanel->display, t('Save'), NULL); |
| 653 | break; |
| 654 | case 'layset': |
| 655 | $saved = panels_edit_layout_settings($pcpanel->display, t('Save'), NULL); |
| 656 | break; |
| 657 | } |
| 658 | |
| 659 | if (!isset($_POST['op'])) { |
| 660 | $error = FALSE; |
| 661 | if ($op == 'content') { |
| 662 | print theme('page', $saved, FALSE); |
| 663 | return FALSE; |
| 664 | } |
| 665 | return $saved; |
| 666 | } |
| 667 | elseif ($_POST['op'] == 'Save' && is_object($saved)) { // if it's not an object at this stage, something's wrong. error out |
| 668 | if ($isnew) { |
| 669 | $pcpanel->display = $saved; |
| 670 | $pcpanel->did = $pcpanel->display->did; |
| 671 | $pcpanel->usedef = 0; |
| 672 | $pcpanel->grouptype = $type; |
| 673 | og_collections_save_pcpanel($pcpanel, TRUE); |
| 674 | } |
| 675 | $success = 'The settings for this pre-configured panel have been successfully updated.'; |
| 676 | } |
| 677 | else { |
| 678 | $error .= 'An unknown error occurred, causing the panels edit function to return an unidentified string. No changes have been saved to the pre-configured panel, but changes MAY have been saved to the panels display.'; // returns string on errors |
| 679 | } |
| 680 | } |
| 681 | |
| 682 | function og_collections_admin() { |
| 683 | $ops = variable_get('og_collections_settings', 0); |
| 684 | $helptext = t("<p>Group 'pre-configured panels' are saved collections of panels and settings that encompass all the options you are able to manually set for an individual group using OG Panels. By defining collections, you can automatically apply these collections to new groups as they are created.</p>"); |
| 685 | switch ($ops) { |
| 686 | case 0: |
| 687 | $helptext .= t(" |
| 688 | <p>Once activated, OG Collections allows varying levels of granularity in configuring these pre-configured panels. However, collections are currently disabled. Select one of the 'Enabled' settings below to begin collections.</p> |
| 689 | <ul><li>Selecting 'Enabled - One Overall Template' will cause ALL of your group types to use the same pre-configured panel.</li> |
| 690 | <li>Selecting 'Enabled - Templates Per Type' will allow you to define pre-configured panels for each group type you have defined in !ogadmin.</li></ul>", array('!ogadmin' => l(t('Organic Groups Configuration'), 'admin/og/og'))); |
| 691 | break; |
| 692 | case 1: |
| 693 | // TODO need to write up additional helptext for circumstances where the user may be switching from one collections configuration to another, once the backend has been written |
| 694 | |
| 695 | break; |
| 696 | case 2: |
| 697 | // TODO ditto above |
| 698 | break; |
| 699 | } |
| 700 | |
| 701 | $options = array('Disabled', 'Enabled - One Overall Template', 'Enabled - Templates Per Type'); |
| 702 | $form['og_collections']['helptext'] = array('#value' => $helptext); |
| 703 | $form['og_collections']['collectionsetting'] = array ( |
| 704 | '#type' => 'radios', |
| 705 | '#title' => t('Group Collections Settings'), |
| 706 | '#options' => $options, |
| 707 | '#default_value' => $ops, |
| 708 | '#required' => TRUE, |
| 709 | ); |
| 710 | $form['submit'] = array( |
| 711 | '#type' => 'submit', |
| 712 | '#value' => t('Save Configuration'), |
| 713 | '#id' => 'panels-dnd-save', |
| 714 | ); |
| 715 | return $form; |
| 716 | } |
| 717 | |
| 718 | function og_collections_admin_submit($form, $form_values) { |
| 719 | variable_set('og_collections_settings', $form_values['collectionsetting']); |
| 720 | if ($form_values['collectionsetting'] == 0) { |
| 721 | $msg = t('Group Collections have been disabled. Any pre-configured panel configuration you have done will be accessible if you reactive Group Collections.'); |
| 722 | } |
| 723 | else if ($form_values['collectionsetting'] == 1) { |
| 724 | $msg = t('Group Collections have been enabled, using one collection for all group types. You can configure your collection in !ogpanel.', array('!ogpanel' => l(t('Panel Templates'), 'admin/og/og_collections/collectioncfg'))); |
| 725 | } |
| 726 | else if ($form_values['collectionsetting'] == 2) { |
| 727 | $msg = t("Group Collections have been enabled, with one pre-configured panel allowed per group type. You can configure all of your collections in !ogpanel. Make sure to set up pre-configured panels for all desired group types now, as there is currently no way to retrofit existing groups with pre-configured panels you update later.", array('!ogpanel' => l(t('OG Collections Configuration'), 'admin/og/og_collections/collectioncfg'))); |
| 728 | } |
| 729 | drupal_set_message($msg); |
| 730 | cache_clear_all('*', 'cache_menu', TRUE); |
| 731 | return NULL; |
| 732 | } |
| 733 | |
| 734 | /** |
| 735 | * Implementation of hook_nodeapi() |
| 736 | * |
| 737 | * og_collections uses nodeapi to trigger the automated duplication of |
| 738 | * pcpanel collections into actual og panels whenever a group of the |
| 739 | * appropriate type is created. |
| 740 | * |
| 741 | * // TODO consider switching to workflow_ng for this |
| 742 | * |
| 743 | */ |
| 744 | function og_collections_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { |
| 745 | switch ($op) { |
| 746 | case 'insert': |
| 747 | if ($collectionsetting = variable_get('og_collections_settings', FALSE)) { |
| 748 | $group_types = og_collections_group_types(); |
| 749 | if (in_array($node->type, array_keys($group_types))) { |
| 750 | $multi = $collectionsetting == 1 ? FALSE : TRUE; |
| 751 | $defaultcfg = og_collections_load_collectioncfg(); // we'll need the default regardless of $multi |
| 752 | if ($multi) { |
| 753 | $collectioncfg = og_collections_load_collectioncfg($node->type); |
| 754 | foreach ($collectioncfg as $pcpid => $conf) { |
| 755 | if (!empty($conf['active'])) { |
| 756 | $toinsert[$pcpid] = !empty($conf['usedef']) ? $defaultcfg[$pcpid]['did'] : $conf['did']; // $conf will theoretically have the right $did either way, but this is the surefire way |
| 757 | } |
| 758 | } |
| 759 | } |
| 760 | else { |
| 761 | $type = 'default'; |
| 762 | $collectioncfg = $defaultcfg; |
| 763 | foreach ($collectioncfg as $pcpid => $conf) { |
| 764 | if (!empty($conf['active'])) { |
| 765 | $toinsert[$pcpid] = $conf['did']; |
| 766 | } |
| 767 | } |
| 768 | } |
| 769 | } |
| 770 | |
| 771 | if (!is_null($toinsert)) { |
| 772 | // now, attach the pcpanels to the nid via og_panels! |
| 773 | foreach ($toinsert as $pcpid => $did) { |
| 774 | $status = _og_collections_panelize_group($did, $node->nid, $collectioncfg[$pcpid], $pcpid); |
| 775 | if ($status == 'error') { |
| 776 | $message = t("Error occurred while adding the '!page_title'' pre-configured panel to the new '!groupname' group.", array('!page_title' => $collectioncfg[$pcpid]['page_title'], '!groupname' => $node->title)); |
| 777 | } |
| 778 | elseif ($status == 'status') { |
| 779 | $message = t("The '!page_title'' pre-configured panel was successfully added to the new '!groupname' group.", array('!page_title' => $collectioncfg[$pcpid]['page_title'], '!groupname' => $node->title)); |
| 780 | } |
| 781 | drupal_set_message($message, $status); |
| 782 | } |
| 783 | } |
| 784 | } |
| 785 | break; |
| 786 | } |
| 787 | } |
| 788 | |
| 789 | /** |
| 790 | * Add a pcpanel to a newly-created group, per the parameters passed in. |
| 791 | * |
| 792 | * @param int $did |
| 793 | * the did of the display being exported |
| 794 | * @param int $nid |
| 795 | * the nid of the newly-added group node |
| 796 | * @param array $conf |
| 797 | * a configuration array specific to the pcpanel being added in this iteration (@see og_collections_nodeapi()) |
| 798 | * @param int $pcpid |
| 799 | * the pcpid from which the panel is being instantiated |
| 800 | * @return string $status |
| 801 | * the type of message to report back on adding the pcpanel with - status or error |
| 802 | */ |
| 803 | function _og_collections_panelize_group($did, $nid, $conf, $pcpid) { |
| 804 | $display = panels_load_display($did); |
| 805 | og_collections_export_display($display, $nid); |
| 806 | panels_save_display($display); |
| 807 | $fields = og_collections_panel_fields(); |
| 808 | $conf['nid'] = $nid; |
| 809 | $conf['did'] = $display->did; |
| 810 | $conf['frompcpanel'] = $pcpid; // FIXME there needs to be a better, more comprehensive method of tracking this relationship. dids can go away, all too easily |
| 811 | if (!empty($conf['default_page'])) { // by default, og_panels removes any paths that were assigned to homepages. if this is gonna be a homepage, don't put in a path |
| 812 | $conf['path'] = ''; |
| 813 | } |
| 814 | foreach ($fields as $field => $value) { |
| 815 | $f[] = $field; |
| 816 | $q[] = $value; |
| 817 | $v[] = $conf[$field]; |
| 818 | } |
| 819 | |
| 820 | db_query("INSERT INTO {og_panels} (". implode(', ', $f) .") VALUES (". implode(', ', $q) .")", $v); |
| 821 | $status = db_error(); |
| 822 | return $status ? 'error' : 'status'; // returns string to set $status in drupal_set_message |
| 823 | } |
| 824 | |
| 825 | // ------------------------------------------------------------------------- |
| 826 | // Collections Helper functions, esp. save/load |
| 827 | |
| 828 | /** |
| 829 | * Adds/removes fields from the collectioncfg table as needed. |
| 830 | * |
| 831 | * Plays nice with both mysql and pgsql. The ONLY time this function gets called is when a pcpanel is deleted, or a new one is created. |
| 832 | * |
| 833 | * @param string $fieldname |
| 834 | * @param string $op |
| 835 | * must be either 'add' or 'drop' |
| 836 | * @return mixed |
| 837 | * ONLY returns FALSE if a bad $op value has been passed. Otherwise, void |
| 838 | */ |
| 839 | function og_collections_manage_db($fieldname, $op) { |
| 840 | if (strtolower($op) != ('add' || 'drop')) { |
| 841 | // bad $op |
| 842 | return FALSE; |
| 843 | } |
| 844 | switch ($GLOBALS['db_type']) { |
| 845 | case 'mysql': |
| 846 | case 'mysqli': |
| 847 | if ($op == 'add') { |
| 848 | db_query("ALTER TABLE {og_collections} ADD COLUMN $fieldname LONGTEXT NOT NULL"); |
| 849 | } |
| 850 | elseif ($op == 'drop') { |
| 851 | db_query("ALTER TABLE {og_collections} DROP COLUMN $fieldname"); |
| 852 | } |
| 853 | break; |
| 854 | |
| 855 | case 'pgsql': |
| 856 | if ($op == 'add') { |
| 857 | db_add_column($ret, 'og_collections', $fieldname, 'TEXT'); |
| 858 | } |
| 859 | elseif ($op == 'drop') { |
| 860 | db_query("ALTER TABLE {og_collections} DROP $fieldname"); |
| 861 | } |
| 862 | break; |
| 863 | } |
| 864 | } |
| 865 | |
| 866 | |
| 867 | /** |
| 868 | * Update the database with the new id values for the exported pcpanel. |
| 869 | * |
| 870 | * @param obj $pcpanel |
| 871 | * A pcpanel object. Only needs $collectioncfg values to perform this operation; $display is unnecessary |
| 872 | */ |
| 873 | function og_collections_pcpanel_handle_export($pcpanel) { |
| 874 | db_query("DELETE FROM {og_collections_pcpanel} WHERE pcpid = %d AND grouptype = '%s'", $pcpanel->pcpid, $pcpanel->grouptype); // in case of a residual display that avoided deletion |
| 875 | db_query("INSERT INTO {og_collections_pcpanel} (did, pcpid, grouptype) VALUES (%d, %d, '%s')", $pcpanel->did, $pcpanel->pcpid, $pcpanel->grouptype); |
| 876 | } |
| 877 | |
| 878 | function og_collections_export_display(&$display, $nid = NULL) { |
| 879 | eval(panels_export_display($display)); |
| 880 | panels_load_include('plugins'); |
| 881 | panels_load_include('common'); |
| 882 | $display->context = !is_null($nid) ? array('og_panels' => panels_context_create('group', $nid)) : array('og_panels' => panels_context_create_empty('group')); |
| 883 | $display->content_types = panels_common_get_allowed_types('og_panels', $display->context); |
| 884 | return $display; // just to be nice, return as well as by reference |
| 885 | } |
| 886 | |
| 887 | /** |
| 888 | * Loads a pre-configured panel object. |
| 889 | * |
| 890 | * @param mixed $op |
| 891 | * Either a valid $did, or an array that should be defined as follows: |
| 892 | * array($grouptype, $pcpid), corresponding to values in the og_collections_pcpanel table. |
| 893 | * @param bool $loaddisplay = TRUE |
| 894 | * If TRUE, the $pcpanel object will also be loaded with corresponding $display information. |
| 895 | * @param string $type2 = NULL |
| 896 | * Use this parameter if the collectioncfg to be loaded is different from the collectioncfg |
| 897 | * corresopnding to param1. Primarily for exporting/reversion. |
| 898 | * @return mixed |
| 899 | * Returns an object if all goes well. If type/pcpid provided were no good, FALSE is returned. |
| 900 | * If a bad did is provided, returns NULL. |
| 901 | */ |
| 902 | function og_collections_load_pcpanel($op, $loaddisplay = TRUE, $type2 = NULL) { |
| 903 | if (is_array($op) && (is_string($op[0]) && is_numeric($op[1]))) { |
| 904 | $result = db_query("SELECT * FROM {og_collections_pcpanel} WHERE grouptype = '%s' AND pcpid = %d", $op[0], $op[1]); |
| 905 | } |
| 906 | elseif (is_numeric($op)) { |
| 907 | $result = db_query("SELECT * FROM {og_collections_pcpanel} WHERE did = %d", $op); |
| 908 | } |
| 909 | |
| 910 | if ($pcpanel = db_fetch_object($result)) { |
| 911 | if ($loaddisplay) { |
| 912 | $pcpanel->display = panels_load_display($pcpanel->did); |
| 913 | panels_load_include('plugins'); |
| 914 | $pcpanel->display->context = array('og_panels' => panels_context_create_empty('group')); |
| 915 | panels_load_include('common'); |
| 916 | $pcpanel->display->content_types = panels_common_get_allowed_types('og_panels', $pcpanel->display->context); // TODO this is a taxing operation - cache it in some way if possible. store content_types in collectioncfg? |
| 917 | } |
| 918 | $collectioncfg = og_collections_load_collectioncfg($type2 ? $type2 : $pcpanel->grouptype); |
| 919 | if (isset($collectioncfg[$pcpanel->pcpid])) { |
| 920 | foreach ($collectioncfg[$pcpanel->pcpid] as $key => $value) { |
| 921 | if ($key != 'did') { |
| 922 | $pcpanel->$key = $value; |
| 923 | } |
| 924 | } |
| 925 | } |
| 926 | return $pcpanel; |
| 927 | } |
| 928 | else { |
| 929 | return is_array($op) ? FALSE : NULL; // returns false if a type/pcpid was provided and got nothing; returns NULL if a did was provided and got nothing |
| 930 | } |
| 931 | } |
| 932 | |
| 933 | /** |
| 934 | * Save a pcpanel object to the database. |
| 935 | * |
| 936 | * @param object $pcpanel |
| 937 | * @param bool $export |
| 938 | */ |
| 939 | function og_collections_save_pcpanel($pcpanel, $export = FALSE) { |
| 940 | $collectioncfg = og_collections_load_collectioncfg($pcpanel->grouptype); |
| 941 | foreach ((array)$pcpanel as $key => $value) { |
| 942 | if (in_array($key, array('pcpid', 'display', 'content_types'))) { |
| 943 | continue; |
| 944 | } |
| 945 | $collectioncfg[$pcpanel->pcpid][$key] = $value; |
| 946 | } |
| 947 | if ($export) { |
| 948 | og_collections_pcpanel_handle_export($pcpanel); |
| 949 | } |
| 950 | og_collections_save_collectioncfg($pcpanel->grouptype, $collectioncfg, array($pcpanel->pcpid)); |
| 951 | } |
| 952 | |
| 953 | /** |
| 954 | * Load all collection configurations into an associative array, keyed by grouptype. |
| 955 | * |
| 956 | * Rows are, by default, cached into a static variable. Will only requery to pick up a new set of |
| 957 | * collectioncfgs if $refresh is TRUE |
| 958 | * |
| 959 | * @param bool $refresh |
| 960 | * @return mixed $rows |
| 961 | * returns FALSE if no results are found. |
| 962 | */ |
| 963 | function og_collections_load_collectioncfgs($refresh = FALSE) { |
| 964 | static $rows; |
| 965 | if (!$rows || $refresh == TRUE) { |
| 966 | $result = db_query("SELECT * FROM {og_collections}"); |
| 967 | if (count(db_fetch_array($result)) != 1) { // only occurs if no pre-configured panels have been created yet. |
| 968 | $result = db_query("SELECT * FROM {og_collections}"); // TODO ugh - have to double-query until D6 solves this problem w/schema |
| 969 | while ($row = db_fetch_array($result)) { |
| 970 | $grouptype = array_shift($row); // gets rid of grouptype, which is always first |
| 971 | foreach ($row as $pcpid => $vals) { |
| 972 | $arr[(int)substr($pcpid, 6)] = $vals ? unserialize($vals) : array(); |
| 973 | } |
| 974 | uasort($arr, '_collectioncfg_sort'); // TODO consider trying to move this into the single load function somehow; could improve performance a bit |
| 975 | $rows[$grouptype] = $arr; |
| 976 | unset ($arr); |
| 977 | } |
| 978 | } |
| 979 | } |
| 980 | return $rows ? $rows : FALSE; |
| 981 | } |
| 982 | |
| 983 | |
| 984 | /** |
| 985 | * Specialized sort function. Sorts a given collectioncfg $conf array by the following criteria: |
| 986 | * 1. Default Page status |
| 987 | * 2. Active status (enabled/disabled in the current pre-configured panel) |
| 988 | * 3. Weight |
| 989 | */ |
| 990 | function _collectioncfg_sort($a, $b) { |
| 991 | $default_page = $b['default_page'] - $a['default_page']; |
| 992 | if ($default_page) { |
| 993 | return $default_page; |
| 994 | } |
| 995 | |
| 996 | $active = $b['active'] - $a['active']; |
| 997 | if ($active) { |
| 998 | return $active; |
| 999 | } |
| 1000 | |
| 1001 | // if ($a['active']) return ($a['weight'] - $b['weight']); |
| 1002 | return ($a['weight'] - $b['weight']); |
| 1003 | } |
| 1004 | |
| 1005 | /** |
| 1006 | * As with og_collections_load_collectioncfgs, uses static var to reduce db queries. only will refresh if explicitly instructed to do so, |
| 1007 | * and does so by passing that parameter on to the other load function |
| 1008 | */ |
| 1009 | function og_collections_load_collectioncfg($type = 'default', $refresh = FALSE) { |
| 1010 | static $collectioncfgs; |
| 1011 | if (!$collectioncfgs || $refresh == TRUE) { |
| 1012 | $collectioncfgs = og_collections_load_collectioncfgs($refresh); |
| 1013 | } |
| 1014 | if ($collectioncfgs) { |
| 1015 | if (!isset($collectioncfgs[$type])) { |
| 1016 | $collectioncfgs[$type] = og_collections_new_collectioncfg($type, $collectioncfgs['default']); |
| 1017 | } |
| 1018 | return $collectioncfgs[$type]; |
| 1019 | } |
| 1020 | } |
| 1021 | |
| 1022 | function og_collections_new_collectioncfg($type, $collectioncfg) { |
| 1023 | db_query("INSERT INTO {og_collections} (grouptype) VALUES ('%s')", $type); |
| 1024 | $pcpids = array_keys($collectioncfg); |
| 1025 | return og_collections_save_collectioncfg($type, $collectioncfg, $pcpids); |
| 1026 | } |
| 1027 |