Skip to content

Commit 43f41c3

Browse files
author
Nathaniel Catchpole
committed
Issue #3031128 by alexpott, TrevorBradley, indigoxela, catch, cilefen, larowlan, jibran: Update from 8.6.7 to 8.6.8 warnings - Drupal\Core\Extension\Extension has no unserializer
(cherry picked from commit bf21c00)
1 parent a01225a commit 43f41c3

File tree

5 files changed

+190
-0
lines changed

5 files changed

+190
-0
lines changed

includes/update.inc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
use Drupal\Component\Graph\Graph;
12+
use Drupal\Core\Update\UpdateKernel;
1213
use Drupal\Core\Utility\Error;
1314

1415
/**
@@ -29,6 +30,10 @@ function update_fix_compatibility() {
2930
$extension_config->set('module', module_config_sort($extension_config->get('module')));
3031
$extension_config->save();
3132
}
33+
34+
// Fix extension objects if the update is being done via Drush 8. In non-Drush
35+
// environments this will already be fixed by the UpdateKernel this point.
36+
UpdateKernel::fixSerializedExtensionObjects(\Drupal::getContainer());
3237
}
3338

3439
/**

lib/Drupal/Core/Update/UpdateKernel.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Drupal\Core\Site\Settings;
88
use Drupal\Core\StackMiddleware\ReverseProxyMiddleware;
99
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
10+
use Symfony\Component\DependencyInjection\ContainerInterface;
1011
use Symfony\Component\HttpFoundation\ParameterBag;
1112
use Symfony\Component\HttpFoundation\Request;
1213
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
@@ -190,4 +191,44 @@ protected function handleAccess(Request $request) {
190191
}
191192
}
192193

194+
/**
195+
* {@inheritdoc}
196+
*/
197+
public function loadLegacyIncludes() {
198+
parent::loadLegacyIncludes();
199+
static::fixSerializedExtensionObjects($this->container);
200+
}
201+
202+
/**
203+
* Fixes caches and theme info if they contain old Extension objects.
204+
*
205+
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
206+
* The container.
207+
*
208+
* @internal
209+
* This function is only to be called by the Drupal core update process.
210+
* Additionally, this function will be removed in minor release of Drupal.
211+
*
212+
* @todo https://www.drupal.org/project/drupal/issues/3031322 Remove once
213+
* Drupal 8.6.x is not supported.
214+
*/
215+
public static function fixSerializedExtensionObjects(ContainerInterface $container) {
216+
// Create a custom error handler that will clear caches if a warning occurs
217+
// while getting 'system.theme.data' from state. If this state value was
218+
// created by Drupal <= 8.6.7 then when it is read by Drupal >= 8.6.8 there
219+
// will be PHP warnings. This silently fixes Drupal so that the update can
220+
// continue.
221+
$callable = function () use ($container) {
222+
foreach ($container->getParameter('cache_bins') as $service_id => $bin) {
223+
$container->get($service_id)->deleteAll();
224+
}
225+
// Also rebuild themes because it uses state as cache.
226+
$container->get('theme_handler')->refreshInfo();
227+
};
228+
229+
set_error_handler($callable, E_ERROR | E_WARNING);
230+
$container->get('state')->get('system.theme.data', []);
231+
restore_error_handler();
232+
}
233+
193234
}
Binary file not shown.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
// @codingStandardsIgnoreFile
3+
4+
use Drupal\Core\Database\Database;
5+
6+
$connection = Database::getConnection();
7+
8+
// Manually configure the test mail collector implementation to prevent
9+
// tests from sending out emails and collect them in state instead.
10+
// While this should be enforced via settings.php prior to installation,
11+
// some tests expect to be able to test mail system implementations.
12+
$config = $connection->select('config')
13+
->fields('config', ['data'])
14+
->condition('collection', '')
15+
->condition('name', 'system.mail')
16+
->execute()
17+
->fetchField();
18+
$config = unserialize($config);
19+
$config['interface']['default'] = 'test_mail_collector';
20+
$connection->update('config')
21+
->fields([
22+
'data' => serialize($config),
23+
'collection' => '',
24+
'name' => 'system.mail',
25+
])
26+
->condition('collection', '')
27+
->condition('name', 'system.mail')
28+
->execute();
29+
30+
// By default, verbosely display all errors and disable all production
31+
// environment optimizations for all tests to avoid needless overhead and
32+
// ensure a sane default experience for test authors.
33+
// @see https://www.drupal.org/node/2259167
34+
$config = $connection->select('config')
35+
->fields('config', ['data'])
36+
->condition('collection', '')
37+
->condition('name', 'system.logging')
38+
->execute()
39+
->fetchField();
40+
$config = unserialize($config);
41+
$config['error_level'] = 'verbose';
42+
$connection->update('config')
43+
->fields([
44+
'data' => serialize($config),
45+
'collection' => '',
46+
'name' => 'system.logging',
47+
])
48+
->condition('collection', '')
49+
->condition('name', 'system.logging')
50+
->execute();
51+
52+
$config = $connection->select('config')
53+
->fields('config', ['data'])
54+
->condition('collection', '')
55+
->condition('name', 'system.performance')
56+
->execute()
57+
->fetchField();
58+
$config = unserialize($config);
59+
$config['css']['preprocess'] = FALSE;
60+
$config['js']['preprocess'] = FALSE;
61+
$connection->update('config')
62+
->fields([
63+
'data' => serialize($config),
64+
'collection' => '',
65+
'name' => 'system.performance',
66+
])
67+
->condition('collection', '')
68+
->condition('name', 'system.performance')
69+
->execute();
70+
71+
// Set an explicit time zone to not rely on the system one, which may vary
72+
// from setup to setup. The Australia/Sydney time zone is chosen so all
73+
// tests are run using an edge case scenario (UTC10 and DST). This choice
74+
// is made to prevent time zone related regressions and reduce the
75+
// fragility of the testing system in general.
76+
$config = $connection->select('config')
77+
->fields('config', ['data'])
78+
->condition('collection', '')
79+
->condition('name', 'system.date')
80+
->execute()
81+
->fetchField();
82+
$config = unserialize($config);
83+
$config['timezone']['default'] = 'Australia/Sydney';
84+
$connection->update('config')
85+
->fields([
86+
'data' => serialize($config),
87+
'collection' => '',
88+
'name' => 'system.date',
89+
])
90+
->condition('collection', '')
91+
->condition('name', 'system.date')
92+
->execute();
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace Drupal\Tests\system\Functional\Update;
4+
5+
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
6+
use Symfony\Component\DependencyInjection\ContainerInterface;
7+
8+
/**
9+
* Updates from 8.6.0 with warm caches.
10+
*
11+
* @group Update
12+
* @group legacy
13+
*/
14+
class WarmCacheUpdateFrom8dot6Test extends UpdatePathTestBase {
15+
16+
/**
17+
* {@inheritdoc}
18+
*/
19+
protected function setDatabaseDumpFiles() {
20+
// Created by installing minimal on 8.6.0, logging on as user 1 and doing:
21+
// php ./core/scripts/db-tools.php dump-database-d8-mysql --schema-only=sessions,watchdog
22+
$this->databaseDumpFiles[0] = __DIR__ . '/../../../../tests/fixtures/update/drupal-8.6.0-minimal-with-warm-caches.sql.gz';
23+
$this->databaseDumpFiles[1] = __DIR__ . '/../../../../tests/fixtures/update/drupal-8.test-config-init.php';
24+
}
25+
26+
/**
27+
* Tests that the content and configuration were properly updated.
28+
*/
29+
public function testUpdatedSite() {
30+
$this->runUpdates();
31+
$this->drupalGet('');
32+
33+
$this->resetAll();
34+
// Ensure that drupal-8.test-config-init.php has run correctly.
35+
$this->assertSame('test_mail_collector', $this->config('system.mail')->get('interface.default'));
36+
$this->assertSame('verbose', $this->config('system.logging')->get('error_level'));
37+
$this->assertSame(FALSE, $this->config('system.performance')->get('css.preprocess'));
38+
$this->assertSame(FALSE, $this->config('system.performance')->get('js.preprocess'));
39+
$this->assertSame('Australia/Sydney', $this->config('system.date')->get('timezone.default'));
40+
}
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
protected function initConfig(ContainerInterface $container) {
46+
// Don't touch configuration before running the updates as this invokes
47+
// \Drupal\system\EventSubscriber\ConfigCacheTag::onSave() which lists
48+
// themes. This functionality is replicated in
49+
// core/modules/system/tests/fixtures/update/drupal-8.test-config-init.php.
50+
}
51+
52+
}

0 commit comments

Comments
 (0)