bug fix for http://drupal.org/node/1883460
[project/sigmaone.git] / sigmaone / vtcore / plugins / regionarea / regionarea.admin
1 <?php
2
3 /**
4  * Implement hook_vtcore_settings()
5  *
6  * Notice that in this form, although
7  * we can use #theme but we opt not to
8  * because using #theme with theme registered
9  * to this theme only will not work if
10  * user change the admin theme to another theme
11  *
12  * Notice that we load all includes file by invoking
13  * vtcore_form_load_includes, that function will also
14  * register the file path so Drupal will reload it
15  * during ajax callback or form rebuild
16  *
17  * Notice that we use value in form state for the theme_key
18  * instead of grabbing one from $global.
19  */
20 function regionarea_vtcore_settings_alter_process(&$form, &$form_state) {
21
22   // Serve the correct theme on ajax request
23   if (arg(0) != 'system' && arg(1) != 'ajax') {
24     $admin_theme = variable_get('admin_theme', '0');
25     $settings = array(
26         'adminTheme' => array(
27                 'theme' => $admin_theme,
28         'theme_token' => drupal_get_token($admin_theme),
29       ),
30     );
31     drupal_add_js($settings, 'setting');
32   }
33
34   // Don't rely on global $theme_key
35   // Use one in form state instead
36   $theme_key = $form_state['build_info']['args'][0];
37   $theme_path = $form_state['build_info']['theme']['theme_path'];
38   $base_theme_path = $form_state['build_info']['theme']['base_theme_path'];
39
40   // Load all includes file and record it in $form_state['build_info']
41   // So Drupal will reload them during ajax process or form rebuild
42   $files = array(
43     $base_theme_path . '/vtcore/plugins/regionarea/regionarea.admin',
44     $base_theme_path . '/vtcore/plugins/regionarea/inc/helper_function.inc.php',
45     $base_theme_path . '/vtcore/plugins/regionarea/inc/subform.inc.php',
46   );
47
48   foreach ($files as $file) {
49     vtcore_form_load_includes($file, $form, $form_state);
50   }
51
52   // User area specific settings
53   $form['region'] = array(
54     '#type' => 'fieldset',
55     '#title' => t('Region Manager'),
56     '#collapsible' => FALSE,
57     '#collapsed' => FALSE,
58     '#weight' => -19,
59     '#group' => 'theme_core',
60     '#attached' => array(
61      'library' => array(
62         array('system', 'ui.sortable'),
63         array('system', 'ui.core')),
64      'js' => array(
65         $base_theme_path . '/vtcore/plugins/regionarea/js/regionarea.js',
66         $base_theme_path . '/vtcore/plugins/regionarea/js/regionareaPlugin.js',
67         ),
68                 'css' => array($base_theme_path . '/vtcore/plugins/regionarea/css/regionarea.css'),
69     ),
70     '#tree' => FALSE,
71   );
72
73   // Build container for configurator
74   $form['region']['configurator'] = array(
75     '#type' => 'container',
76     '#attributes' => array(
77       'id' => 'regionarea-configurator',
78     ),
79   );
80
81   // Give user select box if not on create new template mode
82   $options =  array(
83         '' => '-- ' . t('Select') . ' --',
84         'create_new' => t('Create New Layout'),
85   );
86
87   $options += _regionarea_get_all_layout_files($theme_key);
88   $options += _regionarea_get_all_layout_database($theme_key);
89
90   // @easter_egg
91   // You can set default layout when loading here
92   // $build_mode = 'create_new';
93   $build_mode = '';
94   if (isset($form_state['values'])) {
95     $build_mode = vtcore_get_default_value('layout_select', $form_state['values'], '');
96   }
97
98   $form['region']['configurator']['layout_select'] = array(
99     '#type' => 'select',
100     '#title' => t('Select layout file to process'),
101     '#options' => $options,
102     '#default_value' => $build_mode,
103   );
104
105   $form['region']['configurator']['layout_delete'] = array(
106     '#type' => 'submit',
107     '#name' => 'delete',
108     '#value' => t('Delete'),
109     '#submit' => array('regionarea_layout_delete_submit'),
110     '#weight' => 19,
111   );
112
113   $form['region']['configurator']['layout_process'] = array(
114     '#type' => 'submit',
115     '#name' => 'process',
116     '#value' => t('Process'),
117     '#submit' => array('regionarea_layout_process_submit'),
118     '#weight' => 19,
119     '#ajax' => array(
120       'callback' => 'regionarea_workarea_ajax_refresh',
121       'wrapper' => 'regionarea-workarea',
122       'method' => 'replace',
123       'effect' => 'slide',
124       'path' => 'system/ajax/theme-' . $theme_key,
125       'ajax_page_state' => BASE_THEME,
126     ),
127   );
128
129   // Build container for workspace
130   $form['region']['workarea'] = array(
131     '#type' => 'container',
132     '#attributes' => array(
133       'id' => 'regionarea-workarea',
134     ),
135   );
136
137   // Don't process any further if user hasn't select the correct configuration
138   if (empty($build_mode)) {
139     return $form;
140   }
141
142   // Container for settings
143   $form['region']['workarea']['settings'] = array(
144     '#type' => 'container',
145     '#attributes' => array(
146         'id' => 'workarea-settings',
147     ),
148   );
149
150   // Configuration for this layout
151   if ($build_mode == 'create_new') {
152     $form['region']['workarea']['settings']['layout_new'] = array(
153       '#type' => 'textfield',
154       '#title' => t('New layout filename'),
155       '#default_value' => '',
156       '#field_suffix' => '.layout',
157       '#description' => t('Enter valid default layout filename, such as page--node--1 for url node/1'),
158     );
159   }
160
161   $form['region']['workarea']['settings']['layout_storing'] = array(
162     '#type' => 'select',
163     '#title' => t('Layout file store mode'),
164     '#options' => array(
165         'database' => t('Store in database, variable table'),
166         'theme' => t('Store as layout file in !theme layout theme dynamic directory', array('!theme' => $theme_key)),
167       'plugin' => t('Store as layout file in region area plugin layouts directory'),
168     ),
169   );
170
171   // Build layout_data and layout_data
172   $layout_data = _regionarea_build_layouts_array($build_mode, $theme_key);
173
174   // Quit on empty $layout_data
175   if (empty($layout_data)) {
176     $form['region']['workarea']['empty'] = array(
177       '#markup' => '<div class="empty-layout">' . t('Failed to retrieve valid layout structure.') . '</div>',
178     );
179
180     return $form;
181   }
182
183   // Build place holder for drag and drop
184   // Enabled Areas Container
185   $form['region']['workarea']['enabled_area'] = array(
186     '#type' => 'container',
187     '#attributes' => array(
188       'id' => 'target--enabled--area',
189       'class' => array(
190         'drag-area-target',
191         'enabled-area',
192         'layout-parent',
193       ),
194     ),
195   );
196
197   $form['region']['workarea']['enabled_area']['element_title'] = array(
198     '#type' => 'markup',
199     '#markup' => '<h3 class="region-title">' . t('Workspace') . '</h3>',
200   );
201
202   $form['region']['workarea']['enabled_area']['empty'] = array(
203     '#type' => 'markup',
204     '#markup' => '<p class="emptyslot">' . t('There is no enabled areas available') . '</p>',
205   );
206
207   // Disabled Areas Container
208   $form['region']['workarea']['disabled_area'] = array(
209     '#type' => 'container',
210     '#attributes' => array(
211       'id' => 'target--disabled--area',
212       'class' => array(
213         'drag-area-target',
214         'disabled-area',
215         'layout-parent',
216       ),
217     ),
218   );
219
220   $form['region']['workarea']['disabled_area']['element_title'] = array(
221     '#type' => 'markup',
222     '#markup' => '<h3 class="region-title">' . t('Disabled Areas') . '</h3>',
223   );
224
225   $form['region']['workarea']['disabled_area']['empty'] = array(
226     '#type' => 'markup',
227     '#markup' => '<p class="emptyslot">' . t('There is no disabled areas available') . '</p>',
228   );
229
230   // Disabled Region Container
231   $form['region']['workarea']['disabled_region'] = array(
232     '#type' => 'container',
233     '#attributes' => array(
234       'id' => 'target--disabled--region',
235       'class' => array(
236         'drag-region-target',
237         'disabled-region',
238         'layout-parent',
239       ),
240     ),
241   );
242
243   $form['region']['workarea']['disabled_region']['element_title'] = array(
244     '#type' => 'markup',
245     '#markup' => '<h3 class="region-title">' . t('Disabled Regions') . '</h3>',
246   );
247
248   $form['region']['workarea']['disabled_region']['empty'] = array(
249     '#type' => 'markup',
250     '#markup' => '<p class="emptyslot">' . t('There is no disabled regions available') . '</p>',
251   );
252
253   // Disabled Block Container
254   $form['region']['workarea']['disabled_block'] = array(
255     '#type' => 'container',
256     '#attributes' => array(
257       'id' => 'target--disabled--block',
258       'class' => array(
259         'drag-block-target',
260         'disabled-block',
261         'layout-parent',
262       ),
263     ),
264   );
265
266   $form['region']['workarea']['disabled_block']['element_title'] = array(
267     '#type' => 'markup',
268     '#markup' => '<h3 class="region-title">' . t('Disabled Blocks') . '</h3>',
269   );
270
271   $form['region']['workarea']['disabled_block']['empty'] = array(
272     '#type' => 'markup',
273     '#markup' => '<p class="emptyslot">' . t('There is no disabled blocks available') . '</p>',
274   );
275
276   // Build all available tags
277   $available_tags = array('div' => 'div');
278   vtcore_alter_process('regionarea_available_tags', $available_tags);
279
280   // Build the areas from the layout_data first.
281   foreach ($layout_data['area'] as $area => $area_data) {
282     // Skip if no #enabled key, most likely we got
283     // broken .layout entry
284     if (!isset($area_data['#enabled'])) {
285       continue;
286     }
287
288     if ($area_data['#enabled'] == 1) {
289       $form['region']['workarea']['enabled_area'][$area] = _regionarea_build_area_forms($area, $area_data, $available_tags);
290     }
291     else {
292       $form['region']['workarea']['disabled_area'][$area] = _regionarea_build_area_forms($area, $area_data, $available_tags);
293     }
294   }
295
296   // Build the regions from the layout_data
297   $all_area = array(
298     'disabled' => t('Disabled'),
299   );
300   $all_area += _regionarea_build_parent_select_options($layout_data['area']);
301
302   foreach ($layout_data['region'] as $region => $region_data) {
303     if (isset($layout_data['area'][$region_data['#parent']])
304         && $layout_data['area'][$region_data['#parent']]['#enabled'] == 1
305         && $region_data['#parent'] != 'disabled') {
306       $form['region']['workarea']['enabled_area'][$region_data['#parent']][$region] = _regionarea_build_region_forms($region, $region_data, $all_area, $available_tags);
307     }
308     else {
309       $form['region']['workarea']['disabled_region'][$region] = _regionarea_build_region_forms($region, $region_data, $all_area, $available_tags);
310     }
311   }
312
313
314   // Build the blocks from the layout_data
315   $all_region = array(
316     'disabled' => t('Disabled'),
317   );
318
319   $all_region += _regionarea_build_parent_select_options($layout_data['region']);
320
321   foreach ($layout_data['block'] as $block => $block_data) {
322     $area_parent = '';
323     if ($block_data['#parent'] != 'disabled' && isset($layout_data['region'][$block_data['#parent']])) {
324       $area_parent = $layout_data['region'][$block_data['#parent']]['#parent'];
325     }
326
327     if (isset($layout_data['area'][$area_parent])
328         && isset($layout_data['region'][$block_data['#parent']])
329         && $layout_data['area'][$area_parent]['#enabled'] == 1
330         && $block_data['#parent'] != 'disabled') {
331       $form['region']['workarea']['enabled_area'][$area_parent][$block_data['#parent']][$block] = _regionarea_build_block_forms($block, $block_data, $all_region, $block_data['#block_type']);
332     }
333     else {
334       $form['region']['workarea']['disabled_block'][$block] = _regionarea_build_block_forms($block, $block_data, $all_region, $block_data['#block_type']);
335     }
336   }
337
338   // Add custom submit function
339   if (!in_array('regionarea_submit', $form['#submit'])) {
340     $form['#validate'][] = 'regionarea_validation';
341     $form['#submit'][] = 'regionarea_submit';
342   }
343 }
344
345 /**
346  * Submit callback function to delete the layout
347  */
348 function regionarea_layout_delete_submit(&$form, &$form_state) {
349   $theme_key = $form_state['build_info']['args'][0];
350   $file = $form_state['values']['layout_select'];
351   $paths = pathinfo($file);
352
353   // Layout stored in database, clean out the database
354   if (empty($paths['extension']) && $paths['dirname'] == '.' && isset($form_state['storage']['old_value']['layouts'][$paths['filename']])) {
355     $stored = variable_get('theme_' . $theme_key . '_settings');
356     unset($stored['layouts'][$paths['filename']]);
357
358     variable_set('theme_' . $theme_key . '_settings', $stored);
359     drupal_set_message(t('@file deleted from database.', array('@file' => $file)));
360   }
361   else {
362     // Don't allow to delete default files and plugin specified files
363     $banned = array('theme_default', 'layout', 'adminpage');
364     $path = explode('/', $paths['dirname']);
365     $remove = TRUE;
366     foreach ($banned as $ban) {
367       if (in_array($ban, $path)) {
368         $remove = FALSE;
369       }
370     }
371
372     if ($remove) {
373       $delete = file_unmanaged_delete($file);
374       if ($delete != FALSE) {
375         drupal_set_message(t('@file deleted.', array('@file' => $file)));
376       }
377     }
378     else {
379       drupal_set_message(t('@file cannot be deleted.', array('@file' => $file)));
380     }
381   }
382   // Unset these so form will destroy workarea
383   unset($form_state['values']['layout_select']);
384   unset($form_state['values']['layout_delete']);
385   unset($form_state['values']['layout_process']);
386
387   $form_state['submitted'] = TRUE;
388   $form_state['rebuild'] = TRUE;
389 }
390
391 /**
392  * Submit callback function to build the form
393  * based on selected layout
394  */
395 function regionarea_layout_process_submit(&$form, &$form_state) {
396   $form_state['storage']['old_value']['layout_select'] = $form_state['values']['layout_select'];
397   $form_state['submitted'] = FALSE;
398   $form_state['rebuild'] = TRUE;
399 }
400
401 /**
402  * Validation function for regionarea submit
403  */
404 function regionarea_validation(&$form, &$form_state) {
405   // Give error on empty filename when in create
406   // new layout mode
407   if ($form_state['values']['layout_select'] == 'create_new'
408       && empty($form_state['values']['layout_new'])
409       && isset($form['region']['workarea']['settings']['layout_new'])) {
410     form_set_error('layout_new', t('Filename required'));
411   }
412
413   // Give error on no layout at all
414   $area_enabled = FALSE;
415   foreach ($form_state['values']['area'] as $area => $areadata) {
416     if ($areadata['enabled'] == 1) {
417       $area_enabled = TRUE;
418       break;
419     }
420   }
421
422   if ($area_enabled == FALSE) {
423     form_set_error('workarea', t('At least 1 enabled area required for a valid layout files.'));
424   }
425
426 }
427
428 /**
429  * Main submit function to actually save the
430  * layout arrays either as database or as
431  * file
432  */
433 function regionarea_submit(&$form, &$form_state) {
434   global $vtcore;
435
436   $theme_key = $form_state['build_info']['args'][0];
437   $theme_path = $form_state['build_info']['theme']['theme_path'];
438   $base_theme_path = $form_state['build_info']['theme']['base_theme_path'];
439
440   $data = array();
441   // Move data out from $form_state;
442   _regionarea_build_data_for_saving('area', $data, $form_state);
443   _regionarea_build_data_for_saving('region', $data, $form_state);
444   _regionarea_build_data_for_saving('block', $data, $form_state);
445
446   // Let other plugin connect with this form
447   vtcore_alter_process('regionarea_vtcore_build_data_for_saving', $data, $form_state);
448
449   $storing = $form_state['values']['layout_storing'];
450   $file = $form_state['values']['layout_select'];
451   if (!empty($form_state['values']['layout_new'])) {
452     $file = $form_state['values']['layout_new'];
453   }
454
455   if ($storing == 'database') {
456     // Remove file path from $file
457     $file = basename($file);
458     $file = str_replace('.layout', '', $file);
459     $form_state['values']['layouts'][$file] = $data;
460
461     // Bug fix http://drupal.org/node/1883460
462     $form_state['storage']['old_value']['layouts'][$file] = $data;
463
464     drupal_set_message(t('@file saved to database.', array('@file' => $file)));
465   }
466
467   if ($storing == 'theme') {
468     $file = basename($file);
469     $file = str_replace('.layout', '', $file);
470     $filepath = $theme_path . '/layouts/theme_dynamic';
471     file_prepare_directory($filepath, $options = FILE_CREATE_DIRECTORY);
472     _regionarea_save_layout_file($filepath, $file, $data);
473   }
474
475   if ($storing == 'plugin') {
476     $file = basename($file);
477     $file = str_replace('.layout', '', $file);
478     $filepath = $base_theme_path . '/vtcore/plugins/regionarea/layouts';
479     file_prepare_directory($filepath, $options = FILE_CREATE_DIRECTORY);
480     _regionarea_save_layout_file($filepath, $file, $data);
481   }
482
483   // Do Clean up for sane form rebuilding
484   unset($form_state['values']['area']);
485   unset($form_state['values']['region']);
486   unset($form_state['values']['block']);
487   unset($form_state['values']['layout_new']);
488   unset($form_state['values']['layout_storing']);
489   unset($form_state['values']['layout_delete']);
490   unset($form_state['values']['layout_process']);
491   unset($form_state['values']['layout_select']);
492
493   unset($form_state['storage']['old_value']['area']);
494   unset($form_state['storage']['old_value']['region']);
495   unset($form_state['storage']['old_value']['block']);
496   unset($form_state['storage']['old_value']['layout_new']);
497   unset($form_state['storage']['old_value']['layout_storing']);
498   unset($form_state['storage']['old_value']['layout_delete']);
499   unset($form_state['storage']['old_value']['layout_process']);
500   unset($form_state['storage']['old_value']['layout_select']);
501
502   // Clear stored cache
503   if ($vtcore->cache) {
504     cache_clear_all($theme_key . '--', 'cache', TRUE);
505   }
506 }
507
508 /**
509  * Ajax callback function
510  */
511 function regionarea_configurator_ajax_refresh($form, &$form_state) {
512   return $form['region']['configurator'];
513 }
514
515 /**
516  * Ajax callback function
517  */
518 function regionarea_workarea_ajax_refresh($form, &$form_state) {
519   return $form['region']['workarea'];
520 }
521
522 /**
523  * Implements hook_regionarea_vtcore_block_settings_alter_process().
524  *
525  * We implement this hook to serve the layout plugin default vtcore-block blocks
526  */
527 function regionarea_regionarea_vtcore_block_settings_alter_process(&$form, $block, $block_data, $all_regions = FALSE) {
528   // Skip if not vtcore block
529   if ($block_data['#block_type'] != 'vtcore-block') {
530     return;
531   }
532   switch ($block) {
533     // Additional form setting for logo
534     case 'logo' :
535       $form['block'][$block]['site_title_enable'] = array(
536         '#type' => 'checkbox',
537         '#title' => t('Custom Site Title'),
538         '#default_value' => vtcore_get_default_value('#site_title_enable', $block_data, 1),
539       );
540
541       $form['block'][$block]['site_title'] = array(
542         '#type' => 'textfield',
543         '#default_value' => vtcore_get_default_value('#site_title', $block_data, ''),
544         '#description' => t('Enabling the custom site title by checking the checkbox above will override Drupal standard site name settings as found in admin/config/system/site-information'),
545       );
546
547       $form['block'][$block]['site_slogan_enable'] = array(
548         '#type' => 'checkbox',
549         '#title' => t('Custom site slogan'),
550         '#default_value' => vtcore_get_default_value('#site_slogan_enable', $block_data, 1),
551       );
552
553       $form['block'][$block]['site_slogan'] = array(
554         '#type' => 'textarea',
555         '#default_value' => vtcore_get_default_value('#site_slogan', $block_data, ''),
556         '#description' => t('Enabling the custom site slogan by checking the checkbox above will override Drupal standard site slogan settings as found in admin/config/system/site-information'),
557       );
558     break;
559
560     // Additional form setting for breadcrumb
561     case 'breadcrumb' :
562       $form['block'][$block]['breadcrumb_separator'] = array(
563         '#type' => 'textfield',
564         '#title' => t('Breadcrumb separator'),
565         '#default_value' => vtcore_get_default_value('#breadcrumb_separator', $block_data, ' | '),
566       );
567     break;
568
569     // Additional form setting for tabs
570     case 'tabs' :
571       $form['block'][$block]['tabs_js'] = array(
572         '#type' => 'checkbox',
573         '#title' => t('Enable js'),
574         '#default_value' => vtcore_get_default_value('#tab_js', $block_data, 1),
575       );
576
577       $form['block'][$block]['tabs_js_user'] = array(
578         '#type' => 'checkbox',
579         '#title' => t('Enable js on user page'),
580         '#default_value' =>  vtcore_get_default_value('#tab_js_user', $block_data, 0),
581       );
582
583       $form['block'][$block]['tabs_js_overlay'] = array(
584         '#type' => 'checkbox',
585         '#title' => t('Enable js on overlay'),
586         '#default_value' =>  vtcore_get_default_value('#tab_js_overlay', $block_data, 0),
587       );
588     break;
589   }
590 }