file Schemas.php

Namespace

Drupal\bootstrap\Plugin\Setting
  1. <?php
  2. namespace Drupal\bootstrap\Plugin\Setting;
  3. use Drupal\bootstrap\Bootstrap;
  4. use Drupal\bootstrap\Plugin\Form\SystemThemeSettings;
  5. use Drupal\bootstrap\Utility\Element;
  6. use Drupal\Component\Render\FormattableMarkup;
  7. use Drupal\Core\Form\FormStateInterface;
  8. /**
  9. * The "schemas" theme setting.
  10. *
  11. * @ingroup plugins_setting
  12. * @ingroup plugins_update
  13. *
  14. * @BootstrapSetting(
  15. * id = "schemas",
  16. * type = "hidden",
  17. * weight = -20,
  18. * groups = false,
  19. * )
  20. */
  21. class Schemas extends SettingBase {
  22. /**
  23. * {@inheritdoc}
  24. */
  25. public function alterFormElement(Element $form, FormStateInterface $form_state, $form_id = NULL) {
  26. parent::alterFormElement($form, $form_state, $form_id);
  27. $updates = [];
  28. foreach ($this->theme->getPendingUpdates() as $version => $update) {
  29. $row = [];
  30. $row[] = $update->getSchema();
  31. $row[] = new FormattableMarkup('<strong>@title</strong><p class="help-block">@description</p>', [
  32. '@title' => $update->getLabel(),
  33. '@description' => $update->getDescription(),
  34. ]);
  35. $row[] = $update->getTheme()->getTitle();
  36. $updates[] = [
  37. 'class' => [$update->getSeverity() ?: 'default'],
  38. 'data' => $row,
  39. ];
  40. }
  41. $form['update'] = [
  42. '#type' => 'details',
  43. '#title' => $this->t('Theme Updates'),
  44. '#panel_type' => !!$updates ? 'primary' : 'default',
  45. '#open' => !!$updates,
  46. '#weight' => -20,
  47. ];
  48. $form['update']['table'] = [
  49. '#type' => 'table',
  50. '#header' => [t('Schema'), t('Description'), t('Provider')],
  51. '#empty' => t('There are currently no pending updates for this theme.'),
  52. '#rows' => $updates,
  53. ];
  54. if ($updates) {
  55. $form['update']['actions'] = ['#type' => 'actions'];
  56. $form['update']['actions']['update'] = [
  57. '#type' => 'submit',
  58. '#value' => t('Update theme'),
  59. '#icon' => Bootstrap::glyphicon('open'),
  60. // @todo Setting a class like this is undesirable, create a suggestion.
  61. '#attributes' => [
  62. 'class' => ['btn-primary'],
  63. ],
  64. '#submit' => [[get_class($this), 'updateTheme']],
  65. ];
  66. }
  67. }
  68. /**
  69. * Callback for updating a theme.
  70. *
  71. * @param array $form
  72. * Nested array of form elements that comprise the form.
  73. * @param \Drupal\Core\Form\FormStateInterface $form_state
  74. * The current state of the form.
  75. */
  76. public static function updateTheme(array $form, FormStateInterface $form_state) {
  77. if ($theme = SystemThemeSettings::getTheme(Element::create($form), $form_state)) {
  78. // Due to the fact that the batch API stores it's arguments in DB storage,
  79. // theme based objects cannot be passed as an operation argument here.
  80. // During _batch_page(), the DB item will attempt to restore the arguments
  81. // using unserialize() and the autoload fix include added below may not
  82. // yet have been invoked to register the theme namespaces. So instead,
  83. // we capture the relevant information needed to reconstruct these objects
  84. // in the batch processing callback.
  85. $theme_name = $theme->getName();
  86. // Create an operation for each update.
  87. $operations = [];
  88. foreach ($theme->getPendingUpdates() as $update) {
  89. $operations[] = [
  90. [__CLASS__, 'batchProcessUpdate'],
  91. [$theme_name, $update->getProvider() . ':' . $update->getSchema()],
  92. ];
  93. }
  94. if ($operations) {
  95. $variables = ['@theme_title' => $theme->getTitle()];
  96. batch_set([
  97. 'operations' => $operations,
  98. 'finished' => [__CLASS__, 'batchFinished'],
  99. 'title' => t('Updating @theme_title', $variables),
  100. 'init_message' => \Drupal::translation()->formatPlural(count($operations), 'Initializing 1 theme update for @theme_title...', 'Initializing @count theme updates for @theme_title...', $variables),
  101. 'progress_message' => t('Processing update @current of @total...', $variables),
  102. 'error_message' => t('An error was encountered while attempting to update the @theme_title theme.', $variables),
  103. 'file' => Bootstrap::autoloadFixInclude(),
  104. ]);
  105. }
  106. }
  107. }
  108. /**
  109. * Processes an update in a batch operation.
  110. *
  111. * @param string $theme_name
  112. * The machine name of the theme this update is being applied to.
  113. * @param string $update_id
  114. * The combined identifier of the update being applied, e.g.
  115. * provider:schema.
  116. * @param array $context
  117. * The batch context.
  118. */
  119. public static function batchProcessUpdate($theme_name, $update_id, array &$context) {
  120. // Reconstruct the theme object this update is being applied to.
  121. $theme = Bootstrap::getTheme($theme_name);
  122. // Reconstruct the update plugin that is being applied.
  123. list($provider, $plugin_id) = explode(':', $update_id);
  124. $provider = Bootstrap::getTheme($provider);
  125. /* @type \Drupal\bootstrap\Plugin\Update\UpdateInterface $update */
  126. $update = $provider->getUpdateManager()->createInstance($plugin_id, ['theme' => $provider]);
  127. // Initialize results with theme name and installed schemas.
  128. if (!isset($context['results']['theme_name'])) {
  129. $context['results']['theme_name'] = $theme_name;
  130. }
  131. if (!isset($context['results']['schemas'])) {
  132. $context['results']['schemas'] = $theme->getSetting('schemas', []);
  133. }
  134. $schemas = &$context['results']['schemas'];
  135. $variables = [
  136. '@theme' => $update->getTheme()->getName(),
  137. '@schema' => $update->getSchema(),
  138. '@label' => $update->getLabel(),
  139. ];
  140. // Perform the update.
  141. try {
  142. // Attempt to perform the update.
  143. if ($update->update($theme, $context) === FALSE) {
  144. throw new \Exception(t('Update failed'));
  145. }
  146. // Store the results.
  147. $schemas[$update->getTheme()->getName()] = $update->getSchema();
  148. $context['results']['success'][] = t('<strong>[@theme][@schema] @label</strong>', $variables);
  149. }
  150. // Capture any errors.
  151. catch (\Exception $e) {
  152. $variables['@message'] = $e->getMessage();
  153. $context['results']['errors'][] = t('<strong>[@theme][@schema] @label</strong> - @message', $variables);
  154. }
  155. }
  156. /**
  157. * Batch 'finished' callback.
  158. *
  159. * @param bool $success
  160. * A boolean indicating whether the batch has completed successfully.
  161. * @param array $results
  162. * The value(s) set in $context['results'] in
  163. * \Drupal\bootstrap\Plugin\Setting\Update::batchProcess().
  164. * @param mixed $operations
  165. * If $success is FALSE, contains the operations that remained unprocessed.
  166. */
  167. public static function batchFinished($success, array $results, $operations) {
  168. /* @type \Drupal\bootstrap\Theme $theme */
  169. // Reconstruct the theme object this update is being applied to.
  170. $theme = Bootstrap::getTheme($results['theme_name']);
  171. // Save the current state of the installed schemas.
  172. $theme->setSetting('schemas', $results['schemas']);
  173. // Show successful updates.
  174. if (!empty($results['success'])) {
  175. $list = Element::createStandalone([
  176. '#theme' => 'item_list__theme_update',
  177. '#items' => $results['success'],
  178. '#context' => ['type' => 'success'],
  179. ]);
  180. Bootstrap::message(new FormattableMarkup('@message' . $list->renderPlain(), [
  181. '@message' => t('Successfully completed the following theme updates:'),
  182. ]));
  183. }
  184. // Show failed errors.
  185. if (!empty($results['errors'])) {
  186. $list = Element::createStandalone([
  187. '#theme' => 'item_list__theme_update',
  188. '#items' => $results['errors'],
  189. '#context' => ['type' => 'errors'],
  190. ]);
  191. Bootstrap::message(new FormattableMarkup('@message' . $list->renderPlain(), [
  192. '@message' => t('The following theme updates could not be completed:'),
  193. ]), 'error');
  194. }
  195. }
  196. }

Classes

Name Description
Schemas The "schemas" theme setting.