Advertisement
Guest User

allocated_seating module

a guest
May 26th, 2015
270
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.   echo 'asds';
  483.   exit();
  484.   if (count($field_parents) > 1) {
  485.     //we have a tree arrangement here
  486.     switch (count($field_parents)) {
  487.       case 2:
  488.         //allocated_seating_plan_add_floor($form_state['values'][$field_parents[0]][$field_name], $new_rows, $new_cols, $new_tickets);
  489.         break;
  490.       case 3:
  491.        // allocated_seating_plan_add_floor($form_state['values'][$field_parents[0]][$field_parents[1]][$field_name], $new_rows, $new_cols, $new_tickets);
  492.         break;
  493.       case 4:
  494.        // 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);
  495.         break;
  496.       //that ought to be enough
  497.     }
  498.   }
  499.   else {
  500.     //allocated_seating_plan_add_floor($form_state['values'][$field_name], $new_rows, $new_cols, $new_tickets);
  501.   }
  502.   unset($form_state['submit_handlers']);
  503.   form_execute_handlers('submit', $form, $form_state);
  504.   $form_state['rebuild'] = TRUE;
  505. }
  506.  
  507. /**
  508.  * Default implementation of theme_allocated_seating_seat_select
  509. */
  510. function theme_allocated_seating_seat_select($element) {
  511.   jquery_ui_add(array('ui.sortable', 'ui.droppable', 'ui.tabs'));
  512.   drupal_add_js(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.js');
  513.   drupal_add_css(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.css');
  514.   drupal_add_css(drupal_get_path('module', 'jquery_ui') . '/jquery.ui/themes/default/ui.all.css');
  515.   $output = '<div id="allocated-seating-tabs" class="allocated-seating-seat-select"><ul>';
  516.   $tabs = '';
  517.   foreach (element_children($element['floors']) as $key) {
  518.     $title = $element['floors'][$key]['title']['#value'];
  519.     $output .= '<li><a href="#allocated-seating-tabs-'. $key .'">'. check_plain($title) .'</a></li>';
  520.     $tabs .= '<div id="allocated-seating-tabs-'. $key .'">'.
  521.       $element['floors'][$key]['title']['#value']
  522.       . '<div class="floor-front cols-'. $element['floors'][$key]['#col_count'] .'">'. t('Front') .'</div>'
  523.       .'<ul class="allocated-seating-seats no-drag cols-'. $element['floors'][$key]['#col_count'] .'">';
  524.     foreach (element_children($element['floors'][$key]['rows']) as $row) {
  525.       foreach (element_children($element['floors'][$key]['rows'][$row]['columns']) as $column) {
  526.         $tabs .= '<li class="ui-state-highlight';
  527.         if ($element['floors'][$key]['rows'][$row]['columns'][$column]['#type'] == 'checkbox') {
  528.           $tabs .= '">'. theme('checkbox', $element['floors'][$key]['rows'][$row]['columns'][$column]);
  529.         }
  530.         else {
  531.           $tabs .= ' not-available">&nbsp';
  532.         }
  533.         $tabs .=  '</li>';
  534.       }
  535.     }
  536.     $tabs .= '</ul>'. $values .'<div class="clear"></div></div>';
  537.   }
  538.   $output .= '</ul>';
  539.   $output .= $tabs;
  540.   $output .= '</div>';
  541.   return $output;
  542. }
  543.  
  544. /**
  545.  * Default implementation of theme_allocated_seating_seat_available
  546. */
  547. function theme_allocated_seating_seat_available($plan, $not_available) {
  548.   $blank = 1;
  549.   $element['floors'] = array(
  550.     '#tree' => FALSE, //we structure the data in a nest for theming but only want seat# => 1/0
  551.     '#parents' => array('floors')
  552.   );
  553.   foreach ($plan['floors'] as $f => $floor) {
  554.     $element['floors'][$f] = array(
  555.       '#tree' => FALSE,
  556.       '#col_count' => $floor['col_count'],
  557.       'title' => array(
  558.         '#value' => $floor['title']
  559.       ),
  560.       'rows' => array(
  561.         '#tree' => FALSE,
  562.       )  
  563.     );
  564.     foreach ($floor['rows'] as $r => $row) {
  565.       $element['floors'][$f]['rows'][$r] = array(
  566.         '#tree' => FALSE,
  567.         'columns' => array(
  568.           '#tree' => FALSE,
  569.           '#parents' => array('floors', $f, 'rows', $r, 'columns'),
  570.         )
  571.       );
  572.       foreach ($row['columns'] as $c => $column) {
  573.         $state = 'available';
  574.         if ($column['seat'] &&
  575.             is_numeric($column['seat']) &&
  576.             in_array($column['seat'], $not_available)) {
  577.           $state = 'unavailable';
  578.         }
  579.         //add the seat field
  580.         $element['floors'][$f]['rows'][$r]['columns'][$column['seat']] = array(
  581.           '#value' => '<div class="allocated-seating-seat '. $state .'">'. $column['seat'] .'</div>',
  582.           '#parents' => array('seats', $column['seat']),
  583.         );
  584.       }
  585.     }
  586.   }
  587.   drupal_add_library('system', 'ui.sortable');
  588.   drupal_add_library('system', 'ui.tabs');
  589.   drupal_add_library('system', 'ui.droppable');
  590.   //jquery_ui_add(array('ui.sortable', 'ui.droppable', 'ui.tabs'));
  591.   drupal_add_js(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.js');
  592.   drupal_add_css(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.css');
  593.   drupal_add_css(drupal_get_path('module', 'jquery_ui') . '/jquery.ui/themes/default/ui.all.css');
  594.   $output = '<div id="allocated-seating-tabs" class="allocated-seating-seat-select"><ul>';
  595.   $tabs = '';
  596.   foreach (element_children($element['floors']) as $key) {
  597.     $title = $element['floors'][$key]['title']['#value'];
  598.     $output .= '<li><a href="#allocated-seating-tabs-'. $key .'">'. check_plain($title) .'</a></li>';
  599.     $tabs .= '<div id="allocated-seating-tabs-'. $key .'">'.
  600.       $element['floors'][$key]['title']['#value']
  601.       . '<div class="floor-front cols-'. $element['floors'][$key]['#col_count'] .'">'. t('Front') .'</div>'
  602.       .'<ul class="allocated-seating-seats no-drag cols-'. $element['floors'][$key]['#col_count'] .'">';
  603.     foreach (element_children($element['floors'][$key]['rows']) as $row) {
  604.       foreach (element_children($element['floors'][$key]['rows'][$row]['columns']) as $column) {
  605.         $tabs .= '<li class="ui-state-highlight">'.
  606.           drupal_render($element['floors'][$key]['rows'][$row]['columns'][$column])
  607.         .'</li>';
  608.       }
  609.     }
  610.     $tabs .= '</ul>'. $values .'<div class="clear"></div></div>';
  611.   }
  612.   $output .= '</ul>';
  613.   $output .= $tabs;
  614.   $output .= '</div>';
  615.   return $output;
  616. }
  617.  
  618. /**
  619.  * Default implementation of theme_allocated_seating_seat_design
  620. */
  621. function theme_allocated_seating_seat_design($variable) {
  622.   drupal_add_library('system', 'ui.sortable');
  623.   drupal_add_library('system', 'ui.tabs');
  624.   drupal_add_library('system', 'ui.droppable');
  625.   $element = array_shift($variable);
  626.  
  627.   //jquery_ui_add(array('ui.sortable', 'ui.tabs', 'ui.droppable'));
  628.   drupal_add_js(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.js');
  629.   drupal_add_css(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.css');
  630.   drupal_add_css(drupal_get_path('module', 'jquery_ui') . '/jquery.ui/themes/default/ui.all.css');
  631.   $output = '<div id="as-wrap-'. $element['#id'] .'" class="as-wrap"><div id="allocated-seating-tabs" class="allocated-seating-seat-design"><ul>';
  632.   $tabs = '';
  633.   foreach (element_children($element['floors']) as $key) {
  634.     $inputs = '';
  635.     $title = $element['floors'][$key]['title']['#value'];
  636.     $output .= '<li><a href="#allocated-seating-tabs-'. $key .'">'. check_plain($title) .'</a></li>';
  637.     $tabs .= '<div id="allocated-seating-tabs-'. $key .'" class="floor-details">'.
  638.       '<div class="floor-item">'.
  639.       theme('form_element_label', $element['floors'][$key]['title']).
  640.       theme('textfield', $element['floors'][$key]['title']) .
  641.       '</div><div class="floor-item">'.
  642.       theme('form_element_label', $element['floors'][$key]['row_count']).
  643.       theme('textfield', $element['floors'][$key]['row_count']) .
  644.       '</div><div class="floor-item">'.
  645.       theme('form_element_label', $element['floors'][$key]['col_count']).
  646.       theme('textfield', $element['floors'][$key]['col_count']).
  647.       '</div>'
  648.       . '<div class="floor-front cols-'. $element['floors'][$key]['col_count']['#value'] .'">'. t('Front') .'</div>'
  649.       .'<ul class="allocated-seating-seats connectedSortable ui-helper-reset cols-'. $element['floors'][$key]['col_count']['#value'] .'">';
  650.     foreach (element_children($element['floors'][$key]['rows']) as $row) {
  651.       foreach (element_children($element['floors'][$key]['rows'][$row]['columns']) as $column) {
  652.         $tabs .= '<li class="ui-state-highlight" rel="'. $element['floors'][$key]['rows'][$row]['columns'][$column]['seat']['#value'] .'">'.
  653.                     $element['floors'][$key]['rows'][$row]['columns'][$column]['drag']['#value']
  654.                 .'</li>';
  655.         $inputs .= theme('hidden', $element['floors'][$key]['rows'][$row]['columns'][$column]['seat']);
  656.       }
  657.     }
  658.     $tabs .= $inputs .'</ul>'. $values .'<div class="clear"></div>'.
  659.       drupal_render($element['floors'][$key]['remove_floor'])
  660.       .'</div>';
  661.   }
  662.   $output .= '</ul>';
  663.   $output .= $tabs;
  664.   $output .= '</div><div class="allocated-seating-design-add-floor"><fieldset><legend>'. t('Add a floor') .'</legend>'.
  665.             t('Add a new floor with this many rows/columns').
  666.             drupal_render($element['add_floor_row_count']).
  667.             drupal_render($element['add_floor_col_count']).
  668.             drupal_render($element['add_floor_ticket_count']).
  669.             drupal_render($element['add_floor'])
  670.           .'</fieldset></div>';
  671.   if (!empty($element['#description'])) {
  672.     $output .= ' <div class="description as-description">'. $element['#description'] ."</div>\n";
  673.   }      
  674.   $output .= '</div><div class="clear"></div>';
  675.   return $output;
  676. }
  677.  
  678. /**
  679.  * Validation handler for seat selection
  680. */
  681. function allocated_seating_seat_select_validate($element, &$form_state) {
  682.   $seats = array_sum($form_state['values']['seats']);
  683.   if ($element['#required_seats'] &&
  684.       $element['#required_seats'] != $seats) {
  685.     form_error($element, format_plural($element['#required_seats'],
  686.                                      'Please choose 1 seat',
  687.                                      'Please choose @count seats'));
  688.   }
  689. }
  690.  
  691. /**
  692.  * Call callback handler.
  693.  *
  694.  */
  695. function allocated_seating_ajax() {
  696.   module_load_include('inc', 'node', 'node.pages');
  697.   //get args
  698.  
  699.   $elements = func_get_args();
  700.   $type = array_shift($elements);
  701.   if ($type == 'row' || $type == 'column') {
  702.     $floor = array_shift($elements);
  703.   }
  704.  
  705.  
  706.   //we set submitted as TRUE so prevent _form_builder_ie_cleanup() from triggering
  707.   //submit on ajax that does not involve a button
  708.   $form_state = array('storage' => NULL, 'submitted' => TRUE);
  709.   $form_build_id = $_POST['form_build_id'];
  710.   $form = form_get_cache($form_build_id, $form_state);
  711.   if (isset($_POST['_triggering_element_name'])) {
  712.  
  713.     if($_POST['_triggering_element_name'] == 'op' && $_POST['_triggering_element_value'] == 'Add floor') {
  714.         $form_state['submit_handlers'] = array('allocated_seating_design_add_floor');
  715.     }
  716.   }
  717.  
  718.   unset($form_state['storage']['type']); //don't redo the cached action
  719.   //remove validation (thanks ajax_helper!)
  720.   if (!isset($_POST['op'])) {
  721.     // For the defaults
  722.     $form['#validate'] = NULL;
  723.     $form['#submit'] = NULL;
  724.     // For customly set #validate and #submit handlers.
  725.     $form_state['submit_handlers'] = array();
  726.     $form_state['validate_handlers'] = array();
  727.   }
  728.   $form_id = $form['#form_id'];
  729.   $form['#post'] = $_POST;
  730.   $form['#redirect'] = FALSE;
  731.   $form['#programmed'] = FALSE;
  732.   $form_state['post'] = $_POST;
  733.  
  734.   drupal_process_form($form_id, $form, $form_state);
  735.  
  736.   $form_state['storage']['type'] = $type;
  737.   $form_state['storage']['floor'] = $floor;
  738.   if ($type == 'floor') {
  739.     $form_state['storage']['add_floor_row_count'] = $form_state['values']['add_floor_row_count'];
  740.     $form_state['storage']['add_floor_col_count'] = $form_state['values']['add_floor_col_count'];
  741.   }
  742.  
  743.   $form = drupal_rebuild_form($form_id, $form_state,  $form );
  744.   foreach ($elements as $element) {
  745.     $form = $form[$element];
  746.   }
  747.   if (!$form) {
  748.     watchdog('allocated seating', 'Call method was called with elements not found in resultant form', array(), WATCHDOG_ERROR);
  749.     $form = array(
  750.       'error' => array(
  751.         '#value' => t('An error occured while processing your request, please try again. If the problem persists, please contact the site administrator')
  752.       )
  753.     );
  754.   }
  755.   unset($form['#prefix'], $form['#suffix']); // Prevent duplicate wrappers.
  756.   $javascript = drupal_add_js(NULL, NULL, 'header');
  757.   // Loop through the JS settings and find the settings needed for our buttons.
  758.  
  759.  
  760.   $new_ajax_settings = array();
  761.   if (isset($javascript['settings'])) {
  762.     foreach ($javascript['settings'] as $settings) {
  763.       if (isset($settings['ajax'])) {
  764.         foreach ($settings['ajax'] as $id => $ajax_settings) {
  765.             $new_ajax_settings[$id] = $ajax_settings;
  766.         }
  767.       }
  768.     }
  769.   }
  770.  
  771.   // Add the Call settings needed for our new elements.
  772.   if (!empty($new_ajax_settings)) {
  773.     $output = '<script type="text/javascript">jQuery.extend(Drupal.settings.Ajax, '. drupal_to_js($new_ajax_settings) .');</script>';
  774.   }
  775.  
  776.   return array(array(
  777.     'status'   => TRUE,
  778.     'data'     => theme('status_messages') . $output . drupal_render($form),
  779.     'settings' => call_user_func_array('array_merge_recursive', $javascript['setting']),
  780.     'command' => 'syncSeating'
  781.   ));
  782. }
  783.  
  784. /**
  785.  * Utility to remove a floor from the plan
  786.  * @param $plan array the plan
  787. */
  788. function allocated_seating_plan_remove_floor(&$plan, $floor) {
  789.   if (!isset($plan['floors'][$floor])) {
  790.     return;
  791.   }
  792.   foreach ($plan['floors'][$floor]['rows'] as $row) {
  793.     foreach ($row['columns'] as $col) {
  794.       if ((int)$col['seat'] > 0) {
  795.         form_set_error('', t('You cannot remove this floor, it still contains seats, please move them to another floor first.'));
  796.         return;
  797.       }
  798.     }
  799.   }
  800.   unset($plan['floors'][$floor]);
  801. }
  802.  
  803.  
  804. /**
  805.  * Utility to remove a col from the plan
  806.  * @param $plan array the plan
  807. */
  808. function allocated_seating_plan_remove_column(&$plan, $floor) {
  809.   if (!isset($plan['floors'][$floor])) {
  810.     return;
  811.   }
  812.   $remove_col = count($plan['floors'][$floor]['rows'][0]['columns']) - 1;
  813.   foreach ($plan['floors'][$floor]['rows'] as $row) {
  814.     $col = $row['columns'][$remove_col];
  815.     if ((int)$col['seat'] > 0) {
  816.       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.'));
  817.       return;
  818.     }
  819.   }
  820.   foreach ($plan['floors'][$floor]['rows'] as $key => $row) {
  821.     unset($plan['floors'][$floor]['rows'][$key]['columns'][$remove_col]);
  822.   }
  823. }
  824.  
  825. /**
  826.  * Utility to remove a row from the plan
  827.  * @param $plan array the plan
  828. */
  829. function allocated_seating_plan_remove_row(&$plan, $floor) {
  830.   if (!isset($plan['floors'][$floor])) {
  831.     return;
  832.   }
  833.   $remove_row = count($plan['floors'][$floor]['rows']) - 1;
  834.   foreach ($plan['floors'][$floor]['rows'][$remove_row]['columns'] as $col) {
  835.     if ((int)$col['seat'] > 0) {
  836.       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.'));
  837.       return;
  838.     }
  839.   }
  840.   unset($plan['floors'][$floor]['rows'][$remove_row]);
  841. }
  842.  
  843. /**
  844.  * Utility to add a floor to a plan
  845.  * @param $plan array the plan
  846. */
  847. function allocated_seating_plan_add_floor(&$element, &$post) {
  848.  
  849.   $plan = &$element['#value'];
  850.   $rows = $plan['add_floor_row_count'];
  851.   $cols = $plan['add_floor_col_count'];
  852.   $tickets = $plan['add_floor_ticket_count'];
  853.   $available_tickets = array();
  854.   if ($tickets) {
  855.     if ($tickets > ($rows * $cols)) {
  856.       $tickets = $rows * $cols;
  857.       drupal_set_message(t('You cannot move more than !tix seats to the new floor', array('!tix' => ($rows * $cols))));
  858.     }
  859.     $map = allocated_seating_get_map($plan);
  860.     $seat = count($available_tickets);
  861.     $seats = $map['seats'];
  862.     $seat_numbers = array_keys($seats);
  863.     asort($seat_numbers);
  864.     while ($seat < $tickets) {
  865.       $seat++;
  866.       $new_seat = array_pop($seat_numbers);
  867.       $remove = $seats[$new_seat];
  868.       $available_tickets[] = $new_seat;
  869.       $plan['floors'][$remove['floor']]['rows'][$remove['row']]['columns'][$remove['column']]['seat'] = FALSE;
  870.     }
  871.   }
  872.   $floor = array(
  873.     'title' => t('Floor !floor', array('!floor' => count($plan['floors']) + 1)),
  874.     'rows' => array()
  875.   );
  876.   $row = 0;
  877.   $s = 1;
  878.   while ($row < $rows) {
  879.     $col = 0;
  880.     $floor['rows'][$row] = array('columns' => array()); //add the rows
  881.     while ($col < $cols) {
  882.       if (count($available_tickets) > 0) {
  883.         $seat = array_pop($available_tickets);
  884.       }
  885.       else {
  886.         $seat = FALSE;
  887.       }
  888.       $floor['rows'][$row]['columns'][] = array('seat' => $seat); //add the seat as a blank or a number
  889.       $col++;
  890.     }
  891.     $row++;
  892.   }
  893.   $plan['floors'][] = $floor;
  894. }
  895.  
  896. /**
  897.  * Utility to add row to a floor of a plan
  898.  * @param $plan array the plan
  899.  * @param $floor int the floor delta
  900. */
  901. function allocated_seating_plan_floor_add_row(&$plan, $floor) {
  902.   $cols = count($plan['floors'][$floor]['rows'][0]['columns']);
  903.   $rows = count($plan['floors'][$floor]['rows']);
  904.   $col = 0;
  905.   $row = array('columns' => array()); //create the row
  906.   while ($col < $cols) {
  907.     $row['columns'][] = array('seat' => FALSE); //add the seat as a blank
  908.     $col++;
  909.   }
  910.   $plan['floors'][$floor]['rows'][] = $row;
  911. }
  912.  
  913. /**
  914.  * Utility to add column to a floor of a plan
  915.  * @param $plan array the plan
  916.  * @param $floor int the floor delta
  917. */
  918. function allocated_seating_plan_floor_add_column(&$plan, $floor) {
  919.   $rows = count($plan['floors'][$floor]['rows']);
  920.   $row = 0;
  921.   while ($row < $rows) {
  922.     $plan['floors'][$floor]['rows'][$row]['columns'][] = array('seat' => FALSE);
  923.     $row++;
  924.   }
  925. }
  926.  
  927. /**
  928.  * Utility to setup required js files etc
  929. */
  930. function allocated_seating_setup() {
  931.   drupal_add_library('system', 'ui.sortable');
  932.   drupal_add_library('system', 'ui.tabs');
  933.   drupal_add_library('system', 'ui.droppable');
  934.   //jquery_ui_add(array('ui.sortable', 'ui.tabs', 'ui.droppable'));
  935.   drupal_add_js(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.js');
  936.   drupal_add_css(drupal_get_path('module', 'allocated_seating') .'/allocated_seating.css');
  937. }
  938.  
  939. /**
  940.  * Util to fetch number of rows and columns (seats) submitted in the plan
  941.  * @param $plan array seating plan as submitted in $element['#value']
  942. */
  943. function allocated_seating_total_seats($plan) {
  944.   $seats = 0;
  945.   foreach ($plan['floors'] as $floor) {
  946.     $rows = $floor['row_count'];
  947.     $cols = $floor['col_count'];
  948.     $seats += ($rows * $cols);
  949.   }
  950.   return $seats;
  951. }
  952.  
  953. /**
  954.  * Util to fetch number of rows and columns (seats) submitted in the plan
  955.  * @param $plan array seating plan as submitted in $element['#value']
  956. */
  957. function allocated_seating_plan_seats($plan) {
  958.   $seats = 0;
  959.   foreach ($plan['floors'] as $floor) {
  960.     $rows = count($floor['rows']);
  961.     $cols = count($floor['rows'][0]['columns']);
  962.     $seats += ($rows * $cols);
  963.   }
  964.   return $seats;
  965. }
  966.  
  967. /**
  968.  * Util to fetch number of real seats (non blank) in the plan
  969.  * @param $plan array seating plan as submitted in $element['#value']
  970. */
  971. function allocated_seating_real_seats($plan) {
  972.   $seats = 0;
  973.   foreach ($plan['floors'] as $floor) {
  974.     foreach ($floor['rows'] as $row) {
  975.       foreach ($row['columns'] as $column) {
  976.         if ((int)$column['seat'] > 0) {
  977.           $seats++;
  978.         }
  979.       }
  980.     }
  981.   }
  982.   return $seats;
  983. }
  984.  
  985. /**
  986.  * Util to fetch reveresed map keyed by seat
  987.  * @param $plan array seating plan
  988.  * @return array with two members as follows
  989.  *  seats => array keyed by seat # with array or floor, row and column members
  990.  *  blanks => same but for blanks
  991. */
  992. function allocated_seating_get_map($plan) {
  993.   $map = $blanks = array();
  994.   foreach ($plan['floors'] as $fid => $floor) {
  995.     foreach ($floor['rows'] as $rid => $row) {
  996.       foreach ($row['columns'] as $cid => $column) {
  997.         if ((int)$column['seat'] > 0) {
  998.           $map[$column['seat']] = array('row' => $rid, 'column' => $cid, 'floor' => $fid);
  999.         }
  1000.         else {
  1001.           $blanks[] = array('row' => $rid, 'column' => $cid, 'floor' => $fid);
  1002.         }
  1003.       }
  1004.     }
  1005.   }
  1006.   return array('seats' => $map, 'blanks' => $blanks);
  1007. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement