4 * Contains \Drupal\bootstrap\Plugin\Setting\Schemas.
7 namespace Drupal\bootstrap\Plugin\Setting;
9 use Drupal\bootstrap\Annotation\BootstrapSetting;
10 use Drupal\bootstrap\Bootstrap;
11 use Drupal\bootstrap\Plugin\Form\SystemThemeSettings;
12 use Drupal\bootstrap\Utility\Element;
13 use Drupal\Component\Render\FormattableMarkup;
14 use Drupal\Core\Form\FormStateInterface;
17 * The "schemas" theme setting.
19 * @ingroup plugins_setting
20 * @ingroup plugins_update
29 class Schemas extends SettingBase {
34 public function alterFormElement(Element $form, FormStateInterface $form_state, $form_id = NULL) {
35 parent::alterFormElement($form, $form_state, $form_id);
38 foreach ($this->theme->getPendingUpdates() as $version => $update) {
40 $row[] = $update->getSchema();
41 $row[] = new FormattableMarkup('<strong>@title</strong><p class="help-block">@description</p>', [
42 '@title' => $update->getLabel(),
43 '@description' => $update->getDescription(),
45 $row[] = $update->getTheme()->getTitle();
47 'class' => [$update->getSeverity() ?: 'default'],
54 '#title' => $this->t('Theme Updates'),
55 '#panel_type' => !!$updates ? 'primary' : 'default',
56 '#open' => !!$updates,
60 $form['update']['table'] = [
62 '#header' => [t('Schema'), t('Description'), t('Provider')],
63 '#empty' => t('There are currently no pending updates for this theme.'),
68 $form['update']['actions'] = ['#type' => 'actions'];
69 $form['update']['actions']['update'] = [
71 '#value' => t('Update theme'),
72 '#icon' => Bootstrap::glyphicon('open'),
73 // @todo Setting a class like this is undesirable, create a suggestion.
75 'class' => ['btn-primary'],
77 '#submit' => [[get_class($this), 'updateTheme']],
83 * Callback for updating a theme.
86 * Nested array of form elements that comprise the form.
87 * @param \Drupal\Core\Form\FormStateInterface $form_state
88 * The current state of the form.
90 public static function updateTheme(array $form, FormStateInterface $form_state) {
91 if ($theme = SystemThemeSettings::getTheme($form, $form_state)) {
92 // Due to the fact that the batch API stores it's arguments in DB storage,
93 // theme based objects cannot be passed as an operation argument here.
94 // During _batch_page(), the DB item will attempt to restore the arguments
95 // using unserialize() and the autoload fix include added below may not
96 // yet have been invoked to register the theme namespaces. So instead,
97 // we capture the relevant information needed to reconstruct these objects
98 // in the batch processing callback.
99 $theme_name = $theme->getName();
101 // Create an operation for each update.
103 foreach ($theme->getPendingUpdates() as $update) {
104 $operations[] = [[__CLASS__, 'batchProcessUpdate'], [$theme_name, $update->getProvider() . ':' . $update->getSchema()]];
108 $variables = ['@theme_title' => $theme->getTitle()];
110 'operations' => $operations,
111 'finished' => [__CLASS__, 'batchFinished'],
112 'title' => t('Updating @theme_title', $variables),
113 'init_message' => \Drupal::translation()->formatPlural(count($operations), 'Initializing 1 theme update for @theme_title...', 'Initializing @count theme updates for @theme_title...', $variables),
114 'progress_message' => t('Processing update @current of @total...', $variables),
115 'error_message' => t('An error was encountered while attempting to update the @theme_title theme.', $variables),
116 'file' => Bootstrap::autoloadFixInclude(),
123 * Processes an update in a batch operation.
125 * @param string $theme_name
126 * The machine name of the theme this update is being applied to.
127 * @param string $update_id
128 * The combined identifier of the update being applied, e.g.
130 * @param array $context
133 public static function batchProcessUpdate($theme_name, $update_id, array &$context) {
134 // Reconstruct the theme object this update is being applied to.
135 $theme = Bootstrap::getTheme($theme_name);
137 // Reconstruct the update plugin that is being applied.
138 list($provider, $plugin_id) = explode(':', $update_id);
139 $provider = Bootstrap::getTheme($provider);
141 /** @type \Drupal\bootstrap\Plugin\Update\UpdateInterface $update */
142 $update = $provider->getUpdateManager()->createInstance($plugin_id, ['theme' => $provider]);
144 // Initialize results with theme name and installed schemas.
145 if (!isset($context['results']['theme_name'])) {
146 $context['results']['theme_name'] = $theme_name;
148 if (!isset($context['results']['schemas'])) {
149 $context['results']['schemas'] = $theme->getSetting('schemas', []);
152 $schemas = &$context['results']['schemas'];
155 '@theme' => $update->getTheme()->getName(),
156 '@schema' => $update->getSchema(),
157 '@label' => $update->getLabel(),
160 // Perform the update.
162 // Attempt to perform the update.
163 if ($update->update($theme, $context) === FALSE) {
164 throw new \Exception(t('Update failed'));
167 // Store the results.
168 $schemas[$update->getTheme()->getName()] = $update->getSchema();
170 $context['results']['success'][] = t('<strong>[@theme][@schema] @label</strong>', $variables);
172 // Capture any errors.
173 catch (\Exception $e) {
174 $variables['@message'] = $e->getMessage();
175 $context['results']['errors'][] = t('<strong>[@theme][@schema] @label</strong> - @message', $variables);
180 * Batch 'finished' callback
182 * @param bool $success
183 * A boolean indicating whether the batch has completed successfully.
184 * @param array $results
185 * The value(s) set in $context['results'] in
186 * \Drupal\bootstrap\Plugin\Setting\Update::batchProcess().
188 * If $success is FALSE, contains the operations that remained unprocessed.
190 public static function batchFinished($success, $results, $operations) {
191 /** @type \Drupal\bootstrap\Theme $theme */
192 // Reconstruct the theme object this update is being applied to.
193 $theme = Bootstrap::getTheme($results['theme_name']);
195 // Save the current state of the installed schemas.
196 $theme->setSetting('schemas', $results['schemas']);
198 // Show successful updates.
199 if (!empty($results['success'])) {
200 $list = Element::createStandalone([
201 '#theme' => 'item_list__theme_update',
202 '#items' => $results['success'],
203 '#context' => ['type' => 'success'],
205 drupal_set_message(new FormattableMarkup('@message' . $list->renderPlain(), [
206 '@message' => t('Successfully completed the following theme updates:'),
210 // Show failed errors.
211 if (!empty($results['errors'])) {
212 $list = Element::createStandalone([
213 '#theme' => 'item_list__theme_update',
214 '#items' => $results['errors'],
215 '#context' => ['type' => 'errors'],
217 drupal_set_message(new FormattableMarkup('@message' . $list->renderPlain(), [
218 '@message' => t('The following theme updates could not be completed:'),