Projet

Général

Profil

Paste
Télécharger (31,1 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ctools / drush / ctools.drush.inc @ c2ac6d1d

1 85ad3d82 Assos Assos
<?php
2
3
/**
4
 * @file
5
 * CTools Drush commands.
6
 */
7
8
/**
9
 * Implements hook_drush_command().
10
 */
11
function ctools_drush_command() {
12
  $items = array();
13
14
  $module_text = 'Filter the list of exportables by module. This will come from the \'export_module\' key on the exportable.';
15
  $all_text = 'Perform this operation all CTools exportables available on the system (all tables).';
16
17
  $items['ctools-export'] = array(
18
    'aliases' => array('ctex'),
19
    'callback' => 'ctools_drush_export',
20
    'description' => 'Export multiple CTools exportable objects directly to code.',
21
    'arguments' => array(
22
      'module'    => 'Name of your module.',
23
    ),
24
    'options' => array(
25
      'subdir' => 'The name of the sub directory to create the module in. Defaults to ctools_export which will be placed into sites/all/modules.',
26
      'remove' => 'Remove existing files before writing, except the .module file.',
27
      'filter' => 'Filter the list of exportables by status. Available options are enabled, disabled, overridden, database, code and all. Defaults to enabled.',
28
      'tables' => 'Comma separated list of exportable table names to filter by.',
29
    ),
30
    'examples' => array(
31
      'drush ctex export_module' => 'Export CTools exportables to a module called "export_module".',
32
      'drush ctex export_module --subdir=exports' => 'Same as above, but into the sites/all/modules/exports directory.',
33
      'drush ctex export_module --subdir=exports --remove' => 'Same as above, but automatically removing all files, except for the .module file.',
34
      'drush ctex --filter="views_view"' => 'Filter export selection to the views_view table only.',
35
    ),
36
  );
37
38
  $items['ctools-export-info'] = array(
39
    'aliases' => array('ctei'),
40
    'callback' => 'ctools_drush_export_info',
41
    'description' => 'Show available CTools exportable objects.',
42
    'arguments' => array(),
43
    'options' => array(
44
      'format' => 'Display exportables info in a different format such as print_r, json, export. The default is to show in a tabular format.',
45
      'tables-only' => 'Only show list of exportable types/table names and not available objects.',
46
      'filter' => 'Filter the list of exportables by status. Available options are enabled, disabled, overridden, database, and code.',
47
      'module' => $module_text,
48
    ),
49
    'examples' => array(
50
      'drush ctools-export-info' => 'View export info on all exportables.',
51
      'drush ctools-export-info views_view variable' => 'View export info for views_view and variable exportable types only.',
52
      'drush ctei --filter=enabled' => 'Show all enabled exportables.',
53
      'drush ctei views_view --filter=disabled' => 'Show all enabled exportables.',
54
      'drush ctei views_view --module=node' => 'Show all exportables provided by/on behalf of the node module.',
55
    ),
56
  );
57
58
  $items['ctools-export-view'] = array(
59
    'aliases' => array('ctev'),
60
    'callback' => 'ctools_drush_export_op_command',
61
    'description' => 'View CTools exportable object code output.',
62
    'arguments' => array(
63
      'table name' => 'Base table of the exportable you want to view.',
64
      'machine names' => 'Space separated list of exportables you want to view.',
65
    ),
66
    'options' => array(
67 1e39edcb Assos Assos
      'indent' => 'The string to use for indentation when displaying the exportable export code. Defaults to \'\'.',
68 85ad3d82 Assos Assos
      'no-colour' => 'Remove any colour formatting from export string output. Ideal if you are sending the output of this command to a file.',
69
      'module' => $module_text,
70
      'all' => $all_text,
71
    ),
72
    'examples' => array(
73
      'drush ctools-export-view views_view' => 'View all views exportable objects.',
74
      'drush ctools-export-view views_view archive' => 'View default views archive view.',
75
    ),
76
  );
77
78
  $items['ctools-export-revert'] = array(
79
    'aliases' => array('cter'),
80
    'callback' => 'ctools_drush_export_op_command',
81
    'description' => 'Revert CTools exportables from changes overridden in the database.',
82
    'arguments' => array(
83
      'table name' => 'Base table of the exportable you want to revert.',
84
      'machine names' => 'Space separated list of exportables you want to revert.',
85
    ),
86
    'options' => array(
87
      'module' => $module_text,
88
      'all' => $all_text,
89
    ),
90
    'examples' => array(
91
      'drush ctools-export-revert views_view' => 'Revert all overridden views exportable objects.',
92
      'drush ctools-export-revert views_view archive' => 'Revert overridden default views archive view.',
93
      'drush ctools-export-revert --all' => 'Revert all exportables on the system.',
94
    ),
95
  );
96
97
  $items['ctools-export-enable'] = array(
98
    'aliases' => array('ctee'),
99
    'callback' => 'ctools_drush_export_op_command',
100
    'description' => 'Enable CTools exportables.',
101
    'arguments' => array(
102
      'table name' => 'Base table of the exportable you want to enable.',
103
      'machine names' => 'Space separated list of exportables you want to enable.',
104
    ),
105
    'options' => array(
106
      'module' => $module_text,
107
      'all' => $all_text,
108
    ),
109
    'examples' => array(
110
      'drush ctools-export-enable views_view' => 'Enable all overridden views exportable objects.',
111
      'drush ctools-export-enable views_view archive' => 'Enable overridden default views archive view.',
112
    ),
113
  );
114
115
  $items['ctools-export-disable'] = array(
116
    'aliases' => array('cted'),
117
    'callback' => 'ctools_drush_export_op_command',
118
    'description' => 'Disable CTools exportables.',
119
    'arguments' => array(
120
      'table name' => 'Base table of the exportable you want to disable.',
121
      'machine names' => 'Space separated list of exportables you want to disable.',
122
    ),
123
    'options' => array(
124
      'module' => $module_text,
125
      'all' => $all_text,
126
    ),
127
    'examples' => array(
128
      'drush ctools-export-disable views_view' => 'Disable all overridden views exportable objects.',
129
      'drush ctools-export-disable views_view archive' => 'Disable overridden default views archive view.',
130
    ),
131
  );
132
133
  return $items;
134
}
135
136
/**
137
 * Implementation of hook_drush_help().
138
 */
139
function ctools_drush_help($section) {
140
  switch ($section) {
141
    case 'meta:ctools:title':
142
      return dt('CTools commands');
143 7e72b748 Assos Assos
144 85ad3d82 Assos Assos
    case 'meta:entity:summary':
145
      return dt('CTools drush commands.');
146
  }
147
}
148
149
/**
150 7e72b748 Assos Assos
 * Drush callback: export.
151 85ad3d82 Assos Assos
 */
152
function ctools_drush_export($module = 'foo') {
153
  $error = FALSE;
154
  if (preg_match('@[^a-z_]+@', $module)) {
155
    $error = dt('The name of the module must contain only lowercase letters and underscores') . '.';
156
    drush_log($error, 'error');
157
    return;
158
  }
159
160
  // Filter by tables.
161
  $tables = _ctools_drush_explode_options('tables');
162
163
  // Check status.
164
  $filter = drush_get_option('filter', FALSE);
165
  if (empty($filter)) {
166
    drush_set_option('filter', 'enabled');
167
  }
168
169
  // Selection.
170
  $options = array('all' => dt('Export everything'), 'select' => dt('Make selection'));
171
  $selection = drush_choice($options, dt('Select to proceed'));
172
173
  if (!$selection) {
174
    return;
175
  }
176
177
  // Present the selection screens.
178
  if ($selection == 'select') {
179
    $selections = _ctools_drush_selection_screen($tables);
180
  }
181
  else {
182
    $info = _ctools_drush_export_info($tables, TRUE);
183
    $selections = $info['exportables'];
184
  }
185
186
  // Subdirectory.
187
  $dest_exists = FALSE;
188
  $subdir = drush_get_option('subdir', 'ctools_export');
189
  $dest = 'sites/all/modules/' . $subdir . '/' . $module;
190
191
  // Overwriting files can be set with 'remove' argument.
192
  $remove = drush_get_option('remove', FALSE);
193
194
  // Check if folder exists.
195
  if (file_exists($dest)) {
196
    $dest_exists = TRUE;
197
    if ($remove) {
198
      if (drush_confirm(dt('All files except for the .info and .module files in !module will be removed. You can choose later if you want to overwrite these files as well. Are you sure you want to proceed ?', array('!module' => $module)))) {
199
        $remove = TRUE;
200
        drush_log(dt('Files will be removed'), 'success');
201
      }
202
      else {
203
        drush_log(dt('Export aborted.'), 'success');
204
        return;
205
      }
206
    }
207
  }
208
209
  // Remove files (except for the .module file) if the destination folder exists.
210
  if ($remove && $dest_exists) {
211
    _ctools_drush_file_delete($dest);
212
  }
213
214
  // Create new dir if needed.
215
  if (!$dest_exists) {
216
    if (!file_exists('sites/all/modules/' . $subdir)) {
217
      drush_mkdir('sites/all/modules/' . $subdir);
218
    }
219
  }
220
221
  // Create destination directory.
222
  drush_mkdir($dest);
223
224
  // Load bulk export module.
225
  module_load_include('module', 'bulk_export');
226
227
  // Create options and call Bulk export function.
228
  // We create an array, because maybe in the future we can pass in more
229
  // options to the export function (pre-selected modules and/or exportables).
230
  $options = array(
231
    'name' => $module,
232
    'selections' => $selections,
233
  );
234
  $files = bulk_export_export(TRUE, $options);
235
236
  $alter = array(
237
    'module' => $module,
238
    'files' => $files,
239
  );
240
  // Let other drush commands alter the files.
241
  drush_command_invoke_all_ref('drush_ctex_files_alter', $alter);
242
  $files = $alter['files'];
243
244
  // Start writing.
245
  if (is_array($files)) {
246
    foreach ($files as $base_file => $data) {
247
      $filename = $dest . '/' . $base_file;
248
      // Extra check for .module file.
249
      if ($base_file == ($module . '.module' || $module . '.info') && file_exists($filename)) {
250
        if (!drush_confirm(dt('Do you want to overwrite !module_file', array('!module_file' => $base_file)))) {
251
          drush_log(dt('Writing of !filename skipped. This is the code that was supposed to be written:', array('!filename' => $filename)), 'success');
252
          drush_print('---------');
253
          drush_print(shellColours::getColouredOutput("\n$data", 'light_green'));
254
          drush_print('---------');
255
          continue;
256
        }
257
      }
258
      if (file_put_contents($filename, $data)) {
259
        drush_log(dt('Succesfully written !filename', array('!filename' => $filename)), 'success');
260
      }
261
      else {
262
        drush_log(dt('Error writing !filename', array('!filename' => $filename)), 'error');
263
      }
264
    }
265
  }
266
  else {
267
    drush_log(dt('No files were found to be written.'), 'error');
268
  }
269
}
270
271
/**
272
 * Helper function to select the exportables. By default, all exportables
273
 * will be selected, so it will be easier to deselect them.
274
 *
275
 * @param $tables
276
 */
277
function _ctools_drush_selection_screen(array $tables = array()) {
278
  $selections = $build = array();
279
  $files = system_rebuild_module_data();
280
281
  $selection_number = 0;
282
283
  $info = _ctools_drush_export_info($tables, TRUE);
284
  $exportables = $info['exportables'];
285
  $schemas = $info['schemas'];
286
287
  $export_tables = array();
288
289
  foreach (array_keys($exportables) as $table) {
290
    natcasesort($exportables[$table]);
291
    $export_tables[$table] = $files[$schemas[$table]['module']]->info['name'] . ' (' . $table . ')';
292
  }
293
294
  foreach ($export_tables as $table => $table_title) {
295
    if (!empty($exportables[$table])) {
296
      $table_count = count($exportables[$table]);
297
      $selection_number += $table_count;
298
      foreach ($exportables[$table] as $key => $title) {
299
        $build[$table]['title'] = $table_title;
300
        $build[$table]['items'][$key] = $title;
301
        $build[$table]['count'] = $table_count;
302
        $selections[$table][$key] = $key;
303
      }
304
    }
305
  }
306
307
  drush_print(dt('Number of exportables selected: !number', array('!number' => $selection_number)));
308
  drush_print(dt('By default all exportables are selected. Select a table to deselect exportables. Select "cancel" to start writing the files.'));
309
310
  // Let's go into a loop.
311
  $return = FALSE;
312
  while (!$return) {
313
314
    // Present the tables choice.
315
    $table_rows = array();
316
    foreach ($build as $table => $info) {
317
      $table_rows[$table] = $info['title'] . ' (' . $info['count'] . ')';
318
    }
319
    $table_choice = drush_choice($table_rows, dt('Select a table. Select cancel to start writing files.'));
320
321
    // Bail out.
322
    if (!$table_choice) {
323
      drush_log(dt('Selection mode done, starting to write the files.'), 'notice');
324
      $return = TRUE;
325
      return $selections;
326
    }
327
328
    // Present the exportables choice, using the drush_choice_multiple.
329
    $max = count($build[$table_choice]['items']);
330
    $exportable_rows = array();
331
    foreach ($build[$table_choice]['items'] as $key => $title) {
332
      $exportable_rows[$key] = $title;
333
    }
334
    drush_print(dt('Exportables from !table', array('!table' => $build[$table_choice]['title'])));
335
    $multi_select = drush_choice_multiple($exportable_rows, $selections[$table_choice], dt('Select exportables.'), '!value', '!value (selected)', 0, $max);
336
337
    // Update selections.
338
    if (is_array($multi_select)) {
339
      $build[$table_choice]['count'] = count($multi_select);
340
      $selections[$table_choice] = array();
341
      foreach ($multi_select as $key) {
342 7e72b748 Assos Assos
        $selections[$table_choice][$key] = $key;
343 85ad3d82 Assos Assos
      }
344
    }
345
  }
346
}
347
348
/**
349
 * Delete files in a directory, keeping the .module  and .info files.
350
 *
351
 * @param $path
352
 *   Path to directory in which to remove files.
353
 */
354
function _ctools_drush_file_delete($path) {
355
  if (is_dir($path)) {
356
    $files = new DirectoryIterator($path);
357
    foreach ($files as $fileInfo) {
358
      if (!$fileInfo->isDot() && !in_array($fileInfo->getExtension(), array('module', 'info'))) {
359
        unlink($fileInfo->getPathname());
360
      }
361
    }
362
  }
363
}
364
365
/**
366
 * Drush callback: Export info.
367
 *
368
 * @params $table_names
369
 *   Each argument will be taken as a CTools exportable table name.
370
 */
371
function ctools_drush_export_info() {
372
  // Collect array of table names from args.
373
  $table_names = func_get_args();
374
375
  // Get format option to allow for alternative output.
376
  $format = drush_get_option('format', FALSE);
377
  $tables_only = drush_get_option('tables-only', FALSE);
378
  $filter = drush_get_option('filter', FALSE);
379
  $export_module = drush_get_option('module', FALSE);
380
381
  $load = (bool) $filter || $export_module;
382
383
  // Get info on these tables, or all tables if none specified.
384
  $info = _ctools_drush_export_info($table_names, $load);
385
  $schemas = $info['schemas'];
386
  $exportables = $info['exportables'];
387
388
  if (empty($exportables)) {
389
    drush_log(dt('There are no exportables available.'), 'warning');
390
    return;
391
  }
392
393
  // Filter by export module.
394
  if (is_string($export_module)) {
395
    $exportables = _ctools_drush_export_module_filter($exportables, $export_module);
396
  }
397
398
  if (empty($exportables)) {
399
    drush_log(dt('There are no exportables matching this criteria.'), 'notice');
400
    return;
401
  }
402
403
  $exportable_counts = _ctools_drush_count_exportables($exportables);
404
405
  // Only use array keys if --tables-only option is set.
406
  if ($tables_only) {
407
    $exportables = array_keys($exportables);
408
  }
409
410
  // Use format from --format option if it's present, and send to drush_format.
411
  if ($format) {
412
    // Create array with all exportable info and counts in one.
413
    $output = array(
414
      'exportables' => $exportables,
415
      'count' => $exportable_counts,
416
    );
417
    drush_print(drush_format($output, NULL, $format));
418
  }
419
  // Build a tabular output as default.
420
  else {
421
    $header = $tables_only ? array() : array(dt('Module'), dt('Base table'), dt('Exportables'));
422
    $rows = array();
423
    foreach ($exportables as $table => $info) {
424
      if (is_array($info)) {
425
        $row = array(
426
          $schemas[$table]['module'],
427
          $table,
428
          // Machine name is better for this?
429
          shellColours::getColouredOutput(implode("\n", array_keys($info)), 'light_green') . "\n",
430
        );
431
        $rows[] = $row;
432
      }
433
      else {
434
        $rows[] = array($info);
435
      }
436
    }
437
    if (!empty($rows)) {
438
      drush_print("\n");
439
      array_unshift($rows, $header);
440
      drush_print_table($rows, TRUE, array(20, 20));
441
      drush_print(dt('Total exportables found: !total', array('!total' => $exportable_counts['total'])));
442
      foreach ($exportable_counts['exportables'] as $table_name => $count) {
443
        drush_print(dt('!table_name (!count)', array('!table_name' => $table_name, '!count' => $count)), 2);
444
      }
445
      drush_print("\n");
446
    }
447
  }
448
}
449 7e72b748 Assos Assos
450 85ad3d82 Assos Assos
/**
451
 * Drush callback: Acts as the hub for all op commands to keep
452
 * all arg handling etc in one place.
453
 */
454
function ctools_drush_export_op_command() {
455 c2ac6d1d Assos Assos
  $args = func_get_args();
456 85ad3d82 Assos Assos
  // Get all info for the current drush command.
457
  $command = drush_get_command();
458
  $op = '';
459
460
  switch ($command['command']) {
461
    case 'ctools-export-view':
462
      $op = 'view';
463 7e72b748 Assos Assos
      break;
464
465 85ad3d82 Assos Assos
    case 'ctools-export-revert':
466
      // Revert is same as deleting. As any objects in the db are deleted.
467
      $op = 'delete';
468 7e72b748 Assos Assos
      break;
469
470 85ad3d82 Assos Assos
    case 'ctools-export-enable':
471
      $op = 'enable';
472 7e72b748 Assos Assos
      break;
473
474 85ad3d82 Assos Assos
    case 'ctools-export-disable':
475
      $op = 'disable';
476 7e72b748 Assos Assos
      break;
477 85ad3d82 Assos Assos
  }
478
479
  if (!$op) {
480
    return;
481
  }
482
483
  if (drush_get_option('all', FALSE)) {
484 7e72b748 Assos Assos
    $info = _ctools_drush_export_info(array(), TRUE);
485 85ad3d82 Assos Assos
    $exportable_info = $info['exportables'];
486
487
    $all = drush_confirm(dt('Are you sure you would like to !op all exportables on the system?',
488
      array('!op' => _ctools_drush_export_op_alias($op))));
489
490
    if ($all && $exportable_info) {
491
      foreach ($exportable_info as $table => $exportables) {
492
        if (!empty($exportables)) {
493
          ctools_drush_export_op($op, $table, $exportables);
494
        }
495
      }
496
    }
497
  }
498
  else {
499
    // Table name should always be first arg...
500
    $table_name = array_shift($args);
501
    // Any additional args are assumed to be exportable names.
502
    $object_names = $args;
503
504
    // Return any exportables based on table name, object names, options.
505
    $exportables = _ctools_drush_export_op_command_logic($op, $table_name, $object_names);
506
507
    if ($exportables) {
508
      ctools_drush_export_op($op, $table_name, $exportables);
509
    }
510
  }
511
}
512
513
/**
514
 * Iterate through exportable object names, load them, and pass each
515
 * object to the correct op function.
516
 *
517
 * @param $op
518
 * @param $table_name
519
 * @param $exportables
520
 */
521
function ctools_drush_export_op($op = '', $table_name = '', $exportables = NULL) {
522
  $objects = ctools_export_crud_load_multiple($table_name, array_keys($exportables));
523
524
  $function = '_ctools_drush_export_' . $op;
525
  if (function_exists($function)) {
526
    foreach ($objects as $object) {
527
      $function($table_name, $object);
528
    }
529
  }
530
  else {
531
    drush_log(dt('CTools CRUD function !function doesn\'t exist.',
532
      array('!function' => $function)), 'error');
533
  }
534
}
535
536
/**
537
 * Helper function to abstract logic for selecting exportable types/objects
538
 * from individual commands as they will all share this same error
539
 * handling/arguments for returning list of exportables.
540
 *
541
 * @param $table_name
542
 * @param $object_names
543
 *
544
 * @return
545 7e72b748 Assos Assos
 *   Array of exportable objects (filtered if necessary, by name etc..) or FALSE if not.
546 85ad3d82 Assos Assos
 */
547
function _ctools_drush_export_op_command_logic($op = '', $table_name = NULL, array $object_names = array()) {
548
  if (!$table_name) {
549
    drush_log(dt('Exportable table name empty. Use the --all command if you want to perform this operation on all tables.'), 'error');
550
    return FALSE;
551
  }
552
553
  // Get export info based on table name.
554
  $info = _ctools_drush_export_info(array($table_name), TRUE);
555
556
  if (!isset($info['exportables'][$table_name])) {
557
    drush_log(dt('Exportable table name not found.'), 'error');
558
    return FALSE;
559
  }
560
561
  $exportables = &$info['exportables'];
562
563
  if (empty($object_names)) {
564
    $all = drush_confirm(dt('No object names entered. Would you like to try and !op all exportables of type !type',
565
      array('!op' => _ctools_drush_export_op_alias($op), '!type' => $table_name)));
566
    if (!$all) {
567
      drush_log(dt('Command cancelled'), 'success');
568
      return FALSE;
569
    }
570
  }
571
  else {
572
    // Iterate through object names and check they exist in exportables array.
573
    // Log error and unset them if they don't.
574
    foreach ($object_names as $object_name) {
575
      if (!isset($exportables[$table_name][$object_name])) {
576
        drush_log(dt('Invalid exportable: !exportable', array('!exportable' => $object_name)), 'error');
577
        unset($object_names[$table_name][$object_name]);
578
      }
579
    }
580
    // Iterate through exportables to get just a list of selected ones.
581
    foreach (array_keys($exportables[$table_name]) as $exportable) {
582
      if (!in_array($exportable, $object_names)) {
583
        unset($exportables[$table_name][$exportable]);
584
      }
585
    }
586
  }
587
588
  $export_module = drush_get_option('module', FALSE);
589
590
  if (is_string($export_module)) {
591
    $exportables = _ctools_drush_export_module_filter($exportables, $export_module);
592
  }
593
594
  return $exportables[$table_name];
595
}
596
597
/**
598
 * Return array of CTools exportable info based on available tables returned from
599
 * ctools_export_get_schemas().
600
 *
601
 * @param $table_names
602
 *   Array of table names to return.
603
 * @param $load
604
 *   (bool) should ctools exportable objects be loaded for each type.
605
 *   The default behaviour will load just a list of exportable names.
606
 *
607
 * @return
608
 *   Nested arrays of available exportables, keyed by table name.
609
 */
610
function _ctools_drush_export_info(array $table_names = array(), $load = FALSE) {
611
  ctools_include('export');
612
  // Get available schemas that declare exports.
613
  $schemas = ctools_export_get_schemas(TRUE);
614
  $exportables = array();
615
616
  if (!empty($schemas)) {
617
    // Remove types we don't want, if any.
618
    if (!empty($table_names)) {
619
      foreach (array_keys($schemas) as $table_name) {
620
        if (!in_array($table_name, $table_names)) {
621
          unset($schemas[$table_name]);
622
        }
623
      }
624
    }
625
    // Load array of available exportables for each schema.
626
    foreach ($schemas as $table_name => $schema) {
627
      // Load all objects.
628
      if ($load) {
629
        $exportables[$table_name] = ctools_export_crud_load_all($table_name);
630
      }
631
      // Get a list of exportable names.
632
      else {
633
        if (!empty($schema['export']['list callback']) && function_exists($schema['export']['list callback'])) {
634
          $exportables[$table_name] = $schema['export']['list callback']();
635
        }
636
        else {
637
          $exportables[$table_name] = ctools_export_default_list($table_name, $schema);
638
        }
639
      }
640
    }
641
  }
642
643
  if ($load) {
644
    $filter = drush_get_option('filter', FALSE);
645
    $exportables = _ctools_drush_filter_exportables($exportables, $filter);
646
  }
647
648
  return array('exportables' => $exportables, 'schemas' => $schemas);
649
}
650
651 7e72b748 Assos Assos
/**
652 85ad3d82 Assos Assos
 * View a single object.
653
 *
654
 * @param $table_name
655
 * @param $object
656
 */
657
function _ctools_drush_export_view($table_name, $object) {
658
  $indent = drush_get_option('indent', '');
659
  $no_colour = drush_get_option('no-colour', FALSE);
660
  $export = ctools_export_crud_export($table_name, $object, $indent);
661
  if ($no_colour) {
662
    drush_print("\n$export");
663
  }
664
  else {
665
    drush_print(shellColours::getColouredOutput("\n$export", 'light_green'));
666
  }
667
}
668
669 7e72b748 Assos Assos
/**
670 85ad3d82 Assos Assos
 * Revert a single object.
671
 *
672
 * @param $table_name
673
 * @param $object
674
 */
675
function _ctools_drush_export_delete($table_name, $object) {
676
  $name = _ctools_drush_get_export_name($table_name, $object);
677
678
  if (_ctools_drush_object_is_overridden($object)) {
679
    // Remove from db.
680
    ctools_export_crud_delete($table_name, $object);
681
    drush_log("Reverted object: $name", 'success');
682
  }
683
  else {
684
    drush_log("Nothing to revert for: $name", 'notice');
685
  }
686
}
687
688 7e72b748 Assos Assos
/**
689 85ad3d82 Assos Assos
 * Enable a single object.
690
 *
691
 * @param $table_name
692
 * @param $object
693
 */
694
function _ctools_drush_export_enable($table_name, $object) {
695
  $name = _ctools_drush_get_export_name($table_name, $object);
696
697
  if (_ctools_drush_object_is_disabled($object)) {
698
699
    // Enable object.
700
    ctools_export_crud_enable($table_name, $object);
701
    drush_log("Enabled object: $name", 'success');
702
  }
703
  else {
704
    drush_log("$name is already Enabled", 'notice');
705
  }
706
}
707
708 7e72b748 Assos Assos
/**
709 85ad3d82 Assos Assos
 * Disable a single object.
710
 *
711
 * @param $table_name
712
 * @param $object
713
 */
714
function _ctools_drush_export_disable($table_name, $object) {
715
  $name = _ctools_drush_get_export_name($table_name, $object);
716
717
  if (!_ctools_drush_object_is_disabled($object)) {
718
    // Disable object.
719
    ctools_export_crud_disable($table_name, $object);
720
    drush_log("Disabled object: $name", 'success');
721
  }
722
  else {
723
    drush_log("$name is already disabled", 'notice');
724
  }
725
}
726
727
/**
728
 * Filter a nested array of exportables by export module.
729
 *
730 7e72b748 Assos Assos
 * @param array $exportables
731 85ad3d82 Assos Assos
 *   Passed by reference. A nested array of exportables, keyed by table name.
732 7e72b748 Assos Assos
 * @param string $export_module
733 85ad3d82 Assos Assos
 *   The name of the export module providing the exportable.
734
 */
735
function _ctools_drush_export_module_filter($exportables, $export_module) {
736
  $module_list = module_list();
737
738
  if (!isset($module_list[$export_module])) {
739
    drush_log(dt('Invalid export module: !export_module', array('!export_module' => $export_module)), 'error');
740
  }
741
742
  foreach ($exportables as $table => $objects) {
743
    foreach ($objects as $key => $object) {
744
      if (empty($object->export_module) || ($object->export_module !== $export_module)) {
745
        unset($exportables[$table][$key]);
746
      }
747
    }
748
  }
749
750
  return array_filter($exportables);
751
}
752
753
/**
754
 * Gets the key for an exportable type.
755
 *
756
 * @param $table_name
757
 *   The exportable table name.
758
 * @param $object
759
 *   The exportable object.
760
 *
761
 * @return string
762
 *   The key defined in the export schema data.
763
 */
764
function _ctools_drush_get_export_name($table_name, $object) {
765
  $info = _ctools_drush_export_info(array($table_name));
766
  $key = $info['schemas'][$table_name]['export']['key'];
767
  return $object->{$key};
768
}
769
770
/**
771
 * Determine if an object is disabled.
772
 *
773
 * @param $object
774
 *   Loaded CTools exportable object.
775
 *
776
 * @return TRUE or FALSE
777
 */
778
function _ctools_drush_object_is_disabled($object) {
779
  return (isset($object->disabled) && ($object->disabled == TRUE)) ? TRUE : FALSE;
780
}
781
782
/**
783
 * Determine if an object is enabled.
784
 *
785 7e72b748 Assos Assos
 * @see _ctools_drush_object_is_disabled()
786 85ad3d82 Assos Assos
 */
787
function _ctools_drush_object_is_enabled($object) {
788
  return (empty($object->disabled)) ? TRUE : FALSE;
789
}
790
791
/**
792
 * Determine if an object is overridden.
793
 */
794
function _ctools_drush_object_is_overridden($object) {
795
  $status = EXPORT_IN_CODE + EXPORT_IN_DATABASE;
796
  return ($object->export_type == $status) ? TRUE : FALSE;
797
}
798
799
/**
800
 * Determine if an object is not overridden.
801
 */
802
function _ctools_drush_object_is_not_overridden($object) {
803
  $status = EXPORT_IN_CODE + EXPORT_IN_DATABASE;
804
  return ($object->export_type == $status) ? FALSE : TRUE;
805
}
806
807
/**
808
 * Determine if an object is only in the db.
809
 */
810
function _ctools_drush_object_is_db_only($object) {
811
  return ($object->export_type == EXPORT_IN_DATABASE) ? TRUE : FALSE;
812
}
813
814
/**
815
 * Determine if an object is not in the db.
816
 */
817
function _ctools_drush_object_is_not_db_only($object) {
818
  return ($object->export_type == EXPORT_IN_DATABASE) ? FALSE : TRUE;
819
}
820
821
/**
822
 * Determine if an object is a code only default.
823
 */
824
function _ctools_drush_object_is_code_only($object) {
825
  return ($object->export_type == EXPORT_IN_CODE) ? TRUE : FALSE;
826
}
827
828
/**
829
 * Determine if an object is not a code only default.
830
 */
831
function _ctools_drush_object_is_not_code_only($object) {
832
  return ($object->export_type == EXPORT_IN_CODE) ? FALSE : TRUE;
833
}
834
835
/**
836
 * Return an array of count information based on exportables array.
837
 *
838
 * @param $exportables
839
 *   Array of exportables to count.
840
 *
841
 * @return
842 7e72b748 Assos Assos
 *   Array of count data containing the following:
843 85ad3d82 Assos Assos
 *     'total' - A total count of all exportables.
844
 *     'exportables' - An array of exportable counts per table.
845
 */
846
function _ctools_drush_count_exportables($exportables) {
847
  $count = array('exportables' => array());
848
849
  foreach ($exportables as $table => $objects) {
850
    // Add the object count for each table.
851
    $count['exportables'][$table] = count($objects);
852
  }
853
854
  // Once all tables have been counted, total these up.
855
  $count['total'] = array_sum($count['exportables']);
856
857
  return $count;
858
}
859
860
/**
861
 * Filters a collection of exportables based on filters.
862
 *
863
 * @param $exportables
864
 * @param $filter
865
 */
866
function _ctools_drush_filter_exportables($exportables, $filter) {
867
  $eval = FALSE;
868
869
  if (is_string($filter)) {
870
    switch ($filter) {
871
      // Show enabled exportables only.
872
      case 'enabled':
873
        $eval = '_ctools_drush_object_is_disabled';
874 7e72b748 Assos Assos
        break;
875
876 85ad3d82 Assos Assos
      // Show disabled exportables only.
877
      case 'disabled':
878
        $eval = '_ctools_drush_object_is_enabled';
879 7e72b748 Assos Assos
        break;
880
881 85ad3d82 Assos Assos
      // Show overridden exportables only.
882
      case 'overridden':
883
        $eval = '_ctools_drush_object_is_not_overridden';
884 7e72b748 Assos Assos
        break;
885
886 85ad3d82 Assos Assos
      // Show database only exportables.
887
      case 'database':
888
        $eval = '_ctools_drush_object_is_not_db_only';
889 7e72b748 Assos Assos
        break;
890
891 85ad3d82 Assos Assos
      // Show code only exportables.
892
      case 'code':
893
        $eval = '_ctools_drush_object_is_not_code_only';
894 7e72b748 Assos Assos
        break;
895
896 85ad3d82 Assos Assos
      // Do nothing.
897
      case 'all':
898
        break;
899 7e72b748 Assos Assos
900 85ad3d82 Assos Assos
      default:
901
        drush_log(dt('Invalid filter option. Available options are: enabled, disabled, overridden, database, and code.'), 'error');
902
        return;
903
    }
904
905
    if ($eval) {
906
      foreach ($exportables as $table => $objects) {
907
        foreach ($objects as $key => $object) {
908
          if ($eval($object)) {
909
            unset($exportables[$table][$key]);
910
          }
911
        }
912
      }
913
    }
914
  }
915
916
  return array_filter($exportables);
917
}
918
919
/**
920
 * Return an alias for an op, that will be used to show as output.
921
 * For now, this is mainly necessary for delete => revert alias.
922
 *
923
 * @param $op
924
 *   The op name. Such as 'enable', 'disable', or 'delete'.
925
 *
926
 * @return
927
 *   The matched alias value or the original $op passed in if not found.
928
 */
929
function _ctools_drush_export_op_alias($op) {
930
  $aliases = array(
931
    'delete' => 'revert',
932
  );
933
934
  if (isset($aliases[$op])) {
935
    return $aliases[$op];
936
  }
937
938
  return $op;
939
}
940
941
/**
942
 * Convert the drush options from a csv list into an array.
943
 *
944
 * @param $drush_option
945
 *   The drush option name to invoke.
946
 *
947
 * @return
948
 *   Exploded array of options.
949
 */
950
function _ctools_drush_explode_options($drush_option) {
951
  $options = drush_get_option($drush_option, array());
952
  if (!empty($options)) {
953
    $options = explode(',', $options);
954
    return array_map('trim', $options);
955
  }
956
957
  return $options;
958
}
959
960
/**
961
 * Class to deal with wrapping output strings with
962
 * colour formatting for the shell.
963
 */
964
class shellColours {
965
966
  private static $foreground_colours = array(
967
    'black' => '0;30',
968
    'dark_gray' => '1;30',
969
    'blue' => '0;34',
970
    'light_blue' => '1;34',
971
    'green' => '0;32',
972
    'light_green' => '1;32',
973
    'cyan' => '0;36',
974
    'light_cyan' => '1;36',
975
    'red' => '0;31',
976
    'light_red' => '1;31',
977
    'purple' => '0;35',
978
    'light_purple' => '1;35',
979
    'brown' => '0;33',
980
    'yellow' => '1;33',
981
    'light_gray' => '0;37',
982
    'white' => '1;37',
983
  );
984
985
  private static $background_colours = array(
986
    'black' => '40',
987
    'red' => '41',
988
    'green' => '42',
989
    'yellow' => '43',
990
    'blue' => '44',
991
    'magenta' => '45',
992
    'cyan' => '46',
993
    'light_gray' => '47',
994
  );
995
996 7e72b748 Assos Assos
  /**
997 c304a780 Assos Assos
   * shellColours constructor.
998 7e72b748 Assos Assos
   */
999 85ad3d82 Assos Assos
  private function __construct() {}
1000
1001 7e72b748 Assos Assos
  /**
1002
   * Returns coloured string.
1003
   */
1004 85ad3d82 Assos Assos
  public static function getColouredOutput($string, $foreground_colour = NULL, $background_colour = NULL) {
1005
    $coloured_string = "";
1006
1007 7e72b748 Assos Assos
    // Check if given foreground colour found.
1008 85ad3d82 Assos Assos
    if ($foreground_colour) {
1009
      $coloured_string .= "\033[" . self::$foreground_colours[$foreground_colour] . "m";
1010
    }
1011 7e72b748 Assos Assos
    // Check if given background colour found.
1012 85ad3d82 Assos Assos
    if ($background_colour) {
1013
      $coloured_string .= "\033[" . self::$background_colours[$background_colour] . "m";
1014
    }
1015
1016 7e72b748 Assos Assos
    // Add string and end colouring.
1017
    $coloured_string .= $string . "\033[0m";
1018 85ad3d82 Assos Assos
1019
    return $coloured_string;
1020
  }
1021
1022 7e72b748 Assos Assos
  /**
1023
   * Returns all foreground colour names.
1024
   */
1025 85ad3d82 Assos Assos
  public static function getForegroundColours() {
1026
    return array_keys(self::$foreground_colours);
1027
  }
1028
1029 7e72b748 Assos Assos
  /**
1030
   * Returns all background colour names.
1031
   */
1032 85ad3d82 Assos Assos
  public static function getBackgroundColours() {
1033
    return array_keys(self::$background_colours);
1034
  }
1035
1036
} // shellColours