data_node.module

Hooks and API functions for Data Node module.

Functions

Namesort descending Description
data_node_active_form Form callback for setting the active node.
data_node_active_form_create_submit Create submit handler for form.
data_node_active_form_submit Submit handler for form.
data_node_active_page Page callback for setting the active node.
data_node_add Add a relationship between a data table and a node.
data_node_add_page Page callback for adding.
data_node_add_path Generate the path for an add link for an item/node pair.
data_node_block_info Implements hook_block_info().
data_node_block_OLD Implements hook_block().
data_node_block_view Implements hook_block_view().
data_node_get_active Get a the current active node. This is used for the collection workflow.
data_node_get_nids Get the nids for a given record.
data_node_get_nodes Get all available nodes for a specific table.
data_node_menu Implements hook_menu().
data_node_permission Implements hook_permission().
data_node_remove Remove a relationship between a data table and a node.
data_node_remove_page Page callback for removing.
data_node_remove_path Generate the path for a remove link for an item/node pair.
data_node_render_add_link Render an add link for a given item..
data_node_render_labels Render node-data labels for a given item.
data_node_render_placeholder_link Render a placeholder when there are no active nodes that can be replaced via AJAX.
data_node_render_remove_link Render a remove link for a given item.
data_node_set_active Set a specific node as the active node. This is used for the collection workflow.
data_node_theme Implements hook_theme().
data_node_views_api Implements hook_views_api().
_data_node_get_title Static cache node titles to avoid unnecessary node loading.
_data_node_hash Create a simple hash of a table name, an id and a nid.

File

sites/all/modules/local_contrib/data/data_node/data_node.module
View source
  1. <?php
  2. /**
  3. * @file
  4. * Hooks and API functions for Data Node module.
  5. */
  6. /**
  7. * Implements hook_views_api().
  8. */
  9. function data_node_views_api() {
  10. return array(
  11. 'api' => '2.0',
  12. 'path' => drupal_get_path('module', 'data_node') . '/views',
  13. );
  14. }
  15. /**
  16. * Implements hook_theme().
  17. */
  18. function data_node_theme() {
  19. return array(
  20. 'data_node_label' => array(
  21. 'variables' => array('table' => NULL, 'id' => NULL, 'nid' => NULL, 'title' => NULL),
  22. 'file' => 'data_node.theme.inc',
  23. ),
  24. 'data_node_active_form' => array(
  25. 'render element' => 'form',
  26. 'file' => 'data_node.theme.inc',
  27. ),
  28. );
  29. }
  30. /**
  31. * Implements hook_block_info().
  32. */
  33. function data_node_block_info() {
  34. $blocks = array();
  35. $tables = data_get_all_tables();
  36. foreach ($tables as $table) {
  37. $meta = $table->get('meta');
  38. if (!empty($meta['data_node']['content_type'])) {
  39. $blocks[$table->get('name')]['info'] = t('Data node: Active node form for !table', array('!table' => $table->get('title')));
  40. }
  41. }
  42. return $blocks;
  43. }
  44. /**
  45. * Implements hook_block_view().
  46. */
  47. function data_node_block_view($delta) {
  48. if (user_access('manage data relations') && $table = data_get_table($delta)) {
  49. // Grab the node type name
  50. $meta = $table->get('meta');
  51. $names = node_type_get_names();
  52. $type_name = check_plain($names[$meta['data_node']['content_type']]);
  53. return array(
  54. 'subject' => t('Active !type', array('!type' => $type_name)),
  55. 'content' => drupal_get_form('data_node_active_form', $table),
  56. );
  57. }
  58. }
  59. /**
  60. * Implements hook_block().
  61. */
  62. function data_node_block_OLD($op = 'list', $delta = 0) { }
  63. /**
  64. * Implements hook_menu().
  65. */
  66. function data_node_menu() {
  67. $items = array();
  68. $items['data-node/add/%data_ui_table/%/%/%'] = array(
  69. 'page callback' => 'data_node_add_page',
  70. 'page arguments' => array(2, 3, 4, 5),
  71. 'access callback' => 'user_access',
  72. 'access arguments' => array('manage data relations'),
  73. 'type' => MENU_CALLBACK,
  74. );
  75. $items['data-node/remove/%data_ui_table/%/%/%'] = array(
  76. 'page callback' => 'data_node_remove_page',
  77. 'page arguments' => array(2, 3, 4, 5),
  78. 'access callback' => 'user_access',
  79. 'access arguments' => array('manage data relations'),
  80. 'type' => MENU_CALLBACK,
  81. );
  82. $items['data-node/active/%data_ui_table/%'] = array(
  83. 'page callback' => 'data_node_active_page',
  84. 'page arguments' => array(2, 3),
  85. 'access callback' => 'user_access',
  86. 'access arguments' => array('manage data relations'),
  87. 'type' => MENU_CALLBACK,
  88. );
  89. $items['admin/structure/data/edit/%data_ui_table/node'] = array(
  90. 'title' => 'Relate to nodes',
  91. 'description' => 'Administer data tables.',
  92. 'page callback' => 'drupal_get_form',
  93. 'page arguments' => array('data_node_settings_form', 4),
  94. 'file' => 'data_node.admin.inc',
  95. 'access arguments' => array('administer data tables'),
  96. 'type' => MENU_LOCAL_TASK,
  97. );
  98. return $items;
  99. }
  100. /**
  101. * Implements hook_permission().
  102. */
  103. function data_node_permission() {
  104. return array(
  105. 'edit data node relations' => array(
  106. 'title' => t('edit data node relations'),
  107. 'description' => t('TODO Add a description for \'edit data node relations\''),
  108. ),
  109. );
  110. }
  111. /**
  112. * Form callback for setting the active node.
  113. */
  114. function data_node_active_form($form, &$form_state, $table) {
  115. $form = array(
  116. '#attributes' => array('class' => 'data-node-active-form'),
  117. '#table' => $table,
  118. '#theme' => 'data_node_active_form',
  119. // These three are here to keep JS from doing reconstructive URL surgery.
  120. 'ajax_url' => array(
  121. '#type' => 'hidden',
  122. '#value' => url('data-node/active/' . $table->get('name')),
  123. '#attributes' => array('class' => 'data-node-ajax-url'),
  124. ),
  125. 'add_url' => array(
  126. '#type' => 'hidden',
  127. '#value' => url('data-node/add/' . $table->get('name')),
  128. '#attributes' => array('class' => 'data-node-add-url'),
  129. ),
  130. 'remove_url' => array(
  131. '#type' => 'hidden',
  132. '#value' => url('data-node/remove/' . $table->get('name')),
  133. '#attributes' => array('class' => 'data-node-remove-url'),
  134. ),
  135. );
  136. $nodes = array(0 => '--' . t('Select') . '--');
  137. $nodes += data_node_get_nodes($table);
  138. // Grab the node type name and provide a creation option
  139. $meta = $table->get('meta');
  140. $names = node_type_get_names();
  141. $type_name = check_plain($names[$meta['data_node']['content_type']]);
  142. if (node_access('create', $meta['data_node']['content_type'])) {
  143. $nodes['new'] = '< ' . t('New !type', array('!type' => $type_name)) . ' >';
  144. }
  145. $form['nid'] = array(
  146. '#type' => 'select',
  147. '#title' => t('Active !type', array('!type' => $type_name)),
  148. '#options' => $nodes,
  149. '#default_value' => data_node_get_active($table->get('name')),
  150. );
  151. if (node_access('create', $meta['data_node']['content_type'])) {
  152. $form['new'] = array('#tree' => FALSE);
  153. $form['new']['type'] = array(
  154. '#type' => 'value',
  155. '#value' => $meta['data_node']['content_type'],
  156. );
  157. $form['new']['title'] = array(
  158. '#type' => 'textfield',
  159. '#size' => 20,
  160. );
  161. $form['new']['create'] = array(
  162. '#type' => 'submit',
  163. '#value' => t('Create'),
  164. '#submit' => array('data_node_active_form_create_submit'),
  165. );
  166. }
  167. $form['submit'] = array(
  168. '#type' => 'submit',
  169. '#value' => t('Set'),
  170. '#submit' => array('data_node_active_form_submit'),
  171. );
  172. return $form;
  173. }
  174. /**
  175. * Submit handler for form.
  176. */
  177. function data_node_active_form_submit($form, &$form_state) {
  178. data_node_set_active($form['#table']->get('name'), $form_state['values']['nid']);
  179. // Redirect ourselves because '#redirect' does not support queries.
  180. $query = array();
  181. foreach ($_GET as $k => $v) {
  182. if ($k != 'q') {
  183. $query[] = "$k=$v";
  184. }
  185. }
  186. // TODO implode('&', $query) needs to be an array of keys and values instead of a string.
  187. drupal_goto($_GET['q'], array('query' => implode('&', $query)));
  188. }
  189. /**
  190. * Create submit handler for form.
  191. */
  192. function data_node_active_form_create_submit($form, &$form_state) {
  193. $title = trim($form_state['values']['title']);
  194. if (!empty($title)) {
  195. global $user;
  196. $node = new stdClass();
  197. $node->uid = $user->uid;
  198. $node->title = $title;
  199. $node->type = $form_state['values']['type'];
  200. $node->body = '';
  201. foreach (variable_get('node_options_' . $node->type, array('status')) as $key) {
  202. $node->{$key} = 1;
  203. }
  204. node_save($node);
  205. data_node_set_active($form['#table']->get('name'), $node->nid);
  206. }
  207. // Redirect ourselves because '#redirect' does not support queries.
  208. $query = array();
  209. foreach ($_GET as $k => $v) {
  210. if ($k != 'q') {
  211. $query[] = "$k=$v";
  212. }
  213. }
  214. // TODO implode('&', $query) needs to be an array of keys and values instead of a string.
  215. drupal_goto($_GET['q'], array('query' => implode('&', $query)));
  216. }
  217. /**
  218. * Page callback for adding.
  219. *
  220. * @todo: add tokenizing drupal_valid_token/drupal_get_token to prevent XSS
  221. */
  222. function data_node_add_page($table, $id, $nid, $token) {
  223. if (drupal_valid_token($token, _data_node_hash($table, $id, $nid))) {
  224. data_node_remove($table, $id, $nid);
  225. data_node_add($table, $id, $nid);
  226. }
  227. // Handle AJAX requests
  228. if (isset($_GET['ajax'])) {
  229. $response = array(
  230. 'status' => TRUE,
  231. 'table' => $table->get('name'),
  232. 'id' => $id,
  233. 'nid' => $nid,
  234. 'labels' => data_node_render_labels($table, $id),
  235. 'add_link' => data_node_render_remove_link($table, $id, $nid),
  236. 'remove_link' => data_node_render_add_link($table, $id, $nid),
  237. );
  238. drupal_json_output($response);
  239. exit;
  240. }
  241. drupal_goto($_GET['q']);
  242. }
  243. /**
  244. * Page callback for setting the active node.
  245. */
  246. function data_node_active_page($table, $nid) {
  247. data_node_set_active($table->get('name'), $nid);
  248. // Handle AJAX requests
  249. if (isset($_GET['ajax'])) {
  250. // Generate new add/remove links to replace stale ones.
  251. $stale = isset($_GET['stale']) ? explode('-', $_GET['stale']) : array();
  252. $refresh = array();
  253. foreach ($stale as $id) {
  254. $node_list = data_node_get_nids($table, $id);
  255. $refresh[$id] = in_array($nid, $node_list) ? data_node_render_remove_link($table, $id, $nid) : data_node_render_add_link($table, $id, $nid);
  256. }
  257. $response = array(
  258. 'status' => TRUE,
  259. 'table' => $table->get('name'),
  260. 'nid' => $nid,
  261. 'refresh' => $refresh,
  262. );
  263. drupal_json_output($response);
  264. exit;
  265. }
  266. drupal_goto($_GET['q']);
  267. }
  268. /**
  269. * Page callback for removing.
  270. *
  271. * @todo: add tokenizing drupal_valid_token/drupal_get_token to prevent XSS
  272. */
  273. function data_node_remove_page($table, $id, $nid, $token) {
  274. if (drupal_valid_token($token, _data_node_hash($table, $id, $nid))) {
  275. data_node_remove($table, $id, $nid);
  276. }
  277. // Handle AJAX requests
  278. if (isset($_GET['ajax'])) {
  279. $response = array(
  280. 'status' => TRUE,
  281. 'table' => $table->get('name'),
  282. 'id' => $id,
  283. 'nid' => $nid,
  284. 'labels' => data_node_render_labels($table, $id),
  285. 'add_link' => data_node_render_remove_link($table, $id, $nid),
  286. 'remove_link' => data_node_render_add_link($table, $id, $nid),
  287. );
  288. drupal_json_output($response);
  289. exit;
  290. }
  291. drupal_goto($_GET['q']);
  292. }
  293. /**
  294. * Add a relationship between a data table and a node.
  295. */
  296. function data_node_add($table, $id, $nid) {
  297. $save = array(
  298. 'data_table_name' => $table->get('name'),
  299. 'id' => $id,
  300. 'nid' => $nid,
  301. );
  302. return drupal_write_record('data_table_node', $save);
  303. }
  304. /**
  305. * Get the nids for a given record.
  306. */
  307. function data_node_get_nids($table, $id) {
  308. $list = array();
  309. $result = db_query("SELECT nid FROM {data_table_node} WHERE data_table_name = :data_table_name AND id = :id", array(':data_table_name' => $table->get('name'), ':id' => $id));
  310. while ($row = db_fetch_object($result)) {
  311. $list[] = $row->nid;
  312. }
  313. return $list;
  314. }
  315. /**
  316. * Remove a relationship between a data table and a node.
  317. */
  318. function data_node_remove($table, $id, $nid) {
  319. // TODO Please review the conversion of this statement to the D7 database API syntax.
  320. /* db_query("DELETE FROM {data_table_node} WHERE data_table_name = '%s' AND id = %d AND nid = %d", $table->get('name'), $id, $nid) */
  321. db_delete('data_table_node')
  322. ->condition('data_table_name', $table->get('name'))
  323. ->condition('id', $id)
  324. ->condition('nid', $nid)
  325. ->execute();
  326. }
  327. /**
  328. * Get all available nodes for a specific table.
  329. */
  330. function data_node_get_nodes($table) {
  331. $nodes = array();
  332. $meta = $table->get('meta');
  333. if ($meta['data_node']['content_type']) {
  334. $result = db_query("SELECT nid, title FROM {node} WHERE type = :type ORDER BY title ASC", array(':type' => $meta['data_node']['content_type']));
  335. while ($node = db_fetch_object($result)) {
  336. $nodes[$node->nid] = $node->title;
  337. }
  338. }
  339. return $nodes;
  340. }
  341. /**
  342. * Set a specific node as the active node. This is used for the collection workflow.
  343. */
  344. function data_node_set_active($table_name, $nid) {
  345. $_SESSION['data_node_active'][$table_name] = $nid;
  346. }
  347. /**
  348. * Get a the current active node. This is used for the collection workflow.
  349. */
  350. function data_node_get_active($table_name) {
  351. return $_SESSION['data_node_active'][$table_name];
  352. }
  353. /**
  354. * Create a simple hash of a table name, an id and a nid.
  355. */
  356. function _data_node_hash($table, $id, $nid) {
  357. return $table->get('name') . $id . $nid;
  358. }
  359. /**
  360. * Static cache node titles to avoid unnecessary node loading.
  361. */
  362. function _data_node_get_title($nid) {
  363. static $nodes = array();
  364. if (!isset($nodes[$nid])) {
  365. $nodes[$nid] = check_plain(db_query("SELECT title FROM {node} WHERE nid = :nid", array(':nid' => $nid))->fetchField());
  366. }
  367. return isset($nodes[$nid]) ? $nodes[$nid] : NULL;
  368. }
  369. /**
  370. * Generate the path for a remove link for an item/node pair.
  371. */
  372. function data_node_remove_path($table, $id, $nid) {
  373. $token = drupal_get_token(_data_node_hash($table, $id, $nid));
  374. $table_name = $table->get('name');
  375. return "data-node/remove/{$table_name}/$id/$nid/$token";
  376. }
  377. /**
  378. * Generate the path for an add link for an item/node pair.
  379. */
  380. function data_node_add_path($table, $id, $nid) {
  381. $token = drupal_get_token(_data_node_hash($table, $id, $nid));
  382. $table_name = $table->get('name');
  383. return "data-node/add/{$table_name}/$id/$nid/$token";
  384. }
  385. /**
  386. * Render node-data labels for a given item.
  387. */
  388. function data_node_render_labels($table, $id) {
  389. $nids = data_node_get_nids($table, $id);
  390. foreach ($nids as $nid) {
  391. $title = _data_node_get_title($nid);
  392. $output .= theme('data_node_label', array('table' => $table, 'id' => $id, 'nid' => $nid, 'title' => $title));
  393. }
  394. $table_name = $table->get('name');
  395. $class = "data_node_labels-{$table_name}-{$id}";
  396. return "<div class='{$class} clear-block'>{$output}</div>";
  397. }
  398. /**
  399. * Render a placeholder when there are no active nodes that can be replaced via AJAX.
  400. */
  401. function data_node_render_placeholder_link($table, $id) {
  402. drupal_add_css(drupal_get_path('module', 'data_node') . '/data_node.css');
  403. drupal_add_js(drupal_get_path('module', 'data_node') . '/data_node.js');
  404. $table_name = $table->get('name');
  405. return "<span class='data-node-placeholder data_node_link-{$table_name}-{$id}-0'></span>";
  406. }
  407. /**
  408. * Render an add link for a given item..
  409. */
  410. function data_node_render_add_link($table, $id, $nid) {
  411. drupal_add_css(drupal_get_path('module', 'data_node') . '/data_node.css');
  412. drupal_add_js(drupal_get_path('module', 'data_node') . '/data_node.js');
  413. $title = _data_node_get_title($nid);
  414. $table_name = $table->get('name');
  415. $class = "data_node_link-{$table_name}-{$id}-{$nid}";
  416. return l(t('Add to !title', array('!title' => $title)), data_node_add_path($table, $id, $nid), array('attributes' => array('class' => "data-node-add $class"), 'query' => drupal_get_destination()));
  417. }
  418. /**
  419. * Render a remove link for a given item.
  420. */
  421. function data_node_render_remove_link($table, $id, $nid) {
  422. drupal_add_css(drupal_get_path('module', 'data_node') . '/data_node.css');
  423. drupal_add_js(drupal_get_path('module', 'data_node') . '/data_node.js');
  424. $title = _data_node_get_title($nid);
  425. $table_name = $table->get('name');
  426. $class = "data_node_link-{$table_name}-{$id}-{$nid}";
  427. return l(t('Remove from !title', array('!title' => $title)), data_node_remove_path($table, $id, $nid), array('attributes' => array('class' => "data-node-remove $class"), 'query' => drupal_get_destination()));
  428. }