tripal_bulk_loader.api.templates.inc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. <?php
  2. /**
  3. * @file
  4. * Provides functions for hooking into bulk loader functionality.
  5. *
  6. * @ingroup tripal_bulk_loader
  7. */
  8. /**
  9. * @defgroup tripal_bulk_loader_api Bulk Loader
  10. * @ingroup tripal_api
  11. * @{
  12. * All functions in this file provide an API to administrative management of
  13. * bulk loader templates.
  14. * @}
  15. */
  16. /**
  17. * Validates an $options array for insert or update of a bulk loader record.
  18. *
  19. * @param $val_type
  20. * The type of validation. Can be either 'insert' or 'update'.
  21. * @param $options
  22. * An array of key/value pairs containing the following keys:
  23. * template_name: The name of the template.
  24. * template_array: The JSON array representing the template.
  25. * Optional:
  26. * strict: If set then only JSON formatted templates are allowed.
  27. * @param $errors
  28. * An empty array where validation error messages will be set. The keys
  29. * of the array will be name of the field from the options array and the
  30. * value is the error message.
  31. * @param $warnings
  32. * An empty array where validation warning messagges will be set. The
  33. * warnings should not stop an insert or an update but should be provided
  34. * to the user as information by a drupal_set_message() if appropriate. The
  35. * keys of the array will be name of the field from the options array and the
  36. * value is the error message.
  37. *
  38. * @return
  39. * If validation fails then FALSE is returned. Any options that do not pass
  40. * validation checks will be added in the $errors array with the key being
  41. * the option and the value being the error message. If validation
  42. * is successful then TRUE is returned.
  43. *
  44. * @ingroup tripal_bulk_loader_api
  45. */
  46. function tripal_validate_bulk_loader_template($val_type, &$options, &$errors, &$warnings = []) {
  47. $template_array = trim($options['template_array']);
  48. $template_name = trim($options['template_name']);
  49. $strict = array_key_exists('strict', $options) ? $options['strict'] : FALSE;
  50. // Make sure the template array is one of the supported types
  51. // DEPRECATED: A stringified version of the array (causes security issues)
  52. if (preg_match('/^array/', $template_array)) {
  53. if ($strict) {
  54. $errors['template_array'] = t('Invalid template array. Please provide
  55. a JSON formatted array');
  56. return FALSE;
  57. }
  58. else {
  59. $warnings['template_array'] = t('Please note that import of
  60. bulk loader templates as PHP arrays as a stringified array is deprecated
  61. and will be removed in future versions of Tripal. Export and import
  62. format will be JSON.');
  63. }
  64. }
  65. // DEPRECATED: A serialized PHP array
  66. elseif (preg_match('/^a:/', $template_array)) {
  67. if ($strict) {
  68. $errors['template_array'] = t('Invalid template array. Please provide
  69. a JSON formatted array');
  70. return FALSE;
  71. }
  72. else {
  73. $warnings['template_array'] = t('Please note that import of
  74. bulk loader templates as PHP serialized arrays is deprecated and will
  75. be removed in future versions of Tripal. Export and import format will
  76. be JSON.');
  77. }
  78. }
  79. // JSON FORMAT
  80. elseif (json_decode($template_array)) {
  81. // This is correct!
  82. }
  83. else {
  84. $errors['template_array'] = t('The template array must be in
  85. JSON format (although PHP strigified arrays and PHP serialized
  86. arrays are temporarily supported for backwards compatibility).');
  87. return FALSE;
  88. }
  89. // Make sure the template name is unique
  90. $name_exists = db_select('tripal_bulk_loader_template', 'tblt')
  91. ->fields('tblt', ['template_id'])
  92. ->condition('name', $template_name)
  93. ->execute()
  94. ->fetchField();
  95. if ($name_exists) {
  96. $errors['template_name'] = t('The template name already exists. Please
  97. choose another name.');
  98. return FALSE;
  99. }
  100. return TRUE;
  101. }
  102. /**
  103. * Inserts a bulk loader template record.
  104. *
  105. * This function validates the options passed prior to insertion of the record.
  106. *
  107. * @param $options
  108. * An array of key/value pairs containing the following keys:
  109. * 'template_name': The name of the template.
  110. * 'template_array': The JSON array representing the template.
  111. * Optional:
  112. * 'strict': If set then only JSON formatted templates are allowed.
  113. * @param $errors
  114. * An empty array where validation error messages will be set. The keys
  115. * of the array will be name of the field from the options array and the
  116. * value is the error message.
  117. * @param $warnings
  118. * An empty array where validation warning messagges will be set. The
  119. * warnings should not stop an insert or an update but should be provided
  120. * to the user as information by a drupal_set_message() if appropriate. The
  121. * keys of the array will be name of the field from the options array and the
  122. * value is the error message.
  123. *
  124. * @return
  125. * TRUE for success and FALSE for failure.
  126. *
  127. * @ingroup tripal_bulk_loader_api
  128. */
  129. function tripal_insert_bulk_loader_template($options, &$errors, &$warnings) {
  130. $success = tripal_validate_bulk_loader_template('insert', $options, $errors, $warnings);
  131. if (!$success) {
  132. foreach ($errors as $field => $message) {
  133. tripal_report_error('tripal_bulkldr', TRIPAL_ERROR, $message);
  134. }
  135. return FALSE;
  136. }
  137. // Insert the bulk loader template.
  138. $template_array = trim($options['template_array']);
  139. $template_name = trim($options['template_name']);
  140. // Previous version of Tripal would export the template as a PHP array.
  141. // This has security implications and is deprecated. This support should
  142. // be reomved in future versions of Tripal, but to support transfers of
  143. // templates between v1.1 and v2.x sites we support it.
  144. if (preg_match('/^array/', $template_array)) {
  145. $tarray = [];
  146. eval("\$tarray = $template_array;");
  147. $template_array = serialize($tarray);
  148. }
  149. // For a brief period, the bulk loader templates were exported as a PHP
  150. // serialized array. We have moved to exporting in JSON as JSON is more
  151. // user friendly. But we must support the serialized PHP array for
  152. // backwards compatibility of v2.0-rc1 sites and v2.x sites.
  153. elseif (preg_match('/^a:/', $template_array)) {
  154. // do nothing it's in PHP serialized format
  155. }
  156. // The typical format is JSON
  157. elseif (json_decode($template_array)) {
  158. $template_array = serialize(json_decode($template_array, TRUE));
  159. }
  160. else {
  161. $errors['template_array'] = t('Unrecognized array type.');
  162. return FALSE;
  163. }
  164. $record = [
  165. 'name' => $template_name,
  166. 'template_array' => $template_array,
  167. 'created' => time(),
  168. 'changed' => time(),
  169. ];
  170. if (!drupal_write_record('tripal_bulk_loader_template', $record)) {
  171. return FALSE;
  172. }
  173. return TRUE;
  174. }
  175. /**
  176. * Meant to be called from a form_validate function to ensure a newly added bulk
  177. * loader record name is unique and not empty.
  178. *
  179. * @param $new_record_name
  180. * The record name to check for uniqueness
  181. * @param $template_id
  182. * The template_id of the template to add the record to
  183. * @param $template_array
  184. * The array describing the template. Optional -will be loaded using
  185. * template_id if not provided
  186. * @param $current_priority
  187. * The priority of the already existing record -checks that the name only
  188. * occurs on this particular record
  189. *
  190. * @return
  191. * TRUE if the record name is not empty and not already in the template_array;
  192. * FALSE otherwise
  193. *
  194. * @ingroup tripal_bulk_loader_api
  195. */
  196. function tripal_is_bulk_loader_record_name_unique($new_record_name, $template_id, $template_array = NULL, $current_priority = NULL) {
  197. // get the template array if it's not supplied
  198. if (empty($template_array)) {
  199. $template = db_query("SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=:template", [':template' => $template_id])->fetchObject();
  200. $template_array = unserialize($template->template_array);
  201. if (!is_array($template_array)) {
  202. return TRUE;
  203. }
  204. }
  205. // Check that the new record name is not empty
  206. if (empty($new_record_name)) {
  207. return FALSE;
  208. }
  209. // Check the new record name is unique
  210. foreach ($template_array as $priority => $t) {
  211. if (strcmp($t['record_id'], $new_record_name) == 0) {
  212. if (($priority != $current_priority) AND ($current_priority !== NULL)) {
  213. return FALSE;
  214. }
  215. }
  216. }
  217. return TRUE;
  218. }
  219. /**
  220. * An API function to delete a record from a template array
  221. *
  222. * @param $delete_priority
  223. * The priority of the record to be deleted
  224. * @param $template_array
  225. * The array describing the template
  226. *
  227. * @return
  228. * The modified template array
  229. *
  230. * @ingroup tripal_bulk_loader_api
  231. */
  232. function tripal_delete_bulk_loader_record($delete_priority, $template_array) {
  233. if (empty($template_array)) {
  234. drupal_set_message("Unable to delete record with a priority of $priority since the template was not supplied", 'error');
  235. return FALSE;
  236. }
  237. $new_template_array = [];
  238. $i = 0;
  239. foreach ($template_array as $priority => $record) {
  240. if ($priority != $delete_priority) {
  241. $new_template_array[$i] = $record;
  242. $i++;
  243. }
  244. }
  245. return $new_template_array;
  246. }
  247. /**
  248. * An API function to delete a field from a template array
  249. *
  250. * @param $priority
  251. * The priority of the record containing the field
  252. * @param $delete_field_index
  253. * The index of the field to be deleted
  254. * @param $template_array
  255. * The array describing the template
  256. *
  257. * @return
  258. * The modified template array
  259. *
  260. * @ingroup tripal_bulk_loader_api
  261. */
  262. function tripal_delete_bulk_loader_field($priority, $delete_field_index, $template_array) {
  263. if (empty($template_array)) {
  264. drupal_set_message("Unable to delete record with a priority of $priority since the template was not supplied", 'error');
  265. return FALSE;
  266. }
  267. // Re-order the remaining fields of the same record to ensure that the indicies are
  268. // 0 to size and. If this is not done, weird behaviour may result
  269. $new_template_array = $template_array;
  270. $new_template_array[$priority]['fields'] = [];
  271. $i = 0;
  272. foreach ($template_array[$priority]['fields'] as $field_index => $field_details) {
  273. if ($field_index != $delete_field_index) {
  274. $new_template_array[$priority]['fields'][$i] = $field_details;
  275. $i++;
  276. }
  277. }
  278. // If this field was the only one in the current record, also delete the record
  279. if (empty($new_template_array[$priority]['fields'])) {
  280. $new_template_array = tripal_delete_bulk_loader_record($priority, $new_template_array);
  281. }
  282. return $new_template_array;
  283. }