source: sipes/modules_contrib/ctools/includes/export.inc @ a8b1f3f

stableversion-3.0
Last change on this file since a8b1f3f was 2efe680, checked in by José Gregorio Puentes <jpuentes@…>, 8 años ago

se actualizo el modulo

  • Propiedad mode establecida a 100755
File size: 31.8 KB
Línea 
1<?php
2
3/**
4 * @file
5 * Contains code to make it easier to have exportable objects.
6 *
7 * Documentation for exportable objects is contained in help/export.html
8 */
9
10/**
11 * A bit flag used to let us know if an object is in the database.
12 */
13define('EXPORT_IN_DATABASE', 0x01);
14
15/**
16 * A bit flag used to let us know if an object is a 'default' in code.
17 */
18define('EXPORT_IN_CODE', 0x02);
19
20/**
21 * @defgroup export_crud CRUD functions for export.
22 * @{
23 * export.inc supports a small number of CRUD functions that should always
24 * work for every exportable object, no matter how complicated. These
25 * functions allow complex objects to provide their own callbacks, but
26 * in most cases, the default callbacks will be used.
27 *
28 * Note that defaults are NOT set in the $schema because it is presumed
29 * that a module's personalized CRUD functions will already know which
30 * $table to use and not want to clutter up the arguments with it.
31 */
32
33/**
34 * Create a new object for the given $table.
35 *
36 * @param $table
37 *   The name of the table to use to retrieve $schema values. This table
38 *   must have an 'export' section containing data or this function
39 *   will fail.
40 * @param $set_defaults
41 *   If TRUE, which is the default, then default values will be retrieved
42 *   from schema fields and set on the object.
43 *
44 * @return
45 *   The loaded object.
46 */
47function ctools_export_crud_new($table, $set_defaults = TRUE) {
48  $schema = ctools_export_get_schema($table);
49  $export = $schema['export'];
50
51  if (!empty($export['create callback']) && function_exists($export['create callback'])) {
52    return $export['create callback']($set_defaults);
53  }
54  else {
55    return ctools_export_new_object($table, $set_defaults);
56  }
57}
58
59/**
60 * Load a single exportable object.
61 *
62 * @param $table
63 *   The name of the table to use to retrieve $schema values. This table
64 *   must have an 'export' section containing data or this function
65 *   will fail.
66 * @param $name
67 *   The unique ID to load. The field for this ID will be specified by
68 *   the export key, which normally defaults to 'name'.
69 *
70 * @return
71 *   The loaded object.
72 */
73function ctools_export_crud_load($table, $name) {
74  $schema = ctools_export_get_schema($table);
75  $export = $schema['export'];
76
77  if (!empty($export['load callback']) && function_exists($export['load callback'])) {
78    return $export['load callback']($name);
79  }
80  else {
81    $result = ctools_export_load_object($table, 'names', array($name));
82    if (isset($result[$name])) {
83      return $result[$name];
84    }
85  }
86}
87
88/**
89 * Load all exportable objects of a given type.
90 *
91 * @param $table
92 *   The name of the table to use to retrieve $schema values. This table
93 *   must have an 'export' section containing data or this function
94 *   will fail.
95 * @param $reset
96 *   If TRUE, the static cache of all objects will be flushed prior to
97 *   loading all. This can be important on listing pages where items
98 *   might have changed on the page load.
99 * @return
100 *   An array of all loaded objects, keyed by the unique IDs of the export key.
101 */
102function ctools_export_crud_load_all($table, $reset = FALSE) {
103  $schema = ctools_export_get_schema($table);
104  if (empty($schema['export'])) {
105    return array();
106  }
107
108  $export = $schema['export'];
109
110  if ($reset) {
111    ctools_export_load_object_reset($table);
112  }
113
114  if (!empty($export['load all callback']) && function_exists($export['load all callback'])) {
115    return $export['load all callback']($reset);
116  }
117  else {
118    return ctools_export_load_object($table, 'all');
119  }
120}
121
122/**
123 * Save a single exportable object.
124 *
125 * @param $table
126 *   The name of the table to use to retrieve $schema values. This table
127 *   must have an 'export' section containing data or this function
128 *   will fail.
129 * @param $object
130 *   The fully populated object to save.
131 *
132 * @return
133 *   Failure to write a record will return FALSE. Otherwise SAVED_NEW or
134 *   SAVED_UPDATED is returned depending on the operation performed. The
135 *   $object parameter contains values for any serial fields defined by the $table
136 */
137function ctools_export_crud_save($table, &$object) {
138  $schema = ctools_export_get_schema($table);
139  $export = $schema['export'];
140
141  if (!empty($export['save callback']) && function_exists($export['save callback'])) {
142    return $export['save callback']($object);
143  }
144  else {
145    // Objects should have a serial primary key. If not, simply fail to write.
146    if (empty($export['primary key'])) {
147      return FALSE;
148    }
149
150    $key = $export['primary key'];
151    if ($object->export_type & EXPORT_IN_DATABASE) {
152      // Existing record.
153      $update = array($key);
154    }
155    else {
156      // New record.
157      $update = array();
158      $object->export_type = EXPORT_IN_DATABASE;
159    }
160    return drupal_write_record($table, $object, $update);
161  }
162}
163
164/**
165 * Delete a single exportable object.
166 *
167 * This only deletes from the database, which means that if an item is in
168 * code, then this is actually a revert.
169 *
170 * @param $table
171 *   The name of the table to use to retrieve $schema values. This table
172 *   must have an 'export' section containing data or this function
173 *   will fail.
174 * @param $object
175 *   The fully populated object to delete, or the export key.
176 */
177function ctools_export_crud_delete($table, $object) {
178  $schema = ctools_export_get_schema($table);
179  $export = $schema['export'];
180
181  if (!empty($export['delete callback']) && function_exists($export['delete callback'])) {
182    return $export['delete callback']($object);
183  }
184  else {
185    // If we were sent an object, get the export key from it. Otherwise
186    // assume we were sent the export key.
187    $value = is_object($object) ? $object->{$export['key']} : $object;
188    db_query("DELETE FROM {" . $table . "} WHERE " . $export['key'] . " = '%s'", $value);
189  }
190}
191
192/**
193 * Get the exported code of a single exportable object.
194 *
195 * @param $table
196 *   The name of the table to use to retrieve $schema values. This table
197 *   must have an 'export' section containing data or this function
198 *   will fail.
199 * @param $object
200 *   The fully populated object to delete, or the export key.
201 * @param $indent
202 *   Any indentation to apply to the code, in case this object is embedded
203 *   into another, for example.
204 *
205 * @return
206 *   A string containing the executable export of the object.
207 */
208function ctools_export_crud_export($table, $object, $indent = '') {
209  $schema = ctools_export_get_schema($table);
210  $export = $schema['export'];
211
212  if (!empty($export['export callback']) && function_exists($export['export callback'])) {
213    return $export['export callback']($object, $indent);
214  }
215  else {
216    return ctools_export_object($table, $object, $indent);
217  }
218}
219
220/**
221 * Turn exported code into an object.
222 *
223 * Note: If the code is poorly formed, this could crash and there is no
224 * way to prevent this.
225 *
226 * @param $table
227 *   The name of the table to use to retrieve $schema values. This table
228 *   must have an 'export' section containing data or this function
229 *   will fail.
230 * @param $code
231 *   The code to eval to create the object.
232 *
233 * @return
234 *   An object created from the export. This object will NOT have been saved
235 *   to the database. In the case of failure, a string containing all errors
236 *   that the system was able to determine.
237 */
238function ctools_export_crud_import($table, $code) {
239  $schema = ctools_export_get_schema($table);
240  $export = $schema['export'];
241
242  if (!empty($export['import callback']) && function_exists($export['import callback'])) {
243    return $export['import callback']($code);
244  }
245  else {
246    ob_start();
247    eval($code);
248    ob_end_clean();
249
250    if (empty(${$export['identifier']})) {
251      $errors = ob_get_contents();
252      if (empty($errors)) {
253        $errors = t('No item found.');
254      }
255      return $errors;
256    }
257
258    $item = ${$export['identifier']};
259
260    // Set these defaults just the same way that ctools_export_new_object sets
261    // them.
262    $item->export_type = NULL;
263    $item->{$export['export type string']} = t('Local');
264
265    return $item;
266  }
267}
268
269/**
270 * @}
271 */
272
273/**
274 * Load some number of exportable objects.
275 *
276 * This function will cache the objects, load subsidiary objects if necessary,
277 * check default objects in code and properly set them up. It will cache
278 * the results so that multiple calls to load the same objects
279 * will not cause problems.
280 *
281 * It attempts to reduce, as much as possible, the number of queries
282 * involved.
283 *
284 * @param $table
285 *   The name of the table to be loaded from. Data is expected to be in the
286 *   schema to make all this work.
287 * @param $type
288 *   A string to notify the loader what the argument is
289 *   - all: load all items. This is the default. $args is unused.
290 *   - names: $args will be an array of specific named objects to load.
291 *   - conditions: $args will be a keyed array of conditions. The conditions
292 *       must be in the schema for this table or errors will result.
293 * @param $args
294 *   An array of arguments whose actual use is defined by the $type argument.
295 */
296function ctools_export_load_object($table, $type = 'all', $args = array()) {
297  $cache = &ctools_static(__FUNCTION__);
298  $cached_database = &ctools_static('ctools_export_load_object_all');
299
300  $schema = ctools_export_get_schema($table);
301  if (empty($schema)) {
302    return array();
303  }
304
305  $join_schemas = array();
306  $export = $schema['export'];
307
308  if (!isset($cache[$table])) {
309    $cache[$table] = array();
310  }
311
312  // If fetching all and cached all, we've done so and we are finished.
313  if ($type == 'all' && !empty($cached_database[$table])) {
314    return $cache[$table];
315  }
316
317  $return = array();
318
319  // Don't load anything we've already cached.
320  if ($type == 'names' && !empty($args)) {
321    foreach ($args as $id => $name) {
322      if (isset($cache[$table][$name])) {
323        $return[$name] = $cache[$table][$name];
324        unset($args[$id]);
325      }
326    }
327
328    // If nothing left to load, return the result.
329    if (empty($args)) {
330      return $return;
331    }
332  }
333
334  // Build the query
335  $query = "SELECT * FROM {" . $table . "} t__0";
336  $alias_count = 1;
337  if (!empty($schema['join'])) {
338    foreach ($schema['join'] as $join_key => $join) {
339      $join_schema = drupal_get_schema($join['table']);
340      if (!empty($join_schema)) {
341        $query .= ' INNER JOIN {' . $join['table'] . '} t__' . $alias_count . ' ON t__0.' . $join['left_key'] . ' = ' . 't__' . $alias_count . '.' . $join['right_key'];
342        $alias_count++;
343        $join_schemas[$join['table']] = $join_schema;
344        if (!empty($join['extra'])) {
345          $query .= ' ' . $join['extra'];
346        }
347      }
348    }
349  }
350
351  $conditions = array();
352  $query_args = array();
353
354  // If they passed in names, add them to the query.
355  if ($type == 'names') {
356    if (!isset($export['key in table'])) {
357      $conditions[] = "$export[key] IN (" . db_placeholders($args, $schema['fields'][$export['key']]['type']) . ")";
358    }
359    else {
360      $conditions[] = "$export[key] IN (" . db_placeholders($args, $join_schemas[$export['key in table']]['fields'][$export['key']]['type']) . ")";
361    }
362    $query_args = $args;
363  }
364  else if ($type == 'conditions') {
365    foreach ($args as $key => $value) {
366      if (isset($schema['fields'][$key])) {
367        $conditions[] = "$key = " . db_type_placeholder($schema['fields'][$key]['type']);
368        $query_args[] = $value;
369      }
370    }
371  }
372
373  // Make a string out of the conditions.
374  if ($conditions) {
375    $query .= " WHERE " . implode(' AND ', $conditions);
376  }
377
378  $result = db_query($query, $query_args);
379
380  $status = variable_get($export['status'], array());
381  // Unpack the results of the query onto objects and cache them.
382  while ($data = db_fetch_object($result)) {
383    if (isset($schema['export']['object factory']) && function_exists($schema['export']['object factory'])) {
384      $object = $schema['export']['object factory']($schema, $data);
385    }
386    else {
387      $object = _ctools_export_unpack_object($schema, $data, $export['object']);
388    }
389    $object->table = $table;
390    $object->{$export['export type string']} = t('Normal');
391    $object->export_type = EXPORT_IN_DATABASE;
392    // Determine if default object is enabled or disabled.
393    if (isset($status[$object->{$export['key']}])) {
394      $object->disabled = $status[$object->{$export['key']}];
395    }
396
397    $cache[$table][$object->{$export['key']}] = $object;
398    if ($type == 'conditions') {
399      $return[$object->{$export['key']}] = $object;
400    }
401  }
402
403  // Load subrecords.
404  if (isset($export['subrecords callback']) && function_exists($export['subrecords callback'])) {
405    $export['subrecords callback']($cache[$table]);
406  }
407
408  if ($defaults = _ctools_export_get_defaults($table, $export)) {
409
410    foreach ($defaults as $object) {
411      if ($type == 'conditions') {
412        // if this does not match all of our conditions, skip it.
413        foreach ($args as $key => $value) {
414          if (!isset($object->$key) || $object->$key != $value) {
415            continue 2;
416          }
417        }
418      }
419      else if ($type == 'names') {
420        if (!in_array($object->{$export['key']}, $args)) {
421          continue;
422        }
423      }
424
425      // Determine if default object is enabled or disabled.
426      if (isset($status[$object->{$export['key']}])) {
427        $object->disabled = $status[$object->{$export['key']}];
428      }
429
430      if (!empty($cache[$table][$object->{$export['key']}])) {
431        $cache[$table][$object->{$export['key']}]->{$export['export type string']} = t('Overridden');
432        $cache[$table][$object->{$export['key']}]->export_type |= EXPORT_IN_CODE;
433        if ($type == 'conditions') {
434          $return[$object->{$export['key']}] = $cache[$table][$object->{$export['key']}];
435        }
436      }
437      else {
438        $object->{$export['export type string']} = t('Default');
439        $object->export_type = EXPORT_IN_CODE;
440        $object->in_code_only = TRUE;
441        $object->table = $table;
442
443        $cache[$table][$object->{$export['key']}] = $object;
444        if ($type == 'conditions') {
445          $return[$object->{$export['key']}] = $object;
446        }
447      }
448    }
449  }
450
451  // If fetching all, we've done so and we are finished.
452  if ($type == 'all') {
453    $cached_database[$table] = TRUE;
454    return $cache[$table];
455  }
456
457  if ($type == 'names') {
458    foreach ($args as $name) {
459      if (isset($cache[$table][$name])) {
460        $return[$name] = $cache[$table][$name];
461      }
462    }
463  }
464
465  // For conditions,
466  return $return;
467}
468
469/**
470 * Reset all static caches in ctools_export_load_object() or static caches for
471 * a given table in ctools_export_load_object().
472 *
473 * @param $table
474 *   String that is the name of a table. If not defined, all static caches in
475 *   ctools_export_load_object() will be reset.
476 */
477function ctools_export_load_object_reset($table = NULL) {
478  // Reset plugin cache to make sure new include files are picked up.
479  ctools_include('plugins');
480  ctools_get_plugins_reset();
481  if (empty($table)) {
482    ctools_static_reset('ctools_export_load_object');
483    ctools_static_reset('ctools_export_load_object_all');
484    ctools_static_reset('_ctools_export_get_defaults');
485  }
486  else {
487    $cache = &ctools_static('ctools_export_load_object');
488    $cached_database = &ctools_static('ctools_export_load_object_all');
489    $cached_defaults = &ctools_static('_ctools_export_get_defaults');
490    unset($cache[$table]);
491    unset($cached_database[$table]);
492    unset($cached_defaults[$table]);
493  }
494}
495
496/**
497 * Get the default version of an object, if it exists.
498 *
499 * This function doesn't care if an object is in the database or not and
500 * does not check. This means that export_type could appear to be incorrect,
501 * because a version could exist in the database. However, it's not
502 * incorrect for this function as it is *only* used for the default
503 * in code version.
504 */
505function ctools_get_default_object($table, $name) {
506  $schema = ctools_export_get_schema($table);
507  $export = $schema['export'];
508
509  if (!$export['default hook']) {
510    return;
511  }
512
513  // @todo add a method to load .inc files for this.
514  $defaults = _ctools_export_get_defaults($table, $export);
515  $status = variable_get($export['status'], array());
516
517  if (!isset($defaults[$name])) {
518    return;
519  }
520
521  $object = $defaults[$name];
522
523  // Determine if default object is enabled or disabled.
524  if (isset($status[$object->{$export['key']}])) {
525    $object->disabled = $status[$object->{$export['key']}];
526  }
527
528  $object->{$export['export type string']} = t('Default');
529  $object->export_type = EXPORT_IN_CODE;
530  $object->in_code_only = TRUE;
531
532  return $object;
533}
534
535/**
536 * Call the hook to get all default objects of the given type from the
537 * export. If configured properly, this could include loading up an API
538 * to get default objects.
539 */
540function _ctools_export_get_defaults($table, $export) {
541  $cache = &ctools_static(__FUNCTION__, array());
542
543  if (!isset($cache[$table])) {
544    $cache[$table] = array();
545
546    if ($export['default hook']) {
547      if (!empty($export['api'])) {
548        ctools_include('plugins');
549        $info = ctools_plugin_api_include($export['api']['owner'], $export['api']['api'],
550          $export['api']['minimum_version'], $export['api']['current_version']);
551        $modules = array_keys($info);
552      }
553      else {
554        $modules = module_implements($export['default hook']);
555      }
556
557      foreach ($modules as $module) {
558        $function = $module . '_' . $export['default hook'];
559        if (function_exists($function)) {
560          foreach ((array) $function($export) as $name => $object) {
561            // Record the module that provides this exportable.
562            if(is_object($object)) {
563              $object->export_module = $module;
564            }
565
566            if (empty($export['api'])) {
567              $cache[$table][$name] = $object;
568            }
569            else {
570              // If version checking is enabled, ensure that the object can be used.
571              if (isset($object->api_version) &&
572                $object->api_version >= $export['api']['minimum_version'] &&
573                $object->api_version <= $export['api']['current_version']) {
574                $cache[$table][$name] = $object;
575              }
576            }
577          }
578        }
579      }
580
581      drupal_alter($export['default hook'], $cache[$table]);
582    }
583  }
584
585  return $cache[$table];
586}
587
588/**
589 * Unpack data loaded from the database onto an object.
590 *
591 * @param $schema
592 *   The schema from drupal_get_schema().
593 * @param $data
594 *   The data as loaded by db_fetch_object().
595 * @param $object
596 *   If an object, data will be unpacked onto it. If a string
597 *   an object of that type will be created.
598 */
599function _ctools_export_unpack_object($schema, $data, $object = 'stdClass') {
600  if (is_string($object)) {
601    if (class_exists($object)) {
602      $object = new $object;
603    }
604    else {
605      $object = new stdClass;
606    }
607  }
608
609  // Go through our schema and build correlations.
610  foreach ($schema['fields'] as $field => $info) {
611    if (isset($data->$field)) {
612      $object->$field = empty($info['serialize']) ? $data->$field : unserialize(db_decode_blob($data->$field));
613    }
614    else {
615      $data->$field = NULL;
616    }
617  }
618
619  if (isset($schema['join'])) {
620    foreach ($schema['join'] as $join_key => $join) {
621      $join_schema = ctools_export_get_schema($join['table']);
622      if (!empty($join['load'])) {
623        foreach ($join['load'] as $field) {
624          $info = $join_schema['fields'][$field];
625          $object->$field = empty($info['serialize']) ? $data->$field : unserialize(db_decode_blob($data->$field));
626        }
627      }
628    }
629  }
630
631  return $object;
632}
633
634/**
635 * Unpack data loaded from the database onto an object.
636 *
637 * @param $table
638 *   The name of the table this object represents.
639 * @param $data
640 *   The data as loaded by db_fetch_object().
641 */
642function ctools_export_unpack_object($table, $data) {
643  $schema = ctools_export_get_schema($table);
644  return _ctools_export_unpack_object($schema, $data, $schema['export']['object']);
645}
646
647/**
648 * Export a field.
649 *
650 * This is a replacement for var_export(), allowing us to more nicely
651 * format exports. It will recurse down into arrays and will try to
652 * properly export bools when it can, though PHP has a hard time with
653 * this since they often end up as strings or ints.
654 */
655function ctools_var_export($var, $prefix = '') {
656  if (is_array($var)) {
657    if (empty($var)) {
658      $output = 'array()';
659    }
660    else {
661      $output = "array(\n";
662      foreach ($var as $key => $value) {
663        $output .= $prefix . "  " . ctools_var_export($key) . " => " . ctools_var_export($value, $prefix . '  ') . ",\n";
664      }
665      $output .= $prefix . ')';
666    }
667  }
668  else if (is_object($var) && get_class($var) === 'stdClass') {
669    // var_export() will export stdClass objects using an undefined
670    // magic method __set_state() leaving the export broken. This
671    // workaround avoids this by casting the object as an array for
672    // export and casting it back to an object when evaluated.
673    $output = '(object) ' . ctools_var_export((array) $var, $prefix);
674  }
675  else if (is_bool($var)) {
676    $output = $var ? 'TRUE' : 'FALSE';
677  }
678  else {
679    $output = var_export($var, TRUE);
680  }
681
682  return $output;
683}
684
685/**
686 * Export an object into code.
687 */
688function ctools_export_object($table, $object, $indent = '', $identifier = NULL, $additions = array(), $additions2 = array()) {
689  $schema = ctools_export_get_schema($table);
690  if (!isset($identifier)) {
691    $identifier = $schema['export']['identifier'];
692  }
693
694  $output = $indent . '$' . $identifier . ' = new ' . get_class($object) . ";\n";
695
696  if ($schema['export']['can disable']) {
697    $output .= $indent . '$' . $identifier . '->disabled = FALSE; /* Edit this to true to make a default ' . $identifier . ' disabled initially */' . "\n";
698  }
699  if (!empty($schema['export']['api']['current_version'])) {
700    $output .= $indent . '$' . $identifier . '->api_version = ' . $schema['export']['api']['current_version'] . ";\n";
701  }
702
703  // Put top additions here:
704  foreach ($additions as $field => $value) {
705    $output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ";\n";
706  }
707
708  $fields = $schema['fields'];
709  if (!empty($schema['join'])) {
710    foreach ($schema['join'] as $join) {
711      if (!empty($join['load'])) {
712        foreach ($join['load'] as $join_field) {
713          $fields[$join_field] = $join['fields'][$join_field];
714        }
715      }
716    }
717  }
718
719  // Go through our schema and joined tables and build correlations.
720  foreach ($fields as $field => $info) {
721    if (!empty($info['no export'])) {
722      continue;
723    }
724    if (!isset($object->$field)) {
725      if (isset($info['default'])) {
726        $object->$field = $info['default'];
727      }
728      else {
729        $object->$field = '';
730      }
731    }
732
733    // Note: This is the *field* export callback, not the table one!
734    if (!empty($info['export callback']) && function_exists($info['export callback'])) {
735      $output .= $indent . '$' . $identifier . '->' . $field . ' = ' . $info['export callback']($object, $field, $object->$field, $indent) . ";\n";
736    }
737    else {
738      $value = $object->$field;
739      if ($info['type'] == 'int') {
740        $value = (isset($info['size']) && $info['size'] == 'tiny') ? (bool) $value : (int) $value;
741      }
742
743      $output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ";\n";
744    }
745  }
746
747  // And bottom additions here
748  foreach ($additions2 as $field => $value) {
749    $output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ";\n";
750  }
751
752  return $output;
753}
754
755/**
756 * Get the schema for a given table.
757 *
758 * This looks for data the export subsystem needs and applies defaults so
759 * that it's easily available.
760 */
761function ctools_export_get_schema($table) {
762  $cache = &ctools_static(__FUNCTION__);
763  if (empty($cache[$table])) {
764    $schema = drupal_get_schema($table);
765
766    if (!isset($schema['export'])) {
767      return array();
768    }
769
770    if (empty($schema['module'])) {
771      return array();
772    }
773
774    // Add some defaults
775    $schema['export'] += array(
776      'key' => 'name',
777      'key name' => 'Name',
778      'object' => 'stdClass',
779      'status' => 'default_' . $table,
780      'default hook' => 'default_' . $table,
781      'can disable' => TRUE,
782      'identifier' => $table,
783      'primary key' => !empty($schema['primary key']) ? $schema['primary key'][0] : '',
784      'bulk export' => TRUE,
785      'list callback' => "$schema[module]_{$table}_list",
786      'to hook code callback' => "$schema[module]_{$table}_to_hook_code",
787      'export type string' => 'type',
788    );
789
790    // If the export definition doesn't have the "primary key" then the CRUD
791    // save callback won't work.
792    if (empty($schema['export']['primary key']) && user_access('administer site configuration')) {
793      drupal_set_message(t('The export definition of @table is missing the "primary key" property.', array('@table' => $table)), 'error');
794    }
795
796    // Notes:
797    // The following callbacks may be defined to override default behavior
798    // when using CRUD functions:
799    //
800    // create callback
801    // load callback
802    // load all callback
803    // save callback
804    // delete callback
805    // export callback
806    // import callback
807    //
808    // See the appropriate ctools_export_crud function for details on what
809    // arguments these callbacks should accept. Please do not call these
810    // directly, always use the ctools_export_crud_* wrappers to ensure
811    // that default implementations are honored.
812    $cache[$table] = $schema;
813  }
814
815  return $cache[$table];
816}
817
818/**
819 * Gets the schemas for all tables with ctools object metadata.
820 */
821function ctools_export_get_schemas($for_export = FALSE) {
822  static $export_tables;
823  if (is_null($export_tables)) {
824    $export_tables = array();
825    $schemas = drupal_get_schema();
826    foreach ($schemas as $table => $schema) {
827      if (!isset($schema['export'])) {
828        unset($schemas[$table]);
829        continue;
830      }
831      $export_tables[$table] = ctools_export_get_schema($table);
832    }
833  }
834  return $for_export ? array_filter($export_tables, '_ctools_export_filter_export_tables') : $export_tables;
835}
836
837function _ctools_export_filter_export_tables($schema) {
838  return !empty($schema['export']['bulk export']);
839}
840
841function ctools_export_get_schemas_by_module($modules = array(), $for_export = FALSE) {
842  $export_tables = array();
843  $list = ctools_export_get_schemas($for_export);
844  foreach ($list as $table => $schema) {
845    $export_tables[$schema['module']][$table] = $schema;
846  }
847  return empty($modules) ? $export_tables : array_keys($export_tables, $modules);
848}
849
850/**
851 * Set the status of a default $object as a variable.
852 *
853 * The status, in this case, is whether or not it is 'disabled'.
854 * This function does not check to make sure $object actually
855 * exists.
856 */
857function ctools_export_set_status($table, $name, $new_status = TRUE) {
858  $schema = ctools_export_get_schema($table);
859  $status = variable_get($schema['export']['status'], array());
860
861  $status[$name] = $new_status;
862  variable_set($schema['export']['status'], $status);
863}
864
865/**
866 * Set the status of a default $object as a variable.
867 *
868 * This is more efficient than ctools_export_set_status because it
869 * will actually unset the variable entirely if it's not necessary,
870 * this saving a bit of space.
871 */
872function ctools_export_set_object_status($object, $new_status = TRUE) {
873  $table = $object->table;
874  $schema = ctools_export_get_schema($table);
875  $export = $schema['export'];
876  $status = variable_get($schema['export']['status'], array());
877
878  // Compare
879  if (!$new_status && $object->export_type & EXPORT_IN_DATABASE) {
880    unset($status[$object->{$export['key']}]);
881  }
882  else {
883    $status[$object->{$export['key']}] = $new_status;
884  }
885
886  variable_set($schema['export']['status'], $status);
887}
888
889/**
890 * Provide a form for displaying an export.
891 *
892 * This is a simple form that should be invoked like this:
893 * @code
894 *   $output = drupal_get_form('ctools_export_form', $code, $object_title);
895 * @endcode
896 */
897function ctools_export_form(&$form_state, $code, $title = '') {
898  $lines = substr_count($code, "\n");
899  $form['code'] = array(
900    '#type' => 'textarea',
901    '#title' => $title,
902    '#default_value' => $code,
903    '#rows' => $lines,
904  );
905
906  return $form;
907}
908
909/**
910 * Create a new object based upon schema values.
911 *
912 * Because 'default' has ambiguous meaning on some fields, we will actually
913 * use 'object default' to fill in default values if default is not set
914 * That's a little safer to use as it won't cause weird database default
915 * situations.
916 */
917function ctools_export_new_object($table, $set_defaults = TRUE) {
918  $schema = ctools_export_get_schema($table);
919  $export = $schema['export'];
920
921  $object = new $export['object'];
922  foreach ($schema['fields'] as $field => $info) {
923    if (isset($info['object default'])) {
924      $object->$field = $info['object default'];
925    }
926    else if (isset($info['default'])) {
927      $object->$field = $info['default'];
928    }
929    else {
930      $object->$field = NULL;
931    }
932  }
933
934  if ($set_defaults) {
935    // Set some defaults so this data always exists.
936    // We don't set the export_type property here, as this object is not saved
937    // yet. We do give it NULL so we don't generate notices trying to read it.
938    $object->export_type = NULL;
939    $object->{$export['export type string']} = t('Local');
940  }
941  return $object;
942}
943
944/**
945 * Convert a group of objects to code based upon input and return this as a larger
946 * export.
947 */
948function ctools_export_to_hook_code(&$code, $table, $names = array(), $name = 'foo') {
949  $schema = ctools_export_get_schema($table);
950  $export = $schema['export'];
951  // Use the schema-specified function for generating hook code, if one exists
952  if (function_exists($export['to hook code callback'])) {
953    $output = $export['to hook code callback']($names, $name);
954  }
955  // Otherwise, the following code generates basic hook code
956  else {
957    $output = ctools_export_default_to_hook_code($schema, $table, $names, $name);
958  }
959
960  if (!empty($output)) {
961    if (isset($export['api'])) {
962      if (isset($code[$export['api']['owner']][$export['api']['api']]['version'])) {
963        $code[$export['api']['owner']][$export['api']['api']]['version'] = max($code[$export['api']['owner']][$export['api']['api']]['version'], $export['api']['minimum_version']);
964      }
965      else {
966        $code[$export['api']['owner']][$export['api']['api']]['version'] = $export['api']['minimum_version'];
967        $code[$export['api']['owner']][$export['api']['api']]['code'] = '';
968      }
969      $code[$export['api']['owner']][$export['api']['api']]['code'] .= $output;
970    }
971    else {
972      if (empty($code['general'])) {
973        $code['general'] = '';
974      }
975      $code['general'] .= $output;
976    }
977  }
978}
979
980/**
981 * Default function to export objects to code.
982 *
983 * Note that if your module provides a 'to hook code callback' then it will
984 * receive only $names and $name as arguments. Your module is presumed to
985 * already know the rest.
986 */
987function ctools_export_default_to_hook_code($schema, $table, $names, $name) {
988  $export = $schema['export'];
989  $output = '';
990  $objects = ctools_export_load_object($table, 'names', $names);
991  if ($objects) {
992    $output = "/**\n";
993    $output .= " * Implements hook_{$export['default hook']}().\n";
994    $output .= " */\n";
995    $output .= "function " . $name . "_{$export['default hook']}() {\n";
996    $output .= "  \${$export['identifier']}s = array();\n\n";
997    foreach ($objects as $object) {
998      $output .= ctools_export_crud_export($table, $object, '  ');
999      $output .= "  \${$export['identifier']}s['" . check_plain($object->$export['key']) . "'] = \${$export['identifier']};\n\n";
1000    }
1001    $output .= "  return \${$export['identifier']}s;\n";
1002    $output .= "}\n";
1003  }
1004
1005  return $output;
1006}
1007/**
1008 * Default function for listing bulk exportable objects.
1009 */
1010function ctools_export_default_list($table, $schema) {
1011  $list = array();
1012
1013  $items = ctools_export_crud_load_all($table);
1014  $export_key = $schema['export']['key'];
1015
1016  foreach ($items as $item) {
1017    // Try a couple of possible obvious title keys:
1018    if (!empty($item->admin_title)) {
1019      $string = "$item->admin_title (" . $item->$export_key . ")";
1020    }
1021    elseif (!empty($item->title)) {
1022      $string = "$item->title (" . $item->$export_key . ")";
1023    }
1024    else {
1025      $string = $item->$export_key;
1026    }
1027    $list[$item->$export_key] = check_plain($string);
1028  }
1029  return $list;
1030}
Nota: Vea TracBrowser para ayuda de uso del navegador del repositorio.