Projet

Général

Profil

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

root / drupal7 / sites / all / modules / ctools / drush / ctools.drush.inc @ 1e39edcb

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