5 * Hooks and API functions for data module.
8 // Constant designating an undefined export state.
9 // Used in absence of EXPORT_IN_CODE, EXPORT_IN_DATABASE
10 define('DATA_EXPORT_UNDEFINED', 0);
13 * Implementation of hook_views_api().
15 function data_views_api() {
18 'path' => drupal_get_path('module', 'data'),
23 * Implementation of hook_features_api().
25 function data_features_api() {
27 'default_hook' => 'data_default',
28 'file' => drupal_get_path('module', 'data') .
'/data.features.inc',
36 * $table = data_create_table('my_table', $schema, 'My table');
37 * $table->save($data);
39 * @see DataTable class.
42 * String that identifies the data table. It is recommended to use
43 * data_name() to generate a table name in the data namespace. For
44 * example: $table = data_get_tabe(data_name('my_table'));
46 * Schema for the table.
48 * A natural title for the table.
51 * A DataTable object if init could create one,
54 function data_create_table($name, $schema, $title = NULL
) {
55 if (_data_get_table($name, NULL
, NULL
, TRUE
)) {
58 return _data_get_table($name, $schema, $title);
62 * Get a table if it exists.
64 * @see DataTable class.
67 * Unique name of the table.
70 * A DataTable object if there is a table with this name,
73 function data_get_table($name) {
74 if ($table = _data_get_table($name)) {
81 * Drop a table - use this instead of $table->drop().
83 function data_drop_table($name) {
84 if ($table = data_get_table($name)) {
86 _data_get_table($name, NULL
, NULL
, TRUE
);
91 * Get schema info for all data allocated tables.
93 * Pull directly from database to avoid race conditions.
95 function data_get_schema() {
97 $result = db_query('SELECT name, table_schema FROM {data_tables}');
98 while ($table = db_fetch_object($result)) {
99 $schema[$table->name
] = unserialize($table->table_schema
);
105 * Load all data tables.
107 function data_get_all_tables() {
109 if ($tables = _data_load_table()) {
110 foreach ($tables as
$table_name => $table) {
111 if ($table = data_get_table($table_name)) {
112 $tables[$table_name] = $table;
120 * Get a list of supported field definitions.
122 * This list is a sub set of Schema API data types
123 * http://drupal.org/node/159605
124 * The keys are simplified handles.
126 function data_get_field_definitions() {
132 'unsigned int' => array(
150 * Get a definition key into a schema API type definition.
152 * If no type can be found, FALSE will be returned.
154 function data_get_field_definition($key) {
155 $definitions = data_get_field_definitions();
156 if (isset($definitions[$key])) {
157 return $definitions[$key];
163 * Get schema API field types supported by Data module.
165 function data_get_field_types() {
166 $definitions = data_get_field_definitions();
168 foreach ($definitions as
$def) {
169 $types[$def['type']] = $def['type'];
175 * Get a Schema API PK definition for a given field type.
177 function data_get_pk_definition($name, $type) {
178 if ($type == 'text') {
179 return array($name, 255);
187 * Get a Schema API index definition for a given field type.
188 * @todo: support multiple name/type combinations.
190 function data_get_index_definition($name, $type) {
191 if ($type == 'text') {
192 return array(array($name, 255));
200 * Create a table name in the data namespace.
201 * @todo: make overridable.
203 function data_name($table) {
204 return 'data_table_'.
$table;
208 * Create a safe name for MySQL field or table names.
212 * - make sure all unsafe characters are removed.
213 * - filter magic words.
216 function data_safe_name($name) {
225 $simple = trim(strtolower(strip_tags($name)));
226 // Limit length to 64 as per http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
227 $simple = substr(strtr($simple, $map), 0, 64);
229 if (is_numeric($simple)) {
230 // We need to escape numerics because Drupal's drupal_write_record()
231 // does not properly escape token MYSQL names.
232 $simple = '__num_'.
$simple;
234 return db_escape_table($simple);
238 * Helper function to create a natural name.
239 * underscored_name -> Underscored name
241 function data_natural_name($name) {
242 return ucfirst(strtolower(str_replace('_', ' ', $name)));
246 * Helper function to generate a schema.
249 * $table->create(data_build_schema($keys));
251 * @todo: check for table name collisions
252 * @todo: add type detection
253 * @todo: add meta info handling
254 * @todo: add primary key handling
255 * @todo: may be add option to add a full fledged schema here?
257 function data_build_schema($keys) {
258 // Build the table definition.
259 // Fall back to varchar if no valid type is given.
260 $fields = $schema = array();
261 foreach ($keys as
$k => $key) {
262 if ($definition = data_get_field_definition($key)) {
263 $fields[data_safe_name($k)] = $definition;
266 $fields[data_safe_name($k)] = data_get_field_definition('varchar');
270 $schema['fields'] = $fields;
271 $schema['indexes'] = array();
276 * Build a full schema api field definition.
279 * Array with at least one key 'type'.
281 function data_build_field_definition($stub) {
283 $spec['type'] = $stub['type'];
284 if ($spec['type'] == 'int') {
285 $spec['unsigned'] = empty($stub['unsigned']) ? FALSE
: TRUE
;
287 if ($spec['type'] == 'varchar') {
288 $spec['length'] = 255;
294 * Export a data table. This does not export the content of a table - only its schema
295 * and any meta information (title, name, meta...).
298 * The name of the table to be exported.
303 * Only available if ctools is installed.
305 function data_export($name, $indent = '') {
306 if (module_exists('ctools')) {
307 ctools_include('export');
308 $result = ctools_export_load_object('data_tables', 'names', array($name));
309 if (isset($result[$name])) {
310 return ctools_export_object('data_tables', $result[$name], $indent);
313 return t('Export requires CTools http://drupal.org/project/ctools');
317 * Internal singleton/factory function for creating a single instance of a DataTable class.
319 * Don't use this function directly. Call data_create_table() or data_get_table() instead.
321 * If a schema is given, _data_get_table() creates the table objects DB structure.
323 * The purpose of this function is to make sure that
325 * a) there is only a single DataTable object for accessing a specific DataTable.
326 * b) there is no DataTable object that does not have an existing table.
328 function _data_get_table($name, $schema = NULL
, $title = NULL
, $reset = FALSE
) {
332 // Simple way of having a way to override the class being used.
333 // This could be refined with a $type parameter in _data_get_table() and depending
335 $class = variable_get('data_table_class', 'DataTable');
337 unset($tables[$name]);
340 if (!isset($tables[$name])) {
341 // Try whether we can load table, then instantiate. Object will then load itself.
342 if (_data_load_table($name, $reset)) {
343 $tables[$name] = new
$class($name);
347 $tables[$name] = new
$class($name, $schema, $title);
349 return isset($tables[$name]) ?
$tables[$name] : FALSE
;
353 * Loads data table info from the database. Uses CTools if available.
355 function _data_load_table($name = NULL
, $reset = FALSE
) {
356 if (module_exists('ctools')) {
357 ctools_include('export');
359 return ctools_export_load_object('data_tables', 'all', array(), $reset);
362 $tables = ctools_export_load_object('data_tables', 'names', array($name), $reset);
363 if (isset($tables[$name])) {
364 return $tables[$name];
369 // If CTools is not available, load directly from DB.
371 $result = db_query('SELECT * FROM {data_tables}');
373 while ($row = db_fetch_object($result)) {
374 foreach (array('table_schema', 'meta') as
$key) {
375 $row->$key = unserialize($row->$key);
378 $row->export_type
= DATA_EXPORT_UNDEFINED
;
379 $tables[$row->name
] = $row;
383 if ($table = db_fetch_object(db_query('SELECT * FROM {data_tables} WHERE name = "%s"', $name))) {
385 $table->export_type
= DATA_EXPORT_UNDEFINED
;
392 * Starts overriding a data table by copying it from the default definition into the DB.
393 * This function does not have any effect if called on a table that does already exist in
396 function _data_override($name) {
397 if (!db_result(db_query('SELECT name FROM {data_tables} WHERE name = "%s"', $name))) {
398 if ($table = _data_load_table($name)) {
399 drupal_write_record('data_tables', $table);
405 * Include class file.
407 function _data_include() {
410 include
drupal_get_path('module', 'data') .
'/data.inc';