?query=1',
+ 'internal:/?query=1',
+ ],
+ 'No leading forward slash' => [
+ 'node/10',
+ 'internal:/node/10',
+ ],
+ 'Leading forward slash' => [
+ '/node/10',
+ 'internal:/node/10',
+ ],
+ 'Existing scheme' => [
+ 'scheme:test',
+ 'scheme:test',
+ ],
+ ];
+ }
+
+}
diff --git a/core/modules/locale/src/StringDatabaseStorage.php b/core/modules/locale/src/StringDatabaseStorage.php
index 57358dc..45bf41d 100644
--- a/core/modules/locale/src/StringDatabaseStorage.php
+++ b/core/modules/locale/src/StringDatabaseStorage.php
@@ -3,6 +3,7 @@
namespace Drupal\locale;
use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Query\Condition;
/**
* Defines a class to store localized strings in the database.
@@ -416,7 +417,7 @@ protected function dbStringSelect(array $conditions, array $options = []) {
elseif ($table_alias == 't' && $join === 'leftJoin') {
// Conditions for target fields when doing an outer join only make
// sense if we add also OR field IS NULL.
- $query->condition(db_or()
+ $query->condition((new Condition('OR'))
->condition($field_alias, (array) $value, 'IN')
->isNull($field_alias)
);
@@ -429,7 +430,7 @@ protected function dbStringSelect(array $conditions, array $options = []) {
// Process other options, string filter, query limit, etc.
if (!empty($options['filters'])) {
if (count($options['filters']) > 1) {
- $filter = db_or();
+ $filter = new Condition('OR');
$query->condition($filter);
}
else {
diff --git a/core/modules/migrate/src/Plugin/migrate/process/FormatDate.php b/core/modules/migrate/src/Plugin/migrate/process/FormatDate.php
new file mode 100644
index 0000000..b197f17
--- /dev/null
+++ b/core/modules/migrate/src/Plugin/migrate/process/FormatDate.php
@@ -0,0 +1,113 @@
+configuration['from_format'])) {
+ throw new MigrateException('Format date plugin is missing from_format configuration.');
+ }
+ if (empty($this->configuration['to_format'])) {
+ throw new MigrateException('Format date plugin is missing to_format configuration.');
+ }
+
+ $fromFormat = $this->configuration['from_format'];
+ $toFormat = $this->configuration['to_format'];
+ $timezone = isset($this->configuration['timezone']) ? $this->configuration['timezone'] : NULL;
+ $settings = isset($this->configuration['settings']) ? $this->configuration['settings'] : [];
+
+ // Attempts to transform the supplied date using the defined input format.
+ // DateTimePlus::createFromFormat can throw exceptions, so we need to
+ // explicitly check for problems.
+ try {
+ $transformed = DateTimePlus::createFromFormat($fromFormat, $value, $timezone, $settings)->format($toFormat);
+ }
+ catch (\InvalidArgumentException $e) {
+ throw new MigrateException(sprintf('Format date plugin could not transform "%s" using the format "%s". Error: %s', $value, $fromFormat, $e->getMessage()), $e->getCode(), $e);
+ }
+ catch (\UnexpectedValueException $e) {
+ throw new MigrateException(sprintf('Format date plugin could not transform "%s" using the format "%s". Error: %s', $value, $fromFormat, $e->getMessage()), $e->getCode(), $e);
+ }
+
+ return $transformed;
+ }
+
+}
diff --git a/core/modules/migrate/src/Plugin/migrate/process/SkipOnEmpty.php b/core/modules/migrate/src/Plugin/migrate/process/SkipOnEmpty.php
index 45626be..c7d3ad5 100644
--- a/core/modules/migrate/src/Plugin/migrate/process/SkipOnEmpty.php
+++ b/core/modules/migrate/src/Plugin/migrate/process/SkipOnEmpty.php
@@ -21,6 +21,9 @@
* - row: Skips the entire row when an empty value is encountered.
* - process: Prevents further processing of the input property when the value
* is empty.
+ * - message: (optional) A message to be logged in the {migrate_message_*} table
+ * for this row. Messages are only logged for the 'row' skip level. If not
+ * set, nothing is logged in the message table.
*
* Examples:
*
@@ -30,9 +33,11 @@
* plugin: skip_on_empty
* method: row
* source: field_name
+ * message: 'Field field_name is missed'
* @endcode
*
- * If field_name is empty, skips the entire row.
+ * If field_name is empty, skips the entire row and the message 'Field
+ * field_name is missed' is logged in the message table.
*
* @code
* process:
@@ -79,7 +84,8 @@ class SkipOnEmpty extends ProcessPluginBase {
*/
public function row($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (!$value) {
- throw new MigrateSkipRowException();
+ $message = !empty($this->configuration['message']) ? $this->configuration['message'] : '';
+ throw new MigrateSkipRowException($message);
}
return $value;
}
diff --git a/core/modules/migrate/src/Plugin/migrate/process/SkipRowIfNotSet.php b/core/modules/migrate/src/Plugin/migrate/process/SkipRowIfNotSet.php
index ab7552e..fa9b3f6 100644
--- a/core/modules/migrate/src/Plugin/migrate/process/SkipRowIfNotSet.php
+++ b/core/modules/migrate/src/Plugin/migrate/process/SkipRowIfNotSet.php
@@ -16,6 +16,8 @@
*
* Available configuration keys:
* - index: The source property to check for.
+ * - message: (optional) A message to be logged in the {migrate_message_*} table
+ * for this row. If not set, nothing is logged in the message table.
*
* Example:
*
@@ -26,10 +28,12 @@
* plugin: skip_row_if_not_set
* index: contact
* source: data
+ * message: "Missed the 'data' key"
* @endcode
*
* This will return $data['contact'] if it exists. Otherwise, the row will be
- * skipped.
+ * skipped and the message "Missed the 'data' key" will be logged in the
+ * message table.
*
* @see \Drupal\migrate\Plugin\MigrateProcessInterface
*
@@ -45,7 +49,8 @@ class SkipRowIfNotSet extends ProcessPluginBase {
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (!isset($value[$this->configuration['index']])) {
- throw new MigrateSkipRowException();
+ $message = !empty($this->configuration['message']) ? $this->configuration['message'] : '';
+ throw new MigrateSkipRowException($message);
}
return $value[$this->configuration['index']];
}
diff --git a/core/modules/migrate/src/Plugin/migrate/process/StaticMap.php b/core/modules/migrate/src/Plugin/migrate/process/StaticMap.php
index d3c93ed..1d68f35 100644
--- a/core/modules/migrate/src/Plugin/migrate/process/StaticMap.php
+++ b/core/modules/migrate/src/Plugin/migrate/process/StaticMap.php
@@ -10,9 +10,98 @@
use Drupal\migrate\MigrateSkipRowException;
/**
- * This plugin changes the current value based on a static lookup map.
+ * Changes the source value based on a static lookup map.
*
- * @link https://www.drupal.org/node/2143521 Online handbook documentation for static_map process plugin @endlink
+ * Maps the input value to another value using an associative array specified in
+ * the configuration.
+ *
+ * Available configuration keys:
+ * - source: The input value - either a scalar or an array.
+ * - map: An array (of 1 or more dimensions) that identifies the mapping between
+ * source values and destination values.
+ * - bypass: (optional) Whether the plugin should proceed when the source is not
+ * found in the map array. Defaults to FALSE.
+ * - TRUE: Return the unmodified input value, or another default value, if one
+ * is specified.
+ * - FALSE: Throw a MigrateSkipRowException.
+ * - default_value: (optional) The value to return if the source is not found in
+ * the map array.
+ *
+ * Examples:
+ *
+ * @code
+ * process:
+ * bar:
+ * plugin: static_map
+ * source: foo
+ * map:
+ * from: to
+ * this: that
+ * @endcode
+ *
+ * If the value of the source property foo was "from" then the value of the
+ * destination property bar will be "to". Similarly "this" becomes "that".
+ * static_map can do a lot more than this: it supports a list of source
+ * properties. This is super useful in module-delta to machine name conversions.
+ *
+ * @code
+ * process:
+ * id:
+ * plugin: static_map
+ * source:
+ * - module
+ * - delta
+ * map:
+ * filter:
+ * 0: filter_html_escape
+ * 1: filter_autop
+ * 2: filter_url
+ * 3: filter_htmlcorrector
+ * 4: filter_html_escape
+ * php:
+ * 0: php_code
+ * @endcode
+ *
+ * If the value of the source properties module and delta are "filter" and "2"
+ * respectively, then the returned value will be "filter_url". By default, if a
+ * value is not found in the map, an exception is thrown.
+ *
+ * When static_map is used to just rename a few things and leave the others, a
+ * "bypass: true" option can be added. In this case, the source value is used
+ * unchanged, e.g.:
+ *
+ * @code
+ * process:
+ * bar:
+ * plugin: static_map
+ * source: foo
+ * map:
+ * from: to
+ * this: that
+ * bypass: TRUE
+ * @endcode
+ *
+ * If the value of the source property "foo" is "from" then the returned value
+ * will be "to", but if the value of "foo" is "another" (a value that is not in
+ * the map) then the source value is used unchanged so the returned value will
+ * be "from" because "bypass" is set to TRUE.
+ *
+ * @code
+ * process:
+ * bar:
+ * plugin: static_map
+ * source: foo
+ * map:
+ * from: to
+ * this: that
+ * default_value: bar
+ * @endcode
+ *
+ * If the value of the source property "foo" is "yet_another" (a value that is
+ * not in the map) then the default_value is used so the returned value will
+ * be "bar".
+ *
+ * @see \Drupal\migrate\Plugin\MigrateProcessInterface
*
* @MigrateProcessPlugin(
* id = "static_map"
diff --git a/core/modules/migrate/src/Plugin/migrate/source/EmbeddedDataSource.php b/core/modules/migrate/src/Plugin/migrate/source/EmbeddedDataSource.php
index 05be56d..0bb35f3 100644
--- a/core/modules/migrate/src/Plugin/migrate/source/EmbeddedDataSource.php
+++ b/core/modules/migrate/src/Plugin/migrate/source/EmbeddedDataSource.php
@@ -1,10 +1,41 @@
[
'name' => 'changed',
diff --git a/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php b/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php
index 8a99cad..00f07a9 100644
--- a/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php
+++ b/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php
@@ -160,8 +160,8 @@ public function testSource(array $source_data, array $expected_data, $expected_c
// If an expected count was given, assert it only if the plugin is
// countable.
if (is_numeric($expected_count)) {
- $this->assertInstanceOf('\Iterator', $plugin);
- $this->assertSame($expected_count, iterator_count($plugin));
+ $this->assertInstanceOf('\Countable', $plugin);
+ $this->assertCount($expected_count, $plugin);
}
$i = 0;
@@ -185,6 +185,11 @@ public function testSource(array $source_data, array $expected_data, $expected_c
}
}
}
+ // False positives occur if the foreach is not entered. So, confirm the
+ // foreach loop was entered if the expected count is greater than 0.
+ if ($expected_count > 0) {
+ $this->assertGreaterThan(0, $i);
+ }
}
}
diff --git a/core/modules/migrate/tests/src/Unit/Event/EventBaseTest.php b/core/modules/migrate/tests/src/Unit/Event/EventBaseTest.php
index 6a52ed6..b712d31 100644
--- a/core/modules/migrate/tests/src/Unit/Event/EventBaseTest.php
+++ b/core/modules/migrate/tests/src/Unit/Event/EventBaseTest.php
@@ -3,12 +3,13 @@
namespace Drupal\Tests\migrate\Unit\Event;
use Drupal\migrate\Event\EventBase;
+use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\migrate\Event\EventBase
* @group migrate
*/
-class EventBaseTest extends \PHPUnit_Framework_TestCase {
+class EventBaseTest extends UnitTestCase {
/**
* Test getMigration method.
diff --git a/core/modules/migrate/tests/src/Unit/Event/MigrateImportEventTest.php b/core/modules/migrate/tests/src/Unit/Event/MigrateImportEventTest.php
index 480fe85..d281433 100644
--- a/core/modules/migrate/tests/src/Unit/Event/MigrateImportEventTest.php
+++ b/core/modules/migrate/tests/src/Unit/Event/MigrateImportEventTest.php
@@ -3,12 +3,13 @@
namespace Drupal\Tests\migrate\Unit\Event;
use Drupal\migrate\Event\MigrateImportEvent;
+use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\migrate\Event\MigrateImportEvent
* @group migrate
*/
-class MigrateImportEventTest extends \PHPUnit_Framework_TestCase {
+class MigrateImportEventTest extends UnitTestCase {
/**
* Test getMigration method.
diff --git a/core/modules/migrate/tests/src/Unit/process/FormatDateTest.php b/core/modules/migrate/tests/src/Unit/process/FormatDateTest.php
new file mode 100644
index 0000000..c1e0c63
--- /dev/null
+++ b/core/modules/migrate/tests/src/Unit/process/FormatDateTest.php
@@ -0,0 +1,124 @@
+ '',
+ 'to_format' => 'Y-m-d',
+ ];
+
+ $this->setExpectedException(MigrateException::class, 'Format date plugin is missing from_format configuration.');
+ $this->plugin = new FormatDate($configuration, 'test_format_date', []);
+ $this->plugin->transform('01/05/1955', $this->migrateExecutable, $this->row, 'field_date');
+ }
+
+ /**
+ * Tests that missing configuration will throw an exception.
+ */
+ public function testMigrateExceptionMissingToFormat() {
+ $configuration = [
+ 'from_format' => 'm/d/Y',
+ 'to_format' => '',
+ ];
+
+ $this->setExpectedException(MigrateException::class, 'Format date plugin is missing to_format configuration.');
+ $this->plugin = new FormatDate($configuration, 'test_format_date', []);
+ $this->plugin->transform('01/05/1955', $this->migrateExecutable, $this->row, 'field_date');
+ }
+
+ /**
+ * Tests that date format mismatches will throw an exception.
+ */
+ public function testMigrateExceptionBadFormat() {
+ $configuration = [
+ 'from_format' => 'm/d/Y',
+ 'to_format' => 'Y-m-d',
+ ];
+
+ $this->setExpectedException(MigrateException::class, 'Format date plugin could not transform "January 5, 1955" using the format "m/d/Y". Error: The date cannot be created from a format.');
+ $this->plugin = new FormatDate($configuration, 'test_format_date', []);
+ $this->plugin->transform('January 5, 1955', $this->migrateExecutable, $this->row, 'field_date');
+ }
+
+ /**
+ * Tests transformation.
+ *
+ * @covers ::transform
+ *
+ * @dataProvider datesDataProvider
+ *
+ * @param $configuration
+ * The configuration of the migration process plugin.
+ * @param $value
+ * The source value for the migration process plugin.
+ * @param $expected
+ * The expected value of the migration process plugin.
+ */
+ public function testTransform($configuration, $value, $expected) {
+ $this->plugin = new FormatDate($configuration, 'test_format_date', []);
+ $actual = $this->plugin->transform($value, $this->migrateExecutable, $this->row, 'field_date');
+
+ $this->assertEquals($expected, $actual);
+ }
+
+ /**
+ * Data provider of test dates.
+ *
+ * @return array
+ * Array of date formats and actual/expected values.
+ */
+ public function datesDataProvider() {
+ return [
+ 'datetime_date' => [
+ 'configuration' => [
+ 'from_format' => 'm/d/Y',
+ 'to_format' => 'Y-m-d',
+ ],
+ 'value' => '01/05/1955',
+ 'expected' => '1955-01-05',
+ ],
+ 'datetime_datetime' => [
+ 'configuration' => [
+ 'from_format' => 'm/d/Y H:i:s',
+ 'to_format' => 'Y-m-d\TH:i:s',
+ ],
+ 'value' => '01/05/1955 10:43:22',
+ 'expected' => '1955-01-05T10:43:22',
+ ],
+ 'empty_values' => [
+ 'configuration' => [
+ 'from_format' => 'm/d/Y',
+ 'to_format' => 'Y-m-d',
+ ],
+ 'value' => '',
+ 'expected' => '',
+ ],
+ 'timezone' => [
+ 'configuration' => [
+ 'from_format' => 'Y-m-d\TH:i:sO',
+ 'to_format' => 'Y-m-d\TH:i:s',
+ 'timezone' => 'America/Managua',
+ ],
+ 'value' => '2004-12-19T10:19:42-0600',
+ 'expected' => '2004-12-19T10:19:42',
+ ],
+ ];
+ }
+
+}
diff --git a/core/modules/migrate/tests/src/Unit/process/SkipOnEmptyTest.php b/core/modules/migrate/tests/src/Unit/process/SkipOnEmptyTest.php
index 66b27cc..08fbef2 100644
--- a/core/modules/migrate/tests/src/Unit/process/SkipOnEmptyTest.php
+++ b/core/modules/migrate/tests/src/Unit/process/SkipOnEmptyTest.php
@@ -1,6 +1,7 @@
assertSame($value, ' ');
}
+ /**
+ * Tests that a skip row exception without a message is raised.
+ *
+ * @covers ::row
+ */
+ public function testRowSkipWithoutMessage() {
+ $configuration = [
+ 'method' => 'row',
+ ];
+ $process = new SkipOnEmpty($configuration, 'skip_on_empty', []);
+ $this->setExpectedException(MigrateSkipRowException::class);
+ $process->transform('', $this->migrateExecutable, $this->row, 'destinationproperty');
+ }
+
+ /**
+ * Tests that a skip row exception with a message is raised.
+ *
+ * @covers ::row
+ */
+ public function testRowSkipWithMessage() {
+ $configuration = [
+ 'method' => 'row',
+ 'message' => 'The value is empty',
+ ];
+ $process = new SkipOnEmpty($configuration, 'skip_on_empty', []);
+ $this->setExpectedException(MigrateSkipRowException::class, 'The value is empty');
+ $process->transform('', $this->migrateExecutable, $this->row, 'destinationproperty');
+ }
+
}
diff --git a/core/modules/migrate/tests/src/Unit/process/SkipRowIfNotSetTest.php b/core/modules/migrate/tests/src/Unit/process/SkipRowIfNotSetTest.php
new file mode 100644
index 0000000..26e5b3f
--- /dev/null
+++ b/core/modules/migrate/tests/src/Unit/process/SkipRowIfNotSetTest.php
@@ -0,0 +1,45 @@
+ 'some_key',
+ ];
+ $process = new SkipRowIfNotSet($configuration, 'skip_row_if_not_set', []);
+ $this->setExpectedException(MigrateSkipRowException::class);
+ $process->transform('', $this->migrateExecutable, $this->row, 'destinationproperty');
+ }
+
+ /**
+ * Tests that a skip row exception with a message is raised.
+ *
+ * @covers ::transform
+ */
+ public function testRowSkipWithMessage() {
+ $configuration = [
+ 'index' => 'some_key',
+ 'message' => "The 'some_key' key is not set",
+ ];
+ $process = new SkipRowIfNotSet($configuration, 'skip_row_if_not_set', []);
+ $this->setExpectedException(MigrateSkipRowException::class, "The 'some_key' key is not set");
+ $process->transform('', $this->migrateExecutable, $this->row, 'destinationproperty');
+ }
+
+}
diff --git a/core/modules/migrate_drupal/migrate_drupal.services.yml b/core/modules/migrate_drupal/migrate_drupal.services.yml
index 71a0b27..23b3492 100644
--- a/core/modules/migrate_drupal/migrate_drupal.services.yml
+++ b/core/modules/migrate_drupal/migrate_drupal.services.yml
@@ -1,4 +1,12 @@
services:
+ plugin.manager.migrate.field:
+ class: Drupal\migrate_drupal\Plugin\MigrateFieldPluginManager
+ arguments:
+ - field
+ - '@container.namespaces'
+ - '@cache.discovery'
+ - '@module_handler'
+ - '\Drupal\migrate_drupal\Annotation\MigrateField'
plugin.manager.migrate.cckfield:
class: Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManager
arguments:
@@ -7,3 +15,4 @@ services:
- '@cache.discovery'
- '@module_handler'
- '\Drupal\migrate_drupal\Annotation\MigrateCckField'
+ deprecated: The "%service_id%" service is deprecated. You should use the 'plugin.manager.migrate.field' service instead. See https://www.drupal.org/node/2751897
diff --git a/core/modules/migrate_drupal/src/Annotation/MigrateCckField.php b/core/modules/migrate_drupal/src/Annotation/MigrateCckField.php
index 5e5a500..73949e1 100644
--- a/core/modules/migrate_drupal/src/Annotation/MigrateCckField.php
+++ b/core/modules/migrate_drupal/src/Annotation/MigrateCckField.php
@@ -2,53 +2,20 @@
namespace Drupal\migrate_drupal\Annotation;
-use Drupal\Component\Annotation\Plugin;
+@trigger_error('MigrateCckField is deprecated in Drupal 8.3.x and will be
+removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateField
+instead.', E_USER_DEPRECATED);
/**
- * Defines a cckfield plugin annotation object.
+ * Deprecated: Defines a cckfield plugin annotation object.
*
- * cckfield plugins are variously responsible for handling the migration of
- * CCK fields from Drupal 6 to Drupal 8, and Field API fields from Drupal 7
- * to Drupal 8. They are allowed to alter CCK-related migrations when migrations
- * are being generated, and can compute destination field types for individual
- * fields during the actual migration process.
+ * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use
+ * \Drupal\migrate_drupal\Annotation\MigrateField instead.
*
* Plugin Namespace: Plugin\migrate\cckfield
*
* @Annotation
*/
-class MigrateCckField extends Plugin {
-
- /**
- * @inheritdoc
- */
- public function __construct($values) {
- parent::__construct($values);
- // Provide default value for core property, in case it's missing.
- if (empty($this->definition['core'])) {
- $this->definition['core'] = [6];
- }
- }
-
- /**
- * The plugin ID.
- *
- * @var string
- */
- public $id;
-
- /**
- * Map of D6 and D7 field types to D8 field type plugin IDs.
- *
- * @var string[]
- */
- public $type_map = [];
-
- /**
- * The Drupal core version(s) this plugin applies to.
- *
- * @var int[]
- */
- public $core = [];
+class MigrateCckField extends MigrateField {
}
diff --git a/core/modules/migrate_drupal/src/Annotation/MigrateField.php b/core/modules/migrate_drupal/src/Annotation/MigrateField.php
new file mode 100644
index 0000000..ad78bc9
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Annotation/MigrateField.php
@@ -0,0 +1,54 @@
+definition['core'])) {
+ $this->definition['core'] = [6];
+ }
+ }
+
+ /**
+ * The plugin ID.
+ *
+ * @var string
+ */
+ public $id;
+
+ /**
+ * Map of D6 and D7 field types to D8 field type plugin IDs.
+ *
+ * @var string[]
+ */
+ public $type_map = [];
+
+ /**
+ * The Drupal core version(s) this plugin applies to.
+ *
+ * @var int[]
+ */
+ public $core = [];
+
+}
diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldInterface.php b/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldInterface.php
index b30b2b8..c64738f 100644
--- a/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldInterface.php
+++ b/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldInterface.php
@@ -2,64 +2,19 @@
namespace Drupal\migrate_drupal\Plugin;
-use Drupal\Component\Plugin\PluginInspectionInterface;
+@trigger_error('MigrateCckFieldInterface is deprecated in Drupal 8.3.x and will
+be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateField
+instead.', E_USER_DEPRECATED);
+
use Drupal\migrate\Plugin\MigrationInterface;
-use Drupal\migrate\Row;
/**
* Provides an interface for all CCK field type plugins.
+ *
+ * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use
+ * \Drupal\migrate_drupal\Annotation\MigrateField instead.
*/
-interface MigrateCckFieldInterface extends PluginInspectionInterface {
-
- /**
- * Apply any custom processing to the field migration.
- *
- * @param \Drupal\migrate\Plugin\MigrationInterface $migration
- * The migration entity.
- */
- public function processField(MigrationInterface $migration);
-
- /**
- * Apply any custom processing to the field instance migration.
- *
- * @param \Drupal\migrate\Plugin\MigrationInterface $migration
- * The migration entity.
- */
- public function processFieldInstance(MigrationInterface $migration);
-
- /**
- * Apply any custom processing to the field widget migration.
- *
- * @param \Drupal\migrate\Plugin\MigrationInterface $migration
- * The migration entity.
- */
- public function processFieldWidget(MigrationInterface $migration);
-
- /**
- * Apply any custom processing to the field formatter migration.
- *
- * @param \Drupal\migrate\Plugin\MigrationInterface $migration
- * The migration entity.
- */
- public function processFieldFormatter(MigrationInterface $migration);
-
- /**
- * Get a map between D6 formatters and D8 formatters for this field type.
- *
- * This is used by static::processFieldFormatter() in the base class.
- *
- * @return array
- * The keys are D6 formatters and the values are D8 formatters.
- */
- public function getFieldFormatterMap();
-
- /**
- * Get a map between D6 and D8 widgets for this field type.
- *
- * @return array
- * The keys are D6 field widget types and the values D8 widgets.
- */
- public function getFieldWidgetMap();
+interface MigrateCckFieldInterface extends MigrateFieldInterface {
/**
* Apply any custom processing to the cck bundle migrations.
@@ -73,15 +28,4 @@ public function getFieldWidgetMap();
*/
public function processCckFieldValues(MigrationInterface $migration, $field_name, $data);
- /**
- * Computes the destination type of a migrated field.
- *
- * @param \Drupal\migrate\Row $row
- * The field being migrated.
- *
- * @return string
- * The destination field type.
- */
- public function getFieldType(Row $row);
-
}
diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManager.php b/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManager.php
index 56c7b5b..9ade1e5 100644
--- a/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManager.php
+++ b/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManager.php
@@ -2,54 +2,16 @@
namespace Drupal\migrate_drupal\Plugin;
-use Drupal\Component\Plugin\Exception\PluginNotFoundException;
-use Drupal\migrate\Plugin\MigratePluginManager;
-use Drupal\migrate\Plugin\MigrationInterface;
+@trigger_error('MigrateCckFieldPluginManager is deprecated in Drupal 8.3.x and will
+be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateFieldPluginManager
+instead.', E_USER_DEPRECATED);
/**
- * Plugin manager for migrate cckfield plugins.
+ * Deprecated: Plugin manager for migrate field plugins.
*
- * @see \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
- * @see \Drupal\migrate\Annotation\MigrateCckField
- * @see plugin_api
+ * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use
+ * \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManager instead.
*
* @ingroup migration
*/
-class MigrateCckFieldPluginManager extends MigratePluginManager implements MigrateCckFieldPluginManagerInterface {
-
- /**
- * The default version of core to use for cck field plugins.
- *
- * These plugins were initially only built and used for Drupal 6 fields.
- * Having been extended for Drupal 7 with a "core" annotation, we fall back to
- * Drupal 6 where none exists.
- */
- const DEFAULT_CORE_VERSION = 6;
-
- /**
- * {@inheritdoc}
- */
- public function getPluginIdFromFieldType($field_type, array $configuration = [], MigrationInterface $migration = NULL) {
- $core = static::DEFAULT_CORE_VERSION;
- if (!empty($configuration['core'])) {
- $core = $configuration['core'];
- }
- elseif (!empty($migration->getPluginDefinition()['migration_tags'])) {
- foreach ($migration->getPluginDefinition()['migration_tags'] as $tag) {
- if ($tag == 'Drupal 7') {
- $core = 7;
- }
- }
- }
-
- foreach ($this->getDefinitions() as $plugin_id => $definition) {
- if (in_array($core, $definition['core'])) {
- if (array_key_exists($field_type, $definition['type_map']) || $field_type === $plugin_id) {
- return $plugin_id;
- }
- }
- }
- throw new PluginNotFoundException($field_type);
- }
-
-}
+class MigrateCckFieldPluginManager extends MigrateFieldPluginManager implements MigrateCckFieldPluginManagerInterface { }
diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManagerInterface.php b/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManagerInterface.php
index a5371b9..3d88d77 100644
--- a/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManagerInterface.php
+++ b/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManagerInterface.php
@@ -2,27 +2,14 @@
namespace Drupal\migrate_drupal\Plugin;
-use Drupal\migrate\Plugin\MigratePluginManagerInterface;
-use Drupal\migrate\Plugin\MigrationInterface;
-
-interface MigrateCckFieldPluginManagerInterface extends MigratePluginManagerInterface {
-
- /**
- * Get the plugin ID from the field type.
- *
- * @param string $field_type
- * The field type being migrated.
- * @param array $configuration
- * (optional) An array of configuration relevant to the plugin instance.
- * @param \Drupal\migrate\Plugin\MigrationInterface|null $migration
- * (optional) The current migration instance.
- *
- * @return string
- * The ID of the plugin for the field_type if available.
- *
- * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
- * If the plugin cannot be determined, such as if the field type is invalid.
- */
- public function getPluginIdFromFieldType($field_type, array $configuration = [], MigrationInterface $migration = NULL);
-
-}
+@trigger_error('MigrateCckFieldPluginManagerInterface is deprecated in Drupal 8.3.x
+and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateFieldPluginManagerInterface
+instead.', E_USER_DEPRECATED);
+
+/**
+ * Provides an interface for cck field plugin manager.
+ *
+ * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use
+ * \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface instead.
+ */
+interface MigrateCckFieldPluginManagerInterface extends MigrateFieldPluginManagerInterface { }
diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateFieldInterface.php b/core/modules/migrate_drupal/src/Plugin/MigrateFieldInterface.php
new file mode 100644
index 0000000..c8cecad
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Plugin/MigrateFieldInterface.php
@@ -0,0 +1,87 @@
+getPluginDefinition()['migration_tags'])) {
+ foreach ($migration->getPluginDefinition()['migration_tags'] as $tag) {
+ if ($tag == 'Drupal 7') {
+ $core = 7;
+ }
+ }
+ }
+
+ $definitions = $this->getDefinitions();
+ foreach ($definitions as $plugin_id => $definition) {
+ if (in_array($core, $definition['core'])) {
+ if (array_key_exists($field_type, $definition['type_map']) || $field_type === $plugin_id) {
+ return $plugin_id;
+ }
+ }
+ }
+ throw new PluginNotFoundException($field_type);
+ }
+
+}
diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManagerInterface.php b/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManagerInterface.php
new file mode 100644
index 0000000..7219c2b
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManagerInterface.php
@@ -0,0 +1,28 @@
+cckPluginManager = $cck_manager;
- }
+class CckMigration extends FieldMigration {
/**
* {@inheritdoc}
*/
- public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
- return new static(
- $configuration,
- $plugin_id,
- $plugin_definition,
- $container->get('plugin.manager.migrate.cckfield'),
- $container->get('plugin.manager.migration'),
- $container->get('plugin.manager.migrate.source'),
- $container->get('plugin.manager.migrate.process'),
- $container->get('plugin.manager.migrate.destination'),
- $container->get('plugin.manager.migrate.id_map')
- );
- }
-
- /**
- * {@inheritdoc}
- */
- public function getProcess() {
- if (!$this->init) {
- $this->init = TRUE;
- $source_plugin = $this->migrationPluginManager->createInstance($this->pluginId)->getSourcePlugin();
- if ($source_plugin instanceof RequirementsInterface) {
- try {
- $source_plugin->checkRequirements();
- }
- catch (RequirementsException $e) {
- // Kill the rest of the method.
- $source_plugin = [];
- }
- }
- foreach ($source_plugin as $row) {
- $field_type = $row->getSourceProperty('type');
- try {
- $plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, [], $this);
- }
- catch (PluginNotFoundException $ex) {
- continue;
- }
-
- if (!isset($this->processedFieldTypes[$field_type])) {
- $this->processedFieldTypes[$field_type] = TRUE;
- // Allow the cckfield plugin to alter the migration as necessary so
- // that it knows how to handle fields of this type.
- if (!isset($this->cckPluginCache[$field_type])) {
- $this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($plugin_id, [], $this);
- }
- call_user_func([$this->cckPluginCache[$field_type], $this->pluginDefinition['cck_plugin_method']], $this);
- }
- }
- }
- return parent::getProcess();
- }
+ const PLUGIN_METHOD = 'cck_plugin_method';
}
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/FieldMigration.php b/core/modules/migrate_drupal/src/Plugin/migrate/FieldMigration.php
new file mode 100644
index 0000000..c7aaa2d
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/FieldMigration.php
@@ -0,0 +1,171 @@
+cckPluginManager = $cck_manager;
+ $this->fieldPluginManager = $field_manager;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+ return new static(
+ $configuration,
+ $plugin_id,
+ $plugin_definition,
+ $container->get('plugin.manager.migrate.cckfield'),
+ $container->get('plugin.manager.migrate.field'),
+ $container->get('plugin.manager.migration'),
+ $container->get('plugin.manager.migrate.source'),
+ $container->get('plugin.manager.migrate.process'),
+ $container->get('plugin.manager.migrate.destination'),
+ $container->get('plugin.manager.migrate.id_map')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getProcess() {
+ if (!$this->init) {
+ $this->init = TRUE;
+ $source_plugin = $this->migrationPluginManager->createInstance($this->pluginId)->getSourcePlugin();
+ if ($source_plugin instanceof RequirementsInterface) {
+ try {
+ $source_plugin->checkRequirements();
+ }
+ catch (RequirementsException $e) {
+ // Kill the rest of the method.
+ $source_plugin = [];
+ }
+ }
+ foreach ($source_plugin as $row) {
+ $field_type = $row->getSourceProperty('type');
+
+ try {
+ $plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, [], $this);
+ $Manager = $this->cckPluginManager;
+ }
+ catch (PluginNotFoundException $ex) {
+ try {
+ $plugin_id = $this->fieldPluginManager->getPluginIdFromFieldType($field_type, [], $this);
+ $Manager = $this->fieldPluginManager;
+ }
+ catch (PluginNotFoundException $ex) {
+ continue;
+ }
+ }
+
+ if (!isset($this->processedFieldTypes[$field_type]) && $Manager->hasDefinition($plugin_id)) {
+ $this->processedFieldTypes[$field_type] = TRUE;
+ // Allow the field plugin to alter the migration as necessary so that
+ // it knows how to handle fields of this type.
+ if (!isset($this->fieldPluginCache[$field_type])) {
+ $this->fieldPluginCache[$field_type] = $Manager->createInstance($plugin_id, [], $this);
+ }
+ }
+ $method = $this->pluginDefinition[static::PLUGIN_METHOD];
+ call_user_func([$this->fieldPluginCache[$field_type], $method], $this);
+ }
+ }
+ return parent::getProcess();
+ }
+
+}
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/cckfield/CckFieldPluginBase.php b/core/modules/migrate_drupal/src/Plugin/migrate/cckfield/CckFieldPluginBase.php
index d942bce..79a65a7 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/cckfield/CckFieldPluginBase.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/cckfield/CckFieldPluginBase.php
@@ -2,82 +2,49 @@
namespace Drupal\migrate_drupal\Plugin\migrate\cckfield;
-use Drupal\Core\Plugin\PluginBase;
+@trigger_error('CckFieldPluginBase is deprecated in Drupal 8.3.x and will be
+be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase
+instead.', E_USER_DEPRECATED);
+
use Drupal\migrate\Plugin\MigrationInterface;
-use Drupal\migrate\Row;
-use Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface;
+use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
/**
- * The base class for all cck field plugins.
+ * The base class for all field plugins.
*
- * @see \Drupal\migrate\Plugin\MigratePluginManager
- * @see \Drupal\migrate_drupal\Annotation\MigrateCckField
- * @see \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
- * @see plugin_api
+ * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use
+ * \Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase instead.
*
* @ingroup migration
*/
-abstract class CckFieldPluginBase extends PluginBase implements MigrateCckFieldInterface {
-
- /**
- * {@inheritdoc}
- */
- public function processField(MigrationInterface $migration) {
- $process[0]['map'][$this->pluginId][$this->pluginId] = $this->pluginId;
- $migration->mergeProcessOfProperty('type', $process);
- }
+abstract class CckFieldPluginBase extends FieldPluginBase {
/**
- * {@inheritdoc}
+ * Apply any custom processing to the field bundle migrations.
+ *
+ * @param \Drupal\migrate\Plugin\MigrationInterface $migration
+ * The migration entity.
+ * @param string $field_name
+ * The field name we're processing the value for.
+ * @param array $data
+ * The array of field data from FieldValues::fieldData().
*/
- public function processFieldInstance(MigrationInterface $migration) {
- // Nothing to do by default with field instances.
+ public function processFieldValues(MigrationInterface $migration, $field_name, $data) {
+ // Provide a bridge to the old method declared on the interface and now an
+ // abstract method in this class.
+ return $this->processCckFieldValues($migration, $field_name, $data);
}
/**
- * {@inheritdoc}
+ * Apply any custom processing to the field bundle migrations.
+ *
+ * @param \Drupal\migrate\Plugin\MigrationInterface $migration
+ * The migration entity.
+ * @param string $field_name
+ * The field name we're processing the value for.
+ * @param array $data
+ * The array of field data from FieldValues::fieldData().
*/
- public function processFieldWidget(MigrationInterface $migration) {
- $process = [];
- foreach ($this->getFieldWidgetMap() as $source_widget => $destination_widget) {
- $process['type']['map'][$source_widget] = $destination_widget;
- }
- $migration->mergeProcessOfProperty('options/type', $process);
- }
-
- /**
- * {@inheritdoc}
- */
- public function getFieldWidgetMap() {
- // By default, use the plugin ID for the widget types.
- return [
- $this->pluginId => $this->pluginId . '_default',
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function processFieldFormatter(MigrationInterface $migration) {
- $process = [];
- foreach ($this->getFieldFormatterMap() as $source_format => $destination_format) {
- $process[0]['map'][$this->pluginId][$source_format] = $destination_format;
- }
- $migration->mergeProcessOfProperty('options/type', $process);
- }
-
- /**
- * {@inheritdoc}
- */
- public function getFieldType(Row $row) {
- $field_type = $row->getSourceProperty('type');
-
- if (isset($this->pluginDefinition['type_map'][$field_type])) {
- return $this->pluginDefinition['type_map'][$field_type];
- }
- else {
- return $field_type;
- }
- }
+ abstract public function processCckFieldValues(MigrationInterface $migration, $field_name, $data);
}
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/field/FieldPluginBase.php b/core/modules/migrate_drupal/src/Plugin/migrate/field/FieldPluginBase.php
new file mode 100644
index 0000000..852c6ca
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/field/FieldPluginBase.php
@@ -0,0 +1,83 @@
+pluginId][$this->pluginId] = $this->pluginId;
+ $migration->mergeProcessOfProperty('type', $process);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function processFieldInstance(MigrationInterface $migration) {
+ // Nothing to do by default with field instances.
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function processFieldWidget(MigrationInterface $migration) {
+ $process = [];
+ foreach ($this->getFieldWidgetMap() as $source_widget => $destination_widget) {
+ $process['type']['map'][$source_widget] = $destination_widget;
+ }
+ $migration->mergeProcessOfProperty('options/type', $process);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFieldWidgetMap() {
+ // By default, use the plugin ID for the widget types.
+ return [
+ $this->pluginId => $this->pluginId . '_default',
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function processFieldFormatter(MigrationInterface $migration) {
+ $process = [];
+ foreach ($this->getFieldFormatterMap() as $source_format => $destination_format) {
+ $process[0]['map'][$this->pluginId][$source_format] = $destination_format;
+ }
+ $migration->mergeProcessOfProperty('options/type', $process);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFieldType(Row $row) {
+ $field_type = $row->getSourceProperty('type');
+
+ if (isset($this->pluginDefinition['type_map'][$field_type])) {
+ return $this->pluginDefinition['type_map'][$field_type];
+ }
+ else {
+ return $field_type;
+ }
+ }
+
+}
diff --git a/core/modules/migrate_drupal/tests/fixtures/drupal6.php b/core/modules/migrate_drupal/tests/fixtures/drupal6.php
index 71bccd4..73431ef 100644
--- a/core/modules/migrate_drupal/tests/fixtures/drupal6.php
+++ b/core/modules/migrate_drupal/tests/fixtures/drupal6.php
@@ -43,6 +43,75 @@
'mysql_character_set' => 'utf8',
));
+$connection->schema()->createTable('accesslog', array(
+ 'fields' => array(
+ 'aid' => array(
+ 'type' => 'serial',
+ 'not null' => TRUE,
+ 'size' => 'normal',
+ ),
+ 'sid' => array(
+ 'type' => 'varchar',
+ 'not null' => TRUE,
+ 'length' => '64',
+ 'default' => '',
+ ),
+ 'title' => array(
+ 'type' => 'varchar',
+ 'not null' => FALSE,
+ 'length' => '255',
+ ),
+ 'path' => array(
+ 'type' => 'varchar',
+ 'not null' => FALSE,
+ 'length' => '255',
+ ),
+ 'url' => array(
+ 'type' => 'text',
+ 'not null' => FALSE,
+ 'size' => 'normal',
+ ),
+ 'hostname' => array(
+ 'type' => 'varchar',
+ 'not null' => FALSE,
+ 'length' => '128',
+ ),
+ 'uid' => array(
+ 'type' => 'int',
+ 'not null' => FALSE,
+ 'size' => 'normal',
+ 'default' => '0',
+ 'unsigned' => TRUE,
+ ),
+ 'timer' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'size' => 'normal',
+ 'default' => '0',
+ 'unsigned' => TRUE,
+ ),
+ 'timestamp' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'size' => 'normal',
+ 'default' => '0',
+ 'unsigned' => TRUE,
+ ),
+ ),
+ 'primary key' => array(
+ 'aid',
+ ),
+ 'indexes' => array(
+ 'accesslog_timestamp' => array(
+ 'timestamp',
+ ),
+ 'uid' => array(
+ 'uid',
+ ),
+ ),
+ 'mysql_character_set' => 'utf8',
+));
+
$connection->schema()->createTable('actions', array(
'fields' => array(
'aid' => array(
@@ -391,7 +460,7 @@
'image' => 'http://b.thumbs.redditmedia.com/harEHsUUZVajabtC.png',
'etag' => '"213cc1365b96c310e92053c5551f0504"',
'modified' => '0',
- 'block' => '5',
+ 'block' => '7',
))
->execute();
@@ -641,7 +710,7 @@
'delta' => '0',
'theme' => 'garland',
'status' => '1',
- 'weight' => '0',
+ 'weight' => '-10',
'region' => 'left',
'custom' => '0',
'throttle' => '0',
@@ -656,7 +725,7 @@
'delta' => '1',
'theme' => 'garland',
'status' => '1',
- 'weight' => '0',
+ 'weight' => '-11',
'region' => 'left',
'custom' => '0',
'throttle' => '0',
@@ -746,7 +815,7 @@
'delta' => '2',
'theme' => 'garland',
'status' => '1',
- 'weight' => '-9',
+ 'weight' => '-11',
'region' => 'right',
'custom' => '0',
'throttle' => '0',
@@ -761,7 +830,7 @@
'delta' => '3',
'theme' => 'garland',
'status' => '1',
- 'weight' => '-6',
+ 'weight' => '-10',
'region' => 'right',
'custom' => '0',
'throttle' => '0',
@@ -835,9 +904,9 @@
'module' => 'aggregator',
'delta' => 'feed-5',
'theme' => 'garland',
- 'status' => '0',
+ 'status' => '1',
'weight' => '-2',
- 'region' => '',
+ 'region' => 'right',
'custom' => '0',
'throttle' => '0',
'visibility' => '0',
@@ -925,9 +994,9 @@
'module' => 'book',
'delta' => '0',
'theme' => 'garland',
- 'status' => '0',
+ 'status' => '1',
'weight' => '-4',
- 'region' => '',
+ 'region' => 'right',
'custom' => '0',
'throttle' => '0',
'visibility' => '0',
@@ -950,6 +1019,51 @@
'title' => '',
'cache' => '-1',
))
+->values(array(
+ 'bid' => '22',
+ 'module' => 'forum',
+ 'delta' => '0',
+ 'theme' => 'garland',
+ 'status' => '1',
+ 'weight' => '-8',
+ 'region' => 'left',
+ 'custom' => '0',
+ 'throttle' => '0',
+ 'visibility' => '0',
+ 'pages' => '',
+ 'title' => '',
+ 'cache' => '1',
+))
+->values(array(
+ 'bid' => '23',
+ 'module' => 'forum',
+ 'delta' => '1',
+ 'theme' => 'garland',
+ 'status' => '1',
+ 'weight' => '-9',
+ 'region' => 'left',
+ 'custom' => '0',
+ 'throttle' => '0',
+ 'visibility' => '0',
+ 'pages' => '',
+ 'title' => '',
+ 'cache' => '1',
+))
+->values(array(
+ 'bid' => '24',
+ 'module' => 'statistics',
+ 'delta' => '0',
+ 'theme' => 'garland',
+ 'status' => '1',
+ 'weight' => '0',
+ 'region' => 'right',
+ 'custom' => '0',
+ 'throttle' => '0',
+ 'visibility' => '0',
+ 'pages' => '',
+ 'title' => '',
+ 'cache' => '-1',
+))
->execute();
$connection->schema()->createTable('blocks_roles', array(
@@ -7992,6 +8106,44 @@
'mysql_character_set' => 'utf8',
));
+$connection->schema()->createTable('forum', array(
+ 'fields' => array(
+ 'nid' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'size' => 'normal',
+ 'default' => '0',
+ 'unsigned' => TRUE,
+ ),
+ 'vid' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'size' => 'normal',
+ 'default' => '0',
+ 'unsigned' => TRUE,
+ ),
+ 'tid' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'size' => 'normal',
+ 'default' => '0',
+ 'unsigned' => TRUE,
+ ),
+ ),
+ 'primary key' => array(
+ 'vid',
+ ),
+ 'indexes' => array(
+ 'nid' => array(
+ 'nid',
+ ),
+ 'tid' => array(
+ 'tid',
+ ),
+ ),
+ 'mysql_character_set' => 'utf8',
+));
+
$connection->schema()->createTable('history', array(
'fields' => array(
'uid' => array(
@@ -9148,6 +9300,38 @@
'objectindex' => '139',
'format' => '0',
))
+->values(array(
+ 'lid' => '1664',
+ 'objectid' => 'forum',
+ 'type' => 'type',
+ 'property' => 'name',
+ 'objectindex' => '0',
+ 'format' => '0',
+))
+->values(array(
+ 'lid' => '1665',
+ 'objectid' => 'forum',
+ 'type' => 'type',
+ 'property' => 'title',
+ 'objectindex' => '0',
+ 'format' => '0',
+))
+->values(array(
+ 'lid' => '1666',
+ 'objectid' => 'forum',
+ 'type' => 'type',
+ 'property' => 'body',
+ 'objectindex' => '0',
+ 'format' => '0',
+))
+->values(array(
+ 'lid' => '1667',
+ 'objectid' => 'forum',
+ 'type' => 'type',
+ 'property' => 'description',
+ 'objectindex' => '0',
+ 'format' => '0',
+))
->execute();
$connection->schema()->createTable('i18n_variable', array(
@@ -9194,6 +9378,21 @@
'value' => 'a:2:{i:0;i:1;i:1;i:2;}',
))
->values(array(
+ 'name' => 'statistics_count_content_views',
+ 'language' => 'en',
+ 'value' => 's:1:"1";',
+))
+->values(array(
+ 'name' => 'statistics_enable_access_log',
+ 'language' => 'en',
+ 'value' => 's:1:"0";',
+))
+->values(array(
+ 'name' => 'statistics_flush_accesslog_timer',
+ 'language' => 'en',
+ 'value' => 's:6:"259200";',
+))
+->values(array(
'name' => 'anonymous',
'language' => 'fr',
'value' => 's:8:"fr Guest";',
@@ -21529,6 +21728,41 @@
'source' => 'Delete all translations',
'version' => '6.38-dev',
))
+->values(array(
+ 'lid' => '1664',
+ 'location' => 'type:forum:name',
+ 'textgroup' => 'nodetype',
+ 'source' => 'Forum topic',
+ 'version' => '1',
+))
+->values(array(
+ 'lid' => '1665',
+ 'location' => 'type:forum:title',
+ 'textgroup' => 'nodetype',
+ 'source' => 'Subject',
+ 'version' => '1',
+))
+->values(array(
+ 'lid' => '1666',
+ 'location' => 'type:forum:body',
+ 'textgroup' => 'nodetype',
+ 'source' => 'Body',
+ 'version' => '1',
+))
+->values(array(
+ 'lid' => '1667',
+ 'location' => 'type:forum:description',
+ 'textgroup' => 'nodetype',
+ 'source' => 'A forum topic is the initial post to a new discussion thread within a forum.',
+ 'version' => '1',
+))
+->values(array(
+ 'lid' => '1668',
+ 'location' => 'modules/block/block.js',
+ 'textgroup' => 'default',
+ 'source' => 'The changes to these blocks will not be saved until the Save blocks button is clicked.',
+ 'version' => 'none',
+))
->execute();
$connection->schema()->createTable('locales_target', array(
@@ -32562,6 +32796,384 @@
'p9' => '0',
'updated' => '0',
))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '441',
+ 'plid' => '0',
+ 'link_path' => 'forum',
+ 'router_path' => 'forum',
+ 'link_title' => 'Forums',
+ 'options' => 'a:0:{}',
+ 'module' => 'system',
+ 'hidden' => '1',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '0',
+ 'depth' => '1',
+ 'customized' => '0',
+ 'p1' => '441',
+ 'p2' => '0',
+ 'p3' => '0',
+ 'p4' => '0',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '442',
+ 'plid' => '165',
+ 'link_path' => 'admin/reports/settings',
+ 'router_path' => 'admin/reports/settings',
+ 'link_title' => 'Access log settings',
+ 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:50:"Control details about what and how your site logs.";}}',
+ 'module' => 'system',
+ 'hidden' => '0',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '3',
+ 'depth' => '3',
+ 'customized' => '0',
+ 'p1' => '144',
+ 'p2' => '165',
+ 'p3' => '442',
+ 'p4' => '0',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '443',
+ 'plid' => '158',
+ 'link_path' => 'node/add/forum',
+ 'router_path' => 'node/add/forum',
+ 'link_title' => 'Forum topic',
+ 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:85:"A forum topic is the initial post to a new discussion thread within a forum.";}}',
+ 'module' => 'system',
+ 'hidden' => '0',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '0',
+ 'depth' => '2',
+ 'customized' => '0',
+ 'p1' => '158',
+ 'p2' => '443',
+ 'p3' => '0',
+ 'p4' => '0',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '444',
+ 'plid' => '157',
+ 'link_path' => 'admin/content/forum',
+ 'router_path' => 'admin/content/forum',
+ 'link_title' => 'Forums',
+ 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:61:"Control forums and their hierarchy and change forum settings.";}}',
+ 'module' => 'system',
+ 'hidden' => '0',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '0',
+ 'depth' => '3',
+ 'customized' => '0',
+ 'p1' => '144',
+ 'p2' => '157',
+ 'p3' => '444',
+ 'p4' => '0',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '445',
+ 'plid' => '165',
+ 'link_path' => 'admin/reports/hits',
+ 'router_path' => 'admin/reports/hits',
+ 'link_title' => 'Recent hits',
+ 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:43:"View pages that have recently been visited.";}}',
+ 'module' => 'system',
+ 'hidden' => '0',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '0',
+ 'depth' => '3',
+ 'customized' => '0',
+ 'p1' => '144',
+ 'p2' => '165',
+ 'p3' => '445',
+ 'p4' => '0',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '446',
+ 'plid' => '165',
+ 'link_path' => 'admin/reports/pages',
+ 'router_path' => 'admin/reports/pages',
+ 'link_title' => 'Top pages',
+ 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:41:"View pages that have been hit frequently.";}}',
+ 'module' => 'system',
+ 'hidden' => '0',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '1',
+ 'depth' => '3',
+ 'customized' => '0',
+ 'p1' => '144',
+ 'p2' => '165',
+ 'p3' => '446',
+ 'p4' => '0',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '447',
+ 'plid' => '165',
+ 'link_path' => 'admin/reports/referrers',
+ 'router_path' => 'admin/reports/referrers',
+ 'link_title' => 'Top referrers',
+ 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:19:"View top referrers.";}}',
+ 'module' => 'system',
+ 'hidden' => '0',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '0',
+ 'depth' => '3',
+ 'customized' => '0',
+ 'p1' => '144',
+ 'p2' => '165',
+ 'p3' => '447',
+ 'p4' => '0',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '448',
+ 'plid' => '165',
+ 'link_path' => 'admin/reports/visitors',
+ 'router_path' => 'admin/reports/visitors',
+ 'link_title' => 'Top visitors',
+ 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:34:"View visitors that hit many pages.";}}',
+ 'module' => 'system',
+ 'hidden' => '0',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '2',
+ 'depth' => '3',
+ 'customized' => '0',
+ 'p1' => '144',
+ 'p2' => '165',
+ 'p3' => '448',
+ 'p4' => '0',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '449',
+ 'plid' => '165',
+ 'link_path' => 'admin/reports/access/%',
+ 'router_path' => 'admin/reports/access/%',
+ 'link_title' => 'Details',
+ 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:16:"View access log.";}}',
+ 'module' => 'system',
+ 'hidden' => '-1',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '0',
+ 'depth' => '3',
+ 'customized' => '0',
+ 'p1' => '144',
+ 'p2' => '165',
+ 'p3' => '449',
+ 'p4' => '0',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '450',
+ 'plid' => '157',
+ 'link_path' => 'admin/content/node-type/forum',
+ 'router_path' => 'admin/content/node-type/forum',
+ 'link_title' => 'Forum topic',
+ 'options' => 'a:0:{}',
+ 'module' => 'system',
+ 'hidden' => '-1',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '0',
+ 'depth' => '3',
+ 'customized' => '0',
+ 'p1' => '144',
+ 'p2' => '157',
+ 'p3' => '450',
+ 'p4' => '0',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '451',
+ 'plid' => '444',
+ 'link_path' => 'admin/content/forum/edit/%',
+ 'router_path' => 'admin/content/forum/edit/%',
+ 'link_title' => '',
+ 'options' => 'a:0:{}',
+ 'module' => 'system',
+ 'hidden' => '-1',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '0',
+ 'depth' => '4',
+ 'customized' => '0',
+ 'p1' => '144',
+ 'p2' => '157',
+ 'p3' => '444',
+ 'p4' => '451',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '452',
+ 'plid' => '0',
+ 'link_path' => 'admin/content/node-type/forum/delete',
+ 'router_path' => 'admin/content/node-type/forum/delete',
+ 'link_title' => 'Delete',
+ 'options' => 'a:0:{}',
+ 'module' => 'system',
+ 'hidden' => '-1',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '0',
+ 'depth' => '1',
+ 'customized' => '0',
+ 'p1' => '452',
+ 'p2' => '0',
+ 'p3' => '0',
+ 'p4' => '0',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '453',
+ 'plid' => '444',
+ 'link_path' => 'admin/content/forum/edit/container/%',
+ 'router_path' => 'admin/content/forum/edit/container/%',
+ 'link_title' => 'Edit container',
+ 'options' => 'a:0:{}',
+ 'module' => 'system',
+ 'hidden' => '-1',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '0',
+ 'depth' => '4',
+ 'customized' => '0',
+ 'p1' => '144',
+ 'p2' => '157',
+ 'p3' => '444',
+ 'p4' => '453',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
+->values(array(
+ 'menu_name' => 'navigation',
+ 'mlid' => '454',
+ 'plid' => '444',
+ 'link_path' => 'admin/content/forum/edit/forum/%',
+ 'router_path' => 'admin/content/forum/edit/forum/%',
+ 'link_title' => 'Edit forum',
+ 'options' => 'a:0:{}',
+ 'module' => 'system',
+ 'hidden' => '-1',
+ 'external' => '0',
+ 'has_children' => '0',
+ 'expanded' => '0',
+ 'weight' => '0',
+ 'depth' => '4',
+ 'customized' => '0',
+ 'p1' => '144',
+ 'p2' => '157',
+ 'p3' => '444',
+ 'p4' => '454',
+ 'p5' => '0',
+ 'p6' => '0',
+ 'p7' => '0',
+ 'p8' => '0',
+ 'p9' => '0',
+ 'updated' => '0',
+))
->execute();
$connection->schema()->createTable('menu_router', array(
@@ -34471,6 +35083,182 @@
'file' => 'modules/comment/comment.admin.inc',
))
->values(array(
+ 'path' => 'admin/content/forum',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"administer forums";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:1:{i:0;s:14:"forum_overview";}',
+ 'fit' => '7',
+ 'number_parts' => '3',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/content/forum',
+ 'title' => 'Forums',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '6',
+ 'block_callback' => '',
+ 'description' => 'Control forums and their hierarchy and change forum settings.',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/forum/forum.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/content/forum/add/container',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"administer forums";}',
+ 'page_callback' => 'forum_form_main',
+ 'page_arguments' => 'a:1:{i:0;s:9:"container";}',
+ 'fit' => '31',
+ 'number_parts' => '5',
+ 'tab_parent' => 'admin/content/forum',
+ 'tab_root' => 'admin/content/forum',
+ 'title' => 'Add container',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '128',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/forum/forum.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/content/forum/add/forum',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"administer forums";}',
+ 'page_callback' => 'forum_form_main',
+ 'page_arguments' => 'a:1:{i:0;s:5:"forum";}',
+ 'fit' => '31',
+ 'number_parts' => '5',
+ 'tab_parent' => 'admin/content/forum',
+ 'tab_root' => 'admin/content/forum',
+ 'title' => 'Add forum',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '128',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/forum/forum.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/content/forum/edit/%',
+ 'load_functions' => 'a:1:{i:4;s:15:"forum_term_load";}',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"administer forums";}',
+ 'page_callback' => 'forum_form_main',
+ 'page_arguments' => 'a:0:{}',
+ 'fit' => '30',
+ 'number_parts' => '5',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/content/forum/edit/%',
+ 'title' => '',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '4',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/forum/forum.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/content/forum/edit/container/%',
+ 'load_functions' => 'a:1:{i:5;s:15:"forum_term_load";}',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"administer forums";}',
+ 'page_callback' => 'forum_form_main',
+ 'page_arguments' => 'a:2:{i:0;s:9:"container";i:1;i:5;}',
+ 'fit' => '62',
+ 'number_parts' => '6',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/content/forum/edit/container/%',
+ 'title' => 'Edit container',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '4',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/forum/forum.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/content/forum/edit/forum/%',
+ 'load_functions' => 'a:1:{i:5;s:15:"forum_term_load";}',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"administer forums";}',
+ 'page_callback' => 'forum_form_main',
+ 'page_arguments' => 'a:2:{i:0;s:5:"forum";i:1;i:5;}',
+ 'fit' => '62',
+ 'number_parts' => '6',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/content/forum/edit/forum/%',
+ 'title' => 'Edit forum',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '4',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/forum/forum.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/content/forum/list',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"administer forums";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:1:{i:0;s:14:"forum_overview";}',
+ 'fit' => '15',
+ 'number_parts' => '4',
+ 'tab_parent' => 'admin/content/forum',
+ 'tab_root' => 'admin/content/forum',
+ 'title' => 'List',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '136',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '-10',
+ 'file' => 'modules/forum/forum.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/content/forum/settings',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"administer forums";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:1:{i:0;s:20:"forum_admin_settings";}',
+ 'fit' => '15',
+ 'number_parts' => '4',
+ 'tab_parent' => 'admin/content/forum',
+ 'tab_root' => 'admin/content/forum',
+ 'title' => 'Settings',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '128',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '5',
+ 'file' => 'modules/forum/forum.admin.inc',
+))
+->values(array(
'path' => 'admin/content/node',
'load_functions' => '',
'to_arg_functions' => '',
@@ -35065,6 +35853,182 @@
'file' => 'sites/all/modules/cck/includes/content.admin.inc',
))
->values(array(
+ 'path' => 'admin/content/node-type/forum',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:24:"administer content types";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:2:{i:0;s:14:"node_type_form";i:1;O:8:"stdClass":15:{s:4:"name";s:11:"Forum topic";s:6:"module";s:5:"forum";s:11:"description";s:85:"A forum topic is the initial post to a new discussion thread within a forum.";s:11:"title_label";s:7:"Subject";s:4:"type";s:5:"forum";s:9:"has_title";b:1;s:8:"has_body";b:1;s:10:"body_label";s:4:"Body";s:4:"help";s:0:"";s:14:"min_word_count";i:0;s:6:"custom";b:0;s:8:"modified";b:0;s:6:"locked";b:1;s:9:"orig_type";s:5:"forum";s:6:"is_new";b:1;}}',
+ 'fit' => '15',
+ 'number_parts' => '4',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/content/node-type/forum',
+ 'title' => 'Forum topic',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '4',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/node/content_types.inc',
+))
+->values(array(
+ 'path' => 'admin/content/node-type/forum/delete',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:24:"administer content types";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:2:{i:0;s:24:"node_type_delete_confirm";i:1;O:8:"stdClass":15:{s:4:"name";s:11:"Forum topic";s:6:"module";s:5:"forum";s:11:"description";s:85:"A forum topic is the initial post to a new discussion thread within a forum.";s:11:"title_label";s:7:"Subject";s:4:"type";s:5:"forum";s:9:"has_title";b:1;s:8:"has_body";b:1;s:10:"body_label";s:4:"Body";s:4:"help";s:0:"";s:14:"min_word_count";i:0;s:6:"custom";b:0;s:8:"modified";b:0;s:6:"locked";b:1;s:9:"orig_type";s:5:"forum";s:6:"is_new";b:1;}}',
+ 'fit' => '31',
+ 'number_parts' => '5',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/content/node-type/forum/delete',
+ 'title' => 'Delete',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '4',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/node/content_types.inc',
+))
+->values(array(
+ 'path' => 'admin/content/node-type/forum/display',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:24:"administer content types";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:2:{i:0;s:29:"content_display_overview_form";i:1;s:5:"forum";}',
+ 'fit' => '31',
+ 'number_parts' => '5',
+ 'tab_parent' => 'admin/content/node-type/forum',
+ 'tab_root' => 'admin/content/node-type/forum',
+ 'title' => 'Display fields',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '128',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '2',
+ 'file' => 'sites/all/modules/cck/includes/content.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/content/node-type/forum/display/basic',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:24:"administer content types";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:3:{i:0;s:29:"content_display_overview_form";i:1;s:5:"forum";i:2;s:5:"basic";}',
+ 'fit' => '63',
+ 'number_parts' => '6',
+ 'tab_parent' => 'admin/content/node-type/forum/display',
+ 'tab_root' => 'admin/content/node-type/forum',
+ 'title' => 'Basic',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '136',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'sites/all/modules/cck/includes/content.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/content/node-type/forum/display/print',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:24:"administer content types";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:3:{i:0;s:29:"content_display_overview_form";i:1;s:5:"forum";i:2;s:5:"print";}',
+ 'fit' => '63',
+ 'number_parts' => '6',
+ 'tab_parent' => 'admin/content/node-type/forum/display',
+ 'tab_root' => 'admin/content/node-type/forum',
+ 'title' => 'Print',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '128',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '1',
+ 'file' => 'sites/all/modules/cck/includes/content.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/content/node-type/forum/display/rss',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:24:"administer content types";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:3:{i:0;s:29:"content_display_overview_form";i:1;s:5:"forum";i:2;s:3:"rss";}',
+ 'fit' => '63',
+ 'number_parts' => '6',
+ 'tab_parent' => 'admin/content/node-type/forum/display',
+ 'tab_root' => 'admin/content/node-type/forum',
+ 'title' => 'RSS',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '128',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '1',
+ 'file' => 'sites/all/modules/cck/includes/content.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/content/node-type/forum/edit',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:24:"administer content types";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:2:{i:0;s:14:"node_type_form";i:1;O:8:"stdClass":15:{s:4:"name";s:11:"Forum topic";s:6:"module";s:5:"forum";s:11:"description";s:85:"A forum topic is the initial post to a new discussion thread within a forum.";s:11:"title_label";s:7:"Subject";s:4:"type";s:5:"forum";s:9:"has_title";b:1;s:8:"has_body";b:1;s:10:"body_label";s:4:"Body";s:4:"help";s:0:"";s:14:"min_word_count";i:0;s:6:"custom";b:0;s:8:"modified";b:0;s:6:"locked";b:1;s:9:"orig_type";s:5:"forum";s:6:"is_new";b:1;}}',
+ 'fit' => '31',
+ 'number_parts' => '5',
+ 'tab_parent' => 'admin/content/node-type/forum',
+ 'tab_root' => 'admin/content/node-type/forum',
+ 'title' => 'Edit',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '136',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/node/content_types.inc',
+))
+->values(array(
+ 'path' => 'admin/content/node-type/forum/fields',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:24:"administer content types";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:2:{i:0;s:27:"content_field_overview_form";i:1;s:5:"forum";}',
+ 'fit' => '31',
+ 'number_parts' => '5',
+ 'tab_parent' => 'admin/content/node-type/forum',
+ 'tab_root' => 'admin/content/node-type/forum',
+ 'title' => 'Manage fields',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '128',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '1',
+ 'file' => 'sites/all/modules/cck/includes/content.admin.inc',
+))
+->values(array(
'path' => 'admin/content/node-type/sponsor',
'load_functions' => '',
'to_arg_functions' => '',
@@ -37485,6 +38449,116 @@
'file' => 'modules/system/system.admin.inc',
))
->values(array(
+ 'path' => 'admin/reports/access/%',
+ 'load_functions' => 'a:1:{i:3;N;}',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"access statistics";}',
+ 'page_callback' => 'statistics_access_log',
+ 'page_arguments' => 'a:1:{i:0;i:3;}',
+ 'fit' => '14',
+ 'number_parts' => '4',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/reports/access/%',
+ 'title' => 'Details',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '4',
+ 'block_callback' => '',
+ 'description' => 'View access log.',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/statistics/statistics.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/reports/hits',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"access statistics";}',
+ 'page_callback' => 'statistics_recent_hits',
+ 'page_arguments' => 'a:0:{}',
+ 'fit' => '7',
+ 'number_parts' => '3',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/reports/hits',
+ 'title' => 'Recent hits',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '6',
+ 'block_callback' => '',
+ 'description' => 'View pages that have recently been visited.',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/statistics/statistics.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/reports/pages',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"access statistics";}',
+ 'page_callback' => 'statistics_top_pages',
+ 'page_arguments' => 'a:0:{}',
+ 'fit' => '7',
+ 'number_parts' => '3',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/reports/pages',
+ 'title' => 'Top pages',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '6',
+ 'block_callback' => '',
+ 'description' => 'View pages that have been hit frequently.',
+ 'position' => '',
+ 'weight' => '1',
+ 'file' => 'modules/statistics/statistics.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/reports/referrers',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"access statistics";}',
+ 'page_callback' => 'statistics_top_referrers',
+ 'page_arguments' => 'a:0:{}',
+ 'fit' => '7',
+ 'number_parts' => '3',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/reports/referrers',
+ 'title' => 'Top referrers',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '6',
+ 'block_callback' => '',
+ 'description' => 'View top referrers.',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/statistics/statistics.admin.inc',
+))
+->values(array(
+ 'path' => 'admin/reports/settings',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:29:"administer site configuration";}',
+ 'page_callback' => 'drupal_get_form',
+ 'page_arguments' => 'a:1:{i:0;s:34:"statistics_access_logging_settings";}',
+ 'fit' => '7',
+ 'number_parts' => '3',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/reports/settings',
+ 'title' => 'Access log settings',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '6',
+ 'block_callback' => '',
+ 'description' => 'Control details about what and how your site logs.',
+ 'position' => '',
+ 'weight' => '3',
+ 'file' => 'modules/statistics/statistics.admin.inc',
+))
+->values(array(
'path' => 'admin/reports/status',
'load_functions' => '',
'to_arg_functions' => '',
@@ -37573,6 +38647,28 @@
'file' => 'modules/system/system.admin.inc',
))
->values(array(
+ 'path' => 'admin/reports/visitors',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"access statistics";}',
+ 'page_callback' => 'statistics_top_visitors',
+ 'page_arguments' => 'a:0:{}',
+ 'fit' => '7',
+ 'number_parts' => '3',
+ 'tab_parent' => '',
+ 'tab_root' => 'admin/reports/visitors',
+ 'title' => 'Top visitors',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '6',
+ 'block_callback' => '',
+ 'description' => 'View visitors that hit many pages.',
+ 'position' => '',
+ 'weight' => '2',
+ 'file' => 'modules/statistics/statistics.admin.inc',
+))
+->values(array(
'path' => 'admin/settings',
'load_functions' => '',
'to_arg_functions' => '',
@@ -39971,6 +41067,28 @@
'file' => 'modules/filter/filter.pages.inc',
))
->values(array(
+ 'path' => 'forum',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:14:"access content";}',
+ 'page_callback' => 'forum_page',
+ 'page_arguments' => 'a:0:{}',
+ 'fit' => '1',
+ 'number_parts' => '1',
+ 'tab_parent' => '',
+ 'tab_root' => 'forum',
+ 'title' => 'Forums',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '20',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/forum/forum.pages.inc',
+))
+->values(array(
'path' => 'i18n/node/autocomplete',
'load_functions' => '',
'to_arg_functions' => '',
@@ -40279,6 +41397,28 @@
'file' => '',
))
->values(array(
+ 'path' => 'node/%/track',
+ 'load_functions' => 'a:1:{i:1;s:9:"node_load";}',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"access statistics";}',
+ 'page_callback' => 'statistics_node_tracker',
+ 'page_arguments' => 'a:0:{}',
+ 'fit' => '5',
+ 'number_parts' => '3',
+ 'tab_parent' => 'node/%',
+ 'tab_root' => 'node/%',
+ 'title' => 'Track',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '128',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '2',
+ 'file' => 'modules/statistics/statistics.pages.inc',
+))
+->values(array(
'path' => 'node/%/translate',
'load_functions' => 'a:1:{i:1;s:9:"node_load";}',
'to_arg_functions' => '',
@@ -40411,6 +41551,28 @@
'file' => 'modules/node/node.pages.inc',
))
->values(array(
+ 'path' => 'node/add/forum',
+ 'load_functions' => '',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'node_access',
+ 'access_arguments' => 'a:2:{i:0;s:6:"create";i:1;s:5:"forum";}',
+ 'page_callback' => 'i18ncontent_node_add',
+ 'page_arguments' => 'a:1:{i:0;i:2;}',
+ 'fit' => '7',
+ 'number_parts' => '3',
+ 'tab_parent' => '',
+ 'tab_root' => 'node/add/forum',
+ 'title' => 'Forum topic',
+ 'title_callback' => 'i18nstrings_title_callback',
+ 'title_arguments' => 'a:2:{i:0;s:24:"nodetype:type:forum:name";i:1;s:11:"Forum topic";}',
+ 'type' => '6',
+ 'block_callback' => '',
+ 'description' => 'A forum topic is the initial post to a new discussion thread within a forum.',
+ 'position' => '',
+ 'weight' => '0',
+ 'file' => 'modules/node/node.pages.inc',
+))
+->values(array(
'path' => 'node/add/sponsor',
'load_functions' => '',
'to_arg_functions' => '',
@@ -40917,6 +42079,28 @@
'file' => 'modules/user/user.pages.inc',
))
->values(array(
+ 'path' => 'user/%/track/navigation',
+ 'load_functions' => 'a:1:{i:1;s:9:"user_load";}',
+ 'to_arg_functions' => '',
+ 'access_callback' => 'user_access',
+ 'access_arguments' => 'a:1:{i:0;s:17:"access statistics";}',
+ 'page_callback' => 'statistics_user_tracker',
+ 'page_arguments' => 'a:0:{}',
+ 'fit' => '11',
+ 'number_parts' => '4',
+ 'tab_parent' => 'user/%',
+ 'tab_root' => 'user/%',
+ 'title' => 'Track page visits',
+ 'title_callback' => 't',
+ 'title_arguments' => '',
+ 'type' => '128',
+ 'block_callback' => '',
+ 'description' => '',
+ 'position' => '',
+ 'weight' => '2',
+ 'file' => 'modules/statistics/statistics.pages.inc',
+))
+->values(array(
'path' => 'user/%/view',
'load_functions' => 'a:1:{i:1;s:9:"user_load";}',
'to_arg_functions' => '',
@@ -42036,6 +43220,22 @@
'orig_type' => 'event',
))
->values(array(
+ 'type' => 'forum',
+ 'name' => 'Forum topic',
+ 'module' => 'forum',
+ 'description' => 'A forum topic is the initial post to a new discussion thread within a forum.',
+ 'help' => '',
+ 'has_title' => '1',
+ 'title_label' => 'Subject',
+ 'has_body' => '1',
+ 'body_label' => 'Body',
+ 'min_word_count' => '0',
+ 'custom' => '0',
+ 'modified' => '0',
+ 'locked' => '1',
+ 'orig_type' => 'forum',
+))
+->values(array(
'type' => 'page',
'name' => 'Page',
'module' => 'node',
@@ -42855,7 +44055,7 @@
'bootstrap' => '0',
'schema_version' => '6001',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:10:"Aggregator";s:11:"description";s:57:"Aggregates syndicated content (RSS, RDF, and Atom feeds).";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:10:"Aggregator";s:11:"description";s:57:"Aggregates syndicated content (RSS, RDF, and Atom feeds).";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/block/block.module',
@@ -42867,7 +44067,7 @@
'bootstrap' => '0',
'schema_version' => '0',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:5:"Block";s:11:"description";s:62:"Controls the boxes that are displayed around the main content.";s:7:"package";s:15:"Core - required";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:5:"Block";s:11:"description";s:62:"Controls the boxes that are displayed around the main content.";s:7:"package";s:15:"Core - required";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/blog/blog.module',
@@ -42879,7 +44079,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:4:"Blog";s:11:"description";s:69:"Enables keeping easily and regularly updated user web pages or blogs.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:4:"Blog";s:11:"description";s:69:"Enables keeping easily and regularly updated user web pages or blogs.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/blogapi/blogapi.module',
@@ -42891,7 +44091,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:8:"Blog API";s:11:"description";s:79:"Allows users to post content using applications that support XML-RPC blog APIs.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:8:"Blog API";s:11:"description";s:79:"Allows users to post content using applications that support XML-RPC blog APIs.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/book/book.module',
@@ -42903,7 +44103,7 @@
'bootstrap' => '0',
'schema_version' => '6000',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:4:"Book";s:11:"description";s:63:"Allows users to structure site pages in a hierarchy or outline.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:4:"Book";s:11:"description";s:63:"Allows users to structure site pages in a hierarchy or outline.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/color/color.module',
@@ -42915,7 +44115,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:5:"Color";s:11:"description";s:61:"Allows the user to change the color scheme of certain themes.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:5:"Color";s:11:"description";s:61:"Allows the user to change the color scheme of certain themes.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/comment/comment.module',
@@ -42927,7 +44127,7 @@
'bootstrap' => '0',
'schema_version' => '6005',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:7:"Comment";s:11:"description";s:57:"Allows users to comment on and discuss published content.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:7:"Comment";s:11:"description";s:57:"Allows users to comment on and discuss published content.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/contact/contact.module',
@@ -42939,7 +44139,7 @@
'bootstrap' => '0',
'schema_version' => '6001',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:7:"Contact";s:11:"description";s:61:"Enables the use of both personal and site-wide contact forms.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:7:"Contact";s:11:"description";s:61:"Enables the use of both personal and site-wide contact forms.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/dblog/dblog.module',
@@ -42951,7 +44151,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:16:"Database logging";s:11:"description";s:47:"Logs and records system events to the database.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:16:"Database logging";s:11:"description";s:47:"Logs and records system events to the database.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/filter/filter.module',
@@ -42963,19 +44163,19 @@
'bootstrap' => '0',
'schema_version' => '0',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:6:"Filter";s:11:"description";s:60:"Handles the filtering of content in preparation for display.";s:7:"package";s:15:"Core - required";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:6:"Filter";s:11:"description";s:60:"Handles the filtering of content in preparation for display.";s:7:"package";s:15:"Core - required";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/forum/forum.module',
'name' => 'forum',
'type' => 'module',
'owner' => '',
- 'status' => '0',
+ 'status' => '1',
'throttle' => '0',
'bootstrap' => '0',
- 'schema_version' => '-1',
- 'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:5:"Forum";s:11:"description";s:50:"Enables threaded discussions about general topics.";s:12:"dependencies";a:2:{i:0;s:8:"taxonomy";i:1;s:7:"comment";}s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'schema_version' => '6000',
+ 'weight' => '1',
+ 'info' => 'a:8:{s:4:"name";s:5:"Forum";s:11:"description";s:50:"Enables threaded discussions about general topics.";s:12:"dependencies";a:2:{i:0;s:8:"taxonomy";i:1;s:7:"comment";}s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/help/help.module',
@@ -42987,7 +44187,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:4:"Help";s:11:"description";s:35:"Manages the display of online help.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:4:"Help";s:11:"description";s:35:"Manages the display of online help.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/locale/locale.module',
@@ -42999,7 +44199,7 @@
'bootstrap' => '0',
'schema_version' => '6007',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:6:"Locale";s:11:"description";s:119:"Adds language handling functionality and enables the translation of the user interface to languages other than English.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:6:"Locale";s:11:"description";s:119:"Adds language handling functionality and enables the translation of the user interface to languages other than English.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/menu/menu.module',
@@ -43011,7 +44211,7 @@
'bootstrap' => '0',
'schema_version' => '6000',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:4:"Menu";s:11:"description";s:60:"Allows administrators to customize the site navigation menu.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:4:"Menu";s:11:"description";s:60:"Allows administrators to customize the site navigation menu.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/node/node.module',
@@ -43023,7 +44223,7 @@
'bootstrap' => '0',
'schema_version' => '0',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:4:"Node";s:11:"description";s:66:"Allows content to be submitted to the site and displayed on pages.";s:7:"package";s:15:"Core - required";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:4:"Node";s:11:"description";s:66:"Allows content to be submitted to the site and displayed on pages.";s:7:"package";s:15:"Core - required";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/openid/openid.module',
@@ -43035,7 +44235,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:6:"OpenID";s:11:"description";s:48:"Allows users to log into your site using OpenID.";s:7:"version";s:8:"6.38-dev";s:7:"package";s:15:"Core - optional";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:6:"OpenID";s:11:"description";s:48:"Allows users to log into your site using OpenID.";s:7:"version";s:4:"6.38";s:7:"package";s:15:"Core - optional";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/path/path.module',
@@ -43047,7 +44247,7 @@
'bootstrap' => '0',
'schema_version' => '0',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:4:"Path";s:11:"description";s:28:"Allows users to rename URLs.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:4:"Path";s:11:"description";s:28:"Allows users to rename URLs.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/php/php.module',
@@ -43059,7 +44259,7 @@
'bootstrap' => '0',
'schema_version' => '0',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:10:"PHP filter";s:11:"description";s:50:"Allows embedded PHP code/snippets to be evaluated.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:10:"PHP filter";s:11:"description";s:50:"Allows embedded PHP code/snippets to be evaluated.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/ping/ping.module',
@@ -43071,7 +44271,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:4:"Ping";s:11:"description";s:51:"Alerts other sites when your site has been updated.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:4:"Ping";s:11:"description";s:51:"Alerts other sites when your site has been updated.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/poll/poll.module',
@@ -43083,7 +44283,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:4:"Poll";s:11:"description";s:95:"Allows your site to capture votes on different topics in the form of multiple choice questions.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:4:"Poll";s:11:"description";s:95:"Allows your site to capture votes on different topics in the form of multiple choice questions.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/profile/profile.module',
@@ -43095,7 +44295,7 @@
'bootstrap' => '0',
'schema_version' => '6001',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:7:"Profile";s:11:"description";s:36:"Supports configurable user profiles.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:7:"Profile";s:11:"description";s:36:"Supports configurable user profiles.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/search/search.module',
@@ -43107,19 +44307,19 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:6:"Search";s:11:"description";s:36:"Enables site-wide keyword searching.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:6:"Search";s:11:"description";s:36:"Enables site-wide keyword searching.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/statistics/statistics.module',
'name' => 'statistics',
'type' => 'module',
'owner' => '',
- 'status' => '0',
+ 'status' => '1',
'throttle' => '0',
- 'bootstrap' => '0',
- 'schema_version' => '-1',
+ 'bootstrap' => '1',
+ 'schema_version' => '6000',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:10:"Statistics";s:11:"description";s:37:"Logs access statistics for your site.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:10:"Statistics";s:11:"description";s:37:"Logs access statistics for your site.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/syslog/syslog.module',
@@ -43131,7 +44331,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:6:"Syslog";s:11:"description";s:41:"Logs and records system events to syslog.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:6:"Syslog";s:11:"description";s:41:"Logs and records system events to syslog.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/system/system.module',
@@ -43143,7 +44343,7 @@
'bootstrap' => '0',
'schema_version' => '6055',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:6:"System";s:11:"description";s:54:"Handles general site configuration for administrators.";s:7:"package";s:15:"Core - required";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:6:"System";s:11:"description";s:54:"Handles general site configuration for administrators.";s:7:"package";s:15:"Core - required";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/taxonomy/taxonomy.module',
@@ -43155,7 +44355,7 @@
'bootstrap' => '0',
'schema_version' => '6001',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:8:"Taxonomy";s:11:"description";s:38:"Enables the categorization of content.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:8:"Taxonomy";s:11:"description";s:38:"Enables the categorization of content.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/throttle/throttle.module',
@@ -43167,7 +44367,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:8:"Throttle";s:11:"description";s:66:"Handles the auto-throttling mechanism, to control site congestion.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:8:"Throttle";s:11:"description";s:66:"Handles the auto-throttling mechanism, to control site congestion.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/tracker/tracker.module',
@@ -43179,7 +44379,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:7:"Tracker";s:11:"description";s:43:"Enables tracking of recent posts for users.";s:12:"dependencies";a:1:{i:0;s:7:"comment";}s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:7:"Tracker";s:11:"description";s:43:"Enables tracking of recent posts for users.";s:12:"dependencies";a:1:{i:0;s:7:"comment";}s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/translation/translation.module',
@@ -43191,7 +44391,7 @@
'bootstrap' => '0',
'schema_version' => '0',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:19:"Content translation";s:11:"description";s:57:"Allows content to be translated into different languages.";s:12:"dependencies";a:1:{i:0;s:6:"locale";}s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:19:"Content translation";s:11:"description";s:57:"Allows content to be translated into different languages.";s:12:"dependencies";a:1:{i:0;s:6:"locale";}s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/trigger/trigger.module',
@@ -43203,7 +44403,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:7:"Trigger";s:11:"description";s:90:"Enables actions to be fired on certain system events, such as when new content is created.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:7:"Trigger";s:11:"description";s:90:"Enables actions to be fired on certain system events, such as when new content is created.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/update/update.module',
@@ -43215,7 +44415,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:13:"Update status";s:11:"description";s:88:"Checks the status of available updates for Drupal and your installed modules and themes.";s:7:"version";s:8:"6.38-dev";s:7:"package";s:15:"Core - optional";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:13:"Update status";s:11:"description";s:88:"Checks the status of available updates for Drupal and your installed modules and themes.";s:7:"version";s:4:"6.38";s:7:"package";s:15:"Core - optional";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/upload/upload.module',
@@ -43227,7 +44427,7 @@
'bootstrap' => '0',
'schema_version' => '6000',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:6:"Upload";s:11:"description";s:51:"Allows users to upload and attach files to content.";s:7:"package";s:15:"Core - optional";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:6:"Upload";s:11:"description";s:51:"Allows users to upload and attach files to content.";s:7:"package";s:15:"Core - optional";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'modules/user/user.module',
@@ -43239,7 +44439,7 @@
'bootstrap' => '0',
'schema_version' => '0',
'weight' => '0',
- 'info' => 'a:8:{s:4:"name";s:4:"User";s:11:"description";s:47:"Manages the user registration and login system.";s:7:"package";s:15:"Core - required";s:7:"version";s:8:"6.38-dev";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:8:{s:4:"name";s:4:"User";s:11:"description";s:47:"Manages the user registration and login system.";s:7:"package";s:15:"Core - required";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'sites/all/modules/cck/content.module',
@@ -43266,6 +44466,18 @@
'info' => 'a:10:{s:4:"name";s:12:"Content Copy";s:11:"description";s:51:"Enables ability to import/export field definitions.";s:12:"dependencies";a:1:{i:0;s:7:"content";}s:7:"package";s:3:"CCK";s:4:"core";s:3:"6.x";s:7:"version";s:7:"6.x-2.9";s:7:"project";s:3:"cck";s:9:"datestamp";s:10:"1294407979";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
+ 'filename' => 'sites/all/modules/cck/modules/content_multigroup/content_multigroup.module',
+ 'name' => 'content_multigroup',
+ 'type' => 'module',
+ 'owner' => '',
+ 'status' => '0',
+ 'throttle' => '0',
+ 'bootstrap' => '0',
+ 'schema_version' => '-1',
+ 'weight' => '0',
+ 'info' => 'a:10:{s:4:"name";s:18:"Content Multigroup";s:11:"description";s:81:"Combine multiple CCK fields into repeating field collections that work in unison.";s:12:"dependencies";a:2:{i:0;s:7:"content";i:1;s:10:"fieldgroup";}s:7:"package";s:3:"CCK";s:4:"core";s:3:"6.x";s:7:"version";s:20:"6.x-3.0-alpha4+0-dev";s:7:"project";s:3:"cck";s:9:"datestamp";s:10:"1435195093";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+))
+->values(array(
'filename' => 'sites/all/modules/cck/modules/content_permissions/content_permissions.module',
'name' => 'content_permissions',
'type' => 'module',
@@ -43350,6 +44562,18 @@
'info' => 'a:10:{s:4:"name";s:14:"User Reference";s:11:"description";s:56:"Defines a field type for referencing a user from a node.";s:12:"dependencies";a:3:{i:0;s:7:"content";i:1;s:4:"text";i:2;s:13:"optionwidgets";}s:7:"package";s:3:"CCK";s:4:"core";s:3:"6.x";s:7:"version";s:7:"6.x-2.9";s:7:"project";s:3:"cck";s:9:"datestamp";s:10:"1294407979";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
+ 'filename' => 'sites/all/modules/cck/tests/content_test.module',
+ 'name' => 'content_test',
+ 'type' => 'module',
+ 'owner' => '',
+ 'status' => '0',
+ 'throttle' => '0',
+ 'bootstrap' => '0',
+ 'schema_version' => '-1',
+ 'weight' => '0',
+ 'info' => 'a:12:{s:4:"name";s:12:"Content Test";s:11:"description";s:20:"Test module for CCK.";s:7:"package";s:3:"CCK";s:4:"core";s:3:"6.x";s:12:"dependencies";a:1:{i:0;s:6:"schema";}s:6:"hidden";b:1;s:5:"files";a:1:{i:0;s:19:"content_test.module";}s:7:"version";s:20:"6.x-3.0-alpha4+0-dev";s:7:"project";s:3:"cck";s:9:"datestamp";s:10:"1435195093";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
+))
+->values(array(
'filename' => 'sites/all/modules/date/date/date.module',
'name' => 'date',
'type' => 'module',
@@ -43770,6 +44994,18 @@
'info' => 'a:10:{s:4:"name";s:10:"ImageField";s:11:"description";s:28:"Defines an image field type.";s:4:"core";s:3:"6.x";s:12:"dependencies";a:2:{i:0;s:7:"content";i:1;s:9:"filefield";}s:7:"package";s:3:"CCK";s:7:"version";s:8:"6.x-3.11";s:7:"project";s:10:"imagefield";s:9:"datestamp";s:10:"1365969012";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
+ 'filename' => 'sites/all/modules/jquery_ui/jquery_ui.module',
+ 'name' => 'jquery_ui',
+ 'type' => 'module',
+ 'owner' => '',
+ 'status' => '0',
+ 'throttle' => '0',
+ 'bootstrap' => '0',
+ 'schema_version' => '-1',
+ 'weight' => '0',
+ 'info' => 'a:8:{s:4:"name";s:9:"jQuery UI";s:11:"description";s:55:"Provides the jQuery UI plug-in to other Drupal modules.";s:7:"package";s:14:"User interface";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:7:"version";N;s:3:"php";s:5:"4.3.5";}',
+))
+->values(array(
'filename' => 'sites/all/modules/link/link.module',
'name' => 'link',
'type' => 'module',
@@ -43815,7 +45051,7 @@
'bootstrap' => '0',
'schema_version' => '-1',
'weight' => '0',
- 'info' => 'a:7:{s:4:"name";s:12:"Variable API";s:11:"description";s:12:"Variable API";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:7:"version";N;s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:9:{s:4:"name";s:12:"Variable API";s:11:"description";s:12:"Variable API";s:4:"core";s:3:"6.x";s:7:"version";s:14:"6.x-1.0-alpha1";s:7:"project";s:8:"variable";s:9:"datestamp";s:10:"1414059742";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'sites/all/modules/variable/variable_admin/variable_admin.module',
@@ -43827,7 +45063,7 @@
'bootstrap' => '0',
'schema_version' => '0',
'weight' => '0',
- 'info' => 'a:7:{s:4:"name";s:14:"Variable admin";s:11:"description";s:23:"Variable API - Admin UI";s:4:"core";s:3:"6.x";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:7:"version";N;s:3:"php";s:5:"4.3.5";}',
+ 'info' => 'a:9:{s:4:"name";s:14:"Variable admin";s:11:"description";s:23:"Variable API - Admin UI";s:4:"core";s:3:"6.x";s:7:"version";s:14:"6.x-1.0-alpha1";s:7:"project";s:8:"variable";s:9:"datestamp";s:10:"1414059742";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
))
->values(array(
'filename' => 'sites/all/modules/views/tests/views_test.module',
@@ -44613,8 +45849,8 @@
'signature' => '',
'signature_format' => '0',
'created' => '0',
- 'access' => '1468384823',
- 'login' => '1468384420',
+ 'access' => '1467889223',
+ 'login' => '1467886039',
'status' => '1',
'timezone' => NULL,
'language' => '',
@@ -44903,7 +46139,7 @@
))
->values(array(
'name' => 'book_block_mode',
- 'value' => 's:9:"all pages";',
+ 'value' => 's:10:"book pages";',
))
->values(array(
'name' => 'book_child_type',
@@ -45651,11 +46887,11 @@
))
->values(array(
'name' => 'forum_block_num_0',
- 'value' => 's:1:"5";',
+ 'value' => 's:1:"3";',
))
->values(array(
'name' => 'forum_block_num_1',
- 'value' => 's:1:"5";',
+ 'value' => 's:1:"4";',
))
->values(array(
'name' => 'forum_hot_topic',
@@ -45678,6 +46914,10 @@
'value' => 'a:2:{i:0;i:1;i:1;i:2;}',
))
->values(array(
+ 'name' => 'i18n_lock_node_article',
+ 'value' => 'i:1;',
+))
+->values(array(
'name' => 'image_jpeg_quality',
'value' => 'i:75;',
))
@@ -45687,7 +46927,7 @@
))
->values(array(
'name' => 'javascript_parsed',
- 'value' => 'a:21:{i:0;s:14:"misc/jquery.js";i:1;s:14:"misc/drupal.js";i:2;s:19:"misc/tableheader.js";i:3;s:16:"misc/collapse.js";i:4;s:16:"misc/textarea.js";i:5;s:20:"modules/user/user.js";i:6;s:17:"misc/tabledrag.js";i:7;s:26:"modules/profile/profile.js";i:8;s:12:"misc/form.js";i:9;s:19:"misc/tableselect.js";i:10;s:20:"misc/autocomplete.js";s:10:"refresh:ga";s:7:"waiting";s:10:"refresh:ab";s:7:"waiting";s:10:"refresh:ca";s:7:"waiting";s:10:"refresh:fi";s:7:"waiting";s:10:"refresh:es";s:7:"waiting";i:11;s:16:"misc/progress.js";i:12;s:13:"misc/batch.js";s:10:"refresh:nl";s:7:"waiting";s:10:"refresh:de";s:7:"waiting";s:10:"refresh:pl";s:7:"waiting";}',
+ 'value' => 'a:9:{i:0;s:14:"misc/jquery.js";i:1;s:14:"misc/drupal.js";i:2;s:19:"misc/tableheader.js";i:3;s:16:"misc/collapse.js";s:10:"refresh:fr";s:7:"waiting";s:10:"refresh:zu";s:7:"waiting";i:4;s:17:"misc/tabledrag.js";i:5;s:22:"modules/block/block.js";i:6;s:16:"misc/textarea.js";}',
))
->values(array(
'name' => 'language_content_type_article',
@@ -45698,10 +46938,6 @@
'value' => 's:1:"2";',
))
->values(array(
- 'name' => 'i18n_lock_node_article',
- 'value' => 'i:1;',
-))
-->values(array(
'name' => 'language_count',
'value' => 'i:11;',
))
@@ -45875,27 +47111,27 @@
))
->values(array(
'name' => 'statistics_block_top_all_num',
- 'value' => 'i:0;',
+ 'value' => 's:1:"8";',
))
->values(array(
'name' => 'statistics_block_top_day_num',
- 'value' => 'i:0;',
+ 'value' => 's:1:"7";',
))
->values(array(
'name' => 'statistics_block_top_last_num',
- 'value' => 'i:0;',
+ 'value' => 's:1:"9";',
))
->values(array(
'name' => 'statistics_count_content_views',
- 'value' => 'i:0;',
+ 'value' => 's:1:"1";',
))
->values(array(
'name' => 'statistics_enable_access_log',
- 'value' => 'i:0;',
+ 'value' => 's:1:"0";',
))
->values(array(
'name' => 'statistics_flush_accesslog_timer',
- 'value' => 'i:259200;',
+ 'value' => 's:6:"259200";',
))
->values(array(
'name' => 'syslog_facility',
@@ -46280,6 +47516,10 @@
'type' => 'article',
))
->values(array(
+ 'vid' => '1',
+ 'type' => 'forum',
+))
+->values(array(
'vid' => '4',
'type' => 'page',
))
diff --git a/core/modules/migrate_drupal/tests/fixtures/drupal7.php b/core/modules/migrate_drupal/tests/fixtures/drupal7.php
index 8c96dae..1831171 100644
--- a/core/modules/migrate_drupal/tests/fixtures/drupal7.php
+++ b/core/modules/migrate_drupal/tests/fixtures/drupal7.php
@@ -42953,6 +42953,15 @@
'module' => 'taxonomy',
'weight' => '0',
))
+->values(array(
+ 'vid' => '4',
+ 'name' => 'vocabulary name much longer than thirty two characters',
+ 'machine_name' => 'vocabulary_name_much_longer_than_thirty_two_characters',
+ 'description' => 'description of vocabulary name much longer than thirty two characters',
+ 'hierarchy' => '1',
+ 'module' => 'taxonomy',
+ 'weight' => '0',
+))
->execute();
$connection->schema()->createTable('tracker_node', array(
diff --git a/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/migrate_field_plugin_manager_test.info.yml b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/migrate_field_plugin_manager_test.info.yml
new file mode 100644
index 0000000..db67a4f
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/migrate_field_plugin_manager_test.info.yml
@@ -0,0 +1,6 @@
+name: 'Migrate field plugin manager test'
+type: module
+description: 'Example module demonstrating the field plugin manager in the Migrate API.'
+package: Testing
+version: VERSION
+core: 8.x
diff --git a/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/migrate_field_plugin_manager_test.module b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/migrate_field_plugin_manager_test.module
new file mode 100644
index 0000000..9f9da0d
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/migrate_field_plugin_manager_test.module
@@ -0,0 +1,14 @@
+mergeProcessOfProperty($field_name, [
+ 'class' => __CLASS__,
+ ]);
+ }
+
+}
diff --git a/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6FileField.php b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6FileField.php
new file mode 100644
index 0000000..08ca88c
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6FileField.php
@@ -0,0 +1,31 @@
+container
+ ->get('plugin.manager.migration')
+ ->getDefinition('d6_node:story');
+
+ $this->assertSame(FileField::class, $migration['process']['field_test_filefield']['class']);
+ }
+
+}
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/MigrateFieldPluginManagerTest.php b/core/modules/migrate_drupal/tests/src/Kernel/MigrateFieldPluginManagerTest.php
new file mode 100644
index 0000000..7c3c5a4
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/src/Kernel/MigrateFieldPluginManagerTest.php
@@ -0,0 +1,51 @@
+container->get('plugin.manager.migrate.field');
+
+ try {
+ // If this test passes, getPluginIdFromFieldType will raise a
+ // PluginNotFoundException and we'll never reach fail().
+ $plugin_manager->getPluginIdFromFieldType('filefield', ['core' => 7]);
+ $this->fail('Expected Drupal\Component\Plugin\Exception\PluginNotFoundException.');
+ }
+ catch (PluginNotFoundException $e) {
+ $this->assertIdentical($e->getMessage(), "Plugin ID 'filefield' was not found.");
+ }
+
+ $this->assertIdentical('d6_file', $plugin_manager->getPluginIdFromFieldType('file', ['core' => 6]));
+
+ // Test fallback when no core version is specified.
+ $this->assertIdentical('d6_no_core_version_specified', $plugin_manager->getPluginIdFromFieldType('d6_no_core_version_specified', ['core' => 6]));
+
+ try {
+ // If this test passes, getPluginIdFromFieldType will raise a
+ // PluginNotFoundException and we'll never reach fail().
+ $plugin_manager->getPluginIdFromFieldType('d6_no_core_version_specified', ['core' => 7]);
+ $this->fail('Expected Drupal\Component\Plugin\Exception\PluginNotFoundException.');
+ }
+ catch (PluginNotFoundException $e) {
+ $this->assertIdentical($e->getMessage(), "Plugin ID 'd6_no_core_version_specified' was not found.");
+ }
+ }
+
+}
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/VariableMultiRowTest.php b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/VariableMultiRowTest.php
new file mode 100644
index 0000000..932af99
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/VariableMultiRowTest.php
@@ -0,0 +1,57 @@
+ 'foo', 'value' => 'i:1;'],
+ ['name' => 'bar', 'value' => 'b:0;'],
+ ];
+
+ // The expected results.
+ $tests[0]['expected_data'] = [
+ [
+ 'name' => 'foo',
+ 'value' => 1,
+ ],
+ [
+ 'name' => 'bar',
+ 'value' => FALSE,
+ ],
+ ];
+
+ // The expected count.
+ $tests[0]['expected_count'] = NULL;
+
+ // The source plugin configuration.
+ $tests[0]['configuration']['variables'] = [
+ 'foo',
+ 'bar',
+ ];
+
+ return $tests;
+ }
+
+}
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/VariableTest.php b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/VariableTest.php
new file mode 100644
index 0000000..b68c4b4
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/VariableTest.php
@@ -0,0 +1,54 @@
+ 'foo', 'value' => 'i:1;'],
+ ['name' => 'bar', 'value' => 'b:0;'],
+ ];
+
+ // The expected results.
+ $tests[0]['expected_data'] = [
+ [
+ 'id' => 'foo',
+ 'foo' => 1,
+ 'bar' => FALSE,
+ ],
+ ];
+
+ // The expected count.
+ $tests[0]['expected_count'] = NULL;
+
+ // The source plugin configuration.
+ $tests[0]['configuration']['variables'] = [
+ 'foo',
+ 'bar',
+ ];
+
+ return $tests;
+ }
+
+}
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d6/i18nVariableTest.php b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d6/i18nVariableTest.php
new file mode 100644
index 0000000..8c3e604
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d6/i18nVariableTest.php
@@ -0,0 +1,77 @@
+ 'site_slogan',
+ 'language' => 'fr',
+ 'value' => 's:19:"Migrate est génial";',
+ ],
+ [
+ 'name' => 'site_name',
+ 'language' => 'fr',
+ 'value' => 's:11:"nom de site";',
+ ],
+ [
+ 'name' => 'site_slogan',
+ 'language' => 'mi',
+ 'value' => 's:19:"Ko whakamataku heke";',
+ ],
+ [
+ 'name' => 'site_name',
+ 'language' => 'mi',
+ 'value' => 's:9:"ingoa_pae";',
+ ],
+ ];
+
+ // The expected results.
+ $tests[0]['expected_data'] = [
+ [
+ 'language' => 'fr',
+ 'site_slogan' => 'Migrate est génial',
+ 'site_name' => 'nom de site',
+ ],
+ [
+ 'language' => 'mi',
+ 'site_slogan' => 'Ko whakamataku heke',
+ 'site_name' => 'ingoa_pae',
+ ],
+ ];
+
+ // The expected count.
+ $tests[0]['expected_count'] = NULL;
+
+ // The migration configuration.
+ $tests[0]['configuration']['variables'] = [
+ 'site_slogan',
+ 'site_name',
+ ];
+
+ return $tests;
+ }
+
+}
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/dependencies/MigrateDependenciesTest.php b/core/modules/migrate_drupal/tests/src/Kernel/dependencies/MigrateDependenciesTest.php
index ba0dc5a..1a30489 100644
--- a/core/modules/migrate_drupal/tests/src/Kernel/dependencies/MigrateDependenciesTest.php
+++ b/core/modules/migrate_drupal/tests/src/Kernel/dependencies/MigrateDependenciesTest.php
@@ -33,17 +33,18 @@ public function testMigrateDependenciesOrder() {
'd6_node:company',
'd6_node:employee',
'd6_node:event',
+ 'd6_node:forum',
'd6_node:page',
+ 'd6_user',
+ 'd6_node_type',
+ 'd6_node_settings',
+ 'd6_filter_format',
'd6_node:sponsor',
'd6_node:story',
'd6_node:test_event',
'd6_node:test_page',
'd6_node:test_planet',
'd6_node:test_story',
- 'd6_node_type',
- 'd6_node_settings',
- 'd6_filter_format',
- 'd6_user',
'd6_comment_type',
'd6_comment_entity_display',
'd6_comment_entity_form_display',
diff --git a/core/modules/migrate_drupal/tests/src/Unit/source/VariableMultiRowSourceWithHighwaterTest.php b/core/modules/migrate_drupal/tests/src/Unit/source/VariableMultiRowSourceWithHighwaterTest.php
deleted file mode 100644
index f97b7a7..0000000
--- a/core/modules/migrate_drupal/tests/src/Unit/source/VariableMultiRowSourceWithHighwaterTest.php
+++ /dev/null
@@ -1,20 +0,0 @@
-migrationConfiguration['highWaterProperty']['field'] = 'test';
- parent::setup();
- }
-
-}
diff --git a/core/modules/migrate_drupal/tests/src/Unit/source/VariableMultiRowTest.php b/core/modules/migrate_drupal/tests/src/Unit/source/VariableMultiRowTest.php
deleted file mode 100644
index 1ba95ba..0000000
--- a/core/modules/migrate_drupal/tests/src/Unit/source/VariableMultiRowTest.php
+++ /dev/null
@@ -1,12 +0,0 @@
- 'simpletest',
'destination_module' => 'simpletest',
],
- 'd6_statistics_settings' => [
+ 'statistics_settings' => [
'source_module' => 'statistics',
'destination_module' => 'statistics',
],
diff --git a/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php b/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php
index 85a9e79..b635f2a 100644
--- a/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php
+++ b/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php
@@ -30,7 +30,16 @@
*
* @var array
*/
- public static $modules = ['language', 'content_translation', 'migrate_drupal_ui', 'telephone'];
+ public static $modules = [
+ 'language',
+ 'content_translation',
+ 'migrate_drupal_ui',
+ 'telephone',
+ 'aggregator',
+ 'book',
+ 'forum',
+ 'statistics',
+ ];
/**
* {@inheritdoc}
@@ -143,8 +152,9 @@ public function testMigrateUpgrade() {
$this->resetAll();
$expected_counts = $this->getEntityCounts();
- foreach (array_keys(\Drupal::entityTypeManager()->getDefinitions()) as $entity_type) {
- $real_count = count(\Drupal::entityTypeManager()->getStorage($entity_type)->loadMultiple());
+ foreach (array_keys(\Drupal::entityTypeManager()
+ ->getDefinitions()) as $entity_type) {
+ $real_count = \Drupal::entityQuery($entity_type)->count()->execute();
$expected_count = isset($expected_counts[$entity_type]) ? $expected_counts[$entity_type] : 0;
$this->assertEqual($expected_count, $real_count, "Found $real_count $entity_type entities, expected $expected_count.");
}
diff --git a/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php b/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
index 404f21b..29479c4 100644
--- a/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
+++ b/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
@@ -34,42 +34,44 @@ protected function getSourceBasePath() {
*/
protected function getEntityCounts() {
return [
- 'block' => 30,
+ 'aggregator_item' => 1,
+ 'aggregator_feed' => 1,
+ 'block' => 35,
'block_content' => 2,
'block_content_type' => 1,
'comment' => 3,
- 'comment_type' => 2,
+ 'comment_type' => 3,
'contact_form' => 5,
'configurable_language' => 5,
'editor' => 2,
- 'field_config' => 63,
- 'field_storage_config' => 43,
+ 'field_config' => 71,
+ 'field_storage_config' => 46,
'file' => 7,
'filter_format' => 7,
'image_style' => 5,
'language_content_settings' => 2,
'migration' => 105,
'node' => 11,
- 'node_type' => 11,
- 'rdf_mapping' => 5,
+ 'node_type' => 13,
+ 'rdf_mapping' => 7,
'search_page' => 2,
'shortcut' => 2,
'shortcut_set' => 1,
'action' => 22,
'menu' => 8,
'taxonomy_term' => 6,
- 'taxonomy_vocabulary' => 5,
+ 'taxonomy_vocabulary' => 6,
'tour' => 4,
'user' => 7,
'user_role' => 6,
'menu_link_content' => 4,
- 'view' => 12,
+ 'view' => 14,
'date_format' => 11,
- 'entity_form_display' => 15,
+ 'entity_form_display' => 19,
'entity_form_mode' => 1,
- 'entity_view_display' => 32,
- 'entity_view_mode' => 12,
- 'base_field_override' => 33,
+ 'entity_view_display' => 41,
+ 'entity_view_mode' => 14,
+ 'base_field_override' => 38,
];
}
diff --git a/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php b/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php
index 86f1ca9..94a42e2 100644
--- a/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php
+++ b/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php
@@ -34,17 +34,19 @@ protected function getSourceBasePath() {
*/
protected function getEntityCounts() {
return [
+ 'aggregator_item' => 10,
+ 'aggregator_feed' => 1,
'block' => 25,
'block_content' => 1,
'block_content_type' => 1,
'comment' => 1,
- 'comment_type' => 7,
+ 'comment_type' => 8,
// Module 'language' comes with 'en', 'und', 'zxx'. Migration adds 'is'.
'configurable_language' => 4,
'contact_form' => 3,
'editor' => 2,
- 'field_config' => 49,
- 'field_storage_config' => 37,
+ 'field_config' => 52,
+ 'field_storage_config' => 39,
'file' => 2,
'filter_format' => 7,
'image_style' => 6,
@@ -52,25 +54,25 @@ protected function getEntityCounts() {
'migration' => 73,
'node' => 3,
'node_type' => 6,
- 'rdf_mapping' => 5,
+ 'rdf_mapping' => 7,
'search_page' => 2,
'shortcut' => 6,
'shortcut_set' => 2,
'action' => 16,
'menu' => 6,
'taxonomy_term' => 18,
- 'taxonomy_vocabulary' => 3,
+ 'taxonomy_vocabulary' => 4,
'tour' => 4,
'user' => 4,
'user_role' => 3,
'menu_link_content' => 7,
- 'view' => 12,
+ 'view' => 14,
'date_format' => 11,
- 'entity_form_display' => 16,
+ 'entity_form_display' => 18,
'entity_form_mode' => 1,
- 'entity_view_display' => 24,
- 'entity_view_mode' => 11,
- 'base_field_override' => 7,
+ 'entity_view_display' => 29,
+ 'entity_view_mode' => 14,
+ 'base_field_override' => 9,
];
}
diff --git a/core/modules/node/node.permissions.yml b/core/modules/node/node.permissions.yml
index 753ed40..289227c 100644
--- a/core/modules/node/node.permissions.yml
+++ b/core/modules/node/node.permissions.yml
@@ -18,12 +18,13 @@ view own unpublished content:
title: 'View own unpublished content'
view all revisions:
title: 'View all revisions'
+ description: 'To view a revision, you also need permission to view the content item.'
revert all revisions:
title: 'Revert all revisions'
- description: 'Role requires permission view revisions and edit rights for nodes in question or administer nodes.'
+ description: 'To revert a revision, you also need permission to edit the content item.'
delete all revisions:
title: 'Delete all revisions'
- description: 'Role requires permission to view revisions and delete rights for nodes in question or administer nodes.'
+ description: 'To delete a revision, you also need permission to delete the content item.'
permission_callbacks:
- \Drupal\node\NodePermissions::nodeTypePermissions
diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php
index 4f8efe3..c11a188 100644
--- a/core/modules/node/src/Entity/Node.php
+++ b/core/modules/node/src/Entity/Node.php
@@ -61,6 +61,11 @@
* "published" = "status",
* "uid" = "uid",
* },
+ * revision_metadata_keys = {
+ * "revision_user" = "revision_uid",
+ * "revision_created" = "revision_timestamp",
+ * "revision_log_message" = "revision_log"
+ * },
* bundle_entity_type = "node_type",
* field_ui_base_route = "entity.node_type.edit_form",
* common_reference_target = TRUE,
@@ -453,14 +458,12 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['revision_timestamp'] = BaseFieldDefinition::create('created')
->setLabel(t('Revision timestamp'))
->setDescription(t('The time that the current revision was created.'))
- ->setQueryable(FALSE)
->setRevisionable(TRUE);
$fields['revision_uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Revision user ID'))
->setDescription(t('The user ID of the author of the current revision.'))
->setSetting('target_type', 'user')
- ->setQueryable(FALSE)
->setRevisionable(TRUE);
$fields['revision_log'] = BaseFieldDefinition::create('string_long')
diff --git a/core/modules/node/src/NodePermissions.php b/core/modules/node/src/NodePermissions.php
index 5754d71..1996360 100644
--- a/core/modules/node/src/NodePermissions.php
+++ b/core/modules/node/src/NodePermissions.php
@@ -62,14 +62,15 @@ protected function buildPermissions(NodeType $type) {
],
"view $type_id revisions" => [
'title' => $this->t('%type_name: View revisions', $type_params),
+ 'description' => t('To view a revision, you also need permission to view the content item.'),
],
"revert $type_id revisions" => [
'title' => $this->t('%type_name: Revert revisions', $type_params),
- 'description' => t('Role requires permission view revisions and edit rights for nodes in question, or administer nodes.'),
+ 'description' => t('To revert a revision, you also need permission to edit the content item.'),
],
"delete $type_id revisions" => [
'title' => $this->t('%type_name: Delete revisions', $type_params),
- 'description' => $this->t('Role requires permission to view revisions and delete rights for nodes in question, or administer nodes.'),
+ 'description' => $this->t('To delete a revision, you also need permission to delete the content item.'),
],
];
}
diff --git a/core/modules/node/src/Plugin/migrate/D6NodeDeriver.php b/core/modules/node/src/Plugin/migrate/D6NodeDeriver.php
index 6d9b67a..536303e 100644
--- a/core/modules/node/src/Plugin/migrate/D6NodeDeriver.php
+++ b/core/modules/node/src/Plugin/migrate/D6NodeDeriver.php
@@ -9,6 +9,7 @@
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate\Plugin\MigrationDeriverTrait;
use Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface;
+use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@@ -39,6 +40,20 @@ class D6NodeDeriver extends DeriverBase implements ContainerDeriverInterface {
protected $cckPluginManager;
/**
+ * Already-instantiated field plugins, keyed by ID.
+ *
+ * @var \Drupal\migrate_drupal\Plugin\MigrateFieldInterface[]
+ */
+ protected $fieldPluginCache;
+
+ /**
+ * The field plugin manager.
+ *
+ * @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface
+ */
+ protected $fieldPluginManager;
+
+ /**
* Whether or not to include translations.
*
* @var bool
@@ -52,12 +67,15 @@ class D6NodeDeriver extends DeriverBase implements ContainerDeriverInterface {
* The base plugin ID for the plugin ID.
* @param \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface $cck_manager
* The CCK plugin manager.
+ * @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_manager
+ * The field plugin manager.
* @param bool $translations
* Whether or not to include translations.
*/
- public function __construct($base_plugin_id, MigrateCckFieldPluginManagerInterface $cck_manager, $translations) {
+ public function __construct($base_plugin_id, MigrateCckFieldPluginManagerInterface $cck_manager, MigrateFieldPluginManagerInterface $field_manager, $translations) {
$this->basePluginId = $base_plugin_id;
$this->cckPluginManager = $cck_manager;
+ $this->fieldPluginManager = $field_manager;
$this->includeTranslations = $translations;
}
@@ -69,6 +87,7 @@ public static function create(ContainerInterface $container, $base_plugin_id) {
return new static(
$base_plugin_id,
$container->get('plugin.manager.migrate.cckfield'),
+ $container->get('plugin.manager.migrate.field'),
$container->get('module_handler')->moduleExists('content_translation')
);
}
@@ -100,7 +119,7 @@ public function getDerivativeDefinitions($base_plugin_definition) {
return $this->derivatives;
}
- // Read all CCK field instance definitions in the source database.
+ // Read all field instance definitions in the source database.
$fields = [];
try {
$source_plugin = static::getSourcePlugin('d6_field_instance');
@@ -112,7 +131,7 @@ public function getDerivativeDefinitions($base_plugin_definition) {
}
catch (RequirementsException $e) {
// If checkRequirements() failed then the content module did not exist and
- // we do not have any CCK fields. Therefore, $fields will be empty and
+ // we do not have any fields. Therefore, $fields will be empty and
// below we'll create a migration just for the node properties.
}
@@ -135,20 +154,31 @@ public function getDerivativeDefinitions($base_plugin_definition) {
$values['migration_dependencies']['required'][] = 'd6_node:' . $node_type;
}
+ /** @var \Drupal\migrate\Plugin\Migration $migration */
$migration = \Drupal::service('plugin.manager.migration')->createStubMigration($values);
if (isset($fields[$node_type])) {
foreach ($fields[$node_type] as $field_name => $info) {
$field_type = $info['type'];
try {
- $plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, ['core' => 6], $migration);
- if (!isset($this->cckPluginCache[$field_type])) {
- $this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($plugin_id, ['core' => 6], $migration);
+ $plugin_id = $this->fieldPluginManager->getPluginIdFromFieldType($field_type, ['core' => 6], $migration);
+ if (!isset($this->fieldPluginCache[$field_type])) {
+ $this->fieldPluginCache[$field_type] = $this->fieldPluginManager->createInstance($plugin_id, ['core' => 6], $migration);
}
- $this->cckPluginCache[$field_type]
- ->processCckFieldValues($migration, $field_name, $info);
+ $this->fieldPluginCache[$field_type]
+ ->processFieldValues($migration, $field_name, $info);
}
catch (PluginNotFoundException $ex) {
- $migration->setProcessOfProperty($field_name, $field_name);
+ try {
+ $plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, ['core' => 6], $migration);
+ if (!isset($this->cckPluginCache[$field_type])) {
+ $this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($plugin_id, ['core' => 6], $migration);
+ }
+ $this->cckPluginCache[$field_type]
+ ->processCckFieldValues($migration, $field_name, $info);
+ }
+ catch (PluginNotFoundException $ex) {
+ $migration->setProcessOfProperty($field_name, $field_name);
+ }
}
}
}
diff --git a/core/modules/node/src/Plugin/migrate/D7NodeDeriver.php b/core/modules/node/src/Plugin/migrate/D7NodeDeriver.php
index a35c376..da01c70 100644
--- a/core/modules/node/src/Plugin/migrate/D7NodeDeriver.php
+++ b/core/modules/node/src/Plugin/migrate/D7NodeDeriver.php
@@ -9,6 +9,7 @@
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate\Plugin\MigrationDeriverTrait;
use Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface;
+use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@@ -39,6 +40,20 @@ class D7NodeDeriver extends DeriverBase implements ContainerDeriverInterface {
protected $cckPluginManager;
/**
+ * Already-instantiated field plugins, keyed by ID.
+ *
+ * @var \Drupal\migrate_drupal\Plugin\MigrateFieldInterface[]
+ */
+ protected $fieldPluginCache;
+
+ /**
+ * The field plugin manager.
+ *
+ * @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface
+ */
+ protected $fieldPluginManager;
+
+ /**
* Whether or not to include translations.
*
* @var bool
@@ -52,12 +67,15 @@ class D7NodeDeriver extends DeriverBase implements ContainerDeriverInterface {
* The base plugin ID for the plugin ID.
* @param \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface $cck_manager
* The CCK plugin manager.
+ * @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_manager
+ * The field plugin manager.
* @param bool $translations
* Whether or not to include translations.
*/
- public function __construct($base_plugin_id, MigrateCckFieldPluginManagerInterface $cck_manager, $translations) {
+ public function __construct($base_plugin_id, MigrateCckFieldPluginManagerInterface $cck_manager, MigrateFieldPluginManagerInterface $field_manager, $translations) {
$this->basePluginId = $base_plugin_id;
$this->cckPluginManager = $cck_manager;
+ $this->fieldPluginManager = $field_manager;
$this->includeTranslations = $translations;
}
@@ -69,6 +87,7 @@ public static function create(ContainerInterface $container, $base_plugin_id) {
return new static(
$base_plugin_id,
$container->get('plugin.manager.migrate.cckfield'),
+ $container->get('plugin.manager.migrate.field'),
$container->get('module_handler')->moduleExists('content_translation')
);
}
@@ -134,15 +153,25 @@ public function getDerivativeDefinitions($base_plugin_definition) {
foreach ($fields[$node_type] as $field_name => $info) {
$field_type = $info['type'];
try {
- $plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, ['core' => 7], $migration);
- if (!isset($this->cckPluginCache[$field_type])) {
- $this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($plugin_id, ['core' => 7], $migration);
+ $plugin_id = $this->fieldPluginManager->getPluginIdFromFieldType($field_type, ['core' => 7], $migration);
+ if (!isset($this->fieldPluginCache[$field_type])) {
+ $this->fieldPluginCache[$field_type] = $this->fieldPluginManager->createInstance($plugin_id, ['core' => 7], $migration);
}
- $this->cckPluginCache[$field_type]
- ->processCckFieldValues($migration, $field_name, $info);
+ $this->fieldPluginCache[$field_type]
+ ->processFieldValues($migration, $field_name, $info);
}
catch (PluginNotFoundException $ex) {
- $migration->setProcessOfProperty($field_name, $field_name);
+ try {
+ $plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, ['core' => 7], $migration);
+ if (!isset($this->cckPluginCache[$field_type])) {
+ $this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($plugin_id, ['core' => 7], $migration);
+ }
+ $this->cckPluginCache[$field_type]
+ ->processCckFieldValues($migration, $field_name, $info);
+ }
+ catch (PluginNotFoundException $ex) {
+ $migration->setProcessOfProperty($field_name, $field_name);
+ }
}
}
}
diff --git a/core/modules/node/src/Plugin/views/argument/UidRevision.php b/core/modules/node/src/Plugin/views/argument/UidRevision.php
index 9e2fb81..0f989a7 100644
--- a/core/modules/node/src/Plugin/views/argument/UidRevision.php
+++ b/core/modules/node/src/Plugin/views/argument/UidRevision.php
@@ -15,7 +15,7 @@ class UidRevision extends Uid {
public function query($group_by = FALSE) {
$this->ensureMyTable();
$placeholder = $this->placeholder();
- $this->query->addWhereExpression(0, "$this->tableAlias.revision_uid = $placeholder OR ((SELECT COUNT(DISTINCT vid) FROM {node_revision} nr WHERE nfr.revision_uid = $placeholder AND nr.nid = $this->tableAlias.nid) > 0)", [$placeholder => $this->argument]);
+ $this->query->addWhereExpression(0, "$this->tableAlias.uid = $placeholder OR ((SELECT COUNT(DISTINCT vid) FROM {node_revision} nr WHERE nr.revision_uid = $placeholder AND nr.nid = $this->tableAlias.nid) > 0)", [$placeholder => $this->argument]);
}
}
diff --git a/core/modules/node/src/Plugin/views/filter/Access.php b/core/modules/node/src/Plugin/views/filter/Access.php
index 73844e1..10ae922 100644
--- a/core/modules/node/src/Plugin/views/filter/Access.php
+++ b/core/modules/node/src/Plugin/views/filter/Access.php
@@ -2,6 +2,7 @@
namespace Drupal\node\Plugin\views\filter;
+use Drupal\Core\Database\Query\Condition;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\filter\FilterPluginBase;
@@ -27,10 +28,10 @@ public function query() {
$account = $this->view->getUser();
if (!$account->hasPermission('bypass node access')) {
$table = $this->ensureMyTable();
- $grants = db_or();
+ $grants = new Condition('OR');
foreach (node_access_grants('view', $account) as $realm => $gids) {
foreach ($gids as $gid) {
- $grants->condition(db_and()
+ $grants->condition((new Condition('AND'))
->condition($table . '.gid', $gid)
->condition($table . '.realm', $realm)
);
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_argument_node_uid_revision.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_argument_node_uid_revision.yml
new file mode 100644
index 0000000..00ee678
--- /dev/null
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_argument_node_uid_revision.yml
@@ -0,0 +1,106 @@
+langcode: en
+status: true
+dependencies:
+ module:
+ - node
+ - user
+id: test_argument_node_uid_revision
+label: test_argument_node_uid_revision
+module: views
+description: ''
+tag: default
+base_table: node_field_data
+base_field: nid
+core: 8.0-dev
+display:
+ default:
+ display_options:
+ access:
+ type: perm
+ cache:
+ type: tag
+ exposed_form:
+ type: basic
+ fields:
+ nid:
+ id: nid
+ table: node_field_data
+ field: nid
+ plugin_id: field
+ entity_type: node
+ entity_field: nid
+ filter_groups:
+ groups:
+ 1: AND
+ operator: AND
+ filters: { }
+ sorts:
+ nid:
+ id: nid
+ table: node_field_data
+ field: nid
+ order: ASC
+ plugin_id: standard
+ relationship: none
+ entity_type: node
+ entity_field: nid
+ pager:
+ type: full
+ query:
+ type: views_query
+ style:
+ type: default
+ row:
+ type: fields
+ display_extenders: { }
+ arguments:
+ uid_revision:
+ id: uid_revision
+ table: node_field_data
+ field: uid_revision
+ relationship: none
+ group_type: group
+ admin_label: ''
+ default_action: empty
+ exception:
+ value: all
+ title_enable: false
+ title: All
+ title_enable: false
+ title: ''
+ default_argument_type: fixed
+ default_argument_options:
+ argument: ''
+ default_argument_skip_url: false
+ summary_options:
+ base_path: ''
+ count: true
+ items_per_page: 25
+ override: false
+ summary:
+ sort_order: asc
+ number_of_records: 0
+ format: default_summary
+ specify_validation: false
+ validate:
+ type: none
+ fail: 'not found'
+ validate_options: { }
+ break_phrase: false
+ not: false
+ entity_type: node
+ plugin_id: node_uid_revision
+ display_plugin: default
+ display_title: Master
+ id: default
+ position: 0
+ cache_metadata:
+ max-age: -1
+ contexts:
+ - 'languages:language_content'
+ - 'languages:language_interface'
+ - url
+ - url.query_args
+ - 'user.node_grants:view'
+ - user.permissions
+ tags: { }
diff --git a/core/modules/node/tests/src/Kernel/Views/ArgumentUidRevisionTest.php b/core/modules/node/tests/src/Kernel/Views/ArgumentUidRevisionTest.php
new file mode 100644
index 0000000..b216f40
--- /dev/null
+++ b/core/modules/node/tests/src/Kernel/Views/ArgumentUidRevisionTest.php
@@ -0,0 +1,93 @@
+installEntitySchema('node');
+ $this->installSchema('node', ['node_access']);
+ $this->installEntitySchema('user');
+ $this->installConfig(['node', 'field']);
+
+ ViewTestData::createTestViews(get_class($this), ['node_test_views']);
+ }
+
+ /**
+ * Tests the node_uid_revision argument.
+ */
+ public function testArgument() {
+ $expected_result = [];
+
+ $author = $this->createUser();
+ $no_author = $this->createUser();
+
+ // Create one node, with the author as the node author.
+ $node1 = Node::create([
+ 'type' => 'default',
+ 'title' => $this->randomMachineName(),
+ ]);
+ $node1->setOwner($author);
+ $node1->save();
+ $expected_result[] = ['nid' => $node1->id()];
+
+ // Create one node of which an additional revision author will be the
+ // author.
+ $node2 = Node::create([
+ 'type' => 'default',
+ 'title' => $this->randomMachineName(),
+ ]);
+ $node2->setRevisionAuthorId($no_author->id());
+ $node2->save();
+ $expected_result[] = ['nid' => $node2->id()];
+
+ // Force to add a new revision.
+ $node2->setNewRevision(TRUE);
+ $node2->setRevisionAuthorId($author->id());
+ $node2->save();
+
+ // Create one node on which the author has neither authorship of revisions
+ // or the main node.
+ $node3 = Node::create([
+ 'type' => 'default',
+ 'title' => $this->randomMachineName(),
+ ]);
+ $node3->setOwner($no_author);
+ $node3->save();
+
+ $view = Views::getView('test_argument_node_uid_revision');
+ $view->initHandlers();
+ $view->setArguments(['uid_revision' => $author->id()]);
+
+ $this->executeView($view);
+ $this->assertIdenticalResultset($view, $expected_result, ['nid' => 'nid']);
+ }
+
+}
diff --git a/core/modules/outside_in/outside_in.module b/core/modules/outside_in/outside_in.module
index a7fab7b..9a0e629 100644
--- a/core/modules/outside_in/outside_in.module
+++ b/core/modules/outside_in/outside_in.module
@@ -34,12 +34,21 @@ function outside_in_help($route_name, RouteMatchInterface $route_match) {
*/
function outside_in_contextual_links_view_alter(&$element, $items) {
if (isset($element['#links']['outside-inblock-configure'])) {
+ // Place outside_in link first.
+ $outside_in_link = $element['#links']['outside-inblock-configure'];
+ unset($element['#links']['outside-inblock-configure']);
+ $element['#links'] = ['outside-inblock-configure' => $outside_in_link] + $element['#links'];
+
$element['#links']['outside-inblock-configure']['attributes'] = [
'class' => ['use-ajax'],
'data-dialog-type' => 'dialog',
'data-dialog-renderer' => 'offcanvas',
'data-outside-in-edit' => TRUE,
];
+ // If this is content block change title to avoid duplicate "Quick Edit".
+ if (isset($element['#links']['block-contentblock-edit'])) {
+ $element['#links']['outside-inblock-configure']['title'] = t('Quick edit settings');
+ }
$element['#attached']['library'][] = 'outside_in/drupal.off_canvas';
}
diff --git a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php
index c62436c..a5dc740 100644
--- a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php
+++ b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php
@@ -2,6 +2,8 @@
namespace Drupal\Tests\outside_in\FunctionalJavascript;
+use Drupal\block_content\Entity\BlockContent;
+use Drupal\block_content\Entity\BlockContentType;
use Drupal\user\Entity\Role;
/**
@@ -26,6 +28,7 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase {
'outside_in',
'quickedit',
'search',
+ 'block_content',
// Add test module to override CSS pointer-events properties because they
// cause test failures.
'outside_in_test_css',
@@ -36,6 +39,10 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase {
*/
protected function setUp() {
parent::setUp();
+
+ $this->createBlockContentType('basic', TRUE);
+ $block_content = $this->createBlockContent('Custom Block', 'basic', TRUE);
+
// @todo Ensure that this test class works against bartik and stark:
// https://www.drupal.org/node/2784881.
$this->enableTheme('bartik');
@@ -49,6 +56,7 @@ protected function setUp() {
]);
$this->drupalLogin($user);
+ $this->placeBlock('block_content:' . $block_content->uuid(), ['id' => 'custom']);
$this->placeBlock('system_powered_by_block', ['id' => 'powered']);
$this->placeBlock('system_branding_block', ['id' => 'branding']);
$this->placeBlock('search_form_block', ['id' => 'search']);
@@ -62,8 +70,13 @@ protected function setUp() {
public function testBlocks($block_id, $new_page_text, $element_selector, $label_selector, $button_text, $toolbar_item) {
$web_assert = $this->assertSession();
$page = $this->getSession()->getPage();
- $block_selector = '#' . $block_id;
+ $block_selector = '#block-' . $block_id;
$this->drupalGet('user');
+
+ $link = $page->find('css', "$block_selector .contextual-links li a");
+ $this->assertEquals('Quick edit', $link->getText(), "'Quick edit' is the first contextual link for the block.");
+ $this->assertContains("/admin/structure/block/manage/$block_id/offcanvas?destination=user/2", $link->getAttribute('href'));
+
if (isset($toolbar_item)) {
// Check that you can open a toolbar tray and it will be closed after
// entering edit mode.
@@ -83,13 +96,13 @@ public function testBlocks($block_id, $new_page_text, $element_selector, $label_
$this->openBlockForm($block_selector);
switch ($block_id) {
- case 'block-powered':
+ case 'powered':
// Fill out form, save the form.
$page->fillField('settings[label]', $new_page_text);
$page->checkField('settings[label_display]');
break;
- case 'block-branding':
+ case 'branding':
// Fill out form, save the form.
$page->fillField('settings[site_information][site_name]', $new_page_text);
break;
@@ -137,7 +150,7 @@ public function testBlocks($block_id, $new_page_text, $element_selector, $label_
public function providerTestBlocks() {
$blocks = [
'block-powered' => [
- 'id' => 'block-powered',
+ 'id' => 'powered',
'new_page_text' => 'Can you imagine anyone showing the label on this block?',
'element_selector' => '.content a',
'label_selector' => 'h2',
@@ -145,7 +158,7 @@ public function providerTestBlocks() {
'toolbar_item' => '#toolbar-item-user',
],
'block-branding' => [
- 'id' => 'block-branding',
+ 'id' => 'branding',
'new_page_text' => 'The site that will live a very short life.',
'element_selector' => 'a[rel="home"]:nth-child(2)',
'label_selector' => '.site-branding__name a',
@@ -153,7 +166,7 @@ public function providerTestBlocks() {
'toolbar_item' => '#toolbar-item-administration',
],
'block-search' => [
- 'id' => 'block-search',
+ 'id' => 'search',
'new_page_text' => NULL,
'element_selector' => '#edit-submit',
'label_selector' => 'h2',
@@ -364,4 +377,80 @@ protected function pressToolbarEditButton() {
$this->assertSession()->assertWaitOnAjaxRequest();
}
+ /**
+ * Creates a custom block.
+ *
+ * @param bool|string $title
+ * (optional) Title of block. When no value is given uses a random name.
+ * Defaults to FALSE.
+ * @param string $bundle
+ * (optional) Bundle name. Defaults to 'basic'.
+ * @param bool $save
+ * (optional) Whether to save the block. Defaults to TRUE.
+ *
+ * @return \Drupal\block_content\Entity\BlockContent
+ * Created custom block.
+ */
+ protected function createBlockContent($title = FALSE, $bundle = 'basic', $save = TRUE) {
+ $title = $title ?: $this->randomName();
+ $block_content = BlockContent::create([
+ 'info' => $title,
+ 'type' => $bundle,
+ 'langcode' => 'en',
+ 'body' => [
+ 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
+ 'format' => 'plain_text',
+ ],
+ ]);
+ if ($block_content && $save === TRUE) {
+ $block_content->save();
+ }
+ return $block_content;
+ }
+
+ /**
+ * Creates a custom block type (bundle).
+ *
+ * @param string $label
+ * The block type label.
+ * @param bool $create_body
+ * Whether or not to create the body field.
+ *
+ * @return \Drupal\block_content\Entity\BlockContentType
+ * Created custom block type.
+ */
+ protected function createBlockContentType($label, $create_body = FALSE) {
+ $bundle = BlockContentType::create([
+ 'id' => $label,
+ 'label' => $label,
+ 'revision' => FALSE,
+ ]);
+ $bundle->save();
+ if ($create_body) {
+ block_content_add_body_field($bundle->id());
+ }
+ return $bundle;
+ }
+
+ /**
+ * Tests that contextual links in custom blocks are changed.
+ *
+ * "Quick edit" is quickedit.module link.
+ * "Quick edit settings" is outside_in.module link.
+ */
+ public function testCustomBlockLinks() {
+ $this->drupalGet('user');
+ $page = $this->getSession()->getPage();
+ $links = $page->findAll('css', "#block-custom .contextual-links li a");
+ $link_labels = [];
+ /** @var \Behat\Mink\Element\NodeElement $link */
+ foreach ($links as $link) {
+ $link_labels[$link->getAttribute('href')] = $link->getText();
+ }
+ $href = array_search('Quick edit', $link_labels);
+ $this->assertEquals('', $href);
+ $href = array_search('Quick edit settings', $link_labels);
+ $this->assertTrue(strstr($href, '/admin/structure/block/manage/custom/offcanvas?destination=user/2') !== FALSE);
+ }
+
}
diff --git a/core/modules/quickedit/quickedit.services.yml b/core/modules/quickedit/quickedit.services.yml
index 692ba2f..3d7d934 100644
--- a/core/modules/quickedit/quickedit.services.yml
+++ b/core/modules/quickedit/quickedit.services.yml
@@ -3,7 +3,7 @@ services:
class: Drupal\quickedit\Plugin\InPlaceEditorManager
parent: default_plugin_manager
access_check.quickedit.entity_field:
- class: Drupal\quickedit\Access\EditEntityFieldAccessCheck
+ class: Drupal\quickedit\Access\QuickEditEntityFieldAccessCheck
tags:
- { name: access_check, applies_to: _access_quickedit_entity_field }
quickedit.editor.selector:
diff --git a/core/modules/quickedit/src/Access/EditEntityFieldAccessCheck.php b/core/modules/quickedit/src/Access/EditEntityFieldAccessCheck.php
index 7b38838..f937908 100644
--- a/core/modules/quickedit/src/Access/EditEntityFieldAccessCheck.php
+++ b/core/modules/quickedit/src/Access/EditEntityFieldAccessCheck.php
@@ -2,61 +2,9 @@
namespace Drupal\quickedit\Access;
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Routing\Access\AccessInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\Core\Entity\EntityInterface;
-
/**
- * Access check for editing entity fields.
+ * @deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0.
*/
-class EditEntityFieldAccessCheck implements AccessInterface, EditEntityFieldAccessCheckInterface {
-
- /**
- * Checks Quick Edit access to the field.
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- * The entity containing the field.
- * @param string $field_name
- * The field name.
- * @param string $langcode
- * The langcode.
- * @param \Drupal\Core\Session\AccountInterface $account
- * The currently logged in account.
- *
- * @return \Drupal\Core\Access\AccessResultInterface
- * The access result.
- *
- * @todo Use the $account argument: https://www.drupal.org/node/2266809.
- */
- public function access(EntityInterface $entity, $field_name, $langcode, AccountInterface $account) {
- if (!$this->validateRequestAttributes($entity, $field_name, $langcode)) {
- return AccessResult::forbidden();
- }
-
- return $this->accessEditEntityField($entity, $field_name);
- }
-
- /**
- * {@inheritdoc}
- */
- public function accessEditEntityField(EntityInterface $entity, $field_name) {
- return $entity->access('update', NULL, TRUE)->andIf($entity->get($field_name)->access('edit', NULL, TRUE));
- }
-
- /**
- * Validates request attributes.
- */
- protected function validateRequestAttributes(EntityInterface $entity, $field_name, $langcode) {
- // Validate the field name and language.
- if (!$field_name || !$entity->hasField($field_name)) {
- return FALSE;
- }
- if (!$langcode || !$entity->hasTranslation($langcode)) {
- return FALSE;
- }
-
- return TRUE;
- }
+class EditEntityFieldAccessCheck extends QuickEditEntityFieldAccessCheck {
}
diff --git a/core/modules/quickedit/src/Access/EditEntityFieldAccessCheckInterface.php b/core/modules/quickedit/src/Access/EditEntityFieldAccessCheckInterface.php
index c7f14e2..cfdb32d 100644
--- a/core/modules/quickedit/src/Access/EditEntityFieldAccessCheckInterface.php
+++ b/core/modules/quickedit/src/Access/EditEntityFieldAccessCheckInterface.php
@@ -2,24 +2,9 @@
namespace Drupal\quickedit\Access;
-use Drupal\Core\Entity\EntityInterface;
-
/**
- * Access check for editing entity fields.
+ * @deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0.
*/
-interface EditEntityFieldAccessCheckInterface {
-
- /**
- * Checks access to edit the requested field of the requested entity.
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- * The entity.
- * @param string $field_name
- * The field name.
- *
- * @return \Drupal\Core\Access\AccessResultInterface
- * The access result.
- */
- public function accessEditEntityField(EntityInterface $entity, $field_name);
+interface EditEntityFieldAccessCheckInterface extends QuickEditEntityFieldAccessCheckInterface {
}
diff --git a/core/modules/quickedit/src/Access/QuickEditEntityFieldAccessCheck.php b/core/modules/quickedit/src/Access/QuickEditEntityFieldAccessCheck.php
new file mode 100644
index 0000000..5404b04
--- /dev/null
+++ b/core/modules/quickedit/src/Access/QuickEditEntityFieldAccessCheck.php
@@ -0,0 +1,62 @@
+validateRequestAttributes($entity, $field_name, $langcode)) {
+ return AccessResult::forbidden();
+ }
+
+ return $this->accessEditEntityField($entity, $field_name);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function accessEditEntityField(EntityInterface $entity, $field_name) {
+ return $entity->access('update', NULL, TRUE)->andIf($entity->get($field_name)->access('edit', NULL, TRUE));
+ }
+
+ /**
+ * Validates request attributes.
+ */
+ protected function validateRequestAttributes(EntityInterface $entity, $field_name, $langcode) {
+ // Validate the field name and language.
+ if (!$field_name || !$entity->hasField($field_name)) {
+ return FALSE;
+ }
+ if (!$langcode || !$entity->hasTranslation($langcode)) {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+}
diff --git a/core/modules/quickedit/src/Access/QuickEditEntityFieldAccessCheckInterface.php b/core/modules/quickedit/src/Access/QuickEditEntityFieldAccessCheckInterface.php
new file mode 100644
index 0000000..1428b48
--- /dev/null
+++ b/core/modules/quickedit/src/Access/QuickEditEntityFieldAccessCheckInterface.php
@@ -0,0 +1,25 @@
+accessChecker = $access_checker;
$this->editorSelector = $editor_selector;
$this->editorManager = $editor_manager;
diff --git a/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php b/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php
index a6705f4..41f26a8 100644
--- a/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php
+++ b/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php
@@ -115,12 +115,12 @@ public function testUserWithoutPermission() {
$this->assertIdentical(Json::encode(['message' => "The 'access in-place editing' permission is required."]), $response);
$this->assertResponse(403);
- // Quick Edit's JavaScript would SearchRankingTestnever hit these endpoints if the metadata
+ // Quick Edit's JavaScript would never hit these endpoints if the metadata
// was empty as above, but we need to make sure that malicious users aren't
// able to use any of the other endpoints either.
$post = ['editors[0]' => 'form'] + $this->getAjaxPageStatePostData();
$response = $this->drupalPost('quickedit/attachments', '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]);
- $message = Json::encode(['message' => "A fatal error occurred: The 'access in-place editing' permission is required."]);
+ $message = Json::encode(['message' => "The 'access in-place editing' permission is required."]);
$this->assertIdentical($message, $response);
$this->assertResponse(403);
$post = ['nocssjs' => 'true'] + $this->getAjaxPageStatePostData();
diff --git a/core/modules/quickedit/tests/modules/src/MockEditEntityFieldAccessCheck.php b/core/modules/quickedit/tests/modules/src/MockEditEntityFieldAccessCheck.php
index b5d9456..7596aa8 100644
--- a/core/modules/quickedit/tests/modules/src/MockEditEntityFieldAccessCheck.php
+++ b/core/modules/quickedit/tests/modules/src/MockEditEntityFieldAccessCheck.php
@@ -2,19 +2,9 @@
namespace Drupal\quickedit_test;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\quickedit\Access\EditEntityFieldAccessCheckInterface;
-
/**
- * Access check for editing entity fields.
+ * @deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0.
*/
-class MockEditEntityFieldAccessCheck implements EditEntityFieldAccessCheckInterface {
-
- /**
- * {@inheritdoc}
- */
- public function accessEditEntityField(EntityInterface $entity, $field_name) {
- return TRUE;
- }
+class MockEditEntityFieldAccessCheck extends MockQuickEditEntityFieldAccessCheck {
}
diff --git a/core/modules/quickedit/tests/modules/src/MockQuickEditEntityFieldAccessCheck.php b/core/modules/quickedit/tests/modules/src/MockQuickEditEntityFieldAccessCheck.php
new file mode 100644
index 0000000..2459c50
--- /dev/null
+++ b/core/modules/quickedit/tests/modules/src/MockQuickEditEntityFieldAccessCheck.php
@@ -0,0 +1,20 @@
+editorManager = $this->container->get('plugin.manager.quickedit.editor');
- $this->accessChecker = new MockEditEntityFieldAccessCheck();
+ $this->accessChecker = new MockQuickEditEntityFieldAccessCheck();
$this->editorSelector = new EditorSelector($this->editorManager, $this->container->get('plugin.manager.field.formatter'));
$this->metadataGenerator = new MetadataGenerator($this->accessChecker, $this->editorSelector, $this->editorManager);
}
diff --git a/core/modules/quickedit/tests/src/Unit/Access/EditEntityFieldAccessCheckTest.php b/core/modules/quickedit/tests/src/Unit/Access/EditEntityFieldAccessCheckTest.php
deleted file mode 100644
index 7e7e0bb..0000000
--- a/core/modules/quickedit/tests/src/Unit/Access/EditEntityFieldAccessCheckTest.php
+++ /dev/null
@@ -1,149 +0,0 @@
-editAccessCheck = new EditEntityFieldAccessCheck();
-
- $cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
- $cache_contexts_manager->assertValidTokens()->willReturn(TRUE);
- $cache_contexts_manager->reveal();
- $container = new Container();
- $container->set('cache_contexts_manager', $cache_contexts_manager);
- \Drupal::setContainer($container);
- }
-
- /**
- * Provides test data for testAccess().
- *
- * @see \Drupal\Tests\edit\Unit\quickedit\Access\EditEntityFieldAccessCheckTest::testAccess()
- */
- public function providerTestAccess() {
- $data = [];
- $data[] = [TRUE, TRUE, AccessResult::allowed()];
- $data[] = [FALSE, TRUE, AccessResult::neutral()];
- $data[] = [TRUE, FALSE, AccessResult::neutral()];
- $data[] = [FALSE, FALSE, AccessResult::neutral()];
-
- return $data;
- }
-
- /**
- * Tests the method for checking access to routes.
- *
- * @param bool $entity_is_editable
- * Whether the subject entity is editable.
- * @param bool $field_storage_is_accessible
- * Whether the user has access to the field storage entity.
- * @param \Drupal\Core\Access\AccessResult $expected_result
- * The expected result of the access call.
- *
- * @dataProvider providerTestAccess
- */
- public function testAccess($entity_is_editable, $field_storage_is_accessible, AccessResult $expected_result) {
- $entity = $this->createMockEntity();
- $entity->expects($this->any())
- ->method('access')
- ->willReturn(AccessResult::allowedIf($entity_is_editable)->cachePerPermissions());
-
- $field_storage = $this->getMock('Drupal\field\FieldStorageConfigInterface');
- $field_storage->expects($this->any())
- ->method('access')
- ->willReturn(AccessResult::allowedIf($field_storage_is_accessible));
-
- $expected_result->cachePerPermissions();
-
- $field_name = 'valid';
- $entity_with_field = clone $entity;
- $entity_with_field->expects($this->any())
- ->method('get')
- ->with($field_name)
- ->will($this->returnValue($field_storage));
- $entity_with_field->expects($this->once())
- ->method('hasTranslation')
- ->with(LanguageInterface::LANGCODE_NOT_SPECIFIED)
- ->will($this->returnValue(TRUE));
-
- $account = $this->getMock('Drupal\Core\Session\AccountInterface');
- $access = $this->editAccessCheck->access($entity_with_field, $field_name, LanguageInterface::LANGCODE_NOT_SPECIFIED, $account);
- $this->assertEquals($expected_result, $access);
- }
-
- /**
- * Tests checking access to routes that result in AccessResult::isForbidden().
- *
- * @dataProvider providerTestAccessForbidden
- */
- public function testAccessForbidden($field_name, $langcode) {
- $account = $this->getMock('Drupal\Core\Session\AccountInterface');
- $entity = $this->createMockEntity();
- $this->assertEquals(AccessResult::forbidden(), $this->editAccessCheck->access($entity, $field_name, $langcode, $account));
- }
-
- /**
- * Provides test data for testAccessForbidden.
- */
- public function providerTestAccessForbidden() {
- $data = [];
- // Tests the access method without a field_name.
- $data[] = [NULL, LanguageInterface::LANGCODE_NOT_SPECIFIED];
- // Tests the access method with a non-existent field.
- $data[] = ['not_valid', LanguageInterface::LANGCODE_NOT_SPECIFIED];
- // Tests the access method without a langcode.
- $data[] = ['valid', NULL];
- // Tests the access method with an invalid langcode.
- $data[] = ['valid', 'xx-lolspeak'];
- return $data;
- }
-
- /**
- * Returns a mock entity.
- *
- * @return \Drupal\Core\Entity\EntityInterface|\PHPUnit_Framework_MockObject_MockObject
- */
- protected function createMockEntity() {
- $entity = $this->getMockBuilder('Drupal\entity_test\Entity\EntityTest')
- ->disableOriginalConstructor()
- ->getMock();
-
- $entity->expects($this->any())
- ->method('hasTranslation')
- ->will($this->returnValueMap([
- [LanguageInterface::LANGCODE_NOT_SPECIFIED, TRUE],
- ['xx-lolspeak', FALSE],
- ]));
- $entity->expects($this->any())
- ->method('hasField')
- ->will($this->returnValueMap([
- ['valid', TRUE],
- ['not_valid', FALSE],
- ]));
-
- return $entity;
- }
-
-}
diff --git a/core/modules/quickedit/tests/src/Unit/Access/QuickEditEntityFieldAccessCheckTest.php b/core/modules/quickedit/tests/src/Unit/Access/QuickEditEntityFieldAccessCheckTest.php
new file mode 100644
index 0000000..0827436
--- /dev/null
+++ b/core/modules/quickedit/tests/src/Unit/Access/QuickEditEntityFieldAccessCheckTest.php
@@ -0,0 +1,149 @@
+editAccessCheck = new QuickEditEntityFieldAccessCheck();
+
+ $cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
+ $cache_contexts_manager->assertValidTokens()->willReturn(TRUE);
+ $cache_contexts_manager->reveal();
+ $container = new Container();
+ $container->set('cache_contexts_manager', $cache_contexts_manager);
+ \Drupal::setContainer($container);
+ }
+
+ /**
+ * Provides test data for testAccess().
+ *
+ * @see \Drupal\Tests\edit\Unit\quickedit\Access\QuickEditEntityFieldAccessCheckTest::testAccess()
+ */
+ public function providerTestAccess() {
+ $data = [];
+ $data[] = [TRUE, TRUE, AccessResult::allowed()];
+ $data[] = [FALSE, TRUE, AccessResult::neutral()];
+ $data[] = [TRUE, FALSE, AccessResult::neutral()];
+ $data[] = [FALSE, FALSE, AccessResult::neutral()];
+
+ return $data;
+ }
+
+ /**
+ * Tests the method for checking access to routes.
+ *
+ * @param bool $entity_is_editable
+ * Whether the subject entity is editable.
+ * @param bool $field_storage_is_accessible
+ * Whether the user has access to the field storage entity.
+ * @param \Drupal\Core\Access\AccessResult $expected_result
+ * The expected result of the access call.
+ *
+ * @dataProvider providerTestAccess
+ */
+ public function testAccess($entity_is_editable, $field_storage_is_accessible, AccessResult $expected_result) {
+ $entity = $this->createMockEntity();
+ $entity->expects($this->any())
+ ->method('access')
+ ->willReturn(AccessResult::allowedIf($entity_is_editable)->cachePerPermissions());
+
+ $field_storage = $this->getMock('Drupal\field\FieldStorageConfigInterface');
+ $field_storage->expects($this->any())
+ ->method('access')
+ ->willReturn(AccessResult::allowedIf($field_storage_is_accessible));
+
+ $expected_result->cachePerPermissions();
+
+ $field_name = 'valid';
+ $entity_with_field = clone $entity;
+ $entity_with_field->expects($this->any())
+ ->method('get')
+ ->with($field_name)
+ ->will($this->returnValue($field_storage));
+ $entity_with_field->expects($this->once())
+ ->method('hasTranslation')
+ ->with(LanguageInterface::LANGCODE_NOT_SPECIFIED)
+ ->will($this->returnValue(TRUE));
+
+ $account = $this->getMock('Drupal\Core\Session\AccountInterface');
+ $access = $this->editAccessCheck->access($entity_with_field, $field_name, LanguageInterface::LANGCODE_NOT_SPECIFIED, $account);
+ $this->assertEquals($expected_result, $access);
+ }
+
+ /**
+ * Tests checking access to routes that result in AccessResult::isForbidden().
+ *
+ * @dataProvider providerTestAccessForbidden
+ */
+ public function testAccessForbidden($field_name, $langcode) {
+ $account = $this->getMock('Drupal\Core\Session\AccountInterface');
+ $entity = $this->createMockEntity();
+ $this->assertEquals(AccessResult::forbidden(), $this->editAccessCheck->access($entity, $field_name, $langcode, $account));
+ }
+
+ /**
+ * Provides test data for testAccessForbidden.
+ */
+ public function providerTestAccessForbidden() {
+ $data = [];
+ // Tests the access method without a field_name.
+ $data[] = [NULL, LanguageInterface::LANGCODE_NOT_SPECIFIED];
+ // Tests the access method with a non-existent field.
+ $data[] = ['not_valid', LanguageInterface::LANGCODE_NOT_SPECIFIED];
+ // Tests the access method without a langcode.
+ $data[] = ['valid', NULL];
+ // Tests the access method with an invalid langcode.
+ $data[] = ['valid', 'xx-lolspeak'];
+ return $data;
+ }
+
+ /**
+ * Returns a mock entity.
+ *
+ * @return \Drupal\Core\Entity\EntityInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected function createMockEntity() {
+ $entity = $this->getMockBuilder('Drupal\entity_test\Entity\EntityTest')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entity->expects($this->any())
+ ->method('hasTranslation')
+ ->will($this->returnValueMap([
+ [LanguageInterface::LANGCODE_NOT_SPECIFIED, TRUE],
+ ['xx-lolspeak', FALSE],
+ ]));
+ $entity->expects($this->any())
+ ->method('hasField')
+ ->will($this->returnValueMap([
+ ['valid', TRUE],
+ ['not_valid', FALSE],
+ ]));
+
+ return $entity;
+ }
+
+}
diff --git a/core/modules/rest/rest.module b/core/modules/rest/rest.module
index afdb9ff..edd74b9 100644
--- a/core/modules/rest/rest.module
+++ b/core/modules/rest/rest.module
@@ -15,13 +15,13 @@ function rest_help($route_name, RouteMatchInterface $route_match) {
case 'help.page.rest':
$output = '';
$output .= '' . t('About') . '
';
- $output .= '' . t('The RESTful Web Services module provides a framework for exposing REST resources on your site. It provides support for content entities (see the Field module help page for more information about entities) such as content, users, taxonomy terms, etc.; REST support for content items of the Node module is enabled by default, and support for other types of content entities can be enabled. Other modules may add support for other types of REST resources. For more information, see the online documentation for the RESTful Web Services module.', [':rest' => 'https://www.drupal.org/documentation/modules/rest', ':field' => (\Drupal::moduleHandler()->moduleExists('field')) ? \Drupal::url('help.page', ['name' => 'field']) : '#']) . '
';
+ $output .= '' . t('The RESTful Web Services module provides a framework for exposing REST resources on your site. It provides support for content entity types such as the main site content, comments, custom blocks, taxonomy terms, and user accounts, etc. (see the Field module help page for more information about entities). REST support for content items of the Node module is enabled by default, and support for other types of content entities can be enabled. Other modules may add support for other types of REST resources. For more information, see the online documentation for the RESTful Web Services module.', [':rest' => 'https://www.drupal.org/documentation/modules/rest', ':field' => (\Drupal::moduleHandler()->moduleExists('field')) ? \Drupal::url('help.page', ['name' => 'field']) : '#']) . '
';
$output .= '' . t('Uses') . '
';
$output .= '';
$output .= '- ' . t('Installing supporting modules') . '
';
$output .= '- ' . t('In order to use REST on a web site, you need to install modules that provide serialization and authentication services. You can use the Core module HAL for serialization and HTTP Basic Authentication for authentication, or install a contributed or custom module.', [':hal' => (\Drupal::moduleHandler()->moduleExists('hal')) ? \Drupal::url('help.page', ['name' => 'hal']) : '#', ':basic_auth' => (\Drupal::moduleHandler()->moduleExists('basic_auth')) ? \Drupal::url('help.page', ['name' => 'basic_auth']) : '#']) . '
';
$output .= '- ' . t('Enabling REST support for an entity type') . '
';
- $output .= '- ' . t('REST support for content items of the Node module is enabled by default, and support for other types of content entities can be enabled. To enable support, you can use a process based on configuration editing or the contributed Rest UI module.', [':config' => 'https://www.drupal.org/documentation/modules/rest', ':restui' => 'https://www.drupal.org/project/restui']) . '
';
+ $output .= '- ' . t('REST support for content types (provided by the Node module) is enabled by default. To enable support for other content entity types, you can use a process based on configuration editing or the contributed REST UI module.', [':node' => (\Drupal::moduleHandler()->moduleExists('node')) ? \Drupal::url('help.page', ['name' => 'node']) : '#', ':config' => 'https://www.drupal.org/documentation/modules/rest', ':restui' => 'https://www.drupal.org/project/restui']) . '
';
$output .= '- ' . t('You will also need to grant anonymous users permission to perform each of the REST operations you want to be available, and set up authentication properly to authorize web requests.') . '
';
$output .= '
';
return $output;
diff --git a/core/modules/rest/src/Annotation/RestResource.php b/core/modules/rest/src/Annotation/RestResource.php
index 0af11a8..d21f24c 100644
--- a/core/modules/rest/src/Annotation/RestResource.php
+++ b/core/modules/rest/src/Annotation/RestResource.php
@@ -23,14 +23,14 @@
class RestResource extends Plugin {
/**
- * The resource plugin ID.
+ * The REST resource plugin ID.
*
* @var string
*/
public $id;
/**
- * The human-readable name of the resource plugin.
+ * The human-readable name of the REST resource plugin.
*
* @ingroup plugin_translatable
*
@@ -41,8 +41,22 @@ class RestResource extends Plugin {
/**
* The serialization class to deserialize serialized data into.
*
+ * @see \Symfony\Component\Serializer\SerializerInterface's "type" parameter.
+ *
* @var string (optional)
*/
public $serialization_class;
+ /**
+ * The URI paths that this REST resource plugin provides.
+ *
+ * Key-value pairs, with link relation type plugin IDs as keys, and URL
+ * templates as values.
+ *
+ * @see core/core.link_relation_types.yml
+ *
+ * @var string[]
+ */
+ public $uri_paths = [];
+
}
diff --git a/core/modules/rest/src/Plugin/ResourceBase.php b/core/modules/rest/src/Plugin/ResourceBase.php
index 3062aa2..50d8d75 100644
--- a/core/modules/rest/src/Plugin/ResourceBase.php
+++ b/core/modules/rest/src/Plugin/ResourceBase.php
@@ -111,16 +111,6 @@ public function routes() {
switch ($method) {
case 'POST':
$route->setPath($create_path);
- // Restrict the incoming HTTP Content-type header to the known
- // serialization formats.
- $route->addRequirements(['_content_type_format' => implode('|', $this->serializerFormats)]);
- $collection->add("$route_name.$method", $route);
- break;
-
- case 'PATCH':
- // Restrict the incoming HTTP Content-type header to the known
- // serialization formats.
- $route->addRequirements(['_content_type_format' => implode('|', $this->serializerFormats)]);
$collection->add("$route_name.$method", $route);
break;
diff --git a/core/modules/rest/src/Plugin/views/display/RestExport.php b/core/modules/rest/src/Plugin/views/display/RestExport.php
index 15abaa6..cd96195 100644
--- a/core/modules/rest/src/Plugin/views/display/RestExport.php
+++ b/core/modules/rest/src/Plugin/views/display/RestExport.php
@@ -435,7 +435,7 @@ public function render() {
$build['#markup'] = ViewsRenderPipelineMarkup::create($build['#markup']);
}
- parent::applyDisplayCachablityMetadata($build);
+ parent::applyDisplayCacheabilityMetadata($build);
return $build;
}
diff --git a/core/modules/rest/src/RequestHandler.php b/core/modules/rest/src/RequestHandler.php
index dd8e31a..e5437cc 100644
--- a/core/modules/rest/src/RequestHandler.php
+++ b/core/modules/rest/src/RequestHandler.php
@@ -11,8 +11,9 @@
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
-use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
+use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
/**
* Acts as intermediate request forwarder for resource plugins.
@@ -59,22 +60,20 @@ public static function create(ContainerInterface $container) {
* The response object.
*/
public function handle(RouteMatchInterface $route_match, Request $request) {
- $method = strtolower($request->getMethod());
-
// Symfony is built to transparently map HEAD requests to a GET request. In
// the case of the REST module's RequestHandler though, we essentially have
// our own light-weight routing system on top of the Drupal/symfony routing
- // system. So, we have to do the same as what the UrlMatcher does: map HEAD
- // requests to the logic for GET. This also guarantees response headers for
- // HEAD requests are identical to those for GET requests, because we just
- // return a GET response. Response::prepare() will transform it to a HEAD
- // response at the very last moment.
+ // system. So, we have to respect the decision that the routing system made:
+ // we look not at the request method, but at the route's method. All REST
+ // routes are guaranteed to have _method set.
+ // Response::prepare() will transform it to a HEAD response at the very last
+ // moment.
// @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4
// @see \Symfony\Component\Routing\Matcher\UrlMatcher::matchCollection()
// @see \Symfony\Component\HttpFoundation\Response::prepare()
- if ($method === 'head') {
- $method = 'get';
- }
+ $method = strtolower($route_match->getRouteObject()->getMethods()[0]);
+ assert(count($route_match->getRouteObject()->getMethods()) === 1);
+
$resource_config_id = $route_match->getRouteObject()->getDefault('_rest_resource_config');
/** @var \Drupal\rest\RestResourceConfigInterface $resource_config */
@@ -89,29 +88,32 @@ public function handle(RouteMatchInterface $route_match, Request $request) {
if (!empty($received)) {
$format = $request->getContentType();
- // Only allow serialization formats that are explicitly configured. If no
- // formats are configured allow all and hope that the serializer knows the
- // format. If the serializer cannot handle it an exception will be thrown
- // that bubbles up to the client.
- $request_method = $request->getMethod();
- if (in_array($format, $resource_config->getFormats($request_method))) {
- $definition = $resource->getPluginDefinition();
+ $definition = $resource->getPluginDefinition();
+
+ // First decode the request data. We can then determine if the
+ // serialized data was malformed.
+ try {
+ $unserialized = $serializer->decode($received, $format, ['request_method' => $method]);
+ }
+ catch (UnexpectedValueException $e) {
+ // If an exception was thrown at this stage, there was a problem
+ // decoding the data. Throw a 400 http exception.
+ throw new BadRequestHttpException($e->getMessage());
+ }
+
+ // Then attempt to denormalize if there is a serialization class.
+ if (!empty($definition['serialization_class'])) {
try {
- if (!empty($definition['serialization_class'])) {
- $unserialized = $serializer->deserialize($received, $definition['serialization_class'], $format, ['request_method' => $method]);
- }
- // If the plugin does not specify a serialization class just decode
- // the received data.
- else {
- $unserialized = $serializer->decode($received, $format, ['request_method' => $method]);
- }
+ $unserialized = $serializer->denormalize($unserialized, $definition['serialization_class'], $format, ['request_method' => $method]);
}
+ // These two serialization exception types mean there was a problem
+ // with the structure of the decoded data and it's not valid.
catch (UnexpectedValueException $e) {
- throw new BadRequestHttpException($e->getMessage());
+ throw new UnprocessableEntityHttpException($e->getMessage());
+ }
+ catch (InvalidArgumentException $e) {
+ throw new UnprocessableEntityHttpException($e->getMessage());
}
- }
- else {
- throw new UnsupportedMediaTypeHttpException();
}
}
diff --git a/core/modules/rest/src/Routing/ResourceRoutes.php b/core/modules/rest/src/Routing/ResourceRoutes.php
index 6aec267..c21f13c 100644
--- a/core/modules/rest/src/Routing/ResourceRoutes.php
+++ b/core/modules/rest/src/Routing/ResourceRoutes.php
@@ -113,8 +113,15 @@ protected function getRoutesForResourceConfig(RestResourceConfigInterface $rest_
continue;
}
- // The configuration seems legit at this point, so we set the
- // authentication provider and add the route.
+ // The configuration has been validated, so we update the route to:
+ // - set the allowed request body content types/formats for methods that
+ // allow request bodies to be sent
+ // - set the allowed authentication providers
+ if (in_array($method, ['POST', 'PATCH', 'PUT'], TRUE)) {
+ // Restrict the incoming HTTP Content-type header to the allowed
+ // formats.
+ $route->addRequirements(['_content_type_format' => implode('|', $rest_resource_config->getFormats($method))]);
+ }
$route->setOption('_auth', $rest_resource_config->getAuthenticationProviders($method));
$route->setDefault('_rest_resource_config', $rest_resource_config->id());
$collection->add("rest.$name", $route);
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Block/BlockResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Block/BlockResourceTestBase.php
index 0be7622..d86f9b1 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/Block/BlockResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/Block/BlockResourceTestBase.php
@@ -122,9 +122,7 @@ protected function getExpectedCacheContexts() {
protected function getExpectedCacheTags() {
// Because the 'user.permissions' cache context is missing, the cache tag
// for the anonymous user role is never added automatically.
- return array_values(array_filter(parent::getExpectedCacheTags(), function ($tag) {
- return $tag !== 'config:user.role.anonymous';
- }));
+ return array_values(array_diff(parent::getExpectedCacheTags(), ['config:user.role.anonymous']));
}
/**
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php
index 7fe517a..a731727 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php
@@ -280,8 +280,8 @@ public function testPostDxWithoutCriticalBaseFields() {
$response = $this->request('POST', $url, $request_options);
// @todo Uncomment, remove next 3 lines in https://www.drupal.org/node/2820364.
$this->assertSame(500, $response->getStatusCode());
- $this->assertSame(['application/json'], $response->getHeader('Content-Type'));
- $this->assertSame('{"message":"A fatal error occurred: Internal Server Error"}', (string) $response->getBody());
+ $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
+ $this->assertStringStartsWith('The website encountered an unexpected error. Please try again later.Symfony\Component\HttpKernel\Exception\HttpException: Internal Server Error in Drupal\rest\Plugin\rest\resource\EntityResource->post()', (string) $response->getBody());
//$this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response);
// DX: 422 when missing 'entity_id' field.
@@ -303,10 +303,9 @@ public function testPostDxWithoutCriticalBaseFields() {
// DX: 422 when missing 'entity_type' field.
$request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['field_name' => TRUE]), static::$format);
$response = $this->request('POST', $url, $request_options);
- // @todo Uncomment, remove next 3 lines in https://www.drupal.org/node/2820364.
+ // @todo Uncomment, remove next 2 lines in https://www.drupal.org/node/2820364.
$this->assertSame(500, $response->getStatusCode());
- $this->assertSame(['application/json'], $response->getHeader('Content-Type'));
- $this->assertSame('{"message":"A fatal error occurred: Field is unknown."}', (string) $response->getBody());
+ $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
//$this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nfield_name: This value should not be null.\n", $response);
}
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/ContentLanguageSettings/ContentLanguageSettingsJsonAnonTest.php b/core/modules/rest/tests/src/Functional/EntityResource/ContentLanguageSettings/ContentLanguageSettingsJsonAnonTest.php
new file mode 100644
index 0000000..344c733
--- /dev/null
+++ b/core/modules/rest/tests/src/Functional/EntityResource/ContentLanguageSettings/ContentLanguageSettingsJsonAnonTest.php
@@ -0,0 +1,24 @@
+grantPermissionsToTestedRole(['administer languages']);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function createEntity() {
+ // Create a "Camelids" node type.
+ $camelids = NodeType::create([
+ 'name' => 'Camelids',
+ 'type' => 'camelids',
+ ]);
+ $camelids->save();
+
+ $entity = ContentLanguageSettings::create([
+ 'target_entity_type_id' => 'node',
+ 'target_bundle' => 'camelids',
+ ]);
+ $entity->setDefaultLangcode('site_default')
+ ->save();
+
+ return $entity;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExpectedNormalizedEntity() {
+ return [
+ 'default_langcode' => 'site_default',
+ 'dependencies' => [
+ 'config' => [
+ 'node.type.camelids',
+ ],
+ ],
+ 'id' => 'node.camelids',
+ 'langcode' => 'en',
+ 'language_alterable' => FALSE,
+ 'status' => TRUE,
+ 'target_bundle' => 'camelids',
+ 'target_entity_type_id' => 'node',
+ 'uuid' => $this->entity->uuid(),
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getNormalizedPostEntity() {
+ // @todo Update in https://www.drupal.org/node/2300677.
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExpectedCacheContexts() {
+ return [
+ 'languages:language_interface',
+ 'user.permissions',
+ ];
+ }
+
+}
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Editor/EditorJsonAnonTest.php b/core/modules/rest/tests/src/Functional/EntityResource/Editor/EditorJsonAnonTest.php
new file mode 100644
index 0000000..b01ac2a
--- /dev/null
+++ b/core/modules/rest/tests/src/Functional/EntityResource/Editor/EditorJsonAnonTest.php
@@ -0,0 +1,24 @@
+grantPermissionsToTestedRole(['administer filters']);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function createEntity() {
+ // Create a "Llama" filter format.
+ $llama_format = FilterFormat::create([
+ 'name' => 'Llama',
+ 'format' => 'llama',
+ 'langcode' => 'es',
+ 'filters' => [
+ 'filter_html' => [
+ 'status' => TRUE,
+ 'settings' => [
+ 'allowed_html' => ' ',
+ ],
+ ],
+ ],
+ ]);
+
+ $llama_format->save();
+
+ // Create a "Camelids" editor.
+ $camelids = Editor::create([
+ 'format' => 'llama',
+ 'editor' => 'ckeditor',
+ ]);
+ $camelids
+ ->setImageUploadSettings([
+ 'status' => FALSE,
+ 'scheme' => file_default_scheme(),
+ 'directory' => 'inline-images',
+ 'max_size' => '',
+ 'max_dimensions' => [
+ 'width' => '',
+ 'height' => '',
+ ],
+ ])
+ ->save();
+
+ return $camelids;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExpectedNormalizedEntity() {
+ return [
+ 'dependencies' => [
+ 'config' => [
+ 'filter.format.llama',
+ ],
+ 'module' => [
+ 'ckeditor',
+ ],
+ ],
+ 'editor' => 'ckeditor',
+ 'format' => 'llama',
+ 'image_upload' => [
+ 'status' => FALSE,
+ 'scheme' => 'public',
+ 'directory' => 'inline-images',
+ 'max_size' => '',
+ 'max_dimensions' => [
+ 'width' => NULL,
+ 'height' => NULL,
+ ],
+ ],
+ 'langcode' => 'en',
+ 'settings' => [
+ 'toolbar' => [
+ 'rows' => [
+ [
+ [
+ 'name' => 'Formatting',
+ 'items' => [
+ 'Bold',
+ 'Italic',
+ ],
+ ],
+ [
+ 'name' => 'Links',
+ 'items' => [
+ 'DrupalLink',
+ 'DrupalUnlink',
+ ],
+ ],
+ [
+ 'name' => 'Lists',
+ 'items' => [
+ 'BulletedList',
+ 'NumberedList',
+ ],
+ ],
+ [
+ 'name' => 'Media',
+ 'items' => [
+ 'Blockquote',
+ 'DrupalImage',
+ ],
+ ],
+ [
+ 'name' => 'Tools',
+ 'items' => [
+ 'Source',
+ ],
+ ],
+ ],
+ ],
+ ],
+ 'plugins' => [
+ 'language' => [
+ 'language_list' => 'un',
+ ],
+ ],
+ ],
+ 'status' => TRUE,
+ 'uuid' => $this->entity->uuid(),
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getNormalizedPostEntity() {
+ // @todo Update in https://www.drupal.org/node/2300677.
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExpectedCacheContexts() {
+ // @see ::createEntity()
+ return ['user.permissions'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExpectedUnauthorizedAccessMessage($method) {
+ if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
+ return parent::getExpectedUnauthorizedAccessMessage($method);
+ }
+
+ return "The 'administer filters' permission is required.";
+ }
+
+}
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
index e7ce862..81baf9e 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
@@ -531,17 +531,17 @@ public function testGet() {
// DX: 406 when requesting unsupported format.
$response = $this->request('GET', $url, $request_options);
$this->assert406Response($response);
- $this->assertNotSame([static::$mimeType], $response->getHeader('Content-Type'));
+ $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
$request_options[RequestOptions::HEADERS]['Accept'] = static::$mimeType;
- // DX: 406 when requesting unsupported format but specifying Accept header.
- // @todo Update in https://www.drupal.org/node/2825347.
+ // DX: 406 when requesting unsupported format but specifying Accept header:
+ // should result in a text/plain response.
$response = $this->request('GET', $url, $request_options);
$this->assert406Response($response);
- $this->assertSame(['application/json'], $response->getHeader('Content-Type'));
+ $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
$url = Url::fromRoute('rest.entity.' . static::$entityTypeId . '.GET.' . static::$format);
@@ -634,7 +634,7 @@ public function testPost() {
// missing ?_format query string.
$response = $this->request('POST', $url, $request_options);
$this->assertSame(415, $response->getStatusCode());
- $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type'));
+ $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
$this->assertContains(htmlspecialchars('No "Content-Type" request header specified'), (string) $response->getBody());
@@ -724,10 +724,7 @@ public function testPost() {
// DX: 415 when request body in existing but not allowed format.
$response = $this->request('POST', $url, $request_options);
- // @todo Update this in https://www.drupal.org/node/2826407. Also move it
- // higher, before the "no request body" test. That's impossible right now,
- // because the format validation happens too late.
- $this->assertResourceErrorResponse(415, '', $response);
+ $this->assertResourceErrorResponse(415, 'No route found that matches "Content-Type: text/xml"', $response);
$request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType;
@@ -807,7 +804,7 @@ public function testPatch() {
if ($has_canonical_url) {
$this->assertSame(405, $response->getStatusCode());
$this->assertSame(['GET, POST, HEAD'], $response->getHeader('Allow'));
- $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type'));
+ $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
}
else {
$this->assertSame(404, $response->getStatusCode());
@@ -836,7 +833,7 @@ public function testPatch() {
// DX: 415 when no Content-Type request header.
$response = $this->request('PATCH', $url, $request_options);
$this->assertSame(415, $response->getStatusCode());
- $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type'));
+ $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
$this->assertTrue(FALSE !== strpos((string) $response->getBody(), htmlspecialchars('No "Content-Type" request header specified')));
@@ -936,10 +933,7 @@ public function testPatch() {
// DX: 415 when request body in existing but not allowed format.
$response = $this->request('PATCH', $url, $request_options);
- // @todo Update this in https://www.drupal.org/node/2826407. Also move it
- // higher, before the "no request body" test. That's impossible right now,
- // because the format validation happens too late.
- $this->assertResourceErrorResponse(415, '', $response);
+ $this->assertResourceErrorResponse(415, 'No route found that matches "Content-Type: text/xml"', $response);
$request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType;
@@ -996,13 +990,13 @@ public function testDelete() {
$request_options = [];
- // DX: 405 when resource not provisioned, but HTML if canonical route. Plain
+ // DX: 404 when resource not provisioned, but 405 if canonical route. Plain
// text or HTML response because missing ?_format query string.
$response = $this->request('DELETE', $url, $request_options);
if ($has_canonical_url) {
$this->assertSame(405, $response->getStatusCode());
$this->assertSame(['GET, POST, HEAD'], $response->getHeader('Allow'));
- $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type'));
+ $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
}
else {
$this->assertSame(404, $response->getStatusCode());
@@ -1103,10 +1097,9 @@ protected function assertNormalizationEdgeCases($method, Url $url, array $reques
$request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
- // DX: 400 when incorrect entity type bundle is specified.
- // @todo Change to 422 in https://www.drupal.org/node/2827084.
+ // DX: 422 when incorrect entity type bundle is specified.
$response = $this->request($method, $url, $request_options);
- $this->assertResourceErrorResponse(400, '"bad_bundle_name" is not a valid bundle type for denormalization.', $response);
+ $this->assertResourceErrorResponse(422, '"bad_bundle_name" is not a valid bundle type for denormalization.', $response);
}
@@ -1114,10 +1107,9 @@ protected function assertNormalizationEdgeCases($method, Url $url, array $reques
$request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
- // DX: 400 when no entity type bundle is specified.
- // @todo Change to 422 in https://www.drupal.org/node/2827084.
+ // DX: 422 when no entity type bundle is specified.
$response = $this->request($method, $url, $request_options);
- $this->assertResourceErrorResponse(400, sprintf('Could not determine entity type bundle: "%s" field is missing.', $bundle_field_name), $response);
+ $this->assertResourceErrorResponse(422, sprintf('Could not determine entity type bundle: "%s" field is missing.', $bundle_field_name), $response);
}
}
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/FieldConfig/FieldConfigJsonAnonTest.php b/core/modules/rest/tests/src/Functional/EntityResource/FieldConfig/FieldConfigJsonAnonTest.php
new file mode 100644
index 0000000..0e6883a
--- /dev/null
+++ b/core/modules/rest/tests/src/Functional/EntityResource/FieldConfig/FieldConfigJsonAnonTest.php
@@ -0,0 +1,24 @@
+grantPermissionsToTestedRole(['administer node fields']);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function createEntity() {
+ $camelids = NodeType::create([
+ 'name' => 'Camelids',
+ 'type' => 'camelids',
+ ]);
+ $camelids->save();
+
+ $field_storage = FieldStorageConfig::create([
+ 'field_name' => 'field_llama',
+ 'entity_type' => 'node',
+ 'type' => 'text',
+ ]);
+ $field_storage->save();
+
+ $entity = FieldConfig::create([
+ 'field_storage' => $field_storage,
+ 'bundle' => 'camelids',
+ ]);
+ $entity->save();
+
+ return $entity;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExpectedNormalizedEntity() {
+ return [
+ 'bundle' => 'camelids',
+ 'default_value' => [],
+ 'default_value_callback' => '',
+ 'dependencies' => [
+ 'config' => [
+ 'field.storage.node.field_llama',
+ 'node.type.camelids',
+ ],
+ 'module' => [
+ 'text',
+ ],
+ ],
+ 'description' => '',
+ 'entity_type' => 'node',
+ 'field_name' => 'field_llama',
+ 'field_type' => 'text',
+ 'id' => 'node.camelids.field_llama',
+ 'label' => 'field_llama',
+ 'langcode' => 'en',
+ 'required' => FALSE,
+ 'settings' => [],
+ 'status' => TRUE,
+ 'translatable' => TRUE,
+ 'uuid' => $this->entity->uuid(),
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getNormalizedPostEntity() {
+ // @todo Update in https://www.drupal.org/node/2300677.
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExpectedCacheContexts() {
+ return [
+ 'user.permissions',
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExpectedUnauthorizedAccessMessage($method) {
+ if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
+ return parent::getExpectedUnauthorizedAccessMessage($method);
+ }
+
+ return "The 'administer node fields' permission is required.";
+ }
+
+}
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php
index cfbd971..92fad1e 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php
@@ -23,7 +23,6 @@
* {@inheritdoc}
*/
protected static $patchProtectedFieldNames = [
- 'uid',
'created',
'changed',
'promote',
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/RestResourceConfig/RestResourceConfigJsonAnonTest.php b/core/modules/rest/tests/src/Functional/EntityResource/RestResourceConfig/RestResourceConfigJsonAnonTest.php
new file mode 100644
index 0000000..df07140
--- /dev/null
+++ b/core/modules/rest/tests/src/Functional/EntityResource/RestResourceConfig/RestResourceConfigJsonAnonTest.php
@@ -0,0 +1,24 @@
+grantPermissionsToTestedRole(['administer rest resources']);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function createEntity() {
+ $rest_resource_config = RestResourceConfig::create([
+ 'id' => 'llama',
+ 'plugin_id' => 'dblog',
+ 'granularity' => 'method',
+ 'configuration' => [
+ 'GET' => [
+ 'supported_formats' => [
+ 'json',
+ ],
+ 'supported_auth' => [
+ 'cookie',
+ ],
+ ],
+ ],
+ ]);
+ $rest_resource_config->save();
+
+ return $rest_resource_config;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExpectedNormalizedEntity() {
+ return [
+ 'uuid' => $this->entity->uuid(),
+ 'langcode' => 'en',
+ 'status' => TRUE,
+ 'dependencies' => [
+ 'module' => [
+ 'dblog',
+ 'serialization',
+ 'user',
+ ],
+ ],
+ 'id' => 'llama',
+ 'plugin_id' => 'dblog',
+ 'granularity' => 'method',
+ 'configuration' => [
+ 'GET' => [
+ 'supported_formats' => [
+ 'json',
+ ],
+ 'supported_auth' => [
+ 'cookie',
+ ],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getNormalizedPostEntity() {
+ // @todo Update in https://www.drupal.org/node/2300677.
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExpectedCacheContexts() {
+ return [
+ 'user.permissions',
+ ];
+ }
+
+}
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/ShortcutSet/ShortcutSetJsonAnonTest.php b/core/modules/rest/tests/src/Functional/EntityResource/ShortcutSet/ShortcutSetJsonAnonTest.php
new file mode 100644
index 0000000..3720ac6
--- /dev/null
+++ b/core/modules/rest/tests/src/Functional/EntityResource/ShortcutSet/ShortcutSetJsonAnonTest.php
@@ -0,0 +1,24 @@
+grantPermissionsToTestedRole(['access shortcuts']);
+ break;
+
+ case 'POST':
+ case 'PATCH':
+ $this->grantPermissionsToTestedRole(['access shortcuts', 'customize shortcut links']);
+ break;
+
+ case 'DELETE':
+ $this->grantPermissionsToTestedRole(['administer shortcuts']);
+ break;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function createEntity() {
+ $set = ShortcutSet::create([
+ 'id' => 'llama_set',
+ 'label' => 'Llama Set',
+ ]);
+ $set->save();
+ return $set;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExpectedNormalizedEntity() {
+ return [
+ 'id' => 'llama_set',
+ 'uuid' => $this->entity->uuid(),
+ 'label' => 'Llama Set',
+ 'status' => TRUE,
+ 'langcode' => 'en',
+ 'dependencies' => [],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getNormalizedPostEntity() {
+ // @todo Update in https://www.drupal.org/node/2300677.
+ }
+
+}
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php
index 04fe435..199ac09 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php
@@ -213,7 +213,7 @@ public function testPatchDxForSecuritySensitiveBaseFields() {
RequestOptions::HEADERS => [],
RequestOptions::BODY => $this->serializer->encode($request_body, 'json'),
];
- $response = $this->httpClient->request('POST', Url::fromRoute('user.login.http')->setRouteParameter('_format', 'json')->toString(), $request_options);
+ $response = $this->request('POST', Url::fromRoute('user.login.http')->setRouteParameter('_format', 'json'), $request_options);
$this->assertSame(200, $response->getStatusCode());
}
diff --git a/core/modules/rest/tests/src/Functional/ResourceTestBase.php b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
index c346157..c9e4c44 100644
--- a/core/modules/rest/tests/src/Functional/ResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
@@ -94,11 +94,6 @@
public static $modules = ['rest'];
/**
- * @var \GuzzleHttp\ClientInterface
- */
- protected $httpClient;
-
- /**
* {@inheritdoc}
*/
public function setUp() {
@@ -135,10 +130,6 @@ public function setUp() {
// Ensure there's a clean slate: delete all REST resource config entities.
$this->resourceConfigStorage->delete($this->resourceConfigStorage->loadMultiple());
$this->refreshTestStateAfterRestConfigChange();
-
- // Set up a HTTP client that accepts relative URLs.
- $this->httpClient = $this->container->get('http_client_factory')
- ->fromOptions(['base_uri' => $this->baseUrl]);
}
/**
@@ -344,7 +335,8 @@ protected function grantPermissionsToTestedRole(array $permissions) {
protected function request($method, Url $url, array $request_options) {
$request_options[RequestOptions::HTTP_ERRORS] = FALSE;
$request_options = $this->decorateWithXdebugCookie($request_options);
- return $this->httpClient->request($method, $url->toString(), $request_options);
+ $client = $this->getSession()->getDriver()->getClient()->getClient();
+ return $client->request($method, $url->setAbsolute(TRUE)->toString(), $request_options);
}
/**
diff --git a/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php b/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php
index b417e2a..2b88559 100644
--- a/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php
+++ b/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php
@@ -49,7 +49,7 @@ public function setUp() {
*/
public function testHandle() {
$request = new Request();
- $route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_format' => 'json']));
+ $route_match = new RouteMatch('test', (new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_format' => 'json']))->setMethods(['GET']));
$resource = $this->prophesize(StubRequestHandlerResourcePlugin::class);
$resource->get(NULL, $request)
@@ -76,7 +76,7 @@ public function testHandle() {
$this->assertEquals($response, $handler_response);
// We will call the patch method this time.
- $route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_content_type_format' => 'json']));
+ $route_match = new RouteMatch('test', (new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_content_type_format' => 'json']))->setMethods(['PATCH']));
$request->setMethod('PATCH');
$response = new ResourceResponse([]);
$resource->patch(NULL, $request)
diff --git a/core/modules/search/search.module b/core/modules/search/search.module
index bf00878..ae99a87 100644
--- a/core/modules/search/search.module
+++ b/core/modules/search/search.module
@@ -8,6 +8,7 @@
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Cache\Cache;
+use Drupal\Core\Database\Query\Condition;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
@@ -218,7 +219,7 @@ function search_update_totals() {
// search_total. We use a LEFT JOIN between the two tables and keep only the
// rows which fail to join.
$result = db_query("SELECT t.word AS realword, i.word FROM {search_total} t LEFT JOIN {search_index} i ON t.word = i.word WHERE i.word IS NULL", [], ['target' => 'replica']);
- $or = db_or();
+ $or = new Condition('OR');
foreach ($result as $word) {
$or->condition('word', $word->realword);
}
diff --git a/core/modules/search/src/Controller/SearchController.php b/core/modules/search/src/Controller/SearchController.php
index ac078e1..4beb844 100644
--- a/core/modules/search/src/Controller/SearchController.php
+++ b/core/modules/search/src/Controller/SearchController.php
@@ -5,6 +5,7 @@
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Render\RendererInterface;
+use Drupal\search\Form\SearchPageForm;
use Drupal\search\SearchPageInterface;
use Drupal\search\SearchPageRepositoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -84,7 +85,7 @@ public function view(Request $request, SearchPageInterface $entity) {
}
$build['#title'] = $plugin->suggestedTitle();
- $build['search_form'] = $this->entityFormBuilder()->getForm($entity, 'search');
+ $build['search_form'] = $this->formBuilder()->getForm(SearchPageForm::class, $entity);
// Build search results, if keywords or other search parameters are in the
// GET parameters. Note that we need to try the search if 'keys' is in
diff --git a/core/modules/search/src/Entity/SearchPage.php b/core/modules/search/src/Entity/SearchPage.php
index 298331f..85ddc26 100644
--- a/core/modules/search/src/Entity/SearchPage.php
+++ b/core/modules/search/src/Entity/SearchPage.php
@@ -22,7 +22,6 @@
* "form" = {
* "add" = "Drupal\search\Form\SearchPageAddForm",
* "edit" = "Drupal\search\Form\SearchPageEditForm",
- * "search" = "Drupal\search\Form\SearchPageForm",
* "delete" = "Drupal\Core\Entity\EntityDeleteForm"
* }
* },
diff --git a/core/modules/search/src/Form/SearchPageForm.php b/core/modules/search/src/Form/SearchPageForm.php
index 88b99e5..e46195b 100644
--- a/core/modules/search/src/Form/SearchPageForm.php
+++ b/core/modules/search/src/Form/SearchPageForm.php
@@ -2,9 +2,10 @@
namespace Drupal\search\Form;
-use Drupal\Core\Entity\EntityForm;
+use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
+use Drupal\search\SearchPageInterface;
/**
* Provides a search form for site wide search.
@@ -15,10 +16,10 @@
* trigger the search being processed by the controller, and adding in any
* additional query parameters they need to execute search.
*/
-class SearchPageForm extends EntityForm {
+class SearchPageForm extends FormBase {
/**
- * {@inheritdoc}
+ * The search page entity.
*
* @var \Drupal\search\SearchPageInterface
*/
@@ -34,7 +35,9 @@ public function getFormId() {
/**
* {@inheritdoc}
*/
- public function form(array $form, FormStateInterface $form_state) {
+ public function buildForm(array $form, FormStateInterface $form_state, SearchPageInterface $search_page = NULL) {
+ $this->entity = $search_page;
+
$plugin = $this->entity->getPlugin();
$form_state->set('search_page_id', $this->entity->id());
@@ -72,16 +75,7 @@ public function form(array $form, FormStateInterface $form_state) {
// Allow the plugin to add to or alter the search form.
$plugin->searchFormAlter($form, $form_state);
-
- return parent::form($form, $form_state);
- }
-
- /**
- * {@inheritdoc}
- */
- protected function actions(array $form, FormStateInterface $form_state) {
- // The submit button is added in the form directly.
- return [];
+ return $form;
}
/**
diff --git a/core/modules/search/src/Plugin/ConfigurableSearchPluginBase.php b/core/modules/search/src/Plugin/ConfigurableSearchPluginBase.php
index 50a44db..7ad95f1 100644
--- a/core/modules/search/src/Plugin/ConfigurableSearchPluginBase.php
+++ b/core/modules/search/src/Plugin/ConfigurableSearchPluginBase.php
@@ -23,7 +23,7 @@
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
- $this->configuration = NestedArray::mergeDeep($this->defaultConfiguration(), $this->configuration);
+ $this->setConfiguration($configuration);
}
/**
@@ -44,7 +44,7 @@ public function getConfiguration() {
* {@inheritdoc}
*/
public function setConfiguration(array $configuration) {
- $this->configuration = $configuration;
+ $this->configuration = NestedArray::mergeDeep($this->defaultConfiguration(), $configuration);
}
/**
diff --git a/core/modules/search/src/Plugin/SearchInterface.php b/core/modules/search/src/Plugin/SearchInterface.php
index 2f2403c..8f95ce8 100644
--- a/core/modules/search/src/Plugin/SearchInterface.php
+++ b/core/modules/search/src/Plugin/SearchInterface.php
@@ -110,7 +110,7 @@ public function getHelp();
*
* The core search module only invokes this method on active module plugins
* when building a form for them in
- * \Drupal\search\Form\SearchPageForm::form(). A plugin implementing this
+ * \Drupal\search\Form\SearchPageForm::buildForm(). A plugin implementing this
* will also need to implement the buildSearchUrlQuery() method.
*
* @param array $form
diff --git a/core/modules/search/src/Plugin/views/argument/Search.php b/core/modules/search/src/Plugin/views/argument/Search.php
index 82afbbf..7e9f00d 100644
--- a/core/modules/search/src/Plugin/views/argument/Search.php
+++ b/core/modules/search/src/Plugin/views/argument/Search.php
@@ -2,6 +2,7 @@
namespace Drupal\search\Plugin\views\argument;
+use Drupal\Core\Database\Query\Condition;
use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\ViewExecutable;
@@ -76,7 +77,7 @@ public function query($group_by = FALSE) {
else {
$search_index = $this->ensureMyTable();
- $search_condition = db_and();
+ $search_condition = new Condition('AND');
// Create a new join to relate the 'search_total' table to our current 'search_index' table.
$definition = [
@@ -109,7 +110,7 @@ public function query($group_by = FALSE) {
// Add the keyword conditions, as is done in
// SearchQuery::prepareAndNormalize(), but simplified because we are
// only concerned with relevance ranking so we do not need to normalize.
- $or = db_or();
+ $or = new Condition('OR');
foreach ($words as $word) {
$or->condition("$search_index.word", $word);
}
diff --git a/core/modules/search/src/Plugin/views/filter/Search.php b/core/modules/search/src/Plugin/views/filter/Search.php
index c95fd96..ac0f671 100644
--- a/core/modules/search/src/Plugin/views/filter/Search.php
+++ b/core/modules/search/src/Plugin/views/filter/Search.php
@@ -2,6 +2,7 @@
namespace Drupal\search\Plugin\views\filter;
+use Drupal\Core\Database\Query\Condition;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\filter\FilterPluginBase;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
@@ -150,7 +151,7 @@ public function query() {
else {
$search_index = $this->ensureMyTable();
- $search_condition = db_and();
+ $search_condition = new Condition('AND');
// Create a new join to relate the 'search_total' table to our current
// 'search_index' table.
@@ -184,7 +185,7 @@ public function query() {
// Add the keyword conditions, as is done in
// SearchQuery::prepareAndNormalize(), but simplified because we are
// only concerned with relevance ranking so we do not need to normalize.
- $or = db_or();
+ $or = new Condition('OR');
foreach ($words as $word) {
$or->condition("$search_index.word", $word);
}
diff --git a/core/modules/search/src/SearchQuery.php b/core/modules/search/src/SearchQuery.php
index 7c4e07e..dbd0534 100644
--- a/core/modules/search/src/SearchQuery.php
+++ b/core/modules/search/src/SearchQuery.php
@@ -2,6 +2,7 @@
namespace Drupal\search;
+use Drupal\Core\Database\Query\Condition;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Database\Query\SelectExtender;
use Drupal\Core\Database\Query\SelectInterface;
@@ -205,7 +206,7 @@ public function searchExpression($expression, $type) {
$this->addTag('search_' . $type);
// Initialize conditions and status.
- $this->conditions = db_and();
+ $this->conditions = new Condition('AND');
$this->status = 0;
return $this;
@@ -313,7 +314,7 @@ protected function parseSearchExpression() {
}
$has_or = TRUE;
$has_new_scores = FALSE;
- $queryor = db_or();
+ $queryor = new Condition('OR');
foreach ($key as $or) {
list($num_new_scores) = $this->parseWord($or);
$has_new_scores |= $num_new_scores;
@@ -401,7 +402,7 @@ public function prepareAndNormalize() {
}
// Build the basic search query: match the entered keywords.
- $or = db_or();
+ $or = new Condition('OR');
foreach ($this->words as $word) {
$or->condition('i.word', $word);
}
diff --git a/core/modules/search/src/ViewsSearchQuery.php b/core/modules/search/src/ViewsSearchQuery.php
index ca4b16c..ca804a8 100644
--- a/core/modules/search/src/ViewsSearchQuery.php
+++ b/core/modules/search/src/ViewsSearchQuery.php
@@ -74,8 +74,8 @@ public function conditionReplaceString($search, $replace, &$condition) {
$conditions =& $condition['field']->conditions();
foreach ($conditions as $key => &$subcondition) {
if (is_numeric($key)) {
- // As conditions can have subconditions, for example db_or(), the
- // function has to be called recursively.
+ // As conditions can be nested, the function has to be called
+ // recursively.
$this->conditionReplaceString($search, $replace, $subcondition);
}
}
diff --git a/core/modules/serialization/serialization.services.yml b/core/modules/serialization/serialization.services.yml
index 3e47b00..3607182 100644
--- a/core/modules/serialization/serialization.services.yml
+++ b/core/modules/serialization/serialization.services.yml
@@ -33,6 +33,7 @@ services:
# this modules generic field item normalizer.
# @todo Find a better way for this in https://www.drupal.org/node/2575761.
- { name: normalizer, priority: 8 }
+ arguments: ['@entity.repository']
serialization.normalizer.field_item:
class: Drupal\serialization\Normalizer\FieldItemNormalizer
tags:
diff --git a/core/modules/serialization/src/Normalizer/EntityReferenceFieldItemNormalizer.php b/core/modules/serialization/src/Normalizer/EntityReferenceFieldItemNormalizer.php
index 4706bf4..ea2e020 100644
--- a/core/modules/serialization/src/Normalizer/EntityReferenceFieldItemNormalizer.php
+++ b/core/modules/serialization/src/Normalizer/EntityReferenceFieldItemNormalizer.php
@@ -2,12 +2,15 @@
namespace Drupal\serialization\Normalizer;
+use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
+use Symfony\Component\Serializer\Exception\UnexpectedValueException;
/**
* Adds the file URI to embedded file entities.
*/
-class EntityReferenceFieldItemNormalizer extends ComplexDataNormalizer {
+class EntityReferenceFieldItemNormalizer extends FieldItemNormalizer {
/**
* The interface or class that this Normalizer supports.
@@ -17,6 +20,23 @@ class EntityReferenceFieldItemNormalizer extends ComplexDataNormalizer {
protected $supportedInterfaceOrClass = EntityReferenceItem::class;
/**
+ * The entity repository.
+ *
+ * @var \Drupal\Core\Entity\EntityRepositoryInterface
+ */
+ protected $entityRepository;
+
+ /**
+ * Constructs a EntityReferenceFieldItemNormalizer object.
+ *
+ * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
+ * The entity repository.
+ */
+ public function __construct(EntityRepositoryInterface $entity_repository) {
+ $this->entityRepository = $entity_repository;
+ }
+
+ /**
* {@inheritdoc}
*/
public function normalize($field_item, $format = NULL, array $context = []) {
@@ -35,8 +55,32 @@ public function normalize($field_item, $format = NULL, array $context = []) {
$values['url'] = $url;
}
}
-
return $values;
}
+ /**
+ * {@inheritdoc}
+ */
+ protected function constructValue($data, $context) {
+ if (isset($data['target_uuid'])) {
+ /** @var \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $field_item */
+ $field_item = $context['target_instance'];
+ if (empty($data['target_uuid'])) {
+ throw new InvalidArgumentException(sprintf('If provided "target_uuid" cannot be empty for field "%s".', $data['target_type'], $data['target_uuid'], $field_item->getName()));
+ }
+ $target_type = $field_item->getFieldDefinition()->getSetting('target_type');
+ if (!empty($data['target_type']) && $target_type !== $data['target_type']) {
+ throw new UnexpectedValueException(sprintf('The field "%s" property "target_type" must be set to "%s" or omitted.', $field_item->getFieldDefinition()->getName(), $target_type));
+ }
+ if ($entity = $this->entityRepository->loadEntityByUuid($target_type, $data['target_uuid'])) {
+ return ['target_id' => $entity->id()];
+ }
+ else {
+ // Unable to load entity by uuid.
+ throw new InvalidArgumentException(sprintf('No "%s" entity found with UUID "%s" for field "%s".', $data['target_type'], $data['target_uuid'], $field_item->getName()));
+ }
+ }
+ return parent::constructValue($data, $context);
+ }
+
}
diff --git a/core/modules/serialization/tests/src/Unit/CompilerPass/RegisterSerializationClassesCompilerPassTest.php b/core/modules/serialization/tests/src/Unit/CompilerPass/RegisterSerializationClassesCompilerPassTest.php
index 630535d..f9a5b77 100644
--- a/core/modules/serialization/tests/src/Unit/CompilerPass/RegisterSerializationClassesCompilerPassTest.php
+++ b/core/modules/serialization/tests/src/Unit/CompilerPass/RegisterSerializationClassesCompilerPassTest.php
@@ -4,6 +4,7 @@
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\serialization\RegisterSerializationClassesCompilerPass;
+use Drupal\Tests\UnitTestCase;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\Serializer\Serializer;
@@ -11,7 +12,7 @@
* @coversDefaultClass \Drupal\serialization\RegisterSerializationClassesCompilerPass
* @group serialization
*/
-class RegisterSerializationClassesCompilerPassTest extends \PHPUnit_Framework_TestCase {
+class RegisterSerializationClassesCompilerPassTest extends UnitTestCase {
/**
* @covers ::process
diff --git a/core/modules/serialization/tests/src/Unit/Normalizer/EntityReferenceFieldItemNormalizerTest.php b/core/modules/serialization/tests/src/Unit/Normalizer/EntityReferenceFieldItemNormalizerTest.php
index d010a04..e0561a1 100644
--- a/core/modules/serialization/tests/src/Unit/Normalizer/EntityReferenceFieldItemNormalizerTest.php
+++ b/core/modules/serialization/tests/src/Unit/Normalizer/EntityReferenceFieldItemNormalizerTest.php
@@ -3,11 +3,18 @@
namespace Drupal\Tests\serialization\Unit\Normalizer;
use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\Entity\EntityRepositoryInterface;
+use Drupal\Core\Entity\FieldableEntityInterface;
+use Drupal\Core\Field\FieldItemInterface;
+use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\serialization\Normalizer\EntityReferenceFieldItemNormalizer;
use Drupal\Tests\UnitTestCase;
use Prophecy\Argument;
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
+use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\Serializer\Serializer;
/**
@@ -38,10 +45,25 @@ class EntityReferenceFieldItemNormalizerTest extends UnitTestCase {
protected $fieldItem;
/**
+ * The mock entity repository.
+ *
+ * @var \Drupal\Core\Entity\EntityRepositoryInterface|\Prophecy\Prophecy\ObjectProphecy
+ */
+ protected $entityRepository;
+
+ /**
+ * The mock field definition.
+ *
+ * @var \Drupal\Core\Field\FieldDefinitionInterface|\Prophecy\Prophecy\ObjectProphecy
+ */
+ protected $fieldDefinition;
+
+ /**
* {@inheritdoc}
*/
protected function setUp() {
- $this->normalizer = new EntityReferenceFieldItemNormalizer();
+ $this->entityRepository = $this->prophesize(EntityRepositoryInterface::class);
+ $this->normalizer = new EntityReferenceFieldItemNormalizer($this->entityRepository->reveal());
$this->serializer = $this->prophesize(Serializer::class);
// Set up the serializer to return an entity property.
@@ -53,6 +75,9 @@ protected function setUp() {
$this->fieldItem = $this->prophesize(EntityReferenceItem::class);
$this->fieldItem->getIterator()
->willReturn(new \ArrayIterator(['target_id' => []]));
+
+ $this->fieldDefinition = $this->prophesize(FieldDefinitionInterface::class);
+
}
/**
@@ -64,6 +89,14 @@ public function testSupportsNormalization() {
}
/**
+ * @covers ::supportsDenormalization
+ */
+ public function testSupportsDenormalization() {
+ $this->assertTrue($this->normalizer->supportsDenormalization([], EntityReferenceItem::class));
+ $this->assertFalse($this->normalizer->supportsDenormalization([], FieldItemInterface::class));
+ }
+
+ /**
* @covers ::normalize
*/
public function testNormalize() {
@@ -121,4 +154,149 @@ public function testNormalizeWithNoEntity() {
$this->assertSame($expected, $normalized);
}
+ /**
+ * @covers ::denormalize
+ */
+ public function testDenormalizeWithTypeAndUuid() {
+ $data = [
+ 'target_id' => ['value' => 'test'],
+ 'target_type' => 'test_type',
+ 'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb',
+ ];
+
+ $entity = $this->prophesize(FieldableEntityInterface::class);
+ $entity->id()
+ ->willReturn('test')
+ ->shouldBeCalled();
+ $this->entityRepository
+ ->loadEntityByUuid($data['target_type'], $data['target_uuid'])
+ ->willReturn($entity)
+ ->shouldBeCalled();
+
+ $this->fieldItem->setValue(['target_id' => 'test'])->shouldBeCalled();
+
+ $this->assertDenormalize($data);
+ }
+
+ /**
+ * @covers ::denormalize
+ */
+ public function testDenormalizeWithUuidWithoutType() {
+ $data = [
+ 'target_id' => ['value' => 'test'],
+ 'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb',
+ ];
+
+ $entity = $this->prophesize(FieldableEntityInterface::class);
+ $entity->id()
+ ->willReturn('test')
+ ->shouldBeCalled();
+ $this->entityRepository
+ ->loadEntityByUuid('test_type', $data['target_uuid'])
+ ->willReturn($entity)
+ ->shouldBeCalled();
+
+ $this->fieldItem->setValue(['target_id' => 'test'])->shouldBeCalled();
+
+ $this->assertDenormalize($data);
+ }
+
+ /**
+ * @covers ::denormalize
+ */
+ public function testDenormalizeWithUuidWithIncorrectType() {
+ $this->setExpectedException(UnexpectedValueException::class, 'The field "field_reference" property "target_type" must be set to "test_type" or omitted.');
+
+ $data = [
+ 'target_id' => ['value' => 'test'],
+ 'target_type' => 'wrong_type',
+ 'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb',
+ ];
+
+ $this->fieldDefinition
+ ->getName()
+ ->willReturn('field_reference')
+ ->shouldBeCalled();
+
+ $this->assertDenormalize($data);
+ }
+
+ /**
+ * @covers ::denormalize
+ */
+ public function testDenormalizeWithTypeWithIncorrectUuid() {
+ $this->setExpectedException(InvalidArgumentException::class, 'No "test_type" entity found with UUID "unique-but-none-non-existent" for field "field_reference"');
+
+ $data = [
+ 'target_id' => ['value' => 'test'],
+ 'target_type' => 'test_type',
+ 'target_uuid' => 'unique-but-none-non-existent',
+ ];
+ $this->entityRepository
+ ->loadEntityByUuid($data['target_type'], $data['target_uuid'])
+ ->willReturn(NULL)
+ ->shouldBeCalled();
+ $this->fieldItem
+ ->getName()
+ ->willReturn('field_reference')
+ ->shouldBeCalled();
+
+
+ $this->assertDenormalize($data);
+ }
+
+ /**
+ * @covers ::denormalize
+ */
+ public function testDenormalizeWithEmtpyUuid() {
+ $this->setExpectedException(InvalidArgumentException::class, 'If provided "target_uuid" cannot be empty for field "test_type".');
+
+ $data = [
+ 'target_id' => ['value' => 'test'],
+ 'target_type' => 'test_type',
+ 'target_uuid' => '',
+ ];
+ $this->fieldItem
+ ->getName()
+ ->willReturn('field_reference')
+ ->shouldBeCalled();
+
+
+ $this->assertDenormalize($data);
+ }
+
+ /**
+ * @covers ::denormalize
+ */
+ public function testDenormalizeWithId() {
+ $data = [
+ 'target_id' => ['value' => 'test'],
+ ];
+ $this->fieldItem->setValue($data)->shouldBeCalled();
+
+ $this->assertDenormalize($data);
+ }
+
+ /**
+ * Asserts denormalization process is correct for give data.
+ *
+ * @param array $data
+ * The data to denormalize.
+ */
+ protected function assertDenormalize(array $data) {
+ $this->fieldItem->getParent()
+ ->willReturn($this->prophesize(FieldItemListInterface::class)->reveal());
+ $this->fieldItem->getFieldDefinition()->willReturn($this->fieldDefinition->reveal());
+ if (!empty($data['target_uuid'])) {
+ $this->fieldDefinition
+ ->getSetting('target_type')
+ ->willReturn('test_type')
+ ->shouldBeCalled();
+ }
+
+ $context = ['target_instance' => $this->fieldItem->reveal()];
+ $denormalized = $this->normalizer->denormalize($data, EntityReferenceItem::class, 'json', $context);
+ $this->assertSame($context['target_instance'], $denormalized);
+ }
+
}
diff --git a/core/modules/shortcut/src/ShortcutSetAccessControlHandler.php b/core/modules/shortcut/src/ShortcutSetAccessControlHandler.php
index b5ce0e8..3a55f74 100644
--- a/core/modules/shortcut/src/ShortcutSetAccessControlHandler.php
+++ b/core/modules/shortcut/src/ShortcutSetAccessControlHandler.php
@@ -19,6 +19,8 @@ class ShortcutSetAccessControlHandler extends EntityAccessControlHandler {
*/
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
switch ($operation) {
+ case 'view':
+ return AccessResult::allowedIf($account->hasPermission('access shortcuts'))->cachePerPermissions();
case 'update':
if ($account->hasPermission('administer shortcuts')) {
return AccessResult::allowed()->cachePerPermissions();
diff --git a/core/modules/simpletest/simpletest.install b/core/modules/simpletest/simpletest.install
index b6cfc80..5302288 100644
--- a/core/modules/simpletest/simpletest.install
+++ b/core/modules/simpletest/simpletest.install
@@ -6,6 +6,7 @@
*/
use Drupal\Component\Utility\Environment;
+use PHPUnit\Framework\TestCase;
/**
* Minimum value of PHP memory_limit for SimpleTest.
@@ -18,7 +19,7 @@
function simpletest_requirements($phase) {
$requirements = [];
- $has_phpunit = class_exists('\PHPUnit_Framework_TestCase');
+ $has_phpunit = class_exists(TestCase::class);
$has_curl = function_exists('curl_init');
$open_basedir = ini_get('open_basedir');
diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index 7d72aa4..8b1cc23 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -13,6 +13,7 @@
use Drupal\Core\Test\TestDatabase;
use Drupal\simpletest\TestDiscovery;
use Drupal\Tests\Listeners\SimpletestUiPrinter;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\Process\PhpExecutableFinder;
use Drupal\Core\Test\TestStatus;
@@ -412,7 +413,7 @@ function _simpletest_batch_operation($test_list_init, $test_id, &$context) {
// Perform the next test.
$test_class = array_shift($test_list);
- if (is_subclass_of($test_class, \PHPUnit_Framework_TestCase::class)) {
+ if (is_subclass_of($test_class, TestCase::class)) {
$phpunit_results = simpletest_run_phpunit_tests($test_id, [$test_class]);
simpletest_process_phpunit_results($phpunit_results);
$test_results[$test_class] = simpletest_summarize_phpunit_result($phpunit_results)[$test_class];
diff --git a/core/modules/simpletest/src/ContentTypeCreationTrait.php b/core/modules/simpletest/src/ContentTypeCreationTrait.php
index 9ad0a21..ec15b9a 100644
--- a/core/modules/simpletest/src/ContentTypeCreationTrait.php
+++ b/core/modules/simpletest/src/ContentTypeCreationTrait.php
@@ -4,6 +4,7 @@
use Drupal\Component\Render\FormattableMarkup;
use Drupal\node\Entity\NodeType;
+use PHPUnit\Framework\TestCase;
/**
* Provides methods to create content type from given values.
@@ -40,7 +41,7 @@ protected function createContentType(array $values = []) {
$status = $type->save();
node_add_body_field($type);
- if ($this instanceof \PHPUnit_Framework_TestCase) {
+ if ($this instanceof TestCase) {
$this->assertSame($status, SAVED_NEW, (new FormattableMarkup('Created content type %type.', ['%type' => $type->id()]))->__toString());
}
else {
diff --git a/core/modules/simpletest/src/Form/SimpletestTestForm.php b/core/modules/simpletest/src/Form/SimpletestTestForm.php
index f954546..1bf43ce 100644
--- a/core/modules/simpletest/src/Form/SimpletestTestForm.php
+++ b/core/modules/simpletest/src/Form/SimpletestTestForm.php
@@ -71,7 +71,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$form['clean'] = [
'#type' => 'fieldset',
'#title' => $this->t('Clean test environment'),
- '#description' => $this->t('Remove tables with the prefix "simpletest" and temporary directories that are left over from tests that crashed. This is intended for developers when creating tests.'),
+ '#description' => $this->t('Remove tables with the prefix "test" followed by digits and temporary directories that are left over from tests that crashed. This is intended for developers when creating tests.'),
'#weight' => 200,
];
$form['clean']['op'] = [
diff --git a/core/modules/simpletest/tests/fixtures/simpletest_phpunit_run_command_test.php b/core/modules/simpletest/tests/fixtures/simpletest_phpunit_run_command_test.php
index a4ffc7a..42dadfd 100644
--- a/core/modules/simpletest/tests/fixtures/simpletest_phpunit_run_command_test.php
+++ b/core/modules/simpletest/tests/fixtures/simpletest_phpunit_run_command_test.php
@@ -2,6 +2,8 @@
namespace Drupal\Tests\simpletest\Unit;
+use Drupal\Tests\UnitTestCase;
+
/**
* This test crashes PHP.
*
@@ -11,7 +13,7 @@
*
* @see \Drupal\Tests\simpletest\Unit\SimpletestPhpunitRunCommandTest::testSimpletestPhpUnitRunCommand()
*/
-class SimpletestPhpunitRunCommandTestWillDie extends \PHPUnit_Framework_TestCase {
+class SimpletestPhpunitRunCommandTestWillDie extends UnitTestCase {
/**
* Performs the status specified by SimpletestPhpunitRunCommandTestWillDie.
diff --git a/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php b/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php
index a96db96..63fe1bb 100644
--- a/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php
+++ b/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php
@@ -4,15 +4,19 @@
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\File\FileSystemInterface;
+use PHPUnit\Framework\TestCase;
/**
* Tests simpletest_run_phpunit_tests() handles PHPunit fatals correctly.
*
+ * We don't extend Drupal\Tests\UnitTestCase here because its $root property is
+ * not static and we need it to be static here.
+ *
* @group simpletest
*
* @runTestsInSeparateProcesses
*/
-class SimpletestPhpunitRunCommandTest extends \PHPUnit_Framework_TestCase {
+class SimpletestPhpunitRunCommandTest extends TestCase {
/**
* Path to the app root.
diff --git a/core/modules/statistics/src/StatisticsSettingsForm.php b/core/modules/statistics/src/StatisticsSettingsForm.php
index 71a1764..4c06e0b 100644
--- a/core/modules/statistics/src/StatisticsSettingsForm.php
+++ b/core/modules/statistics/src/StatisticsSettingsForm.php
@@ -21,7 +21,7 @@ class StatisticsSettingsForm extends ConfigFormBase {
protected $moduleHandler;
/**
- * Constructs a \Drupal\user\StatisticsSettingsForm object.
+ * Constructs a \Drupal\statistics\StatisticsSettingsForm object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The factory for configuration objects.
diff --git a/core/modules/statistics/src/StatisticsStorageInterface.php b/core/modules/statistics/src/StatisticsStorageInterface.php
index ccb51e4..ad6d6d5 100644
--- a/core/modules/statistics/src/StatisticsStorageInterface.php
+++ b/core/modules/statistics/src/StatisticsStorageInterface.php
@@ -27,7 +27,10 @@ public function recordView($id);
* @param array $ids
* An array of IDs of entities to fetch the views for.
*
- * @return array \Drupal\statistics\StatisticsViewsResult
+ * @return \Drupal\statistics\StatisticsViewsResult[]
+ * An array of value objects representing the number of times each entity
+ * has been viewed. The array is keyed by entity ID. If an ID does not
+ * exist, it will not be present in the array.
*/
public function fetchViews($ids);
@@ -37,7 +40,9 @@ public function fetchViews($ids);
* @param int $id
* The ID of the entity to fetch the views for.
*
- * @return \Drupal\statistics\StatisticsViewsResult
+ * @return \Drupal\statistics\StatisticsViewsResult|false
+ * If the entity exists, a value object representing the number of times if
+ * has been viewed. If it does not exist, FALSE is returned.
*/
public function fetchView($id);
diff --git a/core/modules/statistics/src/Tests/StatisticsLoggingTest.php b/core/modules/statistics/src/Tests/StatisticsLoggingTest.php
index 152c95a..a75f896 100644
--- a/core/modules/statistics/src/Tests/StatisticsLoggingTest.php
+++ b/core/modules/statistics/src/Tests/StatisticsLoggingTest.php
@@ -3,6 +3,7 @@
namespace Drupal\statistics\Tests;
use Drupal\simpletest\WebTestBase;
+use Drupal\node\Entity\Node;
/**
* Tests request logging for cached and uncached pages.
@@ -125,6 +126,17 @@ public function testLogging() {
$this->client->post($base_root . $stats_path, ['form_params' => $post]);
$node_counter = statistics_get($this->node->id());
$this->assertIdentical($node_counter['totalcount'], '1');
+
+ // Try fetching statistics for an invalid node ID and verify it returns
+ // FALSE.
+ $node_id = 1000000;
+ $node = Node::load($node_id);
+ $this->assertNull($node);
+
+ // This is a test specifically for the deprecated statistics_get() function
+ // and so should remain unconverted until that function is removed.
+ $result = statistics_get($node_id);
+ $this->assertIdentical($result, FALSE);
}
}
diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module
index a7f1e10..4d7f42a 100644
--- a/core/modules/statistics/statistics.module
+++ b/core/modules/statistics/statistics.module
@@ -10,6 +10,7 @@
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\node\NodeInterface;
+use Drupal\statistics\StatisticsViewsResult;
/**
* Implements hook_help().
@@ -125,6 +126,12 @@ function statistics_get($id) {
if ($id > 0) {
/** @var \Drupal\statistics\StatisticsViewsResult $statistics */
$statistics = \Drupal::service('statistics.storage.node')->fetchView($id);
+
+ // For backwards compatibility, return FALSE if an invalid node ID was
+ // passed in.
+ if (!($statistics instanceof StatisticsViewsResult)) {
+ return FALSE;
+ }
return [
'totalcount' => $statistics->getTotalCount(),
'daycount' => $statistics->getDayCount(),
diff --git a/core/modules/statistics/tests/src/Kernel/Migrate/d6/MigrateStatisticsConfigsTest.php b/core/modules/statistics/tests/src/Kernel/Migrate/d6/MigrateStatisticsConfigsTest.php
index da6ab30..a9c18a7 100644
--- a/core/modules/statistics/tests/src/Kernel/Migrate/d6/MigrateStatisticsConfigsTest.php
+++ b/core/modules/statistics/tests/src/Kernel/Migrate/d6/MigrateStatisticsConfigsTest.php
@@ -32,7 +32,7 @@ protected function setUp() {
*/
public function testStatisticsSettings() {
$config = $this->config('statistics.settings');
- $this->assertIdentical(0, $config->get('count_content_views'));
+ $this->assertSame(1, $config->get('count_content_views'));
$this->assertConfigSchema(\Drupal::service('config.typed'), 'statistics.settings', $config->get());
}
diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml
index c23ed7e..dce4e97 100644
--- a/core/modules/system/config/schema/system.schema.yml
+++ b/core/modules/system/config/schema/system.schema.yml
@@ -7,6 +7,8 @@ system.site:
uuid:
type: string
label: 'Site UUID'
+ constraints:
+ NotNull: []
name:
type: label
label: 'Site name'
diff --git a/core/modules/system/src/Form/CronForm.php b/core/modules/system/src/Form/CronForm.php
index d4726aa..0779c15 100644
--- a/core/modules/system/src/Form/CronForm.php
+++ b/core/modules/system/src/Form/CronForm.php
@@ -131,7 +131,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#type' => 'checkbox',
'#title' => t('Detailed cron logging'),
'#default_value' => $this->config('system.cron')->get('logging'),
- '#description' => 'Run times of individual cron jobs will be written to watchdog',
+ '#description' => $this->t('Run times of individual cron jobs will be written to watchdog'),
];
$form['actions']['#type'] = 'actions';
diff --git a/core/modules/system/src/Form/ModulesUninstallForm.php b/core/modules/system/src/Form/ModulesUninstallForm.php
index 80348c5..bcd6065 100644
--- a/core/modules/system/src/Form/ModulesUninstallForm.php
+++ b/core/modules/system/src/Form/ModulesUninstallForm.php
@@ -114,12 +114,15 @@ public function buildForm(array $form, FormStateInterface $form_state) {
return $form;
}
- $profile = drupal_get_profile();
+ $profiles = \Drupal::service('profile_handler')->getProfiles();
// Sort all modules by their name.
uasort($uninstallable, 'system_sort_modules_by_info_name');
$validation_reasons = $this->moduleInstaller->validateUninstall(array_keys($uninstallable));
+ // Remove any profiles from the list.
+ $uninstallable = array_diff_key($uninstallable, $profiles);
+
$form['uninstall'] = ['#tree' => TRUE];
foreach ($uninstallable as $module_key => $module) {
$name = $module->info['name'] ?: $module->getName();
@@ -140,10 +143,10 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$form['uninstall'][$module->getName()]['#disabled'] = TRUE;
}
// All modules which depend on this one must be uninstalled first, before
- // we can allow this module to be uninstalled. (The installation profile
- // is excluded from this list.)
+ // we can allow this module to be uninstalled. (Installation profiles are
+ // excluded from this list.)
foreach (array_keys($module->required_by) as $dependent) {
- if ($dependent != $profile && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED) {
+ if (!in_array($dependent, array_keys($profiles)) && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED) {
$name = isset($modules[$dependent]->info['name']) ? $modules[$dependent]->info['name'] : $dependent;
$form['modules'][$module->getName()]['#required_by'][] = $name;
$form['uninstall'][$module->getName()]['#disabled'] = TRUE;
diff --git a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
index c142c86..52daa09 100644
--- a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
+++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
@@ -5,7 +5,6 @@
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Menu\MenuActiveTrailInterface;
use Drupal\Core\Menu\MenuLinkTreeInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -30,13 +29,6 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
protected $menuTree;
/**
- * The active menu trail service.
- *
- * @var \Drupal\Core\Menu\MenuActiveTrailInterface
- */
- protected $menuActiveTrail;
-
- /**
* Constructs a new SystemMenuBlock.
*
* @param array $configuration
@@ -47,13 +39,10 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
* The plugin implementation definition.
* @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_tree
* The menu tree service.
- * @param \Drupal\Core\Menu\MenuActiveTrailInterface $menu_active_trail
- * The active menu trail service.
*/
- public function __construct(array $configuration, $plugin_id, $plugin_definition, MenuLinkTreeInterface $menu_tree, MenuActiveTrailInterface $menu_active_trail) {
+ public function __construct(array $configuration, $plugin_id, $plugin_definition, MenuLinkTreeInterface $menu_tree) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->menuTree = $menu_tree;
- $this->menuActiveTrail = $menu_active_trail;
}
/**
@@ -64,8 +53,7 @@ public static function create(ContainerInterface $container, array $configuratio
$configuration,
$plugin_id,
$plugin_definition,
- $container->get('menu.link_tree'),
- $container->get('menu.active_trail')
+ $container->get('menu.link_tree')
);
}
diff --git a/core/modules/system/src/Tests/Entity/Update/MoveRevisionMetadataFieldsUpdateTest.php b/core/modules/system/src/Tests/Entity/Update/MoveRevisionMetadataFieldsUpdateTest.php
new file mode 100644
index 0000000..ba7e028
--- /dev/null
+++ b/core/modules/system/src/Tests/Entity/Update/MoveRevisionMetadataFieldsUpdateTest.php
@@ -0,0 +1,83 @@
+databaseDumpFiles = [
+ __DIR__ . '/../../../../tests/fixtures/update/drupal-8.2.0.bare.standard_with_entity_test_revlog_enabled.php.gz',
+ __DIR__ . '/../../../../tests/fixtures/update/drupal-8.entity-data-revision-metadata-fields-2248983.php',
+ __DIR__ . '/../../../../tests/fixtures/update/drupal-8.views-revision-metadata-fields-2248983.php',
+ ];
+ }
+
+ /**
+ * Tests that the revision metadata fields are moved correctly.
+ */
+ public function testSystemUpdate8400() {
+ $this->runUpdates();
+
+ foreach (['entity_test_revlog', 'entity_test_mul_revlog'] as $entity_type_id) {
+ /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
+ $storage = \Drupal::entityTypeManager()->getStorage($entity_type_id);
+ /** @var \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type */
+ $entity_type = $storage->getEntityType();
+ $revision_metadata_field_names = $entity_type->getRevisionMetadataKeys();
+
+ $database_schema = \Drupal::database()->schema();
+
+ // Test that the revision metadata fields are present only in the
+ // revision table.
+ foreach ($revision_metadata_field_names as $revision_metadata_field_name) {
+ if ($entity_type->isTranslatable()) {
+ $this->assertFalse($database_schema->fieldExists($entity_type->getDataTable(), $revision_metadata_field_name));
+ $this->assertFalse($database_schema->fieldExists($entity_type->getRevisionDataTable(), $revision_metadata_field_name));
+ }
+ else {
+ $this->assertFalse($database_schema->fieldExists($entity_type->getBaseTable(), $revision_metadata_field_name));
+ }
+ $this->assertTrue($database_schema->fieldExists($entity_type->getRevisionTable(), $revision_metadata_field_name));
+ }
+
+ // Test that the revision metadata values have been transferred correctly
+ // and that the moved fields are accessible.
+ /** @var \Drupal\Core\Entity\RevisionLogInterface $entity_rev_first */
+ $entity_rev_first = $storage->loadRevision(1);
+ $this->assertEqual($entity_rev_first->getRevisionUserId(), '1');
+ $this->assertEqual($entity_rev_first->getRevisionLogMessage(), 'first revision');
+ $this->assertEqual($entity_rev_first->getRevisionCreationTime(), '1476268517');
+
+ /** @var \Drupal\Core\Entity\RevisionLogInterface $entity_rev_second */
+ $entity_rev_second = $storage->loadRevision(2);
+ $this->assertEqual($entity_rev_second->getRevisionUserId(), '1');
+ $this->assertEqual($entity_rev_second->getRevisionLogMessage(), 'second revision');
+ $this->assertEqual($entity_rev_second->getRevisionCreationTime(), '1476268518');
+
+
+ // Test that the views using revision metadata fields are updated
+ // properly.
+ $view = View::load($entity_type_id . '_for_2248983');
+ $displays = $view->get('display');
+ foreach ($displays as $display => $display_data) {
+ foreach ($display_data['display_options']['fields'] as $property_data) {
+ if (in_array($property_data['field'], $revision_metadata_field_names)) {
+ $this->assertEqual($property_data['table'], $entity_type->getRevisionTable());
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 61b2650..614ad9e 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -12,6 +12,9 @@
use Drupal\Core\Path\AliasStorage;
use Drupal\Core\Url;
use Drupal\Core\Database\Database;
+use Drupal\Core\Entity\ContentEntityTypeInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\DrupalKernel;
use Drupal\Core\Site\Settings;
use Drupal\Core\StreamWrapper\PrivateStream;
@@ -1789,3 +1792,138 @@ function system_update_8301() {
->set('profile', \Drupal::installProfile())
->save();
}
+
+/**
+ * Move revision metadata fields to the revision table.
+ */
+function system_update_8400(&$sandbox) {
+ // Due to the fields from RevisionLogEntityTrait not being explicitly
+ // mentioned in the storage they might have been installed wrongly in the base
+ // table for revisionable untranslatable entities and in the data and revision
+ // data tables for revisionable and translatable entities.
+ $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
+ $database = \Drupal::database();
+ $database_schema = $database->schema();
+
+ if (!isset($sandbox['current'])) {
+ // This must be the first run. Initialize the sandbox.
+ $sandbox['current'] = 0;
+
+ $definitions = array_filter(\Drupal::entityTypeManager()->getDefinitions(), function (EntityTypeInterface $entity_type) use ($entity_definition_update_manager) {
+ if ($entity_type = $entity_definition_update_manager->getEntityType($entity_type->id())) {
+ return is_subclass_of($entity_type->getClass(), FieldableEntityInterface::class) && ($entity_type instanceof ContentEntityTypeInterface) && $entity_type->isRevisionable();
+ }
+ return FALSE;
+ });
+ $sandbox['entity_type_ids'] = array_keys($definitions);
+ $sandbox['max'] = count($sandbox['entity_type_ids']);
+ }
+
+ $current_entity_type_key = $sandbox['current'];
+ for ($i = $current_entity_type_key; ($i < $current_entity_type_key + 1) && ($i < $sandbox['max']); $i++) {
+ $entity_type_id = $sandbox['entity_type_ids'][$i];
+ /** @var \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type */
+ $entity_type = $entity_definition_update_manager->getEntityType($entity_type_id);
+
+ $base_fields = \Drupal::service('entity_field.manager')->getBaseFieldDefinitions($entity_type_id);
+ $revision_metadata_fields = $entity_type->getRevisionMetadataKeys();
+ $fields_to_update = array_intersect_key($base_fields, array_flip($revision_metadata_fields));
+
+ if (!empty($fields_to_update)) {
+ // Initialize the entity table names.
+ // @see \Drupal\Core\Entity\Sql\SqlContentEntityStorage::initTableLayout()
+ $base_table = $entity_type->getBaseTable() ?: $entity_type_id;
+ $data_table = $entity_type->getDataTable() ?: $entity_type_id . '_field_data';
+ $revision_table = $entity_type->getRevisionTable() ?: $entity_type_id . '_revision';
+ $revision_data_table = $entity_type->getRevisionDataTable() ?: $entity_type_id . '_field_revision';
+ $revision_field = $entity_type->getKey('revision');
+
+ // No data needs to be migrated if the entity type is not translatable.
+ if ($entity_type->isTranslatable()) {
+ if (!isset($sandbox[$entity_type_id])) {
+ // This must be the first run for this entity type. Initialize the
+ // sub-sandbox for it.
+
+ // Calculate the number of revisions to process.
+ $count = \Drupal::entityQuery($entity_type_id)
+ ->allRevisions()
+ ->count()
+ ->accessCheck(FALSE)
+ ->execute();
+
+ $sandbox[$entity_type_id]['current'] = 0;
+ $sandbox[$entity_type_id]['max'] = $count;
+ }
+ // Define the step size.
+ $steps = Settings::get('entity_update_batch_size', 50);
+
+ // Collect the revision IDs to process.
+ $revisions = \Drupal::entityQuery($entity_type_id)
+ ->allRevisions()
+ ->range($sandbox[$entity_type_id]['current'], $sandbox[$entity_type_id]['current'] + $steps)
+ ->sort($revision_field, 'ASC')
+ ->accessCheck(FALSE)
+ ->execute();
+ $revisions = array_keys($revisions);
+
+ foreach ($fields_to_update as $revision_metadata_field_name => $definition) {
+ // If the revision metadata field is present in the data and the
+ // revision data table, install its definition again with the updated
+ // storage code in order for the field to be installed in the
+ // revision table. Afterwards, copy over the field values and remove
+ // the field from the data and the revision data tables.
+ if ($database_schema->fieldExists($data_table, $revision_metadata_field_name) && $database_schema->fieldExists($revision_data_table, $revision_metadata_field_name)) {
+ // Install the field in the revision table.
+ if (!isset($sandbox[$entity_type_id]['storage_definition_installed'][$revision_metadata_field_name])) {
+ $entity_definition_update_manager->installFieldStorageDefinition($revision_metadata_field_name, $entity_type_id, $entity_type->getProvider(), $definition);
+ $sandbox[$entity_type_id]['storage_definition_installed'][$revision_metadata_field_name] = TRUE;
+ }
+
+ // Apply the field value from the revision data table to the
+ // revision table.
+ foreach ($revisions as $rev_id) {
+ $field_value = $database->select($revision_data_table, 't')
+ ->fields('t', [$revision_metadata_field_name])
+ ->condition($revision_field, $rev_id)
+ ->execute()
+ ->fetchField();
+ $database->update($revision_table)
+ ->condition($revision_field, $rev_id)
+ ->fields([$revision_metadata_field_name => $field_value])
+ ->execute();
+ }
+ }
+ }
+
+ $sandbox[$entity_type_id]['current'] += count($revisions);
+ $sandbox[$entity_type_id]['finished'] = ($sandbox[$entity_type_id]['current'] == $sandbox[$entity_type_id]['max']) || empty($revisions);
+
+ if ($sandbox[$entity_type_id]['finished']) {
+ foreach ($fields_to_update as $revision_metadata_field_name => $definition) {
+ // Drop the field from the data and revision data tables.
+ $database_schema->dropField($data_table, $revision_metadata_field_name);
+ $database_schema->dropField($revision_data_table, $revision_metadata_field_name);
+ }
+ $sandbox['current']++;
+ }
+ }
+ else {
+ foreach ($fields_to_update as $revision_metadata_field_name => $definition) {
+ if ($database_schema->fieldExists($base_table, $revision_metadata_field_name)) {
+ // Install the field in the revision table.
+ $entity_definition_update_manager->installFieldStorageDefinition($revision_metadata_field_name, $entity_type_id, $entity_type->getProvider(), $definition);
+ // Drop the field from the base table.
+ $database_schema->dropField($base_table, $revision_metadata_field_name);
+ }
+ }
+ $sandbox['current']++;
+ }
+ }
+ else {
+ $sandbox['current']++;
+ }
+
+ }
+
+ $sandbox['#finished'] = $sandbox['current'] == $sandbox['max'];
+}
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index a1a6b71..3d01317 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -994,27 +994,13 @@ function system_get_info($type, $name = NULL) {
function _system_rebuild_module_data() {
$listing = new ExtensionDiscovery(\Drupal::root());
- // Find installation profiles. This needs to happen before performing a
- // module scan as the module scan requires knowing what the active profile is.
- // @todo Remove as part of https://www.drupal.org/node/2186491.
- $profiles = $listing->scan('profile');
- $profile = drupal_get_profile();
- if ($profile && isset($profiles[$profile])) {
- // Prime the drupal_get_filename() static cache with the profile info file
- // location so we can use drupal_get_path() on the active profile during
- // the module scan.
- // @todo Remove as part of https://www.drupal.org/node/2186491.
- drupal_get_filename('profile', $profile, $profiles[$profile]->getPathname());
- }
-
// Find modules.
$modules = $listing->scan('module');
- // Include the installation profile in modules that are loaded.
- if ($profile) {
- $modules[$profile] = $profiles[$profile];
- // Installation profile hooks are always executed last.
- $modules[$profile]->weight = 1000;
- }
+
+ // Find profiles.
+ /** @var \Drupal\Core\Extension\ProfileHandlerInterface $profile_handler */
+ $profile_handler = \Drupal::service('profile_handler');
+ $modules = array_merge($modules, $profile_handler->getProfiles());
// Set defaults for module info.
$defaults = [
@@ -1028,7 +1014,14 @@ function _system_rebuild_module_data() {
// Read info files for each module.
foreach ($modules as $key => $module) {
// Look for the info file.
- $module->info = \Drupal::service('info_parser')->parse($module->getPathname());
+ // @todo On the longrun we should leverage the extension lists services,
+ // see https://www.drupal.org/node/2208429.
+ if ($module->getType() === 'profile') {
+ $module->info = $profile_handler->getProfileInfo($module->getName());
+ }
+ else {
+ $module->info = \Drupal::service('info_parser')->parse($module->getPathname());
+ }
// Add the info file modification time, so it becomes available for
// contributed modules to use for ordering module lists.
@@ -1037,12 +1030,6 @@ function _system_rebuild_module_data() {
// Merge in defaults and save.
$modules[$key]->info = $module->info + $defaults;
- // Installation profiles are hidden by default, unless explicitly specified
- // otherwise in the .info.yml file.
- if ($key == $profile && !isset($modules[$key]->info['hidden'])) {
- $modules[$key]->info['hidden'] = TRUE;
- }
-
// Invoke hook_system_info_alter() to give installed modules a chance to
// modify the data in the .info.yml files if necessary.
// @todo Remove $type argument, obsolete with $module->getType().
@@ -1056,15 +1043,18 @@ function _system_rebuild_module_data() {
_system_rebuild_module_data_ensure_required($module, $modules);
}
-
- if ($profile && isset($modules[$profile])) {
- // The installation profile is required, if it's a valid module.
- $modules[$profile]->info['required'] = TRUE;
- // Add a default distribution name if the profile did not provide one.
- // @see install_profile_info()
- // @see drupal_install_profile_distribution_name()
- if (!isset($modules[$profile]->info['distribution']['name'])) {
- $modules[$profile]->info['distribution']['name'] = 'Drupal';
+ // This must be done after _system_rebuild_module_data_ensure_required().
+ $profiles = \Drupal::service('profile_handler')->getProfiles();
+ foreach ($profiles as $profile_name => $profile) {
+ if (isset($modules[$profile_name])) {
+ // Installation profiles are required, if it's a valid module.
+ $modules[$profile_name]->info['required'] = TRUE;
+ // Add a default distribution name if the profile did not provide one.
+ // @see install_profile_info()
+ // @see drupal_install_profile_distribution_name()
+ if (!isset($modules[$profile_name]->info['distribution']['name'])) {
+ $modules[$profile_name]->info['distribution']['name'] = 'Drupal';
+ }
}
}
diff --git a/core/modules/system/tests/fixtures/update/drupal-8.2.0.bare.standard_with_entity_test_revlog_enabled.php.gz b/core/modules/system/tests/fixtures/update/drupal-8.2.0.bare.standard_with_entity_test_revlog_enabled.php.gz
new file mode 100644
index 0000000..1977264
--- /dev/null
+++ b/core/modules/system/tests/fixtures/update/drupal-8.2.0.bare.standard_with_entity_test_revlog_enabled.php.gz
@@ -0,0 +1,517 @@
+‹ŠRX drupal-8.2.0.bare.standard_with_entity_test_revlog_enabled.php ì]is⺶ýÞ¿‚Jݪ>}ê(ǃ<¥ß=ï&IIHB n%[28ÛØfÊûߟŒÍ3&ýŽ¿t¬akkí¥½·dñ?ÿë4œoþ™ú—fcê—|daäb/_·l—d
“|ûó÷ß¿¥~OýK>Ð?ÎSùHEI!ZÊó
-…;-'¥ÛnÊ'ô³UO9×±=âÒA¥§†á¥‚R=ä¥êÄ".ò N©ƒ”ß ©ŒÛq™’O™VoÛ¦wJ%Kyšk8~ÐÈŸß¾u¼qÁ§©pÿΌĘüñóÛ·h¶eÍ7l+õÏÔøÁÙYøéÉ“ß~Ì—yZƒ´Ðo?À_šK¨`OH5ÉoßUÓÖš5ZÐ'–ÿýr]4øí[*õ]7ˆ‰½ï©þ5ý’~màèWôKàá×ß=âÈüþÇø‰eû)«cšÃ§OÏ—“'žñ>ªCç¡5[§cyFÝ"8RçGøßw—t
Ž©ö(F0 ¥rdÏoK{dÒÕ* ºÈÕÈ!O3Œ8:1‰U÷aežû>ß]§óÁ€wêŽåäH&²êÔf8DvnˆÃ¾;®ÑBî Õ$ƒeØ›ìXF»C‚r‹ CumˆäZ-Ð_ÖEfgÙ†ÚWÀ|+µõ¸›}º0(äObÊ(—þ‹\jÑk0¾ÐIkàµÍZ0Hó‰[󈪹ãërK…´Æh¡VSm<ˆCjÇÂæA#O«`¢£Ž9cdê01‰O¶å‡Yú¾ûŸ¬EÉZô·[‹Éú]”~¡5àÿ!û!cÿ Àdô¦]?pîcsKÝÐ2×YßQQŸ$‚¸:Ú}’NÁñt‘$‚?9¼ÄJrÛ/¢ßÓ…Áö=ê—;qVíÙS`¬ €@9†56…EÃ&¶×‰GGug+!}Çp÷CDhíÊ'†´:-êjq¤p\¢…®q¸@Ãi%OC#køίî”a¢†Ž)Üž×,ê(®’|T_€ïþ“Ö¤ü|£ˆÉ–Z,Wu%ˆGŽ@<´ (4a„uÖIXçh¬ã#Ã
+’O ñ$Ä“OB<Ç!ž¸§nÎI8'ᜄsöÂ9£éKh'¡„vÚ9ížfw‰kÃ1!ž„xâIˆgÄî&¬“°NÂ: ë‹uZÄê$œ“pNÂ9 ç‹s‚kHT”lb%´“ÐNB;Ç¢áÅ Zî)g<цեˆÆ÷ÖãꀶÿñäÊ:ÐœÙVÌË¡>Z$Žð®ÉHÚZr9Ó‘/gšgŸu·3§h«{™Ö“[¤éY0¬£l6‡¥ÀQOá’wj†‹ròNÍvr$ïÔ,’ÿß™ëòxëå—zÅ%žr—•:
+…”ëùÔ9. åÕ‰½–2èÇ4’îHÞSTNkñUñp%·PëÜGîíaƒyþÔ£1Z„â®å|âÎÐÆ”'®íö#·û³ìh,Ÿfw¬õ§H¸ÅÂ1Ë‹¶ùñŠ¾+
+n¦ßùçh¡ÈQÖ“Í.Ö;8}ÍHû.“p>û¦é]}†=‰áuÔ7
+åÃÐ<Œ(}{fßÓh·¢µa¤'Nˆjµa·ˆƒê‡ØâåX
Ûó¦ÇŬØn÷bÅ¡Åiúÿh·~áEgÛÌó÷[ù
ª½XIÌw2öf¬ÈÂÚ±Ç`bƒ^¿ÚÅaš±Í…a“¼åÆW…Mû[¦Œ©—߶÷”îb›Ãôº¦ *ÕJâ?Y^½wm¹‡áÌ*nD+Ú±:šEzK‰:òK]ùåêŠöº0œÈäÎu