[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

/sites/all/modules/data/ -> data.module (source)

   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 {}


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7