product_grid.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. <?php
  2. /**
  3. * @file
  4. * Webform module product grid component.
  5. */
  6. /**
  7. * Implements _webform_defaults_component().
  8. */
  9. function _webform_defaults_product_grid() {
  10. return array(
  11. 'name' => '',
  12. 'form_key' => NULL,
  13. 'pid' => 0,
  14. 'weight' => 0,
  15. 'value' => '',
  16. 'mandatory' => 0,
  17. 'extra' => array(
  18. 'options' => '',
  19. 'questions' => '',
  20. 'optrand' => 0,
  21. 'qrand' => 0,
  22. 'title_display' => 0,
  23. 'custom_option_keys' => 0,
  24. 'custom_question_keys' => 0,
  25. 'description' => '',
  26. 'attributes' => array(),
  27. 'private' => FALSE,
  28. 'products' => NULL,
  29. ),
  30. );
  31. }
  32. // Product Grid depends on functions provided by select.
  33. webform_component_include('select');
  34. /**
  35. * Implements _webform_theme_component().
  36. */
  37. function _webform_theme_product_grid() {
  38. return array(
  39. 'uc_webform_render_product_grid' => array(
  40. 'render element' => 'element',
  41. 'file' => 'components/product_grid.inc',
  42. 'path' => drupal_get_path('module', 'uc_webform'),
  43. ),
  44. 'uc_webform_display_product_grid' => array(
  45. 'render element' => 'element',
  46. 'file' => 'components/product_grid.inc',
  47. 'path' => drupal_get_path('module', 'uc_webform'),
  48. ),
  49. );
  50. }
  51. /**
  52. * Implements _webform_edit_component().
  53. */
  54. function theme_uc_webform_render_product_grid($element) {
  55. // TODO: Should this theme uc_webform_render_product_grid be declared in
  56. // hook_theme()?
  57. $temp_rows = array();
  58. $columns = array(array(
  59. 'data' => '',
  60. 'class' => 'uc_webform-product-grid-product',
  61. ));
  62. $option_ids = array();
  63. $product_keys = element_children($element['element']);
  64. // This loop creates the row at the top (which is a list of product options)
  65. // and the first column on the left (which is the product title column).
  66. foreach (element_children($element['element']) as $key) {
  67. $product_element = $element['element'][$key];
  68. // Create a row with the Product title.
  69. $row = array(array(
  70. 'data' => $product_element['#title'],
  71. 'class' => 'uc_webform-product-grid-product',
  72. 'product' => "$key",
  73. ));
  74. foreach ($product_element['#options'] as $optionid => $opt_val) {
  75. if (!in_array($optionid, $option_ids)) {
  76. $columns[] = array(
  77. 'data' => $opt_val,
  78. 'class' => 'checkbox uc_webform-product-grid-option',
  79. 'oid' => $optionid,
  80. );
  81. }
  82. $option_ids[] = $optionid;
  83. }
  84. $temp_rows[] = $row;
  85. }
  86. $final_rows = array();
  87. foreach ($temp_rows as $row) {
  88. $product_key = $row[0]['product'];
  89. $radios = form_process_radios($element['element'][$product_key]);
  90. foreach ($columns as $col) {
  91. if (isset($col['oid'])) {
  92. if (isset($radios[$col['oid']])) {
  93. unset($radios[$col['oid']]['#title']);
  94. $row[] = array(
  95. 'data' => drupal_render($radios[$col['oid']]),
  96. 'class' => 'checkbox webform-grid-option',
  97. );
  98. }
  99. else {
  100. $row[] = array(
  101. 'data' => 'n/a',
  102. 'class' => 'checkbox webform-grid-option',
  103. );
  104. }
  105. }
  106. }
  107. $final_rows[] = $row;
  108. }
  109. $option_count = count($columns) - 1;
  110. $output = theme('table', array(
  111. 'header' => $columns,
  112. 'rows' => $final_rows,
  113. 'attributes' => array(
  114. 'class' => array(
  115. 'uc_webform-product-grid uc_webform-product-grid-' . $option_count,
  116. ),
  117. ),
  118. ));
  119. $variables['element'] = $element;
  120. $variables['value'] = $output;
  121. return $output;
  122. }
  123. /**
  124. * @todo Please document this function.
  125. * @see http://drupal.org/node/1354
  126. */
  127. function theme_uc_webform_display_product_grid($element) {
  128. // TODO: Should this theme uc_webform_display_product_grid be declared in
  129. // hook_theme()?
  130. $output = '';
  131. if (isset($element['#value'])) {
  132. $output = (count($element['#value']) > 1) ? theme('item_list', array('items' => $element['#value'])) : $element['#value'][0];
  133. }
  134. return $output;
  135. }
  136. /**
  137. * Implementation of _webform_edit_component().
  138. */
  139. function _webform_edit_product_grid($component) {
  140. $form = array();
  141. $product_types = uc_product_types();
  142. // I need to limit the users selection to only those products that *do*
  143. // contain attributes.
  144. $attrib_query = db_select('uc_product_attributes', 'pa')
  145. ->fields('pa', array('nid'));
  146. $query = db_select('node', 'n')
  147. ->fields('n', array('nid', 'title'))
  148. ->condition('n.nid', $attrib_query, 'IN');
  149. $query->join('uc_products', 'p', 'p.nid = n.nid');
  150. $query->addField('p', 'model');
  151. $query->orderBy('n.title');
  152. $products = array();
  153. foreach ($query->execute() as $product) {
  154. $products[$product->nid . '_' . $product->model] = check_plain($product->title);
  155. }
  156. // Most options are stored in the "extra" array, which stores any settings
  157. // unique to a particular component type.
  158. $form['extra']['products'] = array(
  159. '#type' => 'select',
  160. '#title' => t('Products'),
  161. '#default_value' => $component['extra']['products'],
  162. '#multiple' => TRUE,
  163. '#description' => t('Please select your products. Only products with attributes are displayed.'),
  164. '#weight' => -3,
  165. '#size' => 20,
  166. '#required' => TRUE,
  167. '#options' => $products,
  168. );
  169. return $form;
  170. }
  171. /**
  172. * Implements _webform_render_component().
  173. */
  174. function _webform_render_product_grid($component) {
  175. $product_nodes = array();
  176. $stock_description = "";
  177. foreach ($component['extra']['products'] as $val) {
  178. $product_info = explode('_', $val, 2);
  179. if (module_exists('uc_stock')) {
  180. $stock_level = uc_stock_level($product_info[1]);
  181. }
  182. else {
  183. $stock_level = FALSE;
  184. }
  185. // Check stock levels. The product is only selectable if it is in stock.
  186. if (($stock_level === FALSE) or (intval($stock_level) > 0)) {
  187. $product_nodes[$val] = node_load($product_info[0]);
  188. }
  189. else {
  190. $node = node_load($product_info[0]);
  191. $stock_description .= check_plain($node->title) . ' ' . t('is out of stock.') . '<br />';
  192. }
  193. }
  194. $element = array(
  195. '#title' => $component['name'],
  196. '#title_display' => $component['extra']['title_display'] ? $component['extra']['title_display'] : 'before',
  197. '#required' => $component['mandatory'],
  198. '#weight' => $component['weight'],
  199. '#description' => $component['extra']['description'] . $stock_description,
  200. '#theme' => 'uc_webform_render_product_grid',
  201. '#theme_wrappers' => array('webform_element'),
  202. '#pre_render' => array('webform_element_title_display'),
  203. '#post_render' => array('webform_element'),
  204. '#webform_component' => $component,
  205. );
  206. // Iterate through each product that will be offered. Products will appear on
  207. // the left of the grid.
  208. if(is_array($product_nodes)) {
  209. foreach ($product_nodes as $key => $product_node) {
  210. if($product_node) {
  211. $element[$key] = array(
  212. '#title' => $product_node->title,
  213. '#required' => $component['mandatory'],
  214. '#type' => 'radios',
  215. '#process' => array('form_process_radios', 'webform_expand_select_ids'),
  216. );
  217. // Iterate through each product option for each product. Product options
  218. // will appear on the top of the grid.
  219. $product_options = array();
  220. foreach ($product_node->attributes as $aid => $attribute) {
  221. foreach ($attribute->options as $option) {
  222. // aid_oid
  223. $product_options[$aid . '_' . $option->oid] = $option->name;
  224. }
  225. }
  226. $element[$key]['#options'] = $product_options;
  227. }
  228. }
  229. drupal_add_js(drupal_get_path('module', 'uc_webform') . '/js/deselect.js');
  230. return $element;
  231. }
  232. }
  233. /**
  234. * Implementation of _webform_display_component().
  235. */
  236. function _webform_display_product_grid($component, $value, $format = 'html') {
  237. $products = array();
  238. foreach ($value as $key => $val) {
  239. $nid_sku = explode('_', $key, 2);
  240. $aid_oid = explode('_', $val, 2);
  241. $node = node_load($nid_sku[0]);
  242. if (!empty($val)) {
  243. $products[] = $node->title . ', SKU: ' . $node->model . ', Attribute: ' . $node->attributes[$aid_oid[0]]->name . ', Option: ' . $node->attributes[$aid_oid[0]]->options[$aid_oid[1]]->name;
  244. }
  245. }
  246. $element = array(
  247. '#title' => $component['name'],
  248. '#weight' => $component['weight'],
  249. '#theme' => 'uc_webform_display_product_grid',
  250. '#component' => $component,
  251. '#format' => $format,
  252. '#post_render' => array('webform_element'),
  253. '#theme_wrappers' => $format == 'html' ? array('webform_element') : array('webform_element_text'),
  254. '#value' => $products,
  255. );
  256. return $element;
  257. }
  258. /**
  259. * Implementation of _webform_analysis_component().
  260. */
  261. function _webform_analysis_product_grid($component, $sids = array()) {
  262. // Create an entire table to be put into the returned row.
  263. $rows = array(array());
  264. $header = array(array());
  265. $product_nids = array();
  266. $option_ids = array();
  267. foreach ($component['extra']['products'] as $product) {
  268. $nid_sku = explode('_', $product, 2);
  269. $product_nids[] = $nid_sku[0];
  270. $product_node = node_load($nid_sku[0]);
  271. // A nid_sku combination is used as the key here.
  272. $rows[$product] = array($product_node->title);
  273. }
  274. // Select the available option IDs and names for each product in the table.
  275. if (!empty($product_nids)) {
  276. $query = db_select('uc_product_options', 'po')
  277. ->fields('po', array('oid'));
  278. $query->join('uc_attribute_options', 'ao', 'ao.oid = po.oid');
  279. $query->addField('ao', 'name');
  280. $query->condition('po.oid', $product_nids, 'IN');
  281. }
  282. // Build the header row.
  283. $options = array();
  284. foreach ($query->execute() as $option) {
  285. // Use the oid as an array key to help when quering the
  286. // webform_submitted_data table (since it stores the oid instead of the
  287. // option name).
  288. $header[$option->oid] = $option->name;
  289. }
  290. $query = db_select('webform_submitted_data', 'wsd')
  291. ->fields('wsd', array('no', 'data'));
  292. $query->addExpression('COUNT(data)', 'datacount');
  293. $query->condition('nid', $component['nid'], '=');
  294. $query->condition('cid', $component['cid'], '=');
  295. $query->groupBy('no');
  296. $query->groupBy('data');
  297. $selections = array();
  298. foreach ($query->execute() as $data) {
  299. $aid_oid = explode('_', $data->data, 2);
  300. // The information is stored in the DB as attribute-ID_option-ID. This line
  301. // removes the attribute ID and leaves the $selections key as the option ID.
  302. if (isset($aid_oid[1])) {
  303. $selections[$data->no][$aid_oid[1]] = $data->datacount;
  304. }
  305. }
  306. foreach ($rows as $rkey => $rval) {
  307. if ($rkey != 0) {
  308. foreach ($header as $hkey => $hval) {
  309. if ($hkey != 0) {
  310. // $rkey = product-nid_sku.
  311. // $hkey = option ID.
  312. $rows[$rkey][] = isset($selections[$rkey][$hkey]) ? $selections[$rkey][$hkey] : 0;
  313. }
  314. }
  315. }
  316. }
  317. $output = theme('table', array(
  318. 'header' => $header,
  319. 'rows' => $rows,
  320. 'attributes' => array(
  321. 'class' => array('webform-product-grid'),
  322. ),
  323. ));
  324. return array(array(array('data' => $output, 'colspan' => 2)));
  325. }
  326. /**
  327. * Implements _webform_table_component().
  328. */
  329. function _webform_table_product_grid($component, $value) {
  330. $output = '';
  331. // Set the value as a single string.
  332. foreach ($value as $key => $val) {
  333. $nid_sku = explode('_', $key, 2);
  334. $aid_oid = explode('_', $val, 2);
  335. if (isset($nid_sku[0])) {
  336. $node = node_load($nid_sku[0]);
  337. // Output the SKU and the option.
  338. if (isset($aid_oid[0]) && isset($aid_oid[1])) {
  339. $output .= $node->model . ' - ' . $node->attributes[$aid_oid[0]]->options[$aid_oid[1]]->name . '<br />';
  340. }
  341. }
  342. }
  343. return $output;
  344. }
  345. /**
  346. * Implements _webform_csv_headers_component().
  347. */
  348. function _webform_csv_headers_product_grid($component, $export_options) {
  349. $headers = array(
  350. 0 => array(),
  351. 1 => array(),
  352. 2 => array(),
  353. );
  354. if ($export_options['select_format'] == 'separate') {
  355. $headers[0][] = '';
  356. $headers[1][] = $component['name'];
  357. $count = 0;
  358. foreach ($component['extra']['products'] as $val) {
  359. $product_info = explode('_', $val, 2);
  360. $node = node_load($product_info[0]);
  361. // Add blank cells.
  362. if ($count != 0) {
  363. // Empty column per sub-field in main header.
  364. $headers[0][] = '';
  365. $headers[1][] = '';
  366. }
  367. // List the product options as header cells.
  368. $headers[2][] = $node->title;
  369. $count++;
  370. }
  371. }
  372. else {
  373. $headers[0][] = '';
  374. $headers[1][] = '';
  375. $headers[2][] = $component['name'];
  376. }
  377. return $headers;
  378. }
  379. /**
  380. * Implements _webform_csv_data_component().
  381. */
  382. function _webform_csv_data_product_grid($component, $export_options, $value) {
  383. $data = array();
  384. // Separate format.
  385. if ($export_options['select_format'] == 'separate') {
  386. foreach ($component['extra']['products'] as $product) {
  387. if (isset($value[$product])) {
  388. $nid_sku = explode('_', $product, 2);
  389. $aid_oid = explode('_', $value[$product], 2);
  390. if (isset($nid_sku[0])) {
  391. $node = node_load($nid_sku[0]);
  392. if (isset($aid_oid[0]) && isset($aid_oid[1])) {
  393. $data[] = $node->attributes[$aid_oid[0]]->options[$aid_oid[1]]->name;
  394. }
  395. }
  396. }
  397. }
  398. }
  399. // Compact format.
  400. else {
  401. $data_string;
  402. foreach ($component['extra']['products'] as $product) {
  403. if (isset($value[$product])) {
  404. $nid_sku = explode('_', $product, 2);
  405. $aid_oid = explode('_', $value[$product], 2);
  406. if (isset($nid_sku[0])) {
  407. $node = node_load($nid_sku[0]);
  408. if (isset($aid_oid[0]) && isset($aid_oid[1])) {
  409. $data_string .= $node->attributes[$aid_oid[0]]->options[$aid_oid[1]]->name . ',';
  410. }
  411. }
  412. }
  413. }
  414. $data[] = rtrim($data_string, ',');
  415. }
  416. return $data;
  417. }