common.inc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. <?php
  2. /**
  3. * @file
  4. * Functions used by more than one Hierarchical Select implementation.
  5. */
  6. /**
  7. * Retrieve a config. If certain settings are not yet configured by the user,
  8. * defaults will be set. These defaults can also be overriden. This allows
  9. * modules to provide their own meaningful defaults.
  10. *
  11. * @param $config_id
  12. * A config id, typically of the form "module-someid", e.g.
  13. * "taxonomy-field_name".
  14. * @param $defaults_override
  15. * Optionally override the defaults.
  16. *
  17. * @return array
  18. * An array of default config.
  19. */
  20. function hierarchical_select_common_config_get($config_id, $defaults_override = array()) {
  21. $config = variable_get('hs_config_' . $config_id, array());
  22. return _hierarchical_select_inherit_default_config($config, $defaults_override);
  23. }
  24. /**
  25. * Set a config.
  26. *
  27. * @param $config_id
  28. * A config id.
  29. * @param $config
  30. * The config to store.
  31. */
  32. function hierarchical_select_common_config_set($config_id, $config) {
  33. variable_set('hs_config_' . $config_id, $config);
  34. }
  35. /**
  36. * Delete a config.
  37. *
  38. * @param $config_id
  39. * The config id to delete.
  40. */
  41. function hierarchical_select_common_config_del($config_id) {
  42. variable_del('hs_config_' . $config_id);
  43. }
  44. /**
  45. * Apply a config to a form item.
  46. *
  47. * @param $form_item
  48. * The form item that will be updated.
  49. * @param $config_id
  50. * A config id.
  51. * @param $defaults_override
  52. * Optionally override the defaults.
  53. * @see hierarchical_select_common_config_get()
  54. */
  55. function hierarchical_select_common_config_apply(&$form_item, $config_id, $defaults_override = array()) {
  56. $config = hierarchical_select_common_config_get($config_id, $defaults_override);
  57. $form_item['#config'] = array_merge((isset($form_item['#config']) && is_array($form_item['#config'])) ? $form_item['#config'] : array(), $config);
  58. }
  59. //----------------------------------------------------------------------------
  60. // Forms API callbacks.
  61. /**
  62. * Form definition of the hierarchical_select_common_config_form form.
  63. */
  64. function hierarchical_select_common_config_form($module, $params, $config_id, $defaults_override, $strings, $max_hierarchy_depth, $preview_is_required) {
  65. $config = hierarchical_select_common_config_get($config_id, $defaults_override);
  66. $args = array(
  67. '!item' => $strings['item'],
  68. '!items' => $strings['items'],
  69. '!entity' => $strings['entity'],
  70. '!entities' => $strings['entities'],
  71. '!hierarchy' => $strings['hierarchy'],
  72. '!hierarchies' => $strings['hierarchies']
  73. );
  74. $form = array(
  75. '#tree' => TRUE,
  76. '#type' => 'fieldset',
  77. '#title' => t('Hierarchical Select configuration'),
  78. '#attributes' => array(
  79. 'class' => array('hierarchical-select-config-form'),
  80. 'id' => 'hierarchical-select-config-form-' . $config_id,
  81. ),
  82. '#attached' => array(
  83. 'css' => array(
  84. drupal_get_path('module', 'hierarchical_select') . '/includes/common_config_form.css'
  85. ),
  86. 'js' => array(
  87. array(
  88. 'type' => 'file',
  89. 'data' => drupal_get_path('module', 'hierarchical_select') . '/includes/common_config_form.js',
  90. ),
  91. array(
  92. 'type' => 'setting',
  93. 'data' => array('HierarchicalSelect' => array('configForm' => array($config_id))),
  94. ),
  95. ),
  96. )
  97. );
  98. $form['config_id'] = array('#type' => 'value', '#value' => $config_id);
  99. // TODO: really make this a *live* preview, i.e. refresh the preview on each
  100. // change in the form. This cannot be done easily in Drupal 5 or 6, so let's
  101. // do so in Drupal 7. See cfg.livePreview in common_config_form.js.
  102. $form['live_preview'] = array(
  103. '#type' => 'fieldset',
  104. '#title' => t('Preview'),
  105. '#description' => t('This is what the Hierarchical Select will look like with your current configuration.'),
  106. '#collapsible' => FALSE,
  107. '#attributes' => array('class' => array('live-preview')),
  108. );
  109. $form['live_preview']['example'] = array(
  110. '#type' => 'hierarchical_select',
  111. '#required' => $preview_is_required,
  112. '#title' => t('Preview'),
  113. '#description' => t('The description.'),
  114. // Skip al validation for this form element: the data collected through it
  115. // is always discarded, it's merely here for illustrative purposes.
  116. '#validated' => TRUE,
  117. );
  118. hierarchical_select_common_config_apply($form['live_preview']['example'], $config_id, array_merge($defaults_override, array('module' => $module, 'params' => $params)));
  119. $form['save_lineage'] = array(
  120. '#type' => 'radios',
  121. '#title' => t('Save lineage'),
  122. '#options' => array(
  123. 1 => t('Save !item lineage', $args),
  124. 0 => t('Save only the deepest !item', $args),
  125. ),
  126. '#default_value' => (isset($config['save_lineage'])) ? $config['save_lineage'] : NULL,
  127. '#description' => t(
  128. 'Saving the !item lineage means saving the <em>the !item itself and all
  129. its ancestors</em>.',
  130. $args
  131. ),
  132. );
  133. $form['enforce_deepest'] = array(
  134. '#type' => 'radios',
  135. '#title' => t('Level choice'),
  136. '#options' => array(
  137. 1 => t('Force the user to choose a !item from a <em>deepest level</em>', $args),
  138. 0 => t('Allow the user to choose a !item from <em>any level</em>', $args),
  139. ),
  140. '#default_value' => (isset($config['enforce_deepest'])) ? $config['enforce_deepest'] : NULL,
  141. '#description' => t(
  142. 'This setting determines from which level in the !hierarchy tree a
  143. user can select a !item.',
  144. $args
  145. ),
  146. '#attributes' => array('class' => array('enforce-deepest')),
  147. );
  148. $form['resizable'] = array(
  149. '#type' => 'radios',
  150. '#title' => t('Resizable'),
  151. '#description' => t(
  152. "When enabled, a handle appears below the Hierarchical Select to allow
  153. the user to dynamically resize it. Double clicking will toggle between
  154. the smallest and a sane 'big size'."
  155. ),
  156. '#options' => array(
  157. 0 => t('Disabled'),
  158. 1 => t('Enabled'),
  159. ),
  160. '#default_value' => (isset($config['resizable'])) ? $config['resizable'] : NULL,
  161. '#attributes' => array('class' => array('resizable')),
  162. );
  163. $form['level_labels'] = array(
  164. '#tree' => TRUE,
  165. '#type' => 'fieldset',
  166. '#title' => t('Level labels'),
  167. '#description' => t(
  168. 'When the user is allowed to choose a !item from any level in the
  169. <em>Level choice</em> setting, you can enter a label for <em>each</em>
  170. level.<br />
  171. However, when the user is only allowed to choose a !item from the
  172. deepest level, then you can only enter a label for the <em>root</em>
  173. level.',
  174. $args
  175. ),
  176. '#collapsible' => TRUE,
  177. );
  178. $form['level_labels']['status'] = array(
  179. '#type' => 'checkbox',
  180. '#title' => t('Enable level labels'),
  181. '#default_value' => (isset($config['level_labels']['status'])) ? $config['level_labels']['status'] : NULL,
  182. '#attributes' => array('class' => array('level-labels-status')),
  183. );
  184. for ($depth = 0; $depth <= $max_hierarchy_depth; $depth++) {
  185. $form['level_labels']['labels'][$depth] = array(
  186. '#type' => 'textfield',
  187. '#size' => 20,
  188. '#maxlength' => 255,
  189. '#default_value' => (isset($config['level_labels']['labels'][$depth])) ? $config['level_labels']['labels'][$depth] : NULL,
  190. '#attributes' => array('class' => array('level-label')),
  191. );
  192. }
  193. $form['level_labels']['#theme'] = 'hierarchical_select_common_config_form_level_labels';
  194. $form['level_labels']['#strings'] = $strings;
  195. $form['dropbox'] = array(
  196. '#type' => 'fieldset',
  197. '#title' => t('Dropbox settings'),
  198. '#description' => t('The dropbox allows the user to <strong>make multiple selections</strong>.'),
  199. '#collapsible' => TRUE,
  200. );
  201. $form['dropbox']['status'] = array(
  202. '#type' => 'checkbox',
  203. '#title' => t('Enable the dropbox'),
  204. '#default_value' => (isset($config['dropbox']['status'])) ? $config['dropbox']['status'] : NULL,
  205. '#attributes' => array('class' => array('dropbox-status')),
  206. );
  207. $form['dropbox']['title'] = array(
  208. '#type' => 'textfield',
  209. '#title' => t('Title'),
  210. '#description' => t('The title you enter here appears above the dropbox.'),
  211. '#size' => 20,
  212. '#maxlength' => 255,
  213. '#default_value' => (isset($config['dropbox']['title'])) ? $config['dropbox']['title'] : NULL,
  214. '#attributes' => array('class' => array('dropbox-title')),
  215. );
  216. $form['dropbox']['limit'] = array(
  217. '#type' => 'textfield',
  218. '#title' => t('Limit the number of selections'),
  219. '#description' => t(
  220. 'Limits the number of selections that can be added to the dropbox.
  221. 0 means no limit.
  222. <br />
  223. Note: the "Save !item lineage" option has no effect on this, even if
  224. a lineage consists of 3 !items, this will count as only one selection
  225. in the dropbox.',
  226. $args
  227. ),
  228. '#size' => 5,
  229. '#maxlength' => 5,
  230. '#default_value' => (isset($config['dropbox']['limit'])) ? $config['dropbox']['limit'] : NULL,
  231. '#attributes' => array('class' => array('dropbox-limit')),
  232. );
  233. $form['dropbox']['reset_hs'] = array(
  234. '#type' => 'radios',
  235. '#title' => t('Reset selection of hierarchical select'),
  236. '#description' => t(
  237. 'This setting determines what will happen to the hierarchical select
  238. when the user has added a selection to the dropbox.'
  239. ),
  240. '#options' => array(
  241. 0 => t('Disabled'),
  242. 1 => t('Enabled'),
  243. ),
  244. '#default_value' => (isset($config['dropbox']['reset_hs'])) ? $config['dropbox']['reset_hs'] : NULL,
  245. '#attributes' => array('class' => array('dropbox-reset-hs')),
  246. );
  247. $form['dropbox']['sort'] = array(
  248. '#type' => 'checkbox',
  249. '#title' => t('Sort dropbox items'),
  250. '#description' => t('Automatically sort items added to the dropbox. If unchecked new items will be added to the end of the dropbox list.'),
  251. '#default_value' => (isset($config['dropbox']['sort'])) ? $config['dropbox']['sort'] : 1,
  252. '#attributes' => array('class' => array('dropbox-sort')),
  253. );
  254. if (module_hook($module, 'hierarchical_select_create_item')) {
  255. $form['editability'] = array(
  256. '#type' => 'fieldset',
  257. '#title' => t('Editability settings'),
  258. '#description' => t(
  259. 'You can allow the user to <strong>add new !items to this
  260. !hierarchy</strong> <em>through</em> Hierarchical Select.',
  261. $args
  262. ),
  263. '#collapsible' => TRUE,
  264. );
  265. $form['editability']['status'] = array(
  266. '#type' => 'checkbox',
  267. '#title' => t('Allow creation of new !items', $args),
  268. '#options' => array(
  269. 0 => t('Disabled'),
  270. 1 => t('Enabled'),
  271. ),
  272. '#default_value' => (isset($config['editability']['status'])) ? $config['editability']['status'] : NULL,
  273. '#attributes' => array('class' => array('editability-status')),
  274. );
  275. for ($depth = 0; $depth <= $max_hierarchy_depth; $depth++) {
  276. $form['editability']['item_types'][$depth] = array(
  277. '#type' => 'textfield',
  278. '#size' => 20,
  279. '#maxlength' => 255,
  280. '#default_value' => (isset($config['editability']['item_types'][$depth])) ? $config['editability']['item_types'][$depth] : NULL,
  281. '#attributes' => array('class' => array('editability-item-type')),
  282. );
  283. }
  284. for ($depth = 0; $depth <= $max_hierarchy_depth; $depth++) {
  285. $form['editability']['allowed_levels'][$depth] = array(
  286. '#type' => 'checkbox',
  287. '#default_value' => (isset($config['editability']['allowed_levels'][$depth])) ? $config['editability']['allowed_levels'][$depth] : 1,
  288. );
  289. }
  290. $form['editability']['allow_new_levels'] = array(
  291. '#type' => 'checkbox',
  292. '#title' => t('Allow creation of new levels'),
  293. '#default_value' => $config['editability']['allow_new_levels'],
  294. '#description' => t(
  295. 'Allow the user to create child !items for !items that do not yet have
  296. children.',
  297. $args
  298. ),
  299. '#attributes' => array('class' => array('editability-allow-new-levels')),
  300. );
  301. $form['editability']['max_levels'] = array(
  302. '#type' => 'select',
  303. '#title' => t('Maximum number of levels allowed'),
  304. '#options' => array(
  305. 0 => t('0 (no limit)'), 1, 2, 3, 4, 5, 6, 7, 8, 9
  306. ),
  307. '#default_value' => (isset($config['editability']['max_levels'])) ? $config['editability']['max_levels'] : NULL,
  308. '#description' => t(
  309. 'When the user is allowed to create new levels, this option prevents
  310. the user from creating extremely deep !hierarchies.',
  311. $args
  312. ),
  313. '#attributes' => array('class' => array('editability-max-levels')),
  314. );
  315. $form['editability']['#theme'] = 'hierarchical_select_common_config_form_editability';
  316. $form['editability']['#strings'] = $strings;
  317. }
  318. if (module_hook($module, 'hierarchical_select_entity_count')) {
  319. $form['entity_count'] = array(
  320. '#type' => 'fieldset',
  321. '#title' => t('Entity Count'),
  322. '#collapsible' => TRUE,
  323. );
  324. $form['entity_count']['enabled'] = array(
  325. '#type' => 'checkbox',
  326. '#title' => t('Display number of entities'),
  327. '#description' => t('Display the number of entities associated with the !item. Do not forget to check which entities should be counted.', $args),
  328. '#default_value' => isset($config['entity_count']['enabled']) ? $config['entity_count']['enabled'] : FALSE,
  329. '#weight' => -1,
  330. '#attributes' => array('class' => array('entity-count-enabled')),
  331. );
  332. $form['entity_count']['require_entity'] = array(
  333. '#type' => 'checkbox',
  334. '#title' => t('Require associated entity'),
  335. '#description' => t('If checked only !items that have at least one entity associated with them will be displayed.', $args),
  336. '#default_value' => (isset($config['entity_count']['require_entity'])) ? $config['entity_count']['require_entity'] : FALSE,
  337. );
  338. $form['entity_count']['settings'] = array(
  339. '#type' => 'fieldset',
  340. '#title' => t('Entity count settings'),
  341. '#collapsible' => TRUE,
  342. '#collapsed' => FALSE,
  343. '#weight' => -1,
  344. '#attributes' => array('class' => array('entity-count-settings')),
  345. );
  346. $form['entity_count']['settings']['count_children'] = array(
  347. '#type' => 'checkbox',
  348. '#title' => t('Also count children of !item.', $args),
  349. '#description' => t('If checked this will result in a larger number because the children will be counted also.'),
  350. '#default_value' => isset($config['entity_count']['settings']['count_children']) ? $config['entity_count']['settings']['count_children'] : FALSE,
  351. );
  352. $form['entity_count']['settings']['entity_types'] = array(
  353. '#type' => 'item',
  354. '#title' => t('Select entities that should be counted.'),
  355. '#description' => t('Select entity type or one of it\'s bundles that should be counted'),
  356. );
  357. $entity_info = entity_get_info();
  358. foreach ($entity_info as $entity => $entity_info) {
  359. if (!empty($entity_info['bundles']) && $entity_info['fieldable'] === TRUE) {
  360. $options = array();
  361. $default_values = array();
  362. $form['entity_count']['settings']['entity_types'][$entity] = array(
  363. '#type' => 'fieldset',
  364. '#title' => check_plain($entity_info['label']),
  365. '#collapsible' => TRUE,
  366. '#collapsed' => TRUE,
  367. );
  368. foreach ($entity_info['bundles'] as $bundle => $bundle_info) {
  369. $options[$bundle] = check_plain($bundle_info['label']);
  370. $default_values[$entity][$bundle] = isset($config['entity_count']['settings']['entity_types'][$entity]['count_' . $entity][$bundle]) ? $config['entity_count']['settings']['entity_types'][$entity]['count_' . $entity][$bundle] : 0;
  371. }
  372. $form['entity_count']['settings']['entity_types'][$entity]['count_' . $entity] = array(
  373. '#type' => 'checkboxes',
  374. '#options' => $options,
  375. '#default_value' => $default_values[$entity],
  376. );
  377. }
  378. }
  379. }
  380. return $form;
  381. }
  382. /**
  383. * Submit callback for the hierarchical_select_common_config_form form.
  384. */
  385. function hierarchical_select_common_config_form_submit($form, &$form_state) {
  386. $config = _hierarchical_select_get_form_item_by_parents($form_state['values'], $form['#hs_common_config_form_parents']);
  387. // Don't include the value of the live preview in the config.
  388. unset($config['live_preview']);
  389. hierarchical_select_common_config_set($config['config_id'], $config);
  390. }
  391. /**
  392. * Get the form element of a form that has a certain lineage of parents.
  393. *
  394. * @param $form
  395. * A structured array for use in the Forms API.
  396. * @param $parents
  397. * An array of parent form element names.
  398. * @return
  399. * The form element that has the specified lineage of parents.
  400. */
  401. function _hierarchical_select_get_form_item_by_parents($form, $parents) {
  402. if (count($parents)) {
  403. $parent = array_shift($parents);
  404. return _hierarchical_select_get_form_item_by_parents($form[$parent], $parents);
  405. }
  406. else {
  407. return $form;
  408. }
  409. }