ViewsCommands.php

Namespace

Drush\CommandFiles\core

Classes

Namesort ascending Description
ViewsCommands

File

lib/Drush/CommandFiles/core/ViewsCommands.php
View source
  1. <?php
  2. namespace Drush\CommandFiles\core;
  3. use Consolidation\AnnotatedCommand\CommandData;
  4. use Consolidation\AnnotatedCommand\CommandError;
  5. use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
  6. use Drush\CommandFiles\DrushCommands;
  7. use Drush\Log\LogLevel;
  8. use Psr\Log\LoggerAwareInterface;
  9. use Psr\Log\LoggerAwareTrait;
  10. use Drupal\views\Views;
  11. class ViewsCommands extends DrushCommands {
  12. /**
  13. * Set several Views settings to more developer-oriented values.
  14. *
  15. * @command views-dev
  16. *
  17. * @bootstrap DRUSH_BOOTSTRAP_DRUPAL_FULL
  18. * @aliases vd
  19. */
  20. public function dev() {
  21. $settings = array(
  22. 'ui.show.listing_filters' => TRUE,
  23. 'ui.show.master_display' => TRUE,
  24. 'ui.show.advanced_column' => TRUE,
  25. 'ui.always_live_preview' => FALSE,
  26. 'ui.always_live_preview_button' => TRUE,
  27. 'ui.show.preview_information' => TRUE,
  28. 'ui.show.sql_query.enabled' => TRUE,
  29. 'ui.show.sql_query.where' => 'above',
  30. 'ui.show.performance_statistics' => TRUE,
  31. 'ui.show.additional_queries' => TRUE,
  32. );
  33. $config = \Drupal::configFactory()->getEditable('views.settings');
  34. foreach ($settings as $setting => $value) {
  35. $config->set($setting, $value);
  36. // Convert boolean values into a string to print.
  37. if (is_bool($value)) {
  38. $value = $value ? 'TRUE' : 'FALSE';
  39. }
  40. // Wrap string values in quotes.
  41. elseif (is_string($value)) {
  42. $value = "\"$value\"";
  43. }
  44. $this->logger->log(LogLevel::SUCCESS, dt('!setting set to !value', array(
  45. '!setting' => $setting,
  46. '!value' => $value
  47. )));
  48. }
  49. // Save the new config.
  50. $config->save();
  51. $this->logger->log(LogLevel::SUCCESS, (dt('New views configuration saved.')));
  52. }
  53. /**
  54. * Get a list of all views in the system.
  55. *
  56. * @command views-list
  57. *
  58. * @option name A string contained in the view's name to filter the results with.
  59. * @option tags A comma-separated list of views tags by which to filter the results.
  60. * @option status Filter views by status. Choices: enabled, disabled.
  61. * @usage drush vl
  62. * Show a list of all available views.
  63. * @usage drush vl --name=blog
  64. * Show a list of views which names contain 'blog'.
  65. * @usage drush vl --tags=tag1,tag2
  66. * Show a list of views tagged with 'tag1' or 'tag2'.
  67. * @usage drush vl --status=enabled
  68. * Show a list of enabled views.
  69. * @table-style default
  70. * @field-labels
  71. * machine-name: Machine name
  72. * label: Name
  73. * description: Description
  74. * status: Status
  75. * tag: Tag
  76. * @default-fields machine-name,label,description,status
  77. * @bootstrap DRUSH_BOOTSTRAP_DRUPAL_FULL
  78. * @aliases vl
  79. *
  80. * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
  81. */
  82. public function vlist($options = ['name' => '', 'tags' => '', 'status' => NULL, 'format' => 'table', 'fields' => '']) {
  83. $disabled_views = array();
  84. $enabled_views = array();
  85. $views = \Drupal::entityTypeManager()->getStorage('view')->loadMultiple();
  86. // Get the --name option.
  87. $name = \_convert_csv_to_array($options['name']);
  88. $with_name = !empty($name) ? TRUE : FALSE;
  89. // Get the --tags option.
  90. $tags = \_convert_csv_to_array($options['tags']);
  91. $with_tags = !empty($tags) ? TRUE : FALSE;
  92. // Get the --status option. Store user input apart to reuse it after.
  93. $status = $options['status'];
  94. // @todo See https://github.com/consolidation/annotated-command/issues/53
  95. if ($status && !in_array($status, array('enabled', 'disabled'))) {
  96. throw new \Exception(dt('Invalid status: @status. Available options are "enabled" or "disabled"', array('@status' => $status)));
  97. }
  98. // Setup a row for each view.
  99. foreach ($views as $view) {
  100. // If options were specified, check that first mismatch push the loop to the
  101. // next view.
  102. if ($with_name && !stristr($view->id(), $name[0])) {
  103. continue;
  104. }
  105. if ($with_tags && !in_array($view->get('tag'), $tags)) {
  106. continue;
  107. }
  108. $status_bool = $status == 'enabled';
  109. if ($status && ($view->status() !== $status_bool)) {
  110. continue;
  111. }
  112. $row = array(
  113. 'machine-name' => $view->id(),
  114. 'label' => $view->label(),
  115. 'description' => $view->get('description'),
  116. 'status' => $view->status() ? dt('Enabled') : dt('Disabled'),
  117. 'tag' => $view->get('tag'),
  118. );
  119. // Place the row in the appropriate array, so we can have disabled views at
  120. // the bottom.
  121. if ($view->status()) {
  122. $enabled_views[] = $row;
  123. }
  124. else{
  125. $disabled_views[] = $row;
  126. }
  127. }
  128. // Sort alphabetically.
  129. asort($disabled_views);
  130. asort($enabled_views);
  131. if (count($enabled_views) || count($disabled_views)) {
  132. $rows = array_merge($enabled_views, $disabled_views);
  133. return new RowsOfFields($rows);
  134. }
  135. else {
  136. $this->logger->log(LogLevel::OK, dt('No views found.'));
  137. }
  138. }
  139. /**
  140. * Execute a view and show a count of the results, or the rendered HTML.
  141. *
  142. * @command views-execute
  143. *
  144. * @param string $view The name of the view to execute.
  145. * @param string $display The display ID to execute. If none specified, the default display will be used.
  146. * @param string $view_args A comma delimited list of values, corresponding to contextual filters.
  147. * @option count Display a count of the results instead of each row.
  148. * @option show-admin-links Show contextual admin links in the rendered markup.
  149. * @bootstrap DRUSH_BOOTSTRAP_DRUPAL_FULL
  150. * @usage drush views-execute my_view
  151. * Show the rendered HTML for the default display for the my_view View.
  152. * @usage drush views-execute my_view page_1 3 --count
  153. * Show a count of my_view:page_1 where the first contextual filter value is 3.
  154. * @usage drush views-execute my_view page_1 3,foo
  155. * Show the rendered HTML of my_view:page_1 where the first two contextual filter values are 3 and 'foo' respectively.
  156. * @bootstrap DRUSH_BOOTSTRAP_DRUPAL_FULL
  157. * @complete \Drush\CommandFiles\core\ViewsCommands::complete
  158. * @validate-entity-load view views
  159. * @aliases vex
  160. *
  161. * @return string
  162. */
  163. public function execute($view, $display = NULL, $view_args = NULL, $options = ['count' => 0, 'show-admin-links' => 0]) {
  164. $view = Views::getView($view);
  165. // Set the display and execute the view.
  166. $view->setDisplay($display);
  167. $view->preExecute(_convert_csv_to_array($view_args));
  168. $view->execute();
  169. if (empty($view->result)) {
  170. $this->logger->log(LogLevel::WARNING, dt('No results returned for this view.'));
  171. return NULL;
  172. }
  173. elseif ($options['count']) {
  174. drush_backend_set_result(count($view->result));
  175. drush_print(count($view->result));
  176. return NULL;
  177. }
  178. else {
  179. // Don't show admin links in markup by default.
  180. $view->hide_admin_links = !$options['show-admin-links'];
  181. $build = $view->preview();
  182. return (string) \Drupal::service('renderer')->renderPlain($build);
  183. }
  184. }
  185. /**
  186. * Get a list of all Views and analyze warnings.
  187. *
  188. * @command views-analyze
  189. * @todo 'drupal dependencies' => array('views', 'views_ui'),
  190. * @todo Command has not been fully tested. How to generate a message?
  191. * @bootstrap DRUSH_BOOTSTRAP_DRUPAL_FULL
  192. * @field-labels
  193. * type: Type
  194. * message: Message
  195. * @aliases va
  196. *
  197. * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields|void
  198. */
  199. public function analyze() {
  200. $messages = NULL;
  201. $messages_count = 0;
  202. $rows = [];
  203. $views = \Drupal::entityTypeManager()->getStorage('view')->loadMultiple();
  204. if (!empty($views)) {
  205. $analyzer = \Drupal::service('views.analyzer');
  206. foreach ($views as $view_name => $view) {
  207. $view = $view->getExecutable();
  208. if ($messages = $analyzer->getMessages($view)) {
  209. $rows[] = [$messages['type'], $messages['message']];
  210. }
  211. }
  212. $this->logger->log(LogLevel::OK, dt('A total of @total views were analyzed and @messages problems were found.', array('@total' => count($views), '@messages' => $messages_count)));
  213. return new RowsOfFields($rows);
  214. }
  215. else {
  216. $this->logger->log(LogLevel::OK, dt('There are no views to analyze'));
  217. }
  218. }
  219. /**
  220. * Enable the specified views.
  221. *
  222. * @command views-enable
  223. * @param string $views A comma delimited list of view names.
  224. * @validate-entity-load view views
  225. * @usage drush ven frontpage,taxonomy_term
  226. * Enable the frontpage and taxonomy_term views.
  227. * @complete \Drush\CommandFiles\core\ViewsCommands::complete
  228. * @bootstrap DRUSH_BOOTSTRAP_DRUPAL_FULL
  229. * @aliases ven
  230. */
  231. public function enable($views) {
  232. $view_names = _convert_csv_to_array($views);
  233. if ($views = \Drupal::entityTypeManager()->getStorage('view')->loadMultiple($view_names)) {
  234. foreach ($views as $view) {
  235. $view->enable();
  236. $view->save();
  237. }
  238. }
  239. $this->logger->log(LogLevel::OK, dt('!str enabled.', ['!str' => implode(', ', $view_names)]));
  240. }
  241. /**
  242. * Disable the specified views.
  243. *
  244. * @command views-disable
  245. * @validate-entity-load view views
  246. * @param string $views A comma delimited list of view names.
  247. * @usage drush vdis frontpage taxonomy_term
  248. * Disable the frontpage and taxonomy_term views.
  249. * @complete \Drush\CommandFiles\core\ViewsCommands::complete
  250. * @bootstrap DRUSH_BOOTSTRAP_DRUPAL_FULL
  251. * @aliases vdis
  252. */
  253. public function disable($views) {
  254. $view_names = _convert_csv_to_array($views);
  255. if ($views = \Drupal::entityTypeManager()->getStorage('view')->loadMultiple($view_names)) {
  256. foreach ($views as $view) {
  257. $view->disable();
  258. $view->save();
  259. }
  260. }
  261. $this->logger->log(LogLevel::OK, dt('!str disabled.', ['!str' => implode(', ', $view_names)]));
  262. }
  263. /**
  264. * Validate that passed View names are valid.
  265. *
  266. * @hook validate @validate-entity-load
  267. * @param \Consolidation\AnnotatedCommand\CommandData $commandData
  268. * @return \Consolidation\AnnotatedCommand\CommandError|null
  269. */
  270. public function validate_entity_load(CommandData $commandData) {
  271. list($entity_type, $arg_name) = explode(' ', $commandData->annotationData()->get('validate-entity-load', NULL));
  272. $names = _convert_csv_to_array($commandData->input()->getArgument($arg_name));
  273. $loaded = \Drupal::entityTypeManager()->getStorage($entity_type)->loadMultiple($names);
  274. if ($missing = array_diff($names, array_keys($loaded))) {
  275. $msg = dt('Unable to load Views: !str', ['!str' => implode(', ', $missing)]);
  276. return new CommandError($msg);
  277. }
  278. }
  279. /**
  280. * A completion callback.
  281. *
  282. * @return array
  283. * An array of available view names.
  284. */
  285. static function complete() {
  286. drush_bootstrap_max();
  287. return array('values' => array_keys(\Drupal::entityTypeManager()->getStorage('view')->loadMultiple()));
  288. }
  289. /**
  290. * @todo See https://github.com/consolidation/annotated-command/issues/56
  291. * Implements hook_cache_clear. Adds a cache clear option for views.
  292. */
  293. // function views_drush_cache_clear(&$types, $include_bootstrapped_types) {
  294. // if ($include_bootstrapped_types && \Drupal::moduleHandler()->moduleExists('views')) {
  295. // $types['views'] = 'views_invalidate_cache';
  296. // }
  297. // }
  298. }