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