Advertisement
Guest User

allocated_seating module

a guest
May 26th, 2015
264
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2. // $Id$
  3. /*
  4.  * @file allocated_seating.module
  5.  * Provides form elements to enable other modules to define allocated seating
  6.  * and collect user input
  7.  * @copyright Copyright(c) 2010 Lee Rowlands
  8.  * @license GPL v2 http://www.fsf.org/licensing/licenses/gpl.html
  9.  * @author Lee Rowlands leerowlands at rowlands-bcs dot com
  10.  *
  11.  */
  12.  
  13. /**
  14.  * Implementation of hook_menu().
  15.  */
  16. function allocated_seating_menu() {
  17.   //generic Call handler, append args to return specific form elements
  18.  
  19.   $items['allocated_seating/ajax'] = array(
  20.     'title'            => 'Generic Call handler',
  21.     'delivery callback' => 'drupal_json_output',
  22.     'page callback'    => 'allocated_seating_ajax',
  23.     'access arguments' =>  array('create seating plans'),
  24.     'type'             => MENU_CALLBACK
  25.   );
  26.   return $items;
  27. }
  28.  
  29.  
  30. /**
  31.  * Implements hook_permission
  32. */
  33.  
  34. function  allocated_seating_permission() {
  35.   return array(
  36.     'create seating plans' => array(
  37.       'title' => t('Create seating plans'),
  38.     )
  39.   );
  40. }
  41.  
  42. /**
  43.  * Implementation of hook_elements_info().
  44.  */
  45. function allocated_seating_element_info() {
  46.   $type['allocated_seating_seat_design'] = array(
  47.     '#input' => TRUE,
  48.     '#tree' => TRUE,
  49.     '#default_value' => array(
  50.       'seats' => 40,
  51.       'row_count' => 2,
  52.       'floor_count' => 1,
  53.       'floors' => array(),
  54.     ),
  55.     '#process' => array('allocated_seating_seat_design_process'),
  56.     '#theme' => array('allocated_seating_seat_design'),
  57.   );
  58.  
  59.   $type['allocated_seating_seat_select'] = array(
  60.     '#input' => TRUE,
  61.     '#tree' => TRUE,
  62.     '#process' => array('allocated_seating_seat_select_process'),
  63.     '#element_validate' => array('allocated_seating_seat_select_validate'),    
  64.     '#required_seats' => NULL,
  65.   );
  66.   return $type;
  67. }
  68.  
  69.  
  70. /**
  71.  * Implementation of hook_theme().
  72.  */
  73. function allocated_seating_theme($existing, $type, $theme, $path) {
  74.   return array(
  75.     'allocated_seating_seat_design' => array(
  76.       'arguments' => array('element' => NULL),
  77.     ),
  78.     'allocated_seating_seat_select' => array(
  79.       'arguments' => array('element' => NULL),
  80.     ),
  81.     'allocated_seating_seat_available' => array(
  82.       'arguments' => array('plan' => array(),
  83.                            'not_available' => array()
  84.                           ),
  85.     ),
  86.   );
  87. }
  88.  
  89. /**
  90.  * Provides processing to expand the form element
  91. */
  92. function allocated_seating_seat_select_process($element, $form_state, $complete_form) {
  93.   if (empty($element['#plan'])) {
  94.     //no floor plan!
  95.     return;
  96.   }
  97.   $plan = $element['#plan'];
  98.   if (!$element['#not_available']) {
  99.     $element['#not_available'] = array();
  100.   }
  101.   $blank = 1;
  102.   $parents = $element['#parents'];
  103.   $element['floors'] = array(
  104.     '#tree' => FALSE, //we structure the data in a nest for theming but only want seat# => 1/0
  105.     '#parents' => array_merge($parents, array('floors'))
  106.   );
  107.   foreach ($plan['floors'] as $f => $floor) {
  108.     $element['floors'][$f] = array(
  109.       '#tree' => FALSE,
  110.       '#col_count' => $floor['col_count'],
  111.       'title' => array(
  112.         '#value' => $floor['title']
  113.       ),
  114.       'rows' => array(
  115.         '#tree' => FALSE,
  116.       )  
  117.     );
  118.     foreach ($floor['rows'] as $r => $row) {
  119.       $element['floors'][$f]['rows'][$r] = array(
  120.         '#tree' => FALSE,
  121.         'columns' => array(
  122.           '#tree' => FALSE,
  123.           '#parents' => array_merge($parents, array('floors', $f, 'rows', $r, 'columns')),
  124.         )
  125.       );
  126.       foreach ($row['columns'] as $c => $column) {
  127.         if ($column['seat'] &&
  128.             is_numeric($column['seat']) &&
  129.             !in_array($column['seat'], $element['#not_available'])) {
  130.           //add the seat checkbox
  131.           $element['floors'][$f]['rows'][$r]['columns'][$column['seat']] = array(
  132.             '#attributes' => array('class' => 'allocated-seating-seat'),
  133.             '#type' => 'checkbox',
  134.             '#parents' => array('seats', $column['seat']),
  135.             '#title' => $column['seat']
  136.           );
  137.         }
  138.         else {
  139.           //add the blank
  140.           $element['floors'][$f]['rows'][$r]['columns']['b_'. $blank] = array(
  141.             '#value' => '&nbsp;'
  142.           );
  143.           $blank++;
  144.         }
  145.       }
  146.     }
  147.   }
  148.   return $element;
  149. }
  150.  
  151. /**
  152.  * Provides processing to expand the form element
  153. */
  154. function allocated_seating_seat_design_process($element, $form_state, $complete_form) {
  155.   static $plan,$post_static;
  156.   // Cache the submitted $_POST data.
  157.   if (!empty($element['#post']) || $post_static === NULL) {
  158.     if (count($element['#array_parents']) == 1) {
  159.       $post = &$element['#post'][$element['#array_parents'][0]];
  160.       $post_static = $element['#post'][$element['#array_parents'][0]];
  161.     }
  162.     elseif (count($element['#array_parents']) == 2) {
  163.       $post = &$element['#post'][$element['#array_parents'][0]][$element['#array_parents'][1]];
  164.       $post_static = $element['#post'][$element['#array_parents'][0]][$element['#array_parents'][1]];
  165.     }
  166.     elseif (count($element['#array_parents']) == 3) {
  167.       $post = &$element['#post'][$element['#array_parents'][0]][$element['#array_parents'][1]][$element['#array_parents'][2]];
  168.       $post_static = $element['#post'][$element['#array_parents'][0]][$element['#array_parents'][1]][$element['#array_parents'][2]];
  169.     }
  170.     else {
  171.       $post = array();
  172.       $post_static = array();
  173.     }
  174.   }
  175.   $all_defaults = array();
  176.   $all_defaults['allocated_seating_seat_design'] = element_info('allocated_seating_seat_design');
  177.   $defaults = $all_defaults['allocated_seating_seat_design']['#default_value'];
  178.   // Ensure there are correct defaults.
  179.   foreach ($all_defaults['allocated_seating_seat_design']['#default_value'] as $var => $default) {
  180.     if (empty($element['#value'][$var])) {
  181.       $element['#value'][$var] = $default;
  182.     }
  183.   }
  184.   if (empty($element['#seats'])) {
  185.     //must know the # of seats!
  186.     return array(
  187.       '#value' => t('Did not receive number of seats for the design, cannot proceed. Please set the #seats element attribute.')
  188.     );
  189.   }
  190.  if (empty($plan)) {
  191.     if (empty($element['#value']['floors'])) {
  192.     $default = array(
  193.       'floors' => array(
  194.         array(
  195.           'title' => t('Floor 1'),
  196.           'rows' => array()
  197.         )
  198.       )
  199.     );//the default
  200.     $cols = ceil($element['#seats'] / 4); //default 4 rows
  201.     $row = 0;
  202.     $s = 1;
  203.     while ($row < 4) {
  204.       $col = 0;
  205.       $default['floors'][0]['rows'][$row] = array('columns' => array()); //add the rows
  206.       while ($col < $cols) {
  207.         if ($s <= $element['#seats']) {
  208.           $seat = $s;
  209.           $s++;
  210.         }
  211.         else {
  212.           $seat = FALSE;
  213.         }
  214.         $default['floors'][0]['rows'][$row]['columns'][] = array('seat' => $seat); //add the seat
  215.         $col++;
  216.       }
  217.       $row++;
  218.     }
  219.     $element['#value'] = $default;
  220.   }
  221.   else {
  222.       // Check if a new floor needs to be added.
  223.       if (!empty($form_state['post']['_triggering_element_name']) && $form_state['post']['_triggering_element_value'] == t('Add floor')) {
  224.         $element['#value'] =  $_POST['ticket_plan'];
  225.         allocated_seating_plan_add_floor($element, $post);
  226.       }
  227.     //make sure our seats matches the number in the plan
  228.     $real_seats = allocated_seating_real_seats($element['#value']);
  229.     $needed_seats = $element['#seats'];
  230.     //do we have enough?
  231.     $total_seats = allocated_seating_plan_seats($element['#value']);
  232.     while ($total_seats < $needed_seats) {
  233.       allocated_seating_plan_floor_add_row($element['#value'], 0);
  234.       $total_seats = allocated_seating_plan_seats($element['#value']);
  235.     }
  236.     if ($needed_seats != $real_seats) {
  237.       //we have an issue here
  238.       $seat_map = allocated_seating_get_map($element['#value']);
  239.       $blanks = $seat_map['blanks'];
  240.       if ($needed_seats < $real_seats) {
  241.         //we need to remove some seats
  242.         while ($needed_seats < $real_seats) {
  243.           $remove = $seat_map['seats'][$real_seats];
  244.           if ($remove) {
  245.             $element['#value']['floors'][$remove['floor']]['rows'][$remove['row']]['columns'][$remove['column']]['seat'] = FALSE;
  246.           }
  247.           $real_seats--;
  248.         }
  249.       }
  250.      
  251.       else {
  252.         //we need to add some
  253.         while ($needed_seats > $real_seats) {
  254.           $real_seats++;
  255.           $blank = array_shift($blanks);
  256.           $element['#value']['floors'][$blank['floor']]['rows'][$blank['row']]['columns'][$blank['column']]['seat'] = $real_seats;
  257.         }
  258.       }
  259.     }
  260.   }
  261.  
  262.   $plan = $element['#value'];
  263. }
  264.   $parents = $element['#parents'];
  265.   $element['floors'] = array(
  266.     '#prefix' => '<div id="as-wrap-'. $element['#id'] .'">',
  267.     '#suffix' => '</div>'
  268.   );
  269.   if ($form_state['storage']['type']) {
  270.     $total_seats = allocated_seating_total_seats($plan);
  271.     if ($total_seats < $element['#seats']) {
  272.       form_set_error(implode('][', $element['#parents']), t('The entered row and column combination is not sufficient to meet the required number of seats, please try again'));
  273.     }
  274.     switch ($form_state['storage']['type']) {
  275.       case 'row':
  276.         $floor = $form_state['storage']['floor'];
  277.         $current_rows = $original_rows = count($plan['floors'][$floor]['rows']);
  278.         $row_count = $plan['floors'][$floor]['row_count'];
  279.         while ($current_rows < $row_count) {
  280.           allocated_seating_plan_floor_add_row($plan, $floor);
  281.           $current_rows++;
  282.         }
  283.         while ($current_rows > $row_count) {
  284.           allocated_seating_plan_remove_row($plan, $floor);
  285.           $current_rows--;
  286.         }
  287.         break;
  288.      
  289.       case 'column':
  290.         $floor = $form_state['storage']['floor'];
  291.         $current_cols = $original_cols = count($plan['floors'][$floor]['rows'][0]['columns']);
  292.         $col_count = $plan['floors'][$floor]['col_count'];
  293.         if ($col_count > 23) {
  294.           form_set_error('', t('The seating designer does not support more than 23 columns.'));
  295.           $col_count = 23;
  296.         }
  297.         while ($current_cols < $col_count) {
  298.           allocated_seating_plan_floor_add_column($plan, $floor);
  299.           $current_cols++;
  300.         }
  301.         while ($current_cols > $col_count) {
  302.           allocated_seating_plan_remove_column($plan, $floor);
  303.           $current_cols--;
  304.         }
  305.         break;
  306.     }
  307.     unset($form_state['storage']['type'], $form_state['storage']['floor']);
  308.   }
  309.   foreach ($plan['floors'] as $f => $floor) {
  310.     $element['floors'][$f] = array(
  311.       '#tree' => TRUE,
  312.       '#parents' => array_merge($parents, array('floors', $f)),
  313.       'title' => array(
  314.         '#type'          => 'textfield',
  315.         '#title'         => t('Floor title'),
  316.         '#parents' => array_merge($parents, array('floors', $f, 'title')),
  317.         '#default_value' => t('Floor !floor', array('!floor' => $f + 1)),
  318.         '#size'          => 10,
  319.         '#maxlength'     => 50,
  320.         '#required'      => TRUE,
  321.       ),
  322.       'row_count' => array(
  323.         '#type'          => 'textfield',
  324.         '#title'         => t('Rows'),
  325.         '#parents' => array_merge($parents, array('floors', $f, 'row_count')),
  326.         '#default_value' => count($floor['rows']),
  327.         '#size'          => 10,
  328.         '#maxlength'     => 10,
  329.         '#required'      => TRUE,
  330.         '#ajax' => array(
  331.           'path' => 'allocated_seating/ajax/row/'. $f + 1 .'/'. $element['#ajax_extra'] . implode('/', $parents),
  332.           'wrapper' => 'as-wrap-'. $element['#id'],
  333.           'event' => 'change',
  334.           'method' => 'replace',
  335.           'effect' => 'fade',
  336.         ),
  337.       ),
  338.       'col_count' => array(
  339.         '#type'          => 'textfield',
  340.         '#title'         => t('Columns'),
  341.         '#parents'       => array_merge($parents, array('floors', $f, 'col_count')),
  342.         '#default_value' => count($floor['rows'][0]['columns']),
  343.         '#size'          => 10,
  344.         '#maxlength'     => 10,
  345.         '#required'      => TRUE,
  346.         '#ajax' => array(
  347.           'event' => 'change',
  348.           'path' => 'allocated_seating/ajax/column/'. $f + 1 .'/'. $element['#ajax_extra'] . implode('/', $parents),
  349.           'wrapper' => 'as-wrap-'. $element['#id'],
  350.           'method' => 'replace',
  351.           'effect' => 'fade',
  352.         ),
  353.       ),
  354.       'remove_floor' => array(
  355.         '#type' => 'submit',
  356.         '#value' => t('Remove floor '). ($f + 1),
  357.         '#submit' => array('allocated_seating_design_remove_floor'),
  358.         '#ajax' => array(
  359.           'path' => 'allocated_seating/ajax/floor/'. $element['#ajax_extra'] . implode('/', $parents),
  360.           'wrapper' => 'as-wrap-'. $element['#id'],
  361.           'method' => 'replace',
  362.           'effect' => 'fade',
  363.         )
  364.       ),
  365.       'rows' => array(
  366.         '#tree' => TRUE,
  367.         '#parents' => array_merge($parents, array('floors', $f, 'rows')),
  368.       )  
  369.     );
  370.     foreach ($floor['rows'] as $r => $row) {
  371.       $element['floors'][$f]['rows'][$r] = array(
  372.         '#tree' => TRUE,
  373.         '#parents' => array_merge($parents, array('floors', $f, 'rows', $r)),
  374.         'columns' => array(
  375.           '#tree' => TRUE,
  376.           '#parents' => array_merge($parents, array('floors', $f, 'rows', $r, 'columns')),
  377.         )
  378.       );
  379.       foreach ($row['columns'] as $c => $column) {
  380.         //add the seat string and value
  381.         $element['floors'][$f]['rows'][$r]['columns'][$c]['drag'] = array(
  382.           '#parents' => array_merge($parents, array('floors', $f, 'rows', $r, 'columns', $c, 'drag')),
  383.           '#attributes' => array('class' => 'allocated-seating-seat'),
  384.           '#type' => '#markup',
  385.           '#value' => $column['seat'] ? $column['seat'] : '&nbsp;'
  386.         );
  387.         $element['floors'][$f]['rows'][$r]['columns'][$c]['seat'] = array(
  388.           '#parents' => array_merge($parents, array('floors', $f, 'rows', $r, 'columns', $c, 'seat')),
  389.           '#type' => 'hidden',
  390.           '#value' => $column['seat']
  391.         );
  392.       }
  393.     }
  394.   }
  395.  
  396.   $element['add_floor_row_count'] = array(
  397.     '#type'          => 'textfield',
  398.     '#title'         => t('Rows'),
  399.     '#default_value' => isset($form_state['post']['add_floor_row_count']) ? $form_state['post']['add_floor_row_count'] : 4,
  400.     '#size'          => 10,
  401.     '#maxlength'     => 10
  402.   );
  403.  
  404.   $element['add_floor_col_count'] = array(
  405.     '#type'          => 'textfield',
  406.     '#title'         => t('Cols'),
  407.     '#default_value' => isset($form_state['post']['add_floor_col_count']) ? $form_state['post']['add_floor_col_count'] : 10,
  408.     '#size'          => 10,
  409.     '#maxlength'     => 10
  410.   );
  411.  
  412.   $element['add_floor_ticket_count'] = array(
  413.     '#type'          => 'textfield',
  414.     '#title'         => t('Tickets'),
  415.     '#default_value' => 0,
  416.     '#size'          => 10,
  417.     '#maxlength'     => 10,
  418.     '#description'   => t('Start with this many tickets on the floor')
  419.   );
  420.  
  421.   $element['add_floor'] = array(
  422.     '#type' => 'submit',
  423.     '#value' => t('Add floor'),
  424.     '#submit' => array('allocated_seating_design_add_floor'),
  425.     '#executes_submit_callback' => true,
  426.     '#ajax' => array(
  427.       'path' => 'allocated_seating/ajax/floor/'. $element['#ajax_extra'] . implode('/', $parents),
  428.       'callback' => 'allocated_seating_design_add_floor',
  429.       'wrapper' => 'as-wrap-'. $element['#id'],
  430.       'method' => 'replace',
  431.       'effect' => 'fade',
  432.     )
  433.   );
  434.   return $element;  
  435. }
  436.  
  437. /**
  438.  * Removes a floor from the design
  439. */
  440. function allocated_seating_design_remove_floor($form, &$form_state) {
  441.   $button = $form_state['clicked_button'];
  442.   $field_parents = $button['#parents'];
  443.   $floor = $field_parents[count($field_parents) - 2];
  444.   $depth = count($field_parents) - 4;
  445.   $field_name = $field_parents[$depth];
  446.   if ($depth > 0) {
  447.     //we have a tree arrangement here
  448.     switch ($depth) {
  449.       case 1:
  450.         allocated_seating_plan_remove_floor($form_state['values'][$field_parents[0]][$field_name], $floor);
  451.         break;
  452.       case 2:
  453.         allocated_seating_plan_remove_floor($form_state['values'][$field_parents[0]][$field_parents[1]][$field_name], $floor);
  454.         break;
  455.       case 3:
  456.         allocated_seating_plan_remove_floor($form_state['values'][$field_parents[0]][$field_parents[1]][$field_parents[2]][$field_name], $floor);
  457.         break;
  458.       //that ought to be enough
  459.     }
  460.   }
  461.   else {
  462.     allocated_seating_plan_remove_floor($form_state['values'][$field_name], $floor);
  463.   }
  464.   unset($form_state['submit_handlers']);
  465.   form_execute_handlers('submit', $form, $form_state);
  466.   $form_state['rebuild'] = TRUE;
  467. }
  468.  
  469. /**
  470.  * Adds a floor to a design
  471. */
  472. function allocated_seating_design_add_floor($form, &$form_state) {
  473.  
  474.   $button = $form_state['clicked_button'];
  475.   $parents = $button['#array_parents'];
  476.   $button_name = array_pop($parents);
  477.   $field_name = array_pop($parents);
  478.   $field_parents = $button['#parents'];
  479.   $new_rows = $form_state['values']['add_floor_row_count'];
  480.   $new_cols = $form_state['values']['add_floor_col_count'];
  481.   $new_tickets = $form_state['values']['add_floor_ticket_count'];
  482.  
  483.   if (count($field_parents) > 1) {
  484.     //we have a tree arrangement here
  485.     switch (count($field_parents)) {
  486.       case 2:
  487.         //allocated_seating_plan_add_floor($form_state['values'][$field_parents[0]][$field_name], $new_rows, $new_cols, $new_tickets);
  488.         break;
  489.       case 3:
  490.        // allocated_seating_plan_add_floor($form_state['values'][$field_parents[0]][$field_parents[1]][$field_name], $new_rows, $new_cols, $new_tickets);
  491.         break;
  492.       case 4:
  493.        // allocated_seating_plan_add_floor($form_state['values'][$field_parents[0]][$field_parents[1]][$field_parents[2]][$field_name], $new_rows, $new_cols, $new_tickets);
  494.         break;
  495.       //that ought to be enough
  496.     }
  497.   }
  498.   else {
  499.     //allocated_seating_plan_add_floor($form_state['values'][$field_name], $new_rows, $new_cols, $new_tickets);
  500.   }
  501.   unset($form_state['submit_handlers']);
  502.   form_execute_handlers('submit', $form, $form_state);
  503.   $form_state['rebuild'] = TRUE;
  504. }
  505.  
  506. /**
  507.  * Default implementation of theme_allocated_seating_seat_select
  508. */
  509. function theme_allocated_seating_seat_select($element) {
  510.   jquery_ui_add(array('ui.sortable', 'ui.droppable', 'ui.tabs'));
  511.   drupal_add_js(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.js');
  512.   drupal_add_css(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.css');
  513.   drupal_add_css(drupal_get_path('module', 'jquery_ui') . '/jquery.ui/themes/default/ui.all.css');
  514.   $output = '<div id="allocated-seating-tabs" class="allocated-seating-seat-select"><ul>';
  515.   $tabs = '';
  516.   foreach (element_children($element['floors']) as $key) {
  517.     $title = $element['floors'][$key]['title']['#value'];
  518.     $output .= '<li><a href="#allocated-seating-tabs-'. $key .'">'. check_plain($title) .'</a></li>';
  519.     $tabs .= '<div id="allocated-seating-tabs-'. $key .'">'.
  520.       $element['floors'][$key]['title']['#value']
  521.       . '<div class="floor-front cols-'. $element['floors'][$key]['#col_count'] .'">'. t('Front') .'</div>'
  522.       .'<ul class="allocated-seating-seats no-drag cols-'. $element['floors'][$key]['#col_count'] .'">';
  523.     foreach (element_children($element['floors'][$key]['rows']) as $row) {
  524.       foreach (element_children($element['floors'][$key]['rows'][$row]['columns']) as $column) {
  525.         $tabs .= '<li class="ui-state-highlight';
  526.         if ($element['floors'][$key]['rows'][$row]['columns'][$column]['#type'] == 'checkbox') {
  527.           $tabs .= '">'. theme('checkbox', $element['floors'][$key]['rows'][$row]['columns'][$column]);
  528.         }
  529.         else {
  530.           $tabs .= ' not-available">&nbsp';
  531.         }
  532.         $tabs .=  '</li>';
  533.       }
  534.     }
  535.     $tabs .= '</ul>'. $values .'<div class="clear"></div></div>';
  536.   }
  537.   $output .= '</ul>';
  538.   $output .= $tabs;
  539.   $output .= '</div>';
  540.   return $output;
  541. }
  542.  
  543. /**
  544.  * Default implementation of theme_allocated_seating_seat_available
  545. */
  546. function theme_allocated_seating_seat_available($plan, $not_available) {
  547.   $blank = 1;
  548.   $element['floors'] = array(
  549.     '#tree' => FALSE, //we structure the data in a nest for theming but only want seat# => 1/0
  550.     '#parents' => array('floors')
  551.   );
  552.   foreach ($plan['floors'] as $f => $floor) {
  553.     $element['floors'][$f] = array(
  554.       '#tree' => FALSE,
  555.       '#col_count' => $floor['col_count'],
  556.       'title' => array(
  557.         '#value' => $floor['title']
  558.       ),
  559.       'rows' => array(
  560.         '#tree' => FALSE,
  561.       )  
  562.     );
  563.     foreach ($floor['rows'] as $r => $row) {
  564.       $element['floors'][$f]['rows'][$r] = array(
  565.         '#tree' => FALSE,
  566.         'columns' => array(
  567.           '#tree' => FALSE,
  568.           '#parents' => array('floors', $f, 'rows', $r, 'columns'),
  569.         )
  570.       );
  571.       foreach ($row['columns'] as $c => $column) {
  572.         $state = 'available';
  573.         if ($column['seat'] &&
  574.             is_numeric($column['seat']) &&
  575.             in_array($column['seat'], $not_available)) {
  576.           $state = 'unavailable';
  577.         }
  578.         //add the seat field
  579.         $element['floors'][$f]['rows'][$r]['columns'][$column['seat']] = array(
  580.           '#value' => '<div class="allocated-seating-seat '. $state .'">'. $column['seat'] .'</div>',
  581.           '#parents' => array('seats', $column['seat']),
  582.         );
  583.       }
  584.     }
  585.   }
  586.   drupal_add_library('system', 'ui.sortable');
  587.   drupal_add_library('system', 'ui.tabs');
  588.   drupal_add_library('system', 'ui.droppable');
  589.   //jquery_ui_add(array('ui.sortable', 'ui.droppable', 'ui.tabs'));
  590.   drupal_add_js(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.js');
  591.   drupal_add_css(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.css');
  592.   drupal_add_css(drupal_get_path('module', 'jquery_ui') . '/jquery.ui/themes/default/ui.all.css');
  593.   $output = '<div id="allocated-seating-tabs" class="allocated-seating-seat-select"><ul>';
  594.   $tabs = '';
  595.   foreach (element_children($element['floors']) as $key) {
  596.     $title = $element['floors'][$key]['title']['#value'];
  597.     $output .= '<li><a href="#allocated-seating-tabs-'. $key .'">'. check_plain($title) .'</a></li>';
  598.     $tabs .= '<div id="allocated-seating-tabs-'. $key .'">'.
  599.       $element['floors'][$key]['title']['#value']
  600.       . '<div class="floor-front cols-'. $element['floors'][$key]['#col_count'] .'">'. t('Front') .'</div>'
  601.       .'<ul class="allocated-seating-seats no-drag cols-'. $element['floors'][$key]['#col_count'] .'">';
  602.     foreach (element_children($element['floors'][$key]['rows']) as $row) {
  603.       foreach (element_children($element['floors'][$key]['rows'][$row]['columns']) as $column) {
  604.         $tabs .= '<li class="ui-state-highlight">'.
  605.           drupal_render($element['floors'][$key]['rows'][$row]['columns'][$column])
  606.         .'</li>';
  607.       }
  608.     }
  609.     $tabs .= '</ul>'. $values .'<div class="clear"></div></div>';
  610.   }
  611.   $output .= '</ul>';
  612.   $output .= $tabs;
  613.   $output .= '</div>';
  614.   return $output;
  615. }
  616.  
  617. /**
  618.  * Default implementation of theme_allocated_seating_seat_design
  619. */
  620. function theme_allocated_seating_seat_design($variable) {
  621.   drupal_add_library('system', 'ui.sortable');
  622.   drupal_add_library('system', 'ui.tabs');
  623.   drupal_add_library('system', 'ui.droppable');
  624.   $element = array_shift($variable);
  625.  
  626.   //jquery_ui_add(array('ui.sortable', 'ui.tabs', 'ui.droppable'));
  627.   drupal_add_js(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.js');
  628.   drupal_add_css(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.css');
  629.   drupal_add_css(drupal_get_path('module', 'jquery_ui') . '/jquery.ui/themes/default/ui.all.css');
  630.   $output = '<div id="as-wrap-'. $element['#id'] .'" class="as-wrap"><div id="allocated-seating-tabs" class="allocated-seating-seat-design"><ul>';
  631.   $tabs = '';
  632.   foreach (element_children($element['floors']) as $key) {
  633.     $inputs = '';
  634.     $title = $element['floors'][$key]['title']['#value'];
  635.     $output .= '<li><a href="#allocated-seating-tabs-'. $key .'">'. check_plain($title) .'</a></li>';
  636.     $tabs .= '<div id="allocated-seating-tabs-'. $key .'" class="floor-details">'.
  637.       '<div class="floor-item">'.
  638.       theme('form_element_label', $element['floors'][$key]['title']).
  639.       theme('textfield', $element['floors'][$key]['title']) .
  640.       '</div><div class="floor-item">'.
  641.       theme('form_element_label', $element['floors'][$key]['row_count']).
  642.       theme('textfield', $element['floors'][$key]['row_count']) .
  643.       '</div><div class="floor-item">'.
  644.       theme('form_element_label', $element['floors'][$key]['col_count']).
  645.       theme('textfield', $element['floors'][$key]['col_count']).
  646.       '</div>'
  647.       . '<div class="floor-front cols-'. $element['floors'][$key]['col_count']['#value'] .'">'. t('Front') .'</div>'
  648.       .'<ul class="allocated-seating-seats connectedSortable ui-helper-reset cols-'. $element['floors'][$key]['col_count']['#value'] .'">';
  649.     foreach (element_children($element['floors'][$key]['rows']) as $row) {
  650.       foreach (element_children($element['floors'][$key]['rows'][$row]['columns']) as $column) {
  651.         $tabs .= '<li class="ui-state-highlight" rel="'. $element['floors'][$key]['rows'][$row]['columns'][$column]['seat']['#value'] .'">'.
  652.                     $element['floors'][$key]['rows'][$row]['columns'][$column]['drag']['#value']
  653.                 .'</li>';
  654.         $inputs .= theme('hidden', $element['floors'][$key]['rows'][$row]['columns'][$column]['seat']);
  655.       }
  656.     }
  657.     $tabs .= $inputs .'</ul>'. $values .'<div class="clear"></div>'.
  658.       drupal_render($element['floors'][$key]['remove_floor'])
  659.       .'</div>';
  660.   }
  661.   $output .= '</ul>';
  662.   $output .= $tabs;
  663.   $output .= '</div><div class="allocated-seating-design-add-floor"><fieldset><legend>'. t('Add a floor') .'</legend>'.
  664.             t('Add a new floor with this many rows/columns').
  665.             drupal_render($element['add_floor_row_count']).
  666.             drupal_render($element['add_floor_col_count']).
  667.             drupal_render($element['add_floor_ticket_count']).
  668.             drupal_render($element['add_floor'])
  669.           .'</fieldset></div>';
  670.   if (!empty($element['#description'])) {
  671.     $output .= ' <div class="description as-description">'. $element['#description'] ."</div>\n";
  672.   }      
  673.   $output .= '</div><div class="clear"></div>';
  674.   return $output;
  675. }
  676.  
  677. /**
  678.  * Validation handler for seat selection
  679. */
  680. function allocated_seating_seat_select_validate($element, &$form_state) {
  681.   $seats = array_sum($form_state['values']['seats']);
  682.   if ($element['#required_seats'] &&
  683.       $element['#required_seats'] != $seats) {
  684.     form_error($element, format_plural($element['#required_seats'],
  685.                                      'Please choose 1 seat',
  686.                                      'Please choose @count seats'));
  687.   }
  688. }
  689.  
  690. /**
  691.  * Call callback handler.
  692.  *
  693.  */
  694. function allocated_seating_ajax() {
  695.   module_load_include('inc', 'node', 'node.pages');
  696.   //get args
  697.  
  698.   $elements = func_get_args();
  699.   $type = array_shift($elements);
  700.   if ($type == 'row' || $type == 'column') {
  701.     $floor = array_shift($elements);
  702.   }
  703.  
  704.  
  705.   //we set submitted as TRUE so prevent _form_builder_ie_cleanup() from triggering
  706.   //submit on ajax that does not involve a button
  707.   $form_state = array('storage' => NULL, 'submitted' => TRUE);
  708.   $form_build_id = $_POST['form_build_id'];
  709.   $form = form_get_cache($form_build_id, $form_state);
  710.   if (isset($_POST['_triggering_element_name'])) {
  711.  
  712.     if($_POST['_triggering_element_name'] == 'op' && $_POST['_triggering_element_value'] == 'Add floor') {
  713.         $form_state['submit_handlers'] = array('allocated_seating_design_add_floor');
  714.     }
  715.   }
  716.  
  717.   unset($form_state['storage']['type']); //don't redo the cached action
  718.   //remove validation (thanks ajax_helper!)
  719.   if (!isset($_POST['op'])) {
  720.     // For the defaults
  721.     $form['#validate'] = NULL;
  722.     $form['#submit'] = NULL;
  723.     // For customly set #validate and #submit handlers.
  724.     $form_state['submit_handlers'] = array();
  725.     $form_state['validate_handlers'] = array();
  726.   }
  727.   $form_id = $form['#form_id'];
  728.   $form['#post'] = $_POST;
  729.   $form['#redirect'] = FALSE;
  730.   $form['#programmed'] = FALSE;
  731.   $form_state['post'] = $_POST;
  732.  
  733.   drupal_process_form($form_id, $form, $form_state);
  734.  
  735.   $form_state['storage']['type'] = $type;
  736.   $form_state['storage']['floor'] = $floor;
  737.   if ($type == 'floor') {
  738.     $form_state['storage']['add_floor_row_count'] = $form_state['values']['add_floor_row_count'];
  739.     $form_state['storage']['add_floor_col_count'] = $form_state['values']['add_floor_col_count'];
  740.   }
  741.  
  742.   $form = drupal_rebuild_form($form_id, $form_state,  $form );
  743.   foreach ($elements as $element) {
  744.     $form = $form[$element];
  745.   }
  746.   if (!$form) {
  747.     watchdog('allocated seating', 'Call method was called with elements not found in resultant form', array(), WATCHDOG_ERROR);
  748.     $form = array(
  749.       'error' => array(
  750.         '#value' => t('An error occured while processing your request, please try again. If the problem persists, please contact the site administrator')
  751.       )
  752.     );
  753.   }
  754.   unset($form['#prefix'], $form['#suffix']); // Prevent duplicate wrappers.
  755.   $javascript = drupal_add_js(NULL, NULL, 'header');
  756.   // Loop through the JS settings and find the settings needed for our buttons.
  757.  
  758.  
  759.   $new_ajax_settings = array();
  760.   if (isset($javascript['settings'])) {
  761.     foreach ($javascript['settings'] as $settings) {
  762.       if (isset($settings['ajax'])) {
  763.         foreach ($settings['ajax'] as $id => $ajax_settings) {
  764.             $new_ajax_settings[$id] = $ajax_settings;
  765.         }
  766.       }
  767.     }
  768.   }
  769.  
  770.   // Add the Call settings needed for our new elements.
  771.   if (!empty($new_ajax_settings)) {
  772.     $output = '<script type="text/javascript">jQuery.extend(Drupal.settings.Ajax, '. drupal_to_js($new_ajax_settings) .');</script>';
  773.   }
  774.  
  775.   return array(array(
  776.     'status'   => TRUE,
  777.     'data'     => theme('status_messages') . $output . drupal_render($form),
  778.     'settings' => call_user_func_array('array_merge_recursive', $javascript['setting']),
  779.     'command' => 'syncSeating'
  780.   ));
  781. }
  782.  
  783. /**
  784.  * Utility to remove a floor from the plan
  785.  * @param $plan array the plan
  786. */
  787. function allocated_seating_plan_remove_floor(&$plan, $floor) {
  788.   if (!isset($plan['floors'][$floor])) {
  789.     return;
  790.   }
  791.   foreach ($plan['floors'][$floor]['rows'] as $row) {
  792.     foreach ($row['columns'] as $col) {
  793.       if ((int)$col['seat'] > 0) {
  794.         form_set_error('', t('You cannot remove this floor, it still contains seats, please move them to another floor first.'));
  795.         return;
  796.       }
  797.     }
  798.   }
  799.   unset($plan['floors'][$floor]);
  800. }
  801.  
  802.  
  803. /**
  804.  * Utility to remove a col from the plan
  805.  * @param $plan array the plan
  806. */
  807. function allocated_seating_plan_remove_column(&$plan, $floor) {
  808.   if (!isset($plan['floors'][$floor])) {
  809.     return;
  810.   }
  811.   $remove_col = count($plan['floors'][$floor]['rows'][0]['columns']) - 1;
  812.   foreach ($plan['floors'][$floor]['rows'] as $row) {
  813.     $col = $row['columns'][$remove_col];
  814.     if ((int)$col['seat'] > 0) {
  815.       form_set_error('', t('You cannot remove the last column from this floor, it still contains seats, please move them to another floor or column first.'));
  816.       return;
  817.     }
  818.   }
  819.   foreach ($plan['floors'][$floor]['rows'] as $key => $row) {
  820.     unset($plan['floors'][$floor]['rows'][$key]['columns'][$remove_col]);
  821.   }
  822. }
  823.  
  824. /**
  825.  * Utility to remove a row from the plan
  826.  * @param $plan array the plan
  827. */
  828. function allocated_seating_plan_remove_row(&$plan, $floor) {
  829.   if (!isset($plan['floors'][$floor])) {
  830.     return;
  831.   }
  832.   $remove_row = count($plan['floors'][$floor]['rows']) - 1;
  833.   foreach ($plan['floors'][$floor]['rows'][$remove_row]['columns'] as $col) {
  834.     if ((int)$col['seat'] > 0) {
  835.       form_set_error('', t('You cannot remove the last row from this floor, it still contains seats, please move them to another floor or row first.'));
  836.       return;
  837.     }
  838.   }
  839.   unset($plan['floors'][$floor]['rows'][$remove_row]);
  840. }
  841.  
  842. /**
  843.  * Utility to add a floor to a plan
  844.  * @param $plan array the plan
  845. */
  846. function allocated_seating_plan_add_floor(&$element, &$post) {
  847.  
  848.   $plan = &$element['#value'];
  849.   $rows = $plan['add_floor_row_count'];
  850.   $cols = $plan['add_floor_col_count'];
  851.   $tickets = $plan['add_floor_ticket_count'];
  852.   $available_tickets = array();
  853.   if ($tickets) {
  854.     if ($tickets > ($rows * $cols)) {
  855.       $tickets = $rows * $cols;
  856.       drupal_set_message(t('You cannot move more than !tix seats to the new floor', array('!tix' => ($rows * $cols))));
  857.     }
  858.     $map = allocated_seating_get_map($plan);
  859.     $seat = count($available_tickets);
  860.     $seats = $map['seats'];
  861.     $seat_numbers = array_keys($seats);
  862.     asort($seat_numbers);
  863.     while ($seat < $tickets) {
  864.       $seat++;
  865.       $new_seat = array_pop($seat_numbers);
  866.       $remove = $seats[$new_seat];
  867.       $available_tickets[] = $new_seat;
  868.       $plan['floors'][$remove['floor']]['rows'][$remove['row']]['columns'][$remove['column']]['seat'] = FALSE;
  869.     }
  870.   }
  871.   $floor = array(
  872.     'title' => t('Floor !floor', array('!floor' => count($plan['floors']) + 1)),
  873.     'rows' => array()
  874.   );
  875.   $row = 0;
  876.   $s = 1;
  877.   while ($row < $rows) {
  878.     $col = 0;
  879.     $floor['rows'][$row] = array('columns' => array()); //add the rows
  880.     while ($col < $cols) {
  881.       if (count($available_tickets) > 0) {
  882.         $seat = array_pop($available_tickets);
  883.       }
  884.       else {
  885.         $seat = FALSE;
  886.       }
  887.       $floor['rows'][$row]['columns'][] = array('seat' => $seat); //add the seat as a blank or a number
  888.       $col++;
  889.     }
  890.     $row++;
  891.   }
  892.   $plan['floors'][] = $floor;
  893. }
  894.  
  895. /**
  896.  * Utility to add row to a floor of a plan
  897.  * @param $plan array the plan
  898.  * @param $floor int the floor delta
  899. */
  900. function allocated_seating_plan_floor_add_row(&$plan, $floor) {
  901.   $cols = count($plan['floors'][$floor]['rows'][0]['columns']);
  902.   $rows = count($plan['floors'][$floor]['rows']);
  903.   $col = 0;
  904.   $row = array('columns' => array()); //create the row
  905.   while ($col < $cols) {
  906.     $row['columns'][] = array('seat' => FALSE); //add the seat as a blank
  907.     $col++;
  908.   }
  909.   $plan['floors'][$floor]['rows'][] = $row;
  910. }
  911.  
  912. /**
  913.  * Utility to add column to a floor of a plan
  914.  * @param $plan array the plan
  915.  * @param $floor int the floor delta
  916. */
  917. function allocated_seating_plan_floor_add_column(&$plan, $floor) {
  918.   $rows = count($plan['floors'][$floor]['rows']);
  919.   $row = 0;
  920.   while ($row < $rows) {
  921.     $plan['floors'][$floor]['rows'][$row]['columns'][] = array('seat' => FALSE);
  922.     $row++;
  923.   }
  924. }
  925.  
  926. /**
  927.  * Utility to setup required js files etc
  928. */
  929. function allocated_seating_setup() {
  930.   drupal_add_library('system', 'ui.sortable');
  931.   drupal_add_library('system', 'ui.tabs');
  932.   drupal_add_library('system', 'ui.droppable');
  933.   //jquery_ui_add(array('ui.sortable', 'ui.tabs', 'ui.droppable'));
  934.   drupal_add_js(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.js');
  935.   drupal_add_css(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.css');
  936. }
  937.  
  938. /**
  939.  * Util to fetch number of rows and columns (seats) submitted in the plan
  940.  * @param $plan array seating plan as submitted in $element['#value']
  941. */
  942. function allocated_seating_total_seats($plan) {
  943.   $seats = 0;
  944.   foreach ($plan['floors'] as $floor) {
  945.     $rows = $floor['row_count'];
  946.     $cols = $floor['col_count'];
  947.     $seats += ($rows * $cols);
  948.   }
  949.   return $seats;
  950. }
  951.  
  952. /**
  953.  * Util to fetch number of rows and columns (seats) submitted in the plan
  954.  * @param $plan array seating plan as submitted in $element['#value']
  955. */
  956. function allocated_seating_plan_seats($plan) {
  957.   $seats = 0;
  958.   foreach ($plan['floors'] as $floor) {
  959.     $rows = count($floor['rows']);
  960.     $cols = count($floor['rows'][0]['columns']);
  961.     $seats += ($rows * $cols);
  962.   }
  963.   return $seats;
  964. }
  965.  
  966. /**
  967.  * Util to fetch number of real seats (non blank) in the plan
  968.  * @param $plan array seating plan as submitted in $element['#value']
  969. */
  970. function allocated_seating_real_seats($plan) {
  971.   $seats = 0;
  972.   foreach ($plan['floors'] as $floor) {
  973.     foreach ($floor['rows'] as $row) {
  974.       foreach ($row['columns'] as $column) {
  975.         if ((int)$column['seat'] > 0) {
  976.           $seats++;
  977.         }
  978.       }
  979.     }
  980.   }
  981.   return $seats;
  982. }
  983.  
  984. /**
  985.  * Util to fetch reveresed map keyed by seat
  986.  * @param $plan array seating plan
  987.  * @return array with two members as follows
  988.  *  seats => array keyed by seat # with array or floor, row and column members
  989.  *  blanks => same but for blanks
  990. */
  991. function allocated_seating_get_map($plan) {
  992.   $map = $blanks = array();
  993.   foreach ($plan['floors'] as $fid => $floor) {
  994.     foreach ($floor['rows'] as $rid => $row) {
  995.       foreach ($row['columns'] as $cid => $column) {
  996.         if ((int)$column['seat'] > 0) {
  997.           $map[$column['seat']] = array('row' => $rid, 'column' => $cid, 'floor' => $fid);
  998.         }
  999.         else {
  1000.           $blanks[] = array('row' => $rid, 'column' => $cid, 'floor' => $fid);
  1001.         }
  1002.       }
  1003.     }
  1004.   }
  1005.   return array('seats' => $map, 'blanks' => $blanks);
  1006. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement