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
|
*/
|
13
|
define('EXPORT_IN_DATABASE', 0x01);
|
14
|
|
15
|
/**
|
16
|
* A bit flag used to let us know if an object is a 'default' in code.
|
17
|
*/
|
18
|
define('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
|
*/
|
47
|
function 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
|
*/
|
73
|
function 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 multiple exportable objects.
|
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 $names
|
96
|
* An array of unique IDs to load. The field for these IDs will be specified
|
97
|
* by the export key, which normally defaults to 'name'.
|
98
|
*
|
99
|
* @return
|
100
|
* An array of the loaded objects.
|
101
|
*/
|
102
|
function ctools_export_crud_load_multiple($table, array $names) {
|
103
|
$schema = ctools_export_get_schema($table);
|
104
|
$export = $schema['export'];
|
105
|
|
106
|
$results = array();
|
107
|
if (!empty($export['load multiple callback']) && function_exists($export['load multiple callback'])) {
|
108
|
$results = $export['load multiple callback']($names);
|
109
|
}
|
110
|
else {
|
111
|
$results = ctools_export_load_object($table, 'names', $names);
|
112
|
}
|
113
|
|
114
|
// Ensure no empty results are returned.
|
115
|
return array_filter($results);
|
116
|
}
|
117
|
|
118
|
/**
|
119
|
* Load all exportable objects of a given type.
|
120
|
*
|
121
|
* @param $table
|
122
|
* The name of the table to use to retrieve $schema values. This table
|
123
|
* must have an 'export' section containing data or this function
|
124
|
* will fail.
|
125
|
* @param $reset
|
126
|
* If TRUE, the static cache of all objects will be flushed prior to
|
127
|
* loading all. This can be important on listing pages where items
|
128
|
* might have changed on the page load.
|
129
|
*
|
130
|
* @return
|
131
|
* An array of all loaded objects, keyed by the unique IDs of the export key.
|
132
|
*/
|
133
|
function ctools_export_crud_load_all($table, $reset = FALSE) {
|
134
|
$schema = ctools_export_get_schema($table);
|
135
|
if (empty($schema['export'])) {
|
136
|
return array();
|
137
|
}
|
138
|
|
139
|
$export = $schema['export'];
|
140
|
|
141
|
if ($reset) {
|
142
|
ctools_export_load_object_reset($table);
|
143
|
}
|
144
|
|
145
|
if (!empty($export['load all callback']) && function_exists($export['load all callback'])) {
|
146
|
return $export['load all callback']($reset);
|
147
|
}
|
148
|
else {
|
149
|
return ctools_export_load_object($table, 'all');
|
150
|
}
|
151
|
}
|
152
|
|
153
|
/**
|
154
|
* Save a single exportable object.
|
155
|
*
|
156
|
* @param $table
|
157
|
* The name of the table to use to retrieve $schema values. This table
|
158
|
* must have an 'export' section containing data or this function
|
159
|
* will fail.
|
160
|
* @param $object
|
161
|
* The fully populated object to save.
|
162
|
*
|
163
|
* @return
|
164
|
* Failure to write a record will return FALSE. Otherwise SAVED_NEW or
|
165
|
* SAVED_UPDATED is returned depending on the operation performed. The
|
166
|
* $object parameter contains values for any serial fields defined by the $table
|
167
|
*/
|
168
|
function ctools_export_crud_save($table, &$object) {
|
169
|
$schema = ctools_export_get_schema($table);
|
170
|
$export = $schema['export'];
|
171
|
|
172
|
if (!empty($export['save callback']) && function_exists($export['save callback'])) {
|
173
|
return $export['save callback']($object);
|
174
|
}
|
175
|
else {
|
176
|
// Objects should have a serial primary key. If not, simply fail to write.
|
177
|
if (empty($export['primary key'])) {
|
178
|
return FALSE;
|
179
|
}
|
180
|
|
181
|
$key = $export['primary key'];
|
182
|
if ($object->export_type & EXPORT_IN_DATABASE) {
|
183
|
// Existing record.
|
184
|
$update = array($key);
|
185
|
}
|
186
|
else {
|
187
|
// New record.
|
188
|
$update = array();
|
189
|
$object->export_type = EXPORT_IN_DATABASE;
|
190
|
}
|
191
|
return drupal_write_record($table, $object, $update);
|
192
|
}
|
193
|
}
|
194
|
|
195
|
/**
|
196
|
* Delete a single exportable object.
|
197
|
*
|
198
|
* This only deletes from the database, which means that if an item is in
|
199
|
* code, then this is actually a revert.
|
200
|
*
|
201
|
* @param $table
|
202
|
* The name of the table to use to retrieve $schema values. This table
|
203
|
* must have an 'export' section containing data or this function
|
204
|
* will fail.
|
205
|
* @param $object
|
206
|
* The fully populated object to delete, or the export key.
|
207
|
*/
|
208
|
function ctools_export_crud_delete($table, $object) {
|
209
|
$schema = ctools_export_get_schema($table);
|
210
|
$export = $schema['export'];
|
211
|
|
212
|
if (!empty($export['delete callback']) && function_exists($export['delete callback'])) {
|
213
|
return $export['delete callback']($object);
|
214
|
}
|
215
|
else {
|
216
|
// If we were sent an object, get the export key from it. Otherwise
|
217
|
// assume we were sent the export key.
|
218
|
$value = is_object($object) ? $object->{$export['key']} : $object;
|
219
|
db_delete($table)
|
220
|
->condition($export['key'], $value)
|
221
|
->execute();
|
222
|
}
|
223
|
}
|
224
|
|
225
|
/**
|
226
|
* Get the exported code of a single exportable object.
|
227
|
*
|
228
|
* @param $table
|
229
|
* The name of the table to use to retrieve $schema values. This table
|
230
|
* must have an 'export' section containing data or this function
|
231
|
* will fail.
|
232
|
* @param $object
|
233
|
* The fully populated object to delete, or the export key.
|
234
|
* @param $indent
|
235
|
* Any indentation to apply to the code, in case this object is embedded
|
236
|
* into another, for example.
|
237
|
*
|
238
|
* @return
|
239
|
* A string containing the executable export of the object.
|
240
|
*/
|
241
|
function ctools_export_crud_export($table, $object, $indent = '') {
|
242
|
$schema = ctools_export_get_schema($table);
|
243
|
$export = $schema['export'];
|
244
|
|
245
|
if (!empty($export['export callback']) && function_exists($export['export callback'])) {
|
246
|
return $export['export callback']($object, $indent);
|
247
|
}
|
248
|
else {
|
249
|
return ctools_export_object($table, $object, $indent);
|
250
|
}
|
251
|
}
|
252
|
|
253
|
/**
|
254
|
* Turn exported code into an object.
|
255
|
*
|
256
|
* Note: If the code is poorly formed, this could crash and there is no
|
257
|
* way to prevent this.
|
258
|
*
|
259
|
* @param $table
|
260
|
* The name of the table to use to retrieve $schema values. This table
|
261
|
* must have an 'export' section containing data or this function
|
262
|
* will fail.
|
263
|
* @param $code
|
264
|
* The code to eval to create the object.
|
265
|
*
|
266
|
* @return
|
267
|
* An object created from the export. This object will NOT have been saved
|
268
|
* to the database. In the case of failure, a string containing all errors
|
269
|
* that the system was able to determine.
|
270
|
*/
|
271
|
function ctools_export_crud_import($table, $code) {
|
272
|
$schema = ctools_export_get_schema($table);
|
273
|
$export = $schema['export'];
|
274
|
|
275
|
if (!empty($export['import callback']) && function_exists($export['import callback'])) {
|
276
|
return $export['import callback']($code);
|
277
|
}
|
278
|
else {
|
279
|
ob_start();
|
280
|
eval($code);
|
281
|
ob_end_clean();
|
282
|
|
283
|
if (empty(${$export['identifier']})) {
|
284
|
$errors = ob_get_contents();
|
285
|
if (empty($errors)) {
|
286
|
$errors = t('No item found.');
|
287
|
}
|
288
|
return $errors;
|
289
|
}
|
290
|
|
291
|
$item = ${$export['identifier']};
|
292
|
|
293
|
// Set these defaults just the same way that ctools_export_new_object sets
|
294
|
// them.
|
295
|
$item->export_type = NULL;
|
296
|
$item->{$export['export type string']} = t('Local');
|
297
|
|
298
|
return $item;
|
299
|
}
|
300
|
}
|
301
|
|
302
|
/**
|
303
|
* Change the status of a certain object.
|
304
|
*
|
305
|
* @param $table
|
306
|
* The name of the table to use to enable a certain object. This table
|
307
|
* must have an 'export' section containing data or this function
|
308
|
* will fail.
|
309
|
* @param $object
|
310
|
* The fully populated object to enable, or the machine readable name.
|
311
|
* @param $status
|
312
|
* The status, in this case, is whether or not it is 'disabled'.
|
313
|
*/
|
314
|
function ctools_export_crud_set_status($table, $object, $status) {
|
315
|
$schema = ctools_export_get_schema($table);
|
316
|
$export = $schema['export'];
|
317
|
|
318
|
if (!empty($export['status callback']) && function_exists($export['status callback'])) {
|
319
|
$export['status callback']($object, $status);
|
320
|
}
|
321
|
else {
|
322
|
if (is_object($object)) {
|
323
|
ctools_export_set_object_status($object, $status);
|
324
|
}
|
325
|
else {
|
326
|
ctools_export_set_status($table, $object, $status);
|
327
|
}
|
328
|
}
|
329
|
|
330
|
}
|
331
|
|
332
|
/**
|
333
|
* Enable a certain object.
|
334
|
*
|
335
|
* @param $table
|
336
|
* The name of the table to use to enable a certain object. This table
|
337
|
* must have an 'export' section containing data or this function
|
338
|
* will fail.
|
339
|
* @param $object
|
340
|
* The fully populated object to enable, or the machine readable name.
|
341
|
*/
|
342
|
function ctools_export_crud_enable($table, $object) {
|
343
|
return ctools_export_crud_set_status($table, $object, FALSE);
|
344
|
}
|
345
|
|
346
|
/**
|
347
|
* Disable a certain object.
|
348
|
*
|
349
|
* @param $table
|
350
|
* The name of the table to use to disable a certain object. This table
|
351
|
* must have an 'export' section containing data or this function
|
352
|
* will fail.
|
353
|
* @param $object
|
354
|
* The fully populated object to disable, or the machine readable name.
|
355
|
*/
|
356
|
function ctools_export_crud_disable($table, $object) {
|
357
|
return ctools_export_crud_set_status($table, $object, TRUE);
|
358
|
}
|
359
|
|
360
|
/**
|
361
|
* @}
|
362
|
*/
|
363
|
|
364
|
/**
|
365
|
* Load some number of exportable objects.
|
366
|
*
|
367
|
* This function will cache the objects, load subsidiary objects if necessary,
|
368
|
* check default objects in code and properly set them up. It will cache
|
369
|
* the results so that multiple calls to load the same objects
|
370
|
* will not cause problems.
|
371
|
*
|
372
|
* It attempts to reduce, as much as possible, the number of queries
|
373
|
* involved.
|
374
|
*
|
375
|
* @param $table
|
376
|
* The name of the table to be loaded from. Data is expected to be in the
|
377
|
* schema to make all this work.
|
378
|
* @param $type
|
379
|
* A string to notify the loader what the argument is
|
380
|
* - all: load all items. This is the default. $args is unused.
|
381
|
* - names: $args will be an array of specific named objects to load.
|
382
|
* - conditions: $args will be a keyed array of conditions. The conditions
|
383
|
* must be in the schema for this table or errors will result.
|
384
|
* @param $args
|
385
|
* An array of arguments whose actual use is defined by the $type argument.
|
386
|
*/
|
387
|
function ctools_export_load_object($table, $type = 'all', $args = array()) {
|
388
|
$cache = &drupal_static(__FUNCTION__);
|
389
|
$cache_table_exists = &drupal_static(__FUNCTION__ . '_table_exists', array());
|
390
|
$cached_database = &drupal_static('ctools_export_load_object_all');
|
391
|
|
392
|
if (!array_key_exists($table, $cache_table_exists)) {
|
393
|
$cache_table_exists[$table] = db_table_exists($table);
|
394
|
}
|
395
|
|
396
|
$schema = ctools_export_get_schema($table);
|
397
|
if (empty($schema) || !$cache_table_exists[$table]) {
|
398
|
return array();
|
399
|
}
|
400
|
|
401
|
$export = $schema['export'];
|
402
|
|
403
|
if (!isset($cache[$table])) {
|
404
|
$cache[$table] = array();
|
405
|
}
|
406
|
|
407
|
// If fetching all and cached all, we've done so and we are finished.
|
408
|
if ($type == 'all' && !empty($cached_database[$table])) {
|
409
|
return $cache[$table];
|
410
|
}
|
411
|
|
412
|
$return = array();
|
413
|
|
414
|
// Don't load anything we've already cached.
|
415
|
if ($type == 'names' && !empty($args)) {
|
416
|
foreach ($args as $id => $name) {
|
417
|
if (isset($cache[$table][$name])) {
|
418
|
$return[$name] = $cache[$table][$name];
|
419
|
unset($args[$id]);
|
420
|
}
|
421
|
}
|
422
|
|
423
|
// If nothing left to load, return the result.
|
424
|
if (empty($args)) {
|
425
|
return $return;
|
426
|
}
|
427
|
}
|
428
|
|
429
|
// Build the query.
|
430
|
$query = db_select($table, 't__0')->fields('t__0');
|
431
|
$alias_count = 1;
|
432
|
if (!empty($schema['join'])) {
|
433
|
foreach ($schema['join'] as $join_key => $join) {
|
434
|
if ($join_schema = drupal_get_schema($join['table'])) {
|
435
|
$query->join($join['table'], 't__' . $alias_count, 't__0.' . $join['left_key'] . ' = ' . 't__' . $alias_count . '.' . $join['right_key']);
|
436
|
$query->fields('t__' . $alias_count);
|
437
|
$alias_count++;
|
438
|
|
439
|
// Allow joining tables to alter the query through a callback.
|
440
|
if (isset($join['callback']) && function_exists($join['callback'])) {
|
441
|
$join['callback']($query, $schema, $join_schema);
|
442
|
}
|
443
|
}
|
444
|
}
|
445
|
}
|
446
|
|
447
|
$conditions = array();
|
448
|
$query_args = array();
|
449
|
|
450
|
// If they passed in names, add them to the query.
|
451
|
if ($type == 'names') {
|
452
|
$query->condition($export['key'], $args, 'IN');
|
453
|
}
|
454
|
elseif ($type == 'conditions') {
|
455
|
foreach ($args as $key => $value) {
|
456
|
if (isset($schema['fields'][$key])) {
|
457
|
$query->condition($key, $value);
|
458
|
}
|
459
|
}
|
460
|
}
|
461
|
|
462
|
$result = $query->execute();
|
463
|
|
464
|
$status = variable_get($export['status'], array());
|
465
|
// Unpack the results of the query onto objects and cache them.
|
466
|
foreach ($result as $data) {
|
467
|
if (isset($schema['export']['object factory']) && function_exists($schema['export']['object factory'])) {
|
468
|
$object = $schema['export']['object factory']($schema, $data);
|
469
|
}
|
470
|
else {
|
471
|
$object = _ctools_export_unpack_object($schema, $data, $export['object']);
|
472
|
}
|
473
|
$object->table = $table;
|
474
|
$object->{$export['export type string']} = t('Normal');
|
475
|
$object->export_type = EXPORT_IN_DATABASE;
|
476
|
// Determine if default object is enabled or disabled.
|
477
|
if (isset($status[$object->{$export['key']}])) {
|
478
|
$object->disabled = $status[$object->{$export['key']}];
|
479
|
}
|
480
|
|
481
|
$cache[$table][$object->{$export['key']}] = $object;
|
482
|
if ($type == 'conditions') {
|
483
|
$return[$object->{$export['key']}] = $object;
|
484
|
}
|
485
|
}
|
486
|
|
487
|
// Load subrecords.
|
488
|
if (isset($export['subrecords callback']) && function_exists($export['subrecords callback'])) {
|
489
|
$export['subrecords callback']($cache[$table]);
|
490
|
}
|
491
|
|
492
|
if ($type == 'names' && !empty($args) && !empty($export['cache defaults'])) {
|
493
|
$defaults = _ctools_export_get_some_defaults($table, $export, $args);
|
494
|
}
|
495
|
else {
|
496
|
$defaults = _ctools_export_get_defaults($table, $export);
|
497
|
}
|
498
|
|
499
|
if ($defaults) {
|
500
|
foreach ($defaults as $object) {
|
501
|
if ($type == 'conditions') {
|
502
|
// If this does not match all of our conditions, skip it.
|
503
|
foreach ($args as $key => $value) {
|
504
|
if (!isset($object->$key)) {
|
505
|
continue 2;
|
506
|
}
|
507
|
if (is_array($value)) {
|
508
|
if (!in_array($object->$key, $value)) {
|
509
|
continue 2;
|
510
|
}
|
511
|
}
|
512
|
elseif ($object->$key != $value) {
|
513
|
continue 2;
|
514
|
}
|
515
|
}
|
516
|
}
|
517
|
elseif ($type == 'names') {
|
518
|
if (!in_array($object->{$export['key']}, $args)) {
|
519
|
continue;
|
520
|
}
|
521
|
}
|
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
|
if (!empty($cache[$table][$object->{$export['key']}])) {
|
529
|
$cache[$table][$object->{$export['key']}]->{$export['export type string']} = t('Overridden');
|
530
|
$cache[$table][$object->{$export['key']}]->export_type |= EXPORT_IN_CODE;
|
531
|
$cache[$table][$object->{$export['key']}]->export_module = isset($object->export_module) ? $object->export_module : NULL;
|
532
|
if ($type == 'conditions') {
|
533
|
$return[$object->{$export['key']}] = $cache[$table][$object->{$export['key']}];
|
534
|
}
|
535
|
}
|
536
|
else {
|
537
|
$object->{$export['export type string']} = t('Default');
|
538
|
$object->export_type = EXPORT_IN_CODE;
|
539
|
$object->in_code_only = TRUE;
|
540
|
$object->table = $table;
|
541
|
|
542
|
$cache[$table][$object->{$export['key']}] = $object;
|
543
|
if ($type == 'conditions') {
|
544
|
$return[$object->{$export['key']}] = $object;
|
545
|
}
|
546
|
}
|
547
|
}
|
548
|
}
|
549
|
|
550
|
// If fetching all, we've done so and we are finished.
|
551
|
if ($type == 'all') {
|
552
|
$cached_database[$table] = TRUE;
|
553
|
return $cache[$table];
|
554
|
}
|
555
|
|
556
|
if ($type == 'names') {
|
557
|
foreach ($args as $name) {
|
558
|
if (isset($cache[$table][$name])) {
|
559
|
$return[$name] = $cache[$table][$name];
|
560
|
}
|
561
|
}
|
562
|
}
|
563
|
|
564
|
return $return;
|
565
|
}
|
566
|
|
567
|
/**
|
568
|
* Reset all static caches in ctools_export_load_object() or static caches for
|
569
|
* a given table in ctools_export_load_object().
|
570
|
*
|
571
|
* @param $table
|
572
|
* String that is the name of a table. If not defined, all static caches in
|
573
|
* ctools_export_load_object() will be reset.
|
574
|
*/
|
575
|
function ctools_export_load_object_reset($table = NULL) {
|
576
|
// Reset plugin cache to make sure new include files are picked up.
|
577
|
ctools_include('plugins');
|
578
|
ctools_get_plugins_reset();
|
579
|
if (empty($table)) {
|
580
|
drupal_static_reset('ctools_export_load_object');
|
581
|
drupal_static_reset('ctools_export_load_object_all');
|
582
|
drupal_static_reset('_ctools_export_get_defaults');
|
583
|
}
|
584
|
else {
|
585
|
$cache = &drupal_static('ctools_export_load_object');
|
586
|
$cached_database = &drupal_static('ctools_export_load_object_all');
|
587
|
$cached_defaults = &drupal_static('_ctools_export_get_defaults');
|
588
|
unset($cache[$table]);
|
589
|
unset($cached_database[$table]);
|
590
|
unset($cached_defaults[$table]);
|
591
|
}
|
592
|
}
|
593
|
|
594
|
/**
|
595
|
* Get the default version of an object, if it exists.
|
596
|
*
|
597
|
* This function doesn't care if an object is in the database or not and
|
598
|
* does not check. This means that export_type could appear to be incorrect,
|
599
|
* because a version could exist in the database. However, it's not
|
600
|
* incorrect for this function as it is *only* used for the default
|
601
|
* in code version.
|
602
|
*/
|
603
|
function ctools_get_default_object($table, $name) {
|
604
|
$schema = ctools_export_get_schema($table);
|
605
|
$export = $schema['export'];
|
606
|
|
607
|
if (!$export['default hook']) {
|
608
|
return;
|
609
|
}
|
610
|
|
611
|
// Try to load individually from cache if this cache is enabled.
|
612
|
if (!empty($export['cache defaults'])) {
|
613
|
$defaults = _ctools_export_get_some_defaults($table, $export, array($name));
|
614
|
}
|
615
|
else {
|
616
|
$defaults = _ctools_export_get_defaults($table, $export);
|
617
|
}
|
618
|
|
619
|
$status = variable_get($export['status'], array());
|
620
|
|
621
|
if (!isset($defaults[$name])) {
|
622
|
return;
|
623
|
}
|
624
|
|
625
|
$object = $defaults[$name];
|
626
|
|
627
|
// Determine if default object is enabled or disabled.
|
628
|
if (isset($status[$object->{$export['key']}])) {
|
629
|
$object->disabled = $status[$object->{$export['key']}];
|
630
|
}
|
631
|
|
632
|
$object->{$export['export type string']} = t('Default');
|
633
|
$object->export_type = EXPORT_IN_CODE;
|
634
|
$object->in_code_only = TRUE;
|
635
|
|
636
|
return $object;
|
637
|
}
|
638
|
|
639
|
/**
|
640
|
* Get export object defaults.
|
641
|
*
|
642
|
* Call the hook to get all default objects of the given type from the
|
643
|
* export. If configured properly, this could include loading up an API
|
644
|
* to get default objects.
|
645
|
*
|
646
|
* @param string $table
|
647
|
* The name of the table to be loaded. Data is expected to be in the
|
648
|
* schema to make all this work.
|
649
|
* @param array $export
|
650
|
* The export definition from the table's hook_schema() definition.
|
651
|
*/
|
652
|
function _ctools_export_get_defaults($table, array $export) {
|
653
|
$cache = &drupal_static(__FUNCTION__, array());
|
654
|
|
655
|
// If defaults may be cached, first see if we can load from cache.
|
656
|
if (!isset($cache[$table]) && !empty($export['cache defaults'])) {
|
657
|
$cache[$table] = _ctools_export_get_defaults_from_cache($table, $export);
|
658
|
}
|
659
|
|
660
|
if (!isset($cache[$table])) {
|
661
|
// If we're caching, attempt to get a lock. We will wait a short time
|
662
|
// on the lock, but not too long, because it's better to just rebuild
|
663
|
// and throw away results than wait too long on a lock.
|
664
|
if (!empty($export['cache defaults'])) {
|
665
|
for ($counter = 0; !($lock = lock_acquire('ctools_export:' . $table)) && $counter > 5; $counter++) {
|
666
|
lock_wait('ctools_export:' . $table, 1);
|
667
|
++$counter;
|
668
|
}
|
669
|
}
|
670
|
|
671
|
$cache[$table] = array();
|
672
|
|
673
|
if ($export['default hook']) {
|
674
|
if (!empty($export['api'])) {
|
675
|
ctools_include('plugins');
|
676
|
$info = ctools_plugin_api_include($export['api']['owner'], $export['api']['api'],
|
677
|
$export['api']['minimum_version'], $export['api']['current_version']);
|
678
|
$modules = array_keys($info);
|
679
|
}
|
680
|
else {
|
681
|
$modules = module_implements($export['default hook']);
|
682
|
}
|
683
|
|
684
|
foreach ($modules as $module) {
|
685
|
$function = $module . '_' . $export['default hook'];
|
686
|
if (function_exists($function)) {
|
687
|
foreach ((array) $function($export) as $name => $object) {
|
688
|
// Record the module that provides this exportable.
|
689
|
$object->export_module = $module;
|
690
|
|
691
|
if (empty($export['api'])) {
|
692
|
$cache[$table][$name] = $object;
|
693
|
}
|
694
|
else {
|
695
|
// If version checking is enabled, ensure that the object can be
|
696
|
// used.
|
697
|
if (isset($object->api_version) &&
|
698
|
version_compare($object->api_version, $export['api']['minimum_version']) >= 0 &&
|
699
|
version_compare($object->api_version, $export['api']['current_version']) <= 0) {
|
700
|
$cache[$table][$name] = $object;
|
701
|
}
|
702
|
}
|
703
|
}
|
704
|
}
|
705
|
}
|
706
|
|
707
|
drupal_alter($export['default hook'], $cache[$table]);
|
708
|
|
709
|
// If we acquired a lock earlier, cache the results and release the
|
710
|
// lock.
|
711
|
if (!empty($lock)) {
|
712
|
// Cache the index.
|
713
|
$index = array_keys($cache[$table]);
|
714
|
cache_set('ctools_export_index:' . $table, $index, $export['default cache bin']);
|
715
|
|
716
|
// Cache each object.
|
717
|
foreach ($cache[$table] as $name => $object) {
|
718
|
cache_set('ctools_export:' . $table . ':' . $name, $object, $export['default cache bin']);
|
719
|
}
|
720
|
lock_release('ctools_export:' . $table);
|
721
|
}
|
722
|
}
|
723
|
}
|
724
|
|
725
|
return $cache[$table];
|
726
|
}
|
727
|
|
728
|
/**
|
729
|
* Attempt to load default objects from cache.
|
730
|
*
|
731
|
* We can be instructed to cache default objects by the schema. If so
|
732
|
* we cache them as an index which is a list of all default objects, and
|
733
|
* then each default object is cached individually.
|
734
|
*
|
735
|
* @return Either an array of cached objects, or NULL indicating a cache
|
736
|
* rebuild is necessary.
|
737
|
*/
|
738
|
function _ctools_export_get_defaults_from_cache($table, $export) {
|
739
|
$data = cache_get('ctools_export_index:' . $table, $export['default cache bin']);
|
740
|
if (!$data || !is_array($data->data)) {
|
741
|
return;
|
742
|
}
|
743
|
|
744
|
// This is the perfectly valid case where there are no default objects,
|
745
|
// and we have cached this state.
|
746
|
if (empty($data->data)) {
|
747
|
return array();
|
748
|
}
|
749
|
|
750
|
$keys = array();
|
751
|
foreach ($data->data as $name) {
|
752
|
$keys[] = 'ctools_export:' . $table . ':' . $name;
|
753
|
}
|
754
|
|
755
|
$data = cache_get_multiple($keys, $export['default cache bin']);
|
756
|
|
757
|
// If any of our indexed keys missed, then we have a fail and we need to
|
758
|
// rebuild.
|
759
|
if (!empty($keys)) {
|
760
|
return;
|
761
|
}
|
762
|
|
763
|
// Now, translate the returned cache objects to actual objects.
|
764
|
$cache = array();
|
765
|
foreach ($data as $cached_object) {
|
766
|
$cache[$cached_object->data->{$export['key']}] = $cached_object->data;
|
767
|
}
|
768
|
|
769
|
return $cache;
|
770
|
}
|
771
|
|
772
|
/**
|
773
|
* Get a limited number of default objects.
|
774
|
*
|
775
|
* This attempts to load the objects directly from cache. If it cannot,
|
776
|
* the cache is rebuilt. This does not disturb the general get defaults
|
777
|
* from cache object.
|
778
|
*
|
779
|
* This function should ONLY be called if default caching is enabled.
|
780
|
* It does not check, it is assumed the caller has already done so.
|
781
|
*/
|
782
|
function _ctools_export_get_some_defaults($table, $export, $names) {
|
783
|
foreach ($names as $name) {
|
784
|
$keys[] = 'ctools_export:' . $table . ':' . $name;
|
785
|
}
|
786
|
|
787
|
$data = cache_get_multiple($keys, $export['default cache bin']);
|
788
|
|
789
|
// Cache hits remove the $key from $keys by reference. Cache
|
790
|
// misses do not. A cache miss indicates we may have to rebuild.
|
791
|
if (!empty($keys)) {
|
792
|
return _ctools_export_get_defaults($table, $export);
|
793
|
}
|
794
|
|
795
|
// Now, translate the returned cache objects to actual objects.
|
796
|
$cache = array();
|
797
|
foreach ($data as $cached_object) {
|
798
|
$cache[$cached_object->data->{$export['key']}] = $cached_object->data;
|
799
|
}
|
800
|
|
801
|
return $cache;
|
802
|
}
|
803
|
|
804
|
/**
|
805
|
* Unpack data loaded from the database onto an object.
|
806
|
*
|
807
|
* @param $schema
|
808
|
* The schema from drupal_get_schema().
|
809
|
* @param $data
|
810
|
* The data as loaded from the database.
|
811
|
* @param $object
|
812
|
* If an object, data will be unpacked onto it. If a string
|
813
|
* an object of that type will be created.
|
814
|
*/
|
815
|
function _ctools_export_unpack_object($schema, $data, $object = 'stdClass') {
|
816
|
if (is_string($object)) {
|
817
|
if (class_exists($object)) {
|
818
|
$object = new $object();
|
819
|
}
|
820
|
else {
|
821
|
$object = new stdClass();
|
822
|
}
|
823
|
}
|
824
|
|
825
|
// Go through our schema and build correlations.
|
826
|
foreach ($schema['fields'] as $field => $info) {
|
827
|
if (isset($data->$field)) {
|
828
|
$object->$field = empty($info['serialize']) ? $data->$field : unserialize($data->$field);
|
829
|
}
|
830
|
else {
|
831
|
$object->$field = NULL;
|
832
|
}
|
833
|
}
|
834
|
|
835
|
if (isset($schema['join'])) {
|
836
|
foreach ($schema['join'] as $join_key => $join) {
|
837
|
$join_schema = ctools_export_get_schema($join['table']);
|
838
|
if (!empty($join['load'])) {
|
839
|
foreach ($join['load'] as $field) {
|
840
|
$info = $join_schema['fields'][$field];
|
841
|
$object->$field = empty($info['serialize']) ? $data->$field : unserialize($data->$field);
|
842
|
}
|
843
|
}
|
844
|
}
|
845
|
}
|
846
|
|
847
|
return $object;
|
848
|
}
|
849
|
|
850
|
/**
|
851
|
* Unpack data loaded from the database onto an object.
|
852
|
*
|
853
|
* @param $table
|
854
|
* The name of the table this object represents.
|
855
|
* @param $data
|
856
|
* The data as loaded from the database.
|
857
|
*/
|
858
|
function ctools_export_unpack_object($table, $data) {
|
859
|
$schema = ctools_export_get_schema($table);
|
860
|
return _ctools_export_unpack_object($schema, $data, $schema['export']['object']);
|
861
|
}
|
862
|
|
863
|
/**
|
864
|
* Export a field.
|
865
|
*
|
866
|
* This is a replacement for var_export(), allowing us to more nicely
|
867
|
* format exports. It will recurse down into arrays and will try to
|
868
|
* properly export bools when it can, though PHP has a hard time with
|
869
|
* this since they often end up as strings or ints.
|
870
|
*/
|
871
|
function ctools_var_export($var, $prefix = '') {
|
872
|
if (is_array($var)) {
|
873
|
if (empty($var)) {
|
874
|
$output = 'array()';
|
875
|
}
|
876
|
else {
|
877
|
$output = "array(\n";
|
878
|
ksort($var);
|
879
|
foreach ($var as $key => $value) {
|
880
|
$output .= $prefix . " " . ctools_var_export($key) . " => " . ctools_var_export($value, $prefix . ' ') . ",\n";
|
881
|
}
|
882
|
$output .= $prefix . ')';
|
883
|
}
|
884
|
}
|
885
|
elseif (is_object($var) && get_class($var) === 'stdClass') {
|
886
|
// var_export() will export stdClass objects using an undefined
|
887
|
// magic method __set_state() leaving the export broken. This
|
888
|
// workaround avoids this by casting the object as an array for
|
889
|
// export and casting it back to an object when evaluated.
|
890
|
$output = '(object) ' . ctools_var_export((array) $var, $prefix);
|
891
|
}
|
892
|
elseif (is_bool($var)) {
|
893
|
$output = $var ? 'TRUE' : 'FALSE';
|
894
|
}
|
895
|
else {
|
896
|
$output = var_export($var, TRUE);
|
897
|
}
|
898
|
|
899
|
return $output;
|
900
|
}
|
901
|
|
902
|
/**
|
903
|
* Export an object into code.
|
904
|
*/
|
905
|
function ctools_export_object($table, $object, $indent = '', $identifier = NULL, $additions = array(), $additions2 = array()) {
|
906
|
$schema = ctools_export_get_schema($table);
|
907
|
if (!isset($identifier)) {
|
908
|
$identifier = $schema['export']['identifier'];
|
909
|
}
|
910
|
|
911
|
$output = $indent . '$' . $identifier . ' = new ' . get_class($object) . "();\n";
|
912
|
|
913
|
if ($schema['export']['can disable']) {
|
914
|
$disabled = !isset($object->disabled) || $object->disabled != TRUE ? 'FALSE' : 'TRUE';
|
915
|
$output .= $indent . '$' . $identifier . '->disabled = ' . $disabled . '; /* Edit this to true to make a default ' . $identifier . ' disabled initially */' . "\n";
|
916
|
}
|
917
|
if (!empty($schema['export']['api']['current_version'])) {
|
918
|
$output .= $indent . '$' . $identifier . '->api_version = ' . $schema['export']['api']['current_version'] . ";\n";
|
919
|
}
|
920
|
|
921
|
// Put top additions here:
|
922
|
foreach ($additions as $field => $value) {
|
923
|
$output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ";\n";
|
924
|
}
|
925
|
|
926
|
$fields = $schema['fields'];
|
927
|
if (!empty($schema['join'])) {
|
928
|
foreach ($schema['join'] as $join) {
|
929
|
if (!empty($join['load'])) {
|
930
|
foreach ($join['load'] as $join_field) {
|
931
|
$fields[$join_field] = $join['fields'][$join_field];
|
932
|
}
|
933
|
}
|
934
|
}
|
935
|
}
|
936
|
|
937
|
// Go through our schema and joined tables and build correlations.
|
938
|
foreach ($fields as $field => $info) {
|
939
|
if (!empty($info['no export'])) {
|
940
|
continue;
|
941
|
}
|
942
|
if (!isset($object->$field)) {
|
943
|
if (isset($info['default'])) {
|
944
|
$object->$field = $info['default'];
|
945
|
}
|
946
|
else {
|
947
|
$object->$field = '';
|
948
|
}
|
949
|
}
|
950
|
|
951
|
// Note: This is the *field* export callback, not the table one!
|
952
|
if (!empty($info['export callback']) && function_exists($info['export callback'])) {
|
953
|
$output .= $indent . '$' . $identifier . '->' . $field . ' = ' . $info['export callback']($object, $field, $object->$field, $indent) . ";\n";
|
954
|
}
|
955
|
else {
|
956
|
$value = $object->$field;
|
957
|
if ($info['type'] == 'int') {
|
958
|
if (isset($info['size']) && $info['size'] == 'tiny') {
|
959
|
$info['boolean'] = (!isset($info['boolean'])) ? $schema['export']['boolean'] : $info['boolean'];
|
960
|
$value = ($info['boolean']) ? (bool) $value : (int) $value;
|
961
|
}
|
962
|
else {
|
963
|
$value = (int) $value;
|
964
|
}
|
965
|
}
|
966
|
|
967
|
$output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ";\n";
|
968
|
}
|
969
|
}
|
970
|
|
971
|
// And bottom additions here.
|
972
|
foreach ($additions2 as $field => $value) {
|
973
|
$output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ";\n";
|
974
|
}
|
975
|
|
976
|
return $output;
|
977
|
}
|
978
|
|
979
|
/**
|
980
|
* Get the schema for a given table.
|
981
|
*
|
982
|
* This looks for data the export subsystem needs and applies defaults so
|
983
|
* that it's easily available.
|
984
|
*/
|
985
|
function ctools_export_get_schema($table) {
|
986
|
static $drupal_static_fast;
|
987
|
if (!isset($drupal_static_fast)) {
|
988
|
$drupal_static_fast['cache'] = &drupal_static(__FUNCTION__);
|
989
|
}
|
990
|
$cache = &$drupal_static_fast['cache'];
|
991
|
|
992
|
if (empty($cache[$table])) {
|
993
|
$schema = drupal_get_schema($table);
|
994
|
|
995
|
// If our schema isn't loaded, it's possible we're in a state where it
|
996
|
// simply hasn't been cached. If we've been asked, let's force the
|
997
|
// issue.
|
998
|
if (!$schema || empty($schema['export'])) {
|
999
|
// Force a schema reset:
|
1000
|
$schema = drupal_get_schema($table, TRUE);
|
1001
|
}
|
1002
|
|
1003
|
if (!isset($schema['export'])) {
|
1004
|
return array();
|
1005
|
}
|
1006
|
|
1007
|
if (empty($schema['module'])) {
|
1008
|
return array();
|
1009
|
}
|
1010
|
|
1011
|
// Add some defaults.
|
1012
|
$schema['export'] += array(
|
1013
|
'key' => 'name',
|
1014
|
'key name' => 'Name',
|
1015
|
'object' => 'stdClass',
|
1016
|
'status' => 'default_' . $table,
|
1017
|
'default hook' => 'default_' . $table,
|
1018
|
'can disable' => TRUE,
|
1019
|
'identifier' => $table,
|
1020
|
'primary key' => !empty($schema['primary key']) ? $schema['primary key'][0] : '',
|
1021
|
'bulk export' => TRUE,
|
1022
|
'list callback' => "$schema[module]_{$table}_list",
|
1023
|
'to hook code callback' => "$schema[module]_{$table}_to_hook_code",
|
1024
|
'cache defaults' => FALSE,
|
1025
|
'default cache bin' => 'cache',
|
1026
|
'export type string' => 'type',
|
1027
|
'boolean' => TRUE,
|
1028
|
);
|
1029
|
|
1030
|
// If the export definition doesn't have the "primary key" then the CRUD
|
1031
|
// save callback won't work.
|
1032
|
if (empty($schema['export']['primary key']) && user_access('administer site configuration')) {
|
1033
|
drupal_set_message(t('The export definition of @table is missing the "primary key" property.', array('@table' => $table)), 'error');
|
1034
|
}
|
1035
|
|
1036
|
// Notes:
|
1037
|
// The following callbacks may be defined to override default behavior
|
1038
|
// when using CRUD functions:
|
1039
|
//
|
1040
|
// create callback
|
1041
|
// load callback
|
1042
|
// load multiple callback
|
1043
|
// load all callback
|
1044
|
// save callback
|
1045
|
// delete callback
|
1046
|
// export callback
|
1047
|
// import callback
|
1048
|
//
|
1049
|
// See the appropriate ctools_export_crud function for details on what
|
1050
|
// arguments these callbacks should accept. Please do not call these
|
1051
|
// directly, always use the ctools_export_crud_* wrappers to ensure
|
1052
|
// that default implementations are honored.
|
1053
|
$cache[$table] = $schema;
|
1054
|
}
|
1055
|
|
1056
|
return $cache[$table];
|
1057
|
}
|
1058
|
|
1059
|
/**
|
1060
|
* Gets the schemas for all tables with ctools object metadata.
|
1061
|
*/
|
1062
|
function ctools_export_get_schemas($for_export = FALSE) {
|
1063
|
$export_tables = &drupal_static(__FUNCTION__);
|
1064
|
if (is_null($export_tables)) {
|
1065
|
$export_tables = array();
|
1066
|
$schemas = drupal_get_schema();
|
1067
|
foreach ($schemas as $table => $schema) {
|
1068
|
if (!isset($schema['export'])) {
|
1069
|
unset($schemas[$table]);
|
1070
|
continue;
|
1071
|
}
|
1072
|
$export_tables[$table] = ctools_export_get_schema($table);
|
1073
|
}
|
1074
|
}
|
1075
|
return $for_export ? array_filter($export_tables, '_ctools_export_filter_export_tables') : $export_tables;
|
1076
|
}
|
1077
|
|
1078
|
function _ctools_export_filter_export_tables($schema) {
|
1079
|
return !empty($schema['export']['bulk export']);
|
1080
|
}
|
1081
|
|
1082
|
function ctools_export_get_schemas_by_module($modules = array(), $for_export = FALSE) {
|
1083
|
$export_tables = array();
|
1084
|
$list = ctools_export_get_schemas($for_export);
|
1085
|
foreach ($list as $table => $schema) {
|
1086
|
$export_tables[$schema['module']][$table] = $schema;
|
1087
|
}
|
1088
|
return empty($modules) ? $export_tables : array_keys($export_tables, $modules);
|
1089
|
}
|
1090
|
|
1091
|
/**
|
1092
|
* Set the status of a default $object as a variable.
|
1093
|
*
|
1094
|
* The status, in this case, is whether or not it is 'disabled'.
|
1095
|
* This function does not check to make sure $object actually
|
1096
|
* exists.
|
1097
|
*/
|
1098
|
function ctools_export_set_status($table, $name, $new_status = TRUE) {
|
1099
|
$schema = ctools_export_get_schema($table);
|
1100
|
$status = variable_get($schema['export']['status'], array());
|
1101
|
|
1102
|
$status[$name] = $new_status;
|
1103
|
variable_set($schema['export']['status'], $status);
|
1104
|
}
|
1105
|
|
1106
|
/**
|
1107
|
* Set the status of a default $object as a variable.
|
1108
|
*
|
1109
|
* This is more efficient than ctools_export_set_status because it
|
1110
|
* will actually unset the variable entirely if it's not necessary,
|
1111
|
* this saving a bit of space.
|
1112
|
*/
|
1113
|
function ctools_export_set_object_status($object, $new_status = TRUE) {
|
1114
|
$table = $object->table;
|
1115
|
$schema = ctools_export_get_schema($table);
|
1116
|
$export = $schema['export'];
|
1117
|
$status = variable_get($export['status'], array());
|
1118
|
|
1119
|
// Compare.
|
1120
|
if (!$new_status && $object->export_type & EXPORT_IN_DATABASE) {
|
1121
|
unset($status[$object->{$export['key']}]);
|
1122
|
}
|
1123
|
else {
|
1124
|
$status[$object->{$export['key']}] = $new_status;
|
1125
|
}
|
1126
|
|
1127
|
variable_set($export['status'], $status);
|
1128
|
}
|
1129
|
|
1130
|
/**
|
1131
|
* Provide a form for displaying an export.
|
1132
|
*
|
1133
|
* This is a simple form that should be invoked like this:
|
1134
|
* @code
|
1135
|
* $output = drupal_get_form('ctools_export_form', $code, $object_title);
|
1136
|
* @endcode
|
1137
|
*/
|
1138
|
function ctools_export_form($form, &$form_state, $code, $title = '') {
|
1139
|
$lines = substr_count($code, "\n");
|
1140
|
$form['code'] = array(
|
1141
|
'#type' => 'textarea',
|
1142
|
'#title' => $title,
|
1143
|
'#default_value' => $code,
|
1144
|
'#rows' => $lines,
|
1145
|
);
|
1146
|
|
1147
|
return $form;
|
1148
|
}
|
1149
|
|
1150
|
/**
|
1151
|
* Create a new object based upon schema values.
|
1152
|
*
|
1153
|
* Because 'default' has ambiguous meaning on some fields, we will actually
|
1154
|
* use 'object default' to fill in default values if default is not set
|
1155
|
* That's a little safer to use as it won't cause weird database default
|
1156
|
* situations.
|
1157
|
*/
|
1158
|
function ctools_export_new_object($table, $set_defaults = TRUE) {
|
1159
|
$schema = ctools_export_get_schema($table);
|
1160
|
$export = $schema['export'];
|
1161
|
|
1162
|
$object = new $export['object']();
|
1163
|
foreach ($schema['fields'] as $field => $info) {
|
1164
|
if (isset($info['object default'])) {
|
1165
|
$object->$field = $info['object default'];
|
1166
|
}
|
1167
|
elseif (isset($info['default'])) {
|
1168
|
$object->$field = $info['default'];
|
1169
|
}
|
1170
|
else {
|
1171
|
$object->$field = NULL;
|
1172
|
}
|
1173
|
}
|
1174
|
|
1175
|
if ($set_defaults) {
|
1176
|
// Set some defaults so this data always exists.
|
1177
|
// We don't set the export_type property here, as this object is not saved
|
1178
|
// yet. We do give it NULL so we don't generate notices trying to read it.
|
1179
|
$object->export_type = NULL;
|
1180
|
$object->{$export['export type string']} = t('Local');
|
1181
|
}
|
1182
|
return $object;
|
1183
|
}
|
1184
|
|
1185
|
/**
|
1186
|
* Convert a group of objects to code based upon input and return this as a larger
|
1187
|
* export.
|
1188
|
*/
|
1189
|
function ctools_export_to_hook_code(&$code, $table, $names = array(), $name = 'foo') {
|
1190
|
$schema = ctools_export_get_schema($table);
|
1191
|
$export = $schema['export'];
|
1192
|
// Use the schema-specified function for generating hook code, if one exists.
|
1193
|
if (function_exists($export['to hook code callback'])) {
|
1194
|
$output = $export['to hook code callback']($names, $name);
|
1195
|
}
|
1196
|
// Otherwise, the following code generates basic hook code.
|
1197
|
else {
|
1198
|
$output = ctools_export_default_to_hook_code($schema, $table, $names, $name);
|
1199
|
}
|
1200
|
|
1201
|
if (!empty($output)) {
|
1202
|
if (isset($export['api'])) {
|
1203
|
if (isset($code[$export['api']['owner']][$export['api']['api']]['version'])) {
|
1204
|
$code[$export['api']['owner']][$export['api']['api']]['version'] = max($code[$export['api']['owner']][$export['api']['api']]['version'], $export['api']['minimum_version']);
|
1205
|
}
|
1206
|
else {
|
1207
|
$code[$export['api']['owner']][$export['api']['api']]['version'] = $export['api']['minimum_version'];
|
1208
|
$code[$export['api']['owner']][$export['api']['api']]['code'] = '';
|
1209
|
}
|
1210
|
$code[$export['api']['owner']][$export['api']['api']]['code'] .= $output;
|
1211
|
}
|
1212
|
else {
|
1213
|
if (empty($code['general'])) {
|
1214
|
$code['general'] = '';
|
1215
|
}
|
1216
|
$code['general'] .= $output;
|
1217
|
}
|
1218
|
}
|
1219
|
}
|
1220
|
|
1221
|
/**
|
1222
|
* Default function to export objects to code.
|
1223
|
*
|
1224
|
* Note that if your module provides a 'to hook code callback' then it will
|
1225
|
* receive only $names and $name as arguments. Your module is presumed to
|
1226
|
* already know the rest.
|
1227
|
*/
|
1228
|
function ctools_export_default_to_hook_code($schema, $table, $names, $name) {
|
1229
|
$export = $schema['export'];
|
1230
|
$output = '';
|
1231
|
$objects = ctools_export_crud_load_multiple($table, $names);
|
1232
|
if ($objects) {
|
1233
|
$output = "/**\n";
|
1234
|
$output .= " * Implements hook_{$export['default hook']}().\n";
|
1235
|
$output .= " */\n";
|
1236
|
$output .= "function " . $name . "_{$export['default hook']}() {\n";
|
1237
|
$output .= " \${$export['identifier']}s = array();\n\n";
|
1238
|
foreach ($objects as $object) {
|
1239
|
$output .= ctools_export_crud_export($table, $object, ' ');
|
1240
|
$output .= " \${$export['identifier']}s['" . check_plain($object->{$export['key']}) . "'] = \${$export['identifier']};\n\n";
|
1241
|
}
|
1242
|
$output .= " return \${$export['identifier']}s;\n";
|
1243
|
$output .= "}\n";
|
1244
|
}
|
1245
|
|
1246
|
return $output;
|
1247
|
}
|
1248
|
|
1249
|
/**
|
1250
|
* Default function for listing bulk exportable objects.
|
1251
|
*/
|
1252
|
function ctools_export_default_list($table, $schema) {
|
1253
|
$list = array();
|
1254
|
|
1255
|
$items = ctools_export_crud_load_all($table);
|
1256
|
$export_key = $schema['export']['key'];
|
1257
|
foreach ($items as $item) {
|
1258
|
// Try a couple of possible obvious title keys:
|
1259
|
$keys = array('admin_title', 'title');
|
1260
|
if (isset($schema['export']['admin_title'])) {
|
1261
|
array_unshift($keys, $schema['export']['admin_title']);
|
1262
|
}
|
1263
|
|
1264
|
$string = '';
|
1265
|
foreach ($keys as $key) {
|
1266
|
if (!empty($item->$key)) {
|
1267
|
$string = $item->$key . " (" . $item->$export_key . ")";
|
1268
|
break;
|
1269
|
}
|
1270
|
}
|
1271
|
|
1272
|
if (empty($string)) {
|
1273
|
$string = $item->$export_key;
|
1274
|
}
|
1275
|
$list[$item->$export_key] = check_plain($string);
|
1276
|
}
|
1277
|
return $list;
|
1278
|
}
|