Fix comment.
[project/data.git] / data.module
CommitLineData
2ace3f91
AB
1<?php
2// $Id$
3a16de16
AB
3/**
4 * @file
5 * Hooks and API functions for data module.
6 */
2ace3f91 7
2ace3f91 8/**
c0bdd519
AB
9 * Implementation of hook_views_api().
10 */
11function data_views_api() {
12 return array(
13 'api' => '2.0',
cff26223 14 'path' => drupal_get_path('module', 'data'),
34583f68 15 );
c0bdd519
AB
16}
17
18/**
f48c6947 19 * Create a table.
825e0da0
AB
20 *
21 * Usage:
f48c6947 22 * $table = data_create_table('my_table', $schema, 'My table');
825e0da0 23 * $table->save($data);
2ace3f91 24 *
5a6fc132
AB
25 * @see DataTable class.
26 *
2ace3f91
AB
27 * @param $name
28 * String that identifies the data table. It is recommended to use
29 * data_name() to generate a table name in the data namespace. For
30 * example: $table = data_get_tabe(data_name('my_table'));
f48c6947
AB
31 * @param $schema
32 * Schema for the table.
825e0da0
AB
33 * @param $title
34 * A natural title for the table.
2ace3f91 35 *
825e0da0
AB
36 * @return
37 * A DataTable object if init could create one,
38 * FALSE if not.
2ace3f91 39 */
f48c6947
AB
40function data_create_table($name, $schema, $title = NULL) {
41 if (_data_get_table($name)) {
825e0da0 42 return FALSE;
2ace3f91 43 }
f48c6947 44 return _data_get_table($name, $schema, $title);
2ace3f91
AB
45}
46
47/**
825e0da0 48 * Get a table if it exists.
5a6fc132
AB
49 *
50 * @see DataTable class.
51 *
825e0da0
AB
52 * @param $name
53 * Unique name of the table.
2ace3f91 54 *
825e0da0
AB
55 * @return
56 * A DataTable object if there is a table with this name,
57 * FALSE if not.
2ace3f91 58 */
825e0da0 59function data_get_table($name) {
f48c6947 60 if ($table = _data_get_table($name)) {
825e0da0
AB
61 return $table;
62 }
63 return FALSE;
2ace3f91
AB
64}
65
66/**
f48c6947
AB
67 * Drop a table - use this instead of $table->drop().
68 */
69function data_drop_table($name) {
70 if ($table = data_get_table($name)) {
71 $table->drop();
72 _data_get_table($name, NULL, NULL, TRUE);
73 }
74}
75
76/**
2ace3f91
AB
77 * Get schema info for all data allocated tables.
78 */
79function data_get_schema() {
80 $schema = array();
81 $tables = data_get_all_tables();
82 foreach ($tables as $table) {
83 $schema[$table->get('name')] = $table->get('table_schema');
84 }
85 return $schema;
86}
87
88/**
89 * Load all data tables.
90 */
91function data_get_all_tables() {
92 $tables = array();
93 $result = db_query('SELECT name FROM {data_tables}');
9933042e
AB
94 while ($row = db_fetch_object($result)) {
95 if ($table = data_get_table($row->name)) {
96 $tables[$row->name] = $table;
97 }
2ace3f91 98 }
f48c6947 99
2ace3f91
AB
100 return $tables;
101}
102
103/**
19aba4f3 104 * Get a list of supported field definitions.
2ace3f91
AB
105 *
106 * This list is a sub set of Schema API data types
107 * http://drupal.org/node/159605
108 * The keys are simplified handles.
2ace3f91 109 */
19aba4f3 110function data_get_field_definitions() {
2ace3f91
AB
111 return array(
112 'int' => array(
113 'type' => 'int',
114 'not null' => FALSE,
115 ),
116 'unsigned int' => array(
117 'type' => 'int',
118 'unsigned' => TRUE,
119 'not null' => FALSE,
120 ),
121 'varchar' => array(
122 'type' => 'varchar',
123 'length' => 255,
124 'not null' => FALSE,
125 ),
126 'text' => array(
127 'type' => 'text',
128 'not null' => FALSE,
129 ),
130 );
131}
132
133/**
19aba4f3 134 * Get a definition key into a schema API type definition.
2ace3f91 135 *
38e93719 136 * If no type can be found, FALSE will be returned.
2ace3f91 137 */
19aba4f3
AB
138function data_get_field_definition($key) {
139 $definitions = data_get_field_definitions();
140 if (isset($definitions[$key])) {
141 return $definitions[$key];
2ace3f91 142 }
38e93719 143 return FALSE;
2ace3f91
AB
144}
145
146/**
19aba4f3
AB
147 * Get schema API field types supported by Data module.
148 */
149function data_get_field_types() {
150 $definitions = data_get_field_definitions();
151 $types = array();
152 foreach ($definitions as $def) {
153 $types[$def['type']] = $def['type'];
154 }
155 return $types;
156}
157
158/**
159 * Get a Schema API PK definition for a given field type.
160 */
161function data_get_pk_definition($name, $type) {
162 if ($type == 'text') {
163 return array($name, 255);
164 }
165 else {
166 return $name;
167 }
168}
169
170/**
171 * Get a Schema API index definition for a given field type.
172 * @todo: support multiple name/type combinations.
173 */
174function data_get_index_definition($name, $type) {
175 if ($type == 'text') {
176 return array(array($name, 255));
177 }
178 else {
179 return array($name);
180 }
181}
182
183/**
2ace3f91
AB
184 * Create a table name in the data namespace.
185 * @todo: make overridable.
186 */
187function data_name($table) {
188 return 'data_table_'. $table;
189}
190
191/**
38e93719
AB
192 * Create a safe name for MySQL field or table names.
193 *
194 * @todo: IMPROVE.
195 *
196 * - make sure all unsafe characters are removed.
197 * - filter magic words.
198 * - test pgsql.
2ace3f91
AB
199 */
200function data_safe_name($name) {
201 $map = array(
202 '.' => '_',
203 ':' => '',
204 '/' => '',
205 '-' => '_',
206 ' ' => '_',
207 ',' => '_',
208 );
209 $simple = trim(strtolower(strip_tags($name)));
210 // Limit length to 64 as per http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
211 $simple = substr(strtr($simple, $map), 0, 64);
212
213 if (is_numeric($simple)) {
214 // We need to escape numerics because Drupal's drupal_write_record()
215 // does not properly escape token MYSQL names.
216 $simple = '__num_'. $simple;
217 }
218 return db_escape_table($simple);
219}
220
221/**
222 * Helper function to create a natural name.
223 * underscored_name -> Underscored name
224 */
225function data_natural_name($name) {
226 return ucfirst(strtolower(str_replace('_', ' ', $name)));
227}
228
229/**
2ace3f91
AB
230 * Helper function to generate a schema.
231 *
232 * Example:
233 * $table->create(data_build_schema($keys));
234 *
235 * @todo: check for table name collisions
236 * @todo: add type detection
237 * @todo: add meta info handling
238 * @todo: add primary key handling
239 * @todo: may be add option to add a full fledged schema here?
240 */
241function data_build_schema($keys) {
38e93719
AB
242 // Build the table definition.
243 // Fall back to varchar if no valid type is given.
19aba4f3
AB
244 $fields = $schema = array();
245 foreach ($keys as $k => $key) {
246 if ($definition = data_get_field_definition($key)) {
247 $fields[data_safe_name($k)] = $definition;
38e93719
AB
248 }
249 else {
19aba4f3 250 $fields[data_safe_name($k)] = data_get_field_definition('varchar');
38e93719 251 }
2ace3f91 252 }
38e93719 253
2ace3f91
AB
254 $schema['fields'] = $fields;
255 $schema['indexes'] = array();
256 return $schema;
257}
258
259/**
19aba4f3 260 * Build a full schema api field definition.
2ace3f91
AB
261 *
262 * @param $stub
263 * Array with at least one key 'type'.
264 */
19aba4f3 265function data_build_field_definition($stub) {
2ace3f91
AB
266 $spec = array();
267 $spec['type'] = $stub['type'];
268 if ($spec['type'] == 'int') {
269 $spec['unsigned'] = empty($stub['unsigned']) ? FALSE : TRUE;
270 }
271 if ($spec['type'] == 'varchar') {
272 $spec['length'] = 255;
273 }
274 return $spec;
275}
276
277/**
83dadde7
AB
278 * Internal singleton/factory function for creating a single instance of a DataTable class.
279 *
280 * Don't use this function directly. Call data_create_table() or data_get_table() instead.
281 *
282 * If a schema is given, _data_get_table() creates the table objects DB structure.
283 *
284 * The purpose of this function is to make sure that
285 *
286 * a) there is only a single DataTable object for accessing a specific DataTable.
287 * b) there is no DataTable object that does not have an existing table.
288 */
289function _data_get_table($name, $schema = NULL, $title = NULL, $reset = FALSE) {
290 _data_include();
291
292 static $tables;
293 // Simple way of having a way to override the class being used.
294 // This could be refined with a $type parameter in _data_get_table() and depending
295 // functions.
296 $class = variable_get('data_table_class', 'DataTable');
297 if ($reset) {
298 unset($tables[$name]);
299 }
300
301 if (!isset($tables[$name])) {
302 if (db_result(db_query('SELECT name FROM {data_tables} WHERE name = "%s"', $name))) {
303 $tables[$name] = new $class($name);
304 }
305 }
306 if ($schema) {
307 $tables[$name] = new $class($name, $schema, $title);
308 }
309 return isset($tables[$name]) ? $tables[$name] : FALSE;
310}
311
312/**
d826902e 313 * Include class file.
2ace3f91 314 */
d826902e
AB
315function _data_include() {
316 static $included;
317 if (!$included) {
318 include drupal_get_path('module', 'data') .'/data.inc';
825e0da0 319 }
d826902e
AB
320 $included = TRUE;
321}