clean install

This commit is contained in:
2024-12-10 15:08:16 +01:00
commit e14eb2d8fd
31193 changed files with 3555714 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
A demonstration of a simple import of a JSON file.
REQUIREMENTS
============
You need the contrib modules Migrate Plus and Migrate Tools.
To make the products.json file available for import, the file will be copied
from the artifacts folder to your sites/default/files folder.
USAGE
=====
Enable the module, check status, import all products and rollback with Drush
drush en migrate_json_example
drush migrate-status
drush migrate-import product
drush migrate-rollback product
See config/optional/migrate_plus.migration.product.yml for details about the
migration.
Thanks to Jeff Geerling and Christophe for the original code:
https://www.jeffgeerling.com/blog/2016/migrate-custom-json-feed-drupal-8-migrate-source-json
https://colorfield.be/blog/drupal-8-json-custom-migration

View File

@@ -0,0 +1,16 @@
{
"product": [
{
"upc": "11111",
"name": "Widget",
"description": "Helpful for many things.",
"price": "14.99"
},
{
"upc": "22222",
"name": "Sprocket",
"description": "Helpful for things needing sprockets.",
"price": "8.99"
}
]
}

View File

@@ -0,0 +1,89 @@
langcode: en
status: true
dependencies:
config:
- field.field.node.product.field_description
- field.field.node.product.field_price
- field.field.node.product.field_upc
- node.type.product
module:
- path
id: node.product.default
targetEntityType: node
bundle: product
mode: default
content:
created:
type: datetime_timestamp
weight: 10
region: content
settings: { }
third_party_settings: { }
field_description:
weight: 123
settings:
size: 60
placeholder: ''
third_party_settings: { }
type: string_textfield
region: content
field_price:
weight: 124
settings:
placeholder: ''
third_party_settings: { }
type: number
region: content
field_upc:
weight: 122
settings:
placeholder: ''
third_party_settings: { }
type: number
region: content
path:
type: path
weight: 30
region: content
settings: { }
third_party_settings: { }
promote:
type: boolean_checkbox
settings:
display_label: true
weight: 15
region: content
third_party_settings: { }
status:
type: boolean_checkbox
settings:
display_label: true
weight: 120
region: content
third_party_settings: { }
sticky:
type: boolean_checkbox
settings:
display_label: true
weight: 16
region: content
third_party_settings: { }
title:
type: string_textfield
weight: -5
region: content
settings:
size: 60
placeholder: ''
third_party_settings: { }
uid:
type: entity_reference_autocomplete
weight: 5
settings:
match_operator: CONTAINS
match_limit: 10
size: 60
placeholder: ''
region: content
third_party_settings: { }
hidden: { }

View File

@@ -0,0 +1,49 @@
langcode: en
status: true
dependencies:
config:
- field.field.node.product.field_description
- field.field.node.product.field_price
- field.field.node.product.field_upc
- node.type.product
module:
- user
id: node.product.default
targetEntityType: node
bundle: product
mode: default
content:
field_description:
weight: 103
label: above
settings:
link_to_entity: false
third_party_settings: { }
type: string
region: content
field_price:
weight: 104
label: above
settings:
thousand_separator: ''
decimal_separator: .
scale: 2
prefix_suffix: true
third_party_settings: { }
type: number_decimal
region: content
field_upc:
weight: 102
label: above
settings:
thousand_separator: ''
prefix_suffix: true
third_party_settings: { }
type: number_integer
region: content
links:
weight: 100
settings: { }
third_party_settings: { }
region: content
hidden: { }

View File

@@ -0,0 +1,18 @@
langcode: en
status: true
dependencies:
config:
- field.storage.node.field_description
- node.type.product
id: node.product.field_description
field_name: field_description
entity_type: node
bundle: product
label: Description
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings: { }
field_type: string

View File

@@ -0,0 +1,22 @@
langcode: en
status: true
dependencies:
config:
- field.storage.node.field_price
- node.type.product
id: node.product.field_price
field_name: field_price
entity_type: node
bundle: product
label: Price
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings:
min: null
max: null
prefix: ''
suffix: ''
field_type: float

View File

@@ -0,0 +1,22 @@
langcode: en
status: true
dependencies:
config:
- field.storage.node.field_upc
- node.type.product
id: node.product.field_upc
field_name: field_upc
entity_type: node
bundle: product
label: UPC
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings:
min: null
max: null
prefix: ''
suffix: ''
field_type: integer

View File

@@ -0,0 +1,23 @@
langcode: en
status: true
dependencies:
enforced:
module:
- migrate_json_example
module:
- node
id: node.field_description
field_name: field_description
entity_type: node
type: string
settings:
max_length: 255
is_ascii: false
case_sensitive: false
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false

View File

@@ -0,0 +1,20 @@
langcode: en
status: true
dependencies:
enforced:
module:
- migrate_json_example
module:
- node
id: node.field_price
field_name: field_price
entity_type: node
type: float
settings: { }
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false

View File

@@ -0,0 +1,22 @@
langcode: en
status: true
dependencies:
enforced:
module:
- migrate_json_example
module:
- node
id: node.field_upc
field_name: field_upc
entity_type: node
type: integer
settings:
unsigned: false
size: normal
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false

View File

@@ -0,0 +1,83 @@
# This migration demonstrates a simple import from a JSON file.
id: product
label: JSON feed of Products
migration_group: Product
migration_tags:
- json example
source:
# We use the JSON source plugin.
plugin: url
# In this example we get data from a local file, to get data from a URL
# define http as data_fetcher_plugin.
# data_fetcher_plugin: http
data_fetcher_plugin: file
data_parser_plugin: json
# The data_parser normally limits the fields passed on to the source plugin
# to fields configured to be used as part of the migration. To support more
# dynamic migrations, the JSON data parser supports including the original
# data for the current row. Simply include the 'include_raw_data' flag set
# to `true` to enable this. This option is disabled by default to minimize
# memory footprint for migrations that do not need this capability.
# include_raw_data: true
# Flags whether to track changes to incoming data. If TRUE, we will maintain
# hashed source rows to determine whether incoming data has changed.
# track_changes: true
# Copy the example JSON file in artifacts folder to sites/default/files folder.
urls:
- 'public://migrate_json_example/products.json'
# An xpath-like selector corresponding to the items to be imported.
item_selector: product
# If no item_selector is present in the JSON file, replace 'product' with '0'.
# item_selector: 0
# Under 'fields', we list the data items to be imported. The first level keys
# are the source field names we want to populate (the names to be used as
# sources in the process configuration below). For each field we're importing,
# we provide a label (optional - this is for display in migration tools) and
# an xpath for retrieving that value. It's important to note that this xpath
# is relative to the elements retrieved by item_selector.
fields:
-
name: upc
label: 'Unique product identifier'
selector: upc
-
name: name
label: 'Product name'
selector: name
-
name: description
label: 'Product description'
selector: description
-
name: price
label: 'Product price'
selector: price
# Under 'ids', we identify source fields populated above which will uniquely
# identify each imported item. The 'type' makes sure the migration map table
# uses the proper schema type for stored the IDs.
ids:
upc:
type: integer
process:
# Note that the source field names here (name, description and price) were
# defined by the 'fields' configuration for the source plugin above.
type:
plugin: default_value
default_value: product
title: name
field_upc: upc
field_description: description
field_price: price
sticky:
plugin: default_value
default_value: 0
uid:
plugin: default_value
default_value: 0
destination:
plugin: 'entity:node'
migration_dependencies: { }
dependencies:
enforced:
module:
- migrate_json_example

View File

@@ -0,0 +1,20 @@
langcode: en
status: true
dependencies:
enforced:
module:
- migrate_json_example
module:
- menu_ui
third_party_settings:
menu_ui:
available_menus:
- main
parent: 'main:'
name: Product
type: product
description: ''
help: ''
new_revision: true
preview_mode: 1
display_submitted: true

View File

@@ -0,0 +1,13 @@
type: module
name: Migrate JSON Example
description: 'Simple JSON Migration example'
package: Examples
core_version_requirement: '>=9.1'
dependencies:
- drupal:migrate
- migrate_plus:migrate_plus
# Information added by Drupal.org packaging script on 2024-11-20
version: '6.0.5'
project: 'migrate_plus'
datestamp: 1732124626

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types = 1);
/**
* @file
* Install, update, and uninstall functions for migrate_json_example.
*/
use Drupal\Core\File\FileSystemInterface;
/**
* Copies the example file to the sites/default/files folder.
*/
function migrate_json_example_install(): void {
// Create the example file directory and ensure it's writable.
$directory = \Drupal::config('system.file')->get('default_scheme') . '://migrate_json_example';
\Drupal::service('file_system')->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
// Copy the example file to example directory.
// @todo Use \Drupal\Core\Extension\ExtensionPathResolver::getPath() when we
// require Drupal > 9.3.0.
$module_path = \Drupal::moduleHandler()->getModule('migrate_json_example')->getPath();
$file_source = $module_path . '/artifacts/products.json';
\Drupal::service('file_system')->copy($file_source, $directory . '/products.json', FileSystemInterface::EXISTS_REPLACE);
}

View File

@@ -0,0 +1,71 @@
<?php
declare(strict_types = 1);
namespace Drupal\Tests\migrate_json_example\Kernel;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
/**
* Tests migrate_json_example migrations.
*
* @group migrate_plus
*/
final class MigrateJsonExampleTest extends MigrateDrupalTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'node',
'file',
'text',
'menu_ui',
'migrate_plus',
];
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->installConfig(['node']);
$this->installEntitySchema('file');
$this->installSchema('file', ['file_usage']);
$this->installSchema('user', ['users_data']);
// Install the module via installer to trigger hook_install.
\Drupal::service('module_installer')->install(['migrate_json_example']);
$this->installConfig(['migrate_json_example']);
}
/**
* Tests the results of "migrate_json_example" migrations.
*/
public function testMigrations(): void {
$node_storage = \Drupal::entityTypeManager()->getStorage('node');
$this->assertCount(0, $node_storage->loadMultiple());
// Execute "product" migration from 'migrate_json_example' module.
$this->executeMigration('product');
$this->assertCount(2, $node_storage->loadMultiple());
}
/**
* Tests whether the module can be uninstalled and installed again.
*
* Also, checks whether the example configs are removed after uninstall.
*/
public function testModuleCleanup(): void {
$test_node_type = 'product';
// Prove that test content type existed before the uninstall process.
$this->assertInstanceOf(NodeType::class, NodeType::load($test_node_type));
\Drupal::service('module_installer')->uninstall(['migrate_json_example']);
// Make sure the test content type was removed.
$this->assertNull(NodeType::load($test_node_type));
// Check whether test configuration files were removed.
\Drupal::service('module_installer')->install(['migrate_json_example']);
}
}