data.module

Hooks and API functions for data module.

Functions

Namesort descending Description
data_alter_table Helper function for adjusting a table's real schema. @todo: this should live in schema module and should use better defined $reason keys.
data_build_field_definition Build a full schema api field definition.
data_build_schema Helper function to generate a schema.
data_create_table Create a table.
data_drop_table Deprecated @todo: remove.
data_export Export a data table. This does not export the content of a table - only its schema and any meta information (title, name, meta...).
data_get_all_tables Load all data tables.
data_get_field_definition Get a definition key into a schema API type definition.
data_get_field_definitions Get a list of supported field definitions.
data_get_field_sizes Get schema API field sizes.
data_get_field_types Get schema API field types supported by Data module.
data_get_handler Get Data handler for a table.
data_get_index_definition Get a Schema API index definition for a given field type. @todo: support multiple name/type combinations.
data_get_pk_definition Get a Schema API PK definition for a given field type.
data_get_table Get a table if it exists.
data_name Create a table name in the data namespace. @todo: make overridable.
data_natural_name Helper function to create a natural name. underscored_name -> Underscored name
data_safe_name Create a safe name for MySQL field or table names.
data_views_api Implements hook_views_api().
_data_load_table Loads data table info from the database and from CTools exportables.
_data_override Starts overriding a data table by copying it from the default definition into the DB. This function does not have any effect if called on a table that does already exist in data_tables.

Classes

Namesort descending Description
DataException Base class for any exceptions thrown in Data.

File

sites/all/modules/local_contrib/data/data.module
View source
  1. <?php
  2. /**
  3. * @file
  4. * Hooks and API functions for data module.
  5. */
  6. /**
  7. * Implements hook_views_api().
  8. */
  9. function data_views_api() {
  10. return array(
  11. 'api' => '2.0',
  12. 'path' => drupal_get_path('module', 'data'),
  13. );
  14. }
  15. /**
  16. * Load all data tables.
  17. */
  18. function data_get_all_tables($reset = FALSE) {
  19. $tables = array();
  20. if ($tables = _data_load_table(NULL, $reset)) {
  21. foreach ($tables as $table_name => $table) {
  22. if ($table = data_get_table($table_name)) {
  23. $tables[$table_name] = $table;
  24. }
  25. }
  26. }
  27. return $tables;
  28. }
  29. /**
  30. * Create a table.
  31. *
  32. * @see DataTable class.
  33. *
  34. * @param $name
  35. * String that identifies the data table. It is recommended to use
  36. * data_name() to generate a table name in the data namespace. For
  37. * example: $table = data_get_tabe(data_name('my_table'));
  38. * @param $schema
  39. * Schema for the table.
  40. * @param $title
  41. * A natural title for the table.
  42. *
  43. * @return
  44. * A DataTable object if one could be created, FALSE otherwise.
  45. */
  46. function data_create_table($name, $schema, $title = NULL) {
  47. $table = DataTable::instance($name);
  48. if ($table->create($schema)) {
  49. if (!empty($title)) {
  50. $table->update(array('title' => $title));
  51. }
  52. return $table;
  53. }
  54. return FALSE;
  55. }
  56. /**
  57. * Get a table if it exists.
  58. *
  59. * @see DataTable class.
  60. *
  61. * @param $name
  62. * Unique name of the table.
  63. *
  64. * @return
  65. * A unique DataTable object if defined, FALSE otherwise.
  66. *
  67. * Note: In some circumstances, a table may be defined while it does not exist
  68. * in the database. In these cases, data_get_table() would still return a valid
  69. * DataTable object.
  70. */
  71. function data_get_table($name) {
  72. $table = DataTable::instance($name);
  73. if ($table->defined()) {
  74. return $table;
  75. }
  76. return FALSE;
  77. }
  78. /**
  79. * @deprecated - use $table->drop() instead.
  80. * @todo: remove.
  81. */
  82. function data_drop_table($name) {
  83. if ($table = data_get_table($name)) {
  84. $table->drop();
  85. }
  86. }
  87. /**
  88. * Get Data handler for a table.
  89. *
  90. * @see class DataHandler
  91. *
  92. * @param $table_name
  93. * String that is the name of a table.
  94. *
  95. * @return
  96. * DataHandler object that provides access to a table's data.
  97. */
  98. function data_get_handler($table_name) {
  99. return DataHandler::instance($table_name);
  100. }
  101. /**
  102. * Get a list of supported field definitions.
  103. *
  104. * This list is a sub set of Schema API data types
  105. * http://drupal.org/node/159605
  106. * The keys are simplified handles.
  107. */
  108. function data_get_field_definitions() {
  109. return array(
  110. 'int' => array(
  111. 'type' => 'int',
  112. 'not null' => FALSE,
  113. ),
  114. 'unsigned int' => array(
  115. 'type' => 'int',
  116. 'unsigned' => TRUE,
  117. 'not null' => FALSE,
  118. ),
  119. 'serial' => array(
  120. 'type' => 'serial',
  121. 'unsigned' => TRUE,
  122. 'not null' => TRUE,
  123. ),
  124. 'varchar' => array(
  125. 'type' => 'varchar',
  126. 'length' => 255,
  127. 'not null' => FALSE,
  128. ),
  129. 'text' => array(
  130. 'type' => 'text',
  131. 'not null' => FALSE,
  132. ),
  133. 'bigtext' => array(
  134. 'type' => 'text',
  135. 'not null' => FALSE,
  136. 'size' => 'big',
  137. ),
  138. 'float' => array(
  139. 'type' => 'float',
  140. 'size' => 'medium',
  141. 'not null' => FALSE,
  142. ),
  143. 'double' => array(
  144. 'type' => 'float',
  145. 'size' => 'big',
  146. 'not null' => FALSE,
  147. ),
  148. 'geometry' => array(
  149. 'type' => 'geometry',
  150. 'mysql_type' => 'geometry',
  151. 'pgsql_type' => 'geometry',
  152. ),
  153. );
  154. }
  155. /**
  156. * Get a definition key into a schema API type definition.
  157. *
  158. * If no type can be found, FALSE will be returned.
  159. */
  160. function data_get_field_definition($key) {
  161. $definitions = data_get_field_definitions();
  162. if (isset($definitions[$key])) {
  163. return $definitions[$key];
  164. }
  165. return FALSE;
  166. }
  167. /**
  168. * Get schema API field types supported by Data module.
  169. */
  170. function data_get_field_types() {
  171. $definitions = data_get_field_definitions();
  172. $types = array();
  173. foreach ($definitions as $def) {
  174. $types[$def['type']] = $def['type'];
  175. }
  176. return $types;
  177. }
  178. /**
  179. * Get schema API field sizes.
  180. */
  181. function data_get_field_sizes() {
  182. $sizes = array('normal', 'tiny', 'small', 'medium', 'big');
  183. return drupal_map_assoc($sizes);
  184. }
  185. /**
  186. * Get a Schema API PK definition for a given field type.
  187. */
  188. function data_get_pk_definition($field_name, $spec) {
  189. if ($spec['type'] == 'text') {
  190. return array($field_name, 255);
  191. }
  192. else {
  193. return $field_name;
  194. }
  195. }
  196. /**
  197. * Get a Schema API index definition for a given field type.
  198. * @todo: support multiple name/type combinations.
  199. */
  200. function data_get_index_definition($field_name, $spec) {
  201. // Default to 255 for now.
  202. if ($spec['type'] == 'text') {
  203. // @todo: what's the right format here? this is broken.
  204. return array(array($field_name, 255));
  205. }
  206. else {
  207. return array($field_name);
  208. }
  209. }
  210. /**
  211. * Create a table name in the data namespace.
  212. * @todo: make overridable.
  213. */
  214. function data_name($table) {
  215. return 'data_table_' . $table;
  216. }
  217. /**
  218. * Create a safe name for MySQL field or table names.
  219. *
  220. * @todo: IMPROVE.
  221. *
  222. * - make sure all unsafe characters are removed.
  223. * - filter magic words.
  224. * - test pgsql.
  225. */
  226. function data_safe_name($name) {
  227. $map = array(
  228. '.' => '_',
  229. ':' => '',
  230. '/' => '',
  231. '-' => '_',
  232. ' ' => '_',
  233. ',' => '_',
  234. );
  235. $simple = trim(strtolower(strip_tags($name)));
  236. // Limit length to 64 as per http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
  237. $simple = substr(strtr($simple, $map), 0, 64);
  238. if (is_numeric($simple)) {
  239. // We need to escape numerics because Drupal's drupal_write_record()
  240. // does not properly escape token MYSQL names.
  241. $simple = '__num_' . $simple;
  242. }
  243. return db_escape_table($simple);
  244. }
  245. /**
  246. * Helper function to create a natural name.
  247. * underscored_name -> Underscored name
  248. */
  249. function data_natural_name($name) {
  250. return ucfirst(strtolower(str_replace('_', ' ', $name)));
  251. }
  252. /**
  253. * Helper function to generate a schema.
  254. *
  255. * Example:
  256. * $table->create(data_build_schema($keys));
  257. *
  258. * @todo: check for table name collisions
  259. * @todo: add type detection
  260. * @todo: add meta info handling
  261. * @todo: add primary key handling
  262. * @todo: may be add option to add a full fledged schema here?
  263. */
  264. function data_build_schema($keys) {
  265. // Build the table definition.
  266. // Fall back to varchar if no valid type is given.
  267. $fields = $schema = array();
  268. foreach ($keys as $k => $key) {
  269. if ($definition = data_get_field_definition($key)) {
  270. $fields[data_safe_name($k)] = $definition;
  271. }
  272. else {
  273. $fields[data_safe_name($k)] = data_get_field_definition('varchar');
  274. }
  275. }
  276. $schema['fields'] = $fields;
  277. $schema['indexes'] = array();
  278. return $schema;
  279. }
  280. /**
  281. * Build a full schema api field definition.
  282. *
  283. * @param $stub
  284. * Array with at least one key 'type'.
  285. */
  286. function data_build_field_definition($stub) {
  287. $spec = array();
  288. $spec['type'] = $stub['type'];
  289. $spec['size'] = empty($stub['size']) ? 'normal' : $stub['size'];
  290. if ($spec['type'] == 'int') {
  291. $spec['unsigned'] = empty($stub['unsigned']) ? FALSE : TRUE;
  292. }
  293. if ($spec['type'] == 'varchar') {
  294. $spec['length'] = 255;
  295. unset($spec['size']);
  296. }
  297. if ($spec['type'] == 'geometry') {
  298. $spec['mysql_type'] = 'geometry';
  299. $spec['pgsql_type'] = 'GEOMETRY';
  300. }
  301. return $spec;
  302. }
  303. /**
  304. * Export a data table. This does not export the content of a table - only its schema
  305. * and any meta information (title, name, meta...).
  306. *
  307. * @param $name
  308. * The name of the table to be exported.
  309. *
  310. * @return
  311. * Exportable code.
  312. */
  313. function data_export($name, $indent = '') {
  314. ctools_include('export');
  315. $result = ctools_export_load_object('data_tables', 'names', array($name));
  316. if (isset($result[$name])) {
  317. return ctools_export_object('data_tables', $result[$name], $indent);
  318. }
  319. }
  320. /**
  321. * Loads data table info from the database and from CTools exportables.
  322. *
  323. * @param $name
  324. * The name of a table to load. If NULL or omitted, all tables are loaded.
  325. * @param $reset
  326. * Whether to reset CTools' static cache.
  327. */
  328. function _data_load_table($name = NULL, $reset = FALSE) {
  329. ctools_include('export');
  330. if ($reset) {
  331. drupal_static_reset('ctools_export_load_object');
  332. drupal_static_reset('ctools_export_load_object_all');
  333. }
  334. if ($name === NULL) {
  335. return ctools_export_load_object('data_tables', 'all', array());
  336. }
  337. else {
  338. $tables = ctools_export_load_object('data_tables', 'names', array($name));
  339. if (isset($tables[$name])) {
  340. return $tables[$name];
  341. }
  342. return FALSE;
  343. }
  344. return FALSE;
  345. }
  346. /**
  347. * Helper function for adjusting a table's real schema.
  348. * @todo: this should live in schema module and should use better defined $reason keys.
  349. *
  350. * @throws DataException on error.
  351. */
  352. function data_alter_table($table, $field_reason) {
  353. list($field, $reason) = explode(': ', $field_reason);
  354. $schema = $table->get('table_schema');
  355. switch ($reason) {
  356. case 'not in database':
  357. if (isset($schema['fields'][$field])) {
  358. $table->addField($field, $schema['fields'][$field]);
  359. }
  360. break;
  361. case 'missing in database':
  362. list($type, $field) = explode(' ', $field);
  363. // @todo: support multiple keys.
  364. if ($type == 'indexes') {
  365. $table->addIndex($field);
  366. }
  367. elseif ($type == 'unique keys') {
  368. $table->addUniqueKey($field);
  369. }
  370. elseif ($type == 'primary key') {
  371. $table->addPrimaryKey($schema['primary keys']);
  372. }
  373. break;
  374. case 'primary key:<br />declared': // @todo: yikes!
  375. $table->dropPrimaryKey();
  376. $table->changePrimaryKey($schema['primary keys']);
  377. case 'missing in schema':
  378. if ($field == 'primary key') {
  379. $table->dropPrimaryKey();
  380. }
  381. break;
  382. case 'unexpected column in database':
  383. $table->dropField($field);
  384. break;
  385. }
  386. }
  387. /**
  388. * Starts overriding a data table by copying it from the default definition into the DB.
  389. * This function does not have any effect if called on a table that does already exist in
  390. * data_tables.
  391. */
  392. function _data_override($name) {
  393. if (!db_query("SELECT name FROM {data_tables} WHERE name = :name", array(':name' => $name))->fetchField()) {
  394. if ($table = _data_load_table($name)) {
  395. drupal_write_record('data_tables', $table);
  396. }
  397. }
  398. }
  399. /**
  400. * Base class for any exceptions thrown in Data.
  401. */
  402. class DataException extends Exception { }