Skip to content
Snippets Groups Projects
Commit 214b1004 authored by Nia Kathoni's avatar Nia Kathoni Committed by Daniel Cothran
Browse files

Issue #3397285 by nikathone: Clean the code for a dev and alpha release to be used for D9 & D10

parent e0efb879
No related branches found
No related tags found
1 merge request!8Issue #3397285: Clean the code for a dev and alpha release to be used for D9 &...
Pipeline #50395 passed with warnings
Showing
with 133 additions and 1846 deletions
################
# DrupalCI GitLabCI template
#
# Gitlab-ci.yml to replicate DrupalCI testing for Contrib
#
# With thanks to:
# * The GitLab Acceleration Initiative participants
# * DrupalSpoons
################
################
# Guidelines
#
# This template is designed to give any Contrib maintainer everything they need to test, without requiring modification. It is also designed to keep up to date with Core Development automatically through the use of include files that can be centrally maintained.
#
# However, you can modify this template if you have additional needs for your project.
################
################
# Includes
#
# Additional configuration can be provided through includes.
# One advantage of include files is that if they are updated upstream, the changes affect all pipelines using that include.
#
# Includes can be overridden by re-declaring anything provided in an include, here in gitlab-ci.yml
# https://docs.gitlab.com/ee/ci/yaml/includes.html#override-included-configuration-values
################
include:
################
# DrupalCI includes:
# As long as you include this, any future includes added by the Drupal Association will be accessible to your pipelines automatically.
# View these include files at https://git.drupalcode.org/project/gitlab_templates/
################
- project: $_GITLAB_TEMPLATES_REPO
ref: $_GITLAB_TEMPLATES_REF
file:
- '/includes/include.drupalci.main.yml'
# EXPERIMENTAL: For Drupal 7, remove the above line and uncomment the below.
# - '/includes/include.drupalci.main-d7.yml'
- '/includes/include.drupalci.variables.yml'
- '/includes/include.drupalci.workflows.yml'
################
# Pipeline configuration variables
#
# These are the variables provided to the Run Pipeline form that a user may want to override.
#
# Docs at https://git.drupalcode.org/project/gitlab_templates/-/blob/1.0.x/includes/include.drupalci.variables.yml
################
# variables:
# SKIP_ESLINT: '1'
###################################################################################
#
# *
# /(
# ((((,
# /(((((((
# ((((((((((*
# ,(((((((((((((((
# ,(((((((((((((((((((
# ((((((((((((((((((((((((*
# *(((((((((((((((((((((((((((((
# ((((((((((((((((((((((((((((((((((*
# *(((((((((((((((((( .((((((((((((((((((
# ((((((((((((((((((. /(((((((((((((((((*
# /((((((((((((((((( .(((((((((((((((((,
# ,(((((((((((((((((( ((((((((((((((((((
# .(((((((((((((((((((( .(((((((((((((((((
# ((((((((((((((((((((((( ((((((((((((((((/
# (((((((((((((((((((((((((((/ ,(((((((((((((((*
# .((((((((((((((/ /(((((((((((((. ,(((((((((((((((
# *(((((((((((((( ,(((((((((((((/ *((((((((((((((.
# ((((((((((((((, /(((((((((((((. ((((((((((((((,
# (((((((((((((/ ,(((((((((((((* ,(((((((((((((,
# *((((((((((((( .((((((((((((((( ,(((((((((((((
# ((((((((((((/ /((((((((((((((((((. ,((((((((((((/
# ((((((((((((( *(((((((((((((((((((((((* *((((((((((((
# ((((((((((((( ,(((((((((((((..((((((((((((( *((((((((((((
# ((((((((((((, /((((((((((((* /((((((((((((/ ((((((((((((
# ((((((((((((( /((((((((((((/ (((((((((((((* ((((((((((((
# (((((((((((((/ /(((((((((((( ,((((((((((((, *((((((((((((
# (((((((((((((( *(((((((((((/ *((((((((((((. ((((((((((((/
# *((((((((((((((((((((((((((, /(((((((((((((((((((((((((
# ((((((((((((((((((((((((( ((((((((((((((((((((((((,
# .(((((((((((((((((((((((/ ,(((((((((((((((((((((((
# ((((((((((((((((((((((/ ,(((((((((((((((((((((/
# *((((((((((((((((((((( (((((((((((((((((((((,
# ,(((((((((((((((((((((, ((((((((((((((((((((/
# ,(((((((((((((((((((((* /((((((((((((((((((((
# ((((((((((((((((((((((, ,/((((((((((((((((((((,
# ,(((((((((((((((((((((((((((((((((((((((((((((((((((
# .(((((((((((((((((((((((((((((((((((((((((((((
# .((((((((((((((((((((((((((((((((((((,.
# .,(((((((((((((((((((((((((.
#
###################################################################################
<?php
/**
* @file
* Denormalizer - API.
*/
use Drupal\Core\Database\Driver\mysql\Select;
/**
* Implements hook_denormalizer_info().
*
* Provide a list of plain tables and entities that should be denormalized.
*/
function hook_denormalizer_info() {
return [
// Non-entity.
'location' => [
'base table' => 'location',
],
// Entity.
'denormalized_table' => [
'entity_type' => 'node',
'bundles' => [
'page',
'story',
],
'changed_key' => 'changed',
],
];
}
/**
* Implements hook_denormalizer_query_alter().
*
* Alter a denormalized query before running.
*/
function hook_denormalizer_alter(Denormalizer $d, Select $q, $denormalized_view, $info) {
if ($denormalized_view == 'denormalized_table') {
$q->addExpression('test', 'something');
}
}
/**
* Implements hook_denormalizer_post_execute().
*
* Alter a denormalized table after running.
*/
function hook_denormalizer_post_execute($denormalized_view, $info) {
if ($denormalized_view == 'denormalized_table') {
// db_query('ALTER TABLE something...');.
}
}
<?php
/**
* @file
* Denormalizer - Inc.
*/
<?php
/**
* @file
* Denormalizer - Drush Inc.
*/
use Drupal\denormalizer\Denormalizer;
/**
* Denormalizer help.
*
* @param array $section
* The array section.
*
* @return \Drupal\Component\Render\FormattableMarkup|\Drupal\Core\StringTranslation\TranslatableMarkup|mixed|string|null
* Help string.
*/
function denormalizer_drush_help(array $section) {
switch ($section) {
case 'drush:denormalize':
return dt("Denormalize schema.");
}
}
/**
* Drush command.
*
* @return array
* Denormalize command.
*/
function denormalizer_drush_command() {
$items = [];
$items['denormalize'] = [
'description' => 'makes a delicious denormalized schema ',
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL,
'options' => [
'reset' => 'Resets tables.',
],
];
return $items;
}
/**
* Denormalize tables.
*/
function drush_denormalizer_denormalize() {
$reset = (bool) drush_get_option('reset');
$d = new Denormalizer();
$d->build();
$d->execute($reset);
}
denormalizer.export:
title: Export
description: Export denormalization.
route_name: denormalizer.export
appears_on:
- denormalizer.settings
denormalizer.table_add:
route_name: entity.denormalizer_table.add_form
title: 'Add table'
......
denormalizer.settings:
title: Denormalizer
description: Configure or run denormalization.
description: Configure denormalization.
route_name: denormalizer.settings
parent: system.admin_config_development
......
<?php
use Drupal\webform\Entity\Webform;
/**
* @file
* Denormalizer - module.
*/
use Drupal\Core\Database\Query\Select;
use Drupal\Core\Database\Database;
use Drupal\Core\Entity\EntityInterface;
use Drupal\denormalizer\Denormalizer;
use Drupal\denormalizer\Entity\DenormalizerTable;
/**
* Implements hook_cron().
*
* Run or reload periodically.
*/
function denormalizer_cron() {
$config = \Drupal::service('config.factory')
->getEditable('denormalizer.settings');
if ($config->get('cron_enabled')) {
$last_run = $config->get('last_run');
$reset = NULL;
if ($config->get('reload_every') && ($last_run + $config->get('reload_every') * 60 * 60) <= \Drupal::time()->getRequestTime()) {
$reset = TRUE;
}
elseif ($config->get('run_every') && ($last_run + $config->get('run_every') * 60 * 60) <= \Drupal::time()->getRequestTime()) {
$reset = FALSE;
}
if (!is_null($reset)) {
$denormalizer = new Denormalizer();
$denormalizer->build();
try {
$denormalizer->execute($reset);
}
catch (PDOException $e) {
if (in_array($e->getCode(), ['42S22', '21S01'])) {
\Drupal::logger('denormalizer')
->info('Different fields detected. Running reload.');
$denormalizer->execute(TRUE);
}
}
$config->set('last_run', \Drupal::time()->getRequestTime())->save();
\Drupal::logger('denormalizer')->info('Ran denormalizer.');
}
}
// @todo see https://www.drupal.org/project/denormalizer/issues/3397286
}
/**
......@@ -75,525 +41,3 @@ function denormalizer_entity_delete(EntityInterface $entity) {
DenormalizerTable::onContentEntityCRUD($entity, FALSE, TRUE);
}
}
/**
* Get denormalizer info from module implementation.
*
* This almost mirrors entity_info() but the 'bundles' key is flat.
*
* @return array
* Denormalizer info.
*
* @throws \Exception
*/
function denormalizer_get_info() {
$info = \Drupal::moduleHandler()->invokeAll('denormalizer_info');
$entity_type_manager = \Drupal::entityTypeManager();
$denormalizer_tbl_storage = $entity_type_manager->getStorage('denormalizer_table');
/** @var \Drupal\denormalizer\Entity\DenormalizerTableInterface[] $tables */
$tables = $denormalizer_tbl_storage->loadByProperties([
'status' => 1,
// Only use the non entity for this process.
'source' => 'non_entity',
]);
foreach ($tables as $table) {
$configuration = $table->getSourceConfiguration();
$info[$table->getDbTableName()] = [
'base table' => $table->getBaseTable(),
'changed_key' => $configuration['changed_key'] ?? '',
'external' => $configuration['external'],
];
}
\Drupal::moduleHandler()->alter('denormalizer_info', $info);
foreach ($info as $target_table => &$entry) {
if (!isset($entry['bundles'])) {
$entry['bundles'] = [];
}
if (isset($entry['entity_type'])) {
$entry += (array) $entity_type_manager->getDefinition($entry['entity_type']);
}
if (!isset($entry['fields'])) {
$entry['fields'] = [];
}
}
return $info;
}
/**
* Get the primary key of a table in the Drupal schema.
*
* @param string $dn_table
* The dn_table.
*
* @return string
* The primary key label.
*/
function denormalizer_get_primary_key($dn_table) {
$d = denormalizer_get_info();
$dn_info = $d[$dn_table];
if (isset($d[$dn_table]['primary key'])) {
// Manually defined primary key.
return $d[$dn_table]['primary key'];
}
if ($dn_table == 'user') {
// Special case for the user table.
return 'uid';
}
// Drupal defined table.
// Replaced "$d['schema_module']" by "$d[$dn_table]['schema_module']".
$schema = drupal_get_module_schema($d[$dn_table]['schema_module'], $d[$dn_table]['base table']);
if (isset($schema['primary key']) && count($schema['primary key']) == 1) {
return $schema['primary key'][0];
}
if (isset($dn_info['surrogate key'])) {
return $dn_info['surrogate key'];
}
}
/**
* Convert db_select to SQL.
*
* Modified from devel module.
*
* @param Drupal\Core\Database\Driver\mysql\Select $query
* SQL query.
*
* @return string
* SQL of db_select object.
*/
function denormalizer_dpq(Select $query) {
$config = \Drupal::service('config.factory')
->getEditable('denormalizer.settings');
if (method_exists($query, 'preExecute')) {
$query->preExecute();
}
$sql = (string) $query;
$quoted = [];
$connection = Database::getConnection();
foreach ((array) $query->arguments() as $key => $val) {
$quoted[$key] = $connection->quote($val);
}
$sql = strtr($sql, $quoted);
if ($config->get('db') == 'external') {
// DB prefix.
$dw_prefix = denormalizer_source_db();
$search = ['{', '}'];
$replace = [$dw_prefix . '.' . $connection->tablePrefix(), ''];
$sql = str_replace($search, $replace, $sql);
}
else {
$sql = $connection->prefixTables($sql);
}
return $sql;
}
/**
* Get the current (source) database name.
*
* @return string
* Query result.
*/
function denormalizer_source_db() {
// TODO: Drupal Rector Notice: Please delete the following comment after.
// You've made any necessary changes.
// You will need to use `\Drupal\core\Database\Database::getConnection()`.
// If you do not yet have access to the container here.
$db = \Drupal::database()->query('select database()')->fetchField();
return $db;
}
/**
* Get the target database name.
*
* @return string
* Database name.
*/
function denormalizer_target_db() {
// TODO: Drupal Rector Notice: Please delete the following comment after.
// You've made any necessary changes.
// You will need to use `\Drupal\core\Database\Database::getConnection()`.
// If you do not yet have access to the container here.
$db = \Drupal::database()->query('select database()')->fetchField();
$config = \Drupal::config('denormalizer.settings');
return $config->get('db_prefix') . $db;
}
/**
* Implements hook_hook_info().
*/
function denormalizer_hook_info() {
$hooks = [];
$hooks['denormalizer_alter'] = [
'group' => 'denormalizer',
];
$hooks['denormalizer_info'] = [
'group' => 'denormalizer',
];
return $hooks;
}
/**
* Implements hook_denormalizer_alter().
*
* Add some default denormalization alters.
*
* @throws \Exception
*/
function denormalizer_denormalizer_alter(Select $q, $view, array $dn) {
if ($view == 'user') {
$q->addJoin('LEFT', 'users_roles', 'ur', 'ur.uid = dn_user.uid');
$q->addJoin('LEFT', 'role', 'r', 'r.rid = ur.rid');
$q->addExpression("group_concat(r.name SEPARATOR '|')", 'roles');
// Group by primary key, so group_concat will work.
$q->groupBy('dn_user.uid');
}
if ($view == 'webform_submissions') {
$fields = &$q->getFields();
// Remove the integer fields and replace them with dates.
unset($fields['submitted']);
$q->addExpression('from_unixtime(submitted)', 'submitted');
unset($fields['completed']);
$q->addExpression('from_unixtime(completed)', 'completed');
unset($fields['modified']);
$q->addExpression('from_unixtime(modified)', 'modified');
}
// @todo: move webform_component_bi into dw db
if ($view == 'webform_component') {
// Remove the name field and replace it with a varchar.
$fields = &$q->getFields();
unset($fields['name']);
unset($fields['weight']);
$q->addExpression('substr(name, 1, 255)', 'name');
unset($fields['extra']);
$q->addExpression('cast(weight as decimal(8,2))', 'weight');
// Create surrogate key.
$q->addExpression("CONCAT_WS('-', nid, dn_webform_component.form_key)", 'pk');
// Extract grid components into their own form components.
// TODO: Drupal Rector Notice: Please delete the following comment after.
// You've made any necessary changes.
// You will need to use `\Drupal\core\Database\Database::getConnection()`.
// If you do not yet have access to the container here.
$result = \Drupal::database()
->query("select nid, cid, form_key, extra, weight from {webform_component} where type='grid'");
// Make a fake empty webform component table.
$start = microtime(TRUE);
$tablename = 'webform_component_bi';
if (db_table_exists($tablename)) {
db_drop_table($tablename);
}
// TODO: Drupal Rector Notice: Please delete the following comment after.
// You've made any necessary changes.
// You will need to use `\Drupal\core\Database\Database::getConnection()`.
// If you do not yet have access to the container here.
\Drupal::database()->query("create table {{$tablename}} select
nid,
cid,
pid,
cast(form_key as char(255)) as form_key,
type,
'' as value,
required,
cast('' as char(255)) as name,
cast(weight as decimal(8,2)) as weight,
cast('' as char(255)) as pk
from {webform_component}
limit 0");
$batchValues = [];
while ($row = $result->fetch()) {
$data = unserialize($row->extra);
if (isset($data['questions'])) {
$questions = list_extract_allowed_values($data['questions'], 'list_text', FALSE);
$i = 0;
foreach ($questions as $key => $question) {
$i++;
$form_key = $row->form_key . '-' . $key;
$batchValues[] = [
'nid' => $row->nid,
'cid' => $row->cid,
'pid' => $row->cid,
'form_key' => $form_key,
'name' => substr($question, 0, 255),
'type' => 'grid_sub',
'weight' => $row->weight + ($i / 100),
'pk' => $row->nid . '-' . $form_key,
];
}
}
}
foreach (array_chunk($batchValues, variable_get('denormalizer_chunk_size', 5000)) as $chunk) {
// TODO: Drupal Rector Notice: Please delete the following comment after.
// You've made any necessary changes.
// You will need to use `\Drupal\core\Database\Database::getConnection()`.
// If you do not yet have access to the container here.
$insert = \Drupal::database()->insert($tablename)->fields([
'nid',
'cid',
'pid',
'form_key',
'name',
'type',
'weight',
'pk',
]);
foreach ($chunk as $set) {
$insert->values($set);
}
$insert->execute();
}
$end = microtime(TRUE);
\Drupal::messenger()
->addStatus("Created intermediate TABLE $tablename with @c records in @s seconds.", [
'@c' => count($batchValues),
'@s' => round($end - $start, 2),
]);
// TODO: Drupal Rector Notice: Please delete the following comment after.
// You've made any necessary changes.
// You will need to use `\Drupal\core\Database\Database::getConnection()`.
// If you do not yet have access to the container here.
$gridcomponents = \Drupal::database()
->select($tablename, 'dn_webform_component')
->fields('dn_webform_component');
// We need to mirror the incremental conditions to this union subquery.
$conditions = $q->havingConditions();
foreach (element_children($conditions) as $key) {
$gridcomponents->havingCondition($conditions[$key]['field'], $conditions[$key]['value'], $conditions[$key]['operator']);
}
$q->union($gridcomponents, 'ALL');
}
// @todo: move webform_component_av into dw db
if ($view == 'webform_submitted_data') {
// Remove the data field and replace it with a varchar.
$fields = &$q->getFields();
unset($fields['data']);
$q->addExpression('substr(data, 1, 255)', 'data');
// Create surrogate key.
$q->addExpression("CONCAT_WS('-', sid, dn_webform_submitted_data.cid, no)", 'pk');
// Dump unserialized data into a temporary table.
$start = microtime(TRUE);
$tablename = 'webform_component_av';
if (db_table_exists($tablename)) {
db_drop_table($tablename);
}
// TODO: Drupal Rector Notice: Please delete the following comment after.
// You've made any necessary changes.
// You will need to use `\Drupal\core\Database\Database::getConnection()`.
// If you do not yet have access to the container here.
\Drupal::database()
->query("create table {{$tablename}} select nid, cid, cast('' as char(255)) as `key`, cast('' as char(255)) as `value` from {webform_component} limit 0");
db_add_primary_key($tablename, ['nid', 'cid', 'key']);
// TODO: Drupal Rector Notice: Please delete the following comment after.
// You've made any necessary changes.
// You will need to use `\Drupal\core\Database\Database::getConnection()`.
// If you do not yet have access to the container here.
$result = \Drupal::database()
->query("select nid, cid, extra from {webform_component} where type in ('grid', 'select')");
$batchValues = [];
while ($row = $result->fetch()) {
$data = unserialize($row->extra);
$items = list_extract_allowed_values(isset($data['items']) ? $data['items'] : $data['options'], 'list_text', FALSE);
foreach ($items as $key => $value) {
$batchValues[] = [
'nid' => $row->nid,
'cid' => $row->cid,
'`key`' => $key,
'value' => substr($value, 0, 255),
];
}
}
foreach (array_chunk($batchValues, variable_get('denormalizer_chunk_size', 5000)) as $chunk) {
// TODO: Drupal Rector Notice: Please delete the following comment after.
// You've made any necessary changes.
// You will need to use `\Drupal\core\Database\Database::getConnection()`.
// If you do not yet have access to the container here.
$insert = \Drupal::database()->insert($tablename)->fields([
'nid',
'cid',
'`key`',
'value',
]);
foreach ($chunk as $set) {
$insert->values($set);
}
$insert->execute();
}
$end = microtime(TRUE);
\Drupal::messenger()
->addStatus("Created intermediate TABLE $tablename with @c records in @s seconds.", [
'@c' => count($batchValues),
'@s' => round($end - $start, 2),
]);
// Join the "webform allowed values" table.
$q->addJoin('LEFT', $tablename, 'wav', 'dn_webform_submitted_data.data = wav.key and dn_webform_submitted_data.cid = wav.cid and dn_webform_submitted_data.nid = wav.nid');
$q->fields('wav', ['value']);
// We really need the form keys.
$q->addJoin('LEFT', 'webform_component', 'wc', 'dn_webform_submitted_data.nid = wc.nid and dn_webform_submitted_data.cid = wc.cid');
// $q->fields('wc', array('form_key'));
$q->addExpression("IF(wc.type != 'grid', form_key, (CONCAT_WS('-', form_key, no)))", 'form_key');
}
}
/**
* Sanitize webform data.
* @param array $webformData
* The webform submitted data.
* @param array $columns
* The webform fields as columns.
*
* @return array $sanitized
* A new formatted data array.
*/
function denormalizer_webform_data_sanitize($webformData, $columns) {
$sanitized = [];
$sid = $webformData[0]->sid;
$element = [];
foreach ($webformData as $index => $column) {
if ($sid == $column->sid) {
foreach ($columns as $col) {
if (!isset($element['webform_id'])) {
$element['webform_id'] = $column->webform_id;
$element['sid'] = $column->sid;
}
if ($column->name == $col) {
$element[$col] = $column->value;
}
elseif ($column->name . "_" . $column->value == $col) {
$element[$col] = 1;
}
}
if ($index == count($webformData) - 1) {
array_push($sanitized, $element);
}
}
else {
$sid = $column->sid;
array_push($sanitized, $element);
$element = [];
foreach ($columns as $col) {
if (!isset($element['webform_id'])) {
$element['webform_id'] = $column->webform_id;
$element['sid'] = $column->sid;
}
if ($column->name == $col) {
$element[$col] = $column->value;
}
elseif ($column->name . "_" . $column->value == $col) {
$element[$col] = 1;
}
}
}
}
return $sanitized;
}
/**
* Add types to the query columns.
* @param array $elements
* The array of columns.
*
* @return array $elements
* A new formatted array..
*/
function denormalizer_webform_sql_columns($elements) {
array_unshift($elements,'sid int unsigned');
array_unshift($elements,'webform_id varchar(32)');
foreach ($elements as $index => $element) {
if ($index !== 0 && $index !== 1) {
$element = $element . ' mediumtext';
$elements[$index] = $element;
}
}
return $elements;
}
/**
* Get elements from the webform decoded object.
* @param string $bundles
* The webform_id.
*
* @return array $columns
* The field elements to transform in columns.
*/
function denormalizer_webform_get_columns($bundles) {
$webform = Webform::load($bundles);
$elements = $webform->getElementsDecoded();
$columns = [];
$fieldTypes = [
'processed_text',
'checkbox',
'select',
'term_select',
'textarea',
'webform_computed_twig',
'webform_likert',
'webform_term_select',
'text\/css',
];
$columns = denormalizer_webform_explore_elements($elements, $columns, $fieldTypes);
return $columns;
}
/**
* A recursive function to look for elements name.
* @param array $elements
* The object to explore.
* @param array $columns
* The columns to build.
* @param array $fieldTypes
* The fields to take in count.
*
* @return array $columns
* The field elements to transform in columns.
*/
function denormalizer_webform_explore_elements($elements,$columns,$fieldTypes) {
foreach ($elements as $key => $element) {
if (is_array($element)) {
if (isset($element['#type']) && in_array($element['#type'], $fieldTypes)) {
array_push($columns, $key);
}
elseif (isset($element['#type']) && in_array($element['#type'], ['webform_likert', 'checkboxes'])) {
foreach ($element['#options'] as $optionKey => $optionValue) {
array_push($columns, $key . '_' . $optionKey);
}
}
elseif (isset($element['#type'])) {
$result = denormalizer_webform_explore_elements($element,$columns, $fieldTypes);
if (!empty($result)) {
foreach ($result as $value) {
if (!in_array($value,$columns)) {
array_push($columns, $value);
}
}
}
}
}
}
return $columns;
}
denormalizer.create:
path: 'admin/config/development/denormalizer/create'
defaults:
_form: '\Drupal\denormalizer\Form\DenormalizerCreateForm'
_title: 'Confirm Creation'
requirements:
_permission: 'administer site configuration'
denormalizer.export:
path: 'admin/config/development/denormalizer/export'
defaults:
_form: '\Drupal\denormalizer\Form\DenormalizerExportForm'
_title: 'Confirm Creation'
requirements:
_permission: 'administer site configuration'
denormalizer.settings:
path: '/admin/config/development/denormalizer'
defaults:
......
services:
denormalizer.manager:
class: Drupal\denormalizer\Service\DenormalizerManager
arguments: ['@entity_type.manager', '@entity_field.manager', '@database']
plugin.manager.schema_denormalizer:
class: Drupal\denormalizer\Plugin\Denormalizer\SchemaDenormalizerManager
parent: default_plugin_manager
services:
denormalizer.commands:
class: Drupal\denormalizer\Commands\DenormalizerCommands
arguments: ['@denormalizer.manager', '@plugin.manager.schema_denormalizer']
tags:
- { name: drush.command }
<?php
namespace Drupal\denormalizer\Annotation;
use Drupal\Component\Annotation\Plugin;
/**
* Defines a Field Denormalizer annotation object.
*
* Plugin Namespace: Plugin\Denormalizer.
*
* @Annotation
*/
class SchemaDenormalizer extends Plugin {
/**
* The plugin ID.
*
* @var string
*/
public $id;
/**
* The human readable of the content entity schema denormalizer.
*
* @var string
*/
public $name;
/**
* Whether content entity associated with this schema denormalizer has.
*
* A bundle.
*
* @var bool
*/
public $hasBundle = FALSE;
/**
* The default bundles the schema denormalizer supports.
*
* @var array
*/
public $bundles = [];
}
<?php
namespace Drupal\denormalizer\Commands;
use Drupal\denormalizer\Plugin\Denormalizer\SchemaDenormalizerManager;
use Drupal\denormalizer\Service\DenormalizerManagerInterface;
use Drush\Commands\DrushCommands;
/**
* Class DenormalizerCommands.
*
* @package Drupal\denormalizer\Commands
*/
class DenormalizerCommands extends DrushCommands {
/**
* The denormalizer manager service.
*
* @var \Drupal\denormalizer\Service\DenormalizerManagerInterface
*/
protected $denormalizerManager;
/**
* The schema denormalizer plugin manager.
*
* @var \Drupal\denormalizer\Plugin\Denormalizer\SchemaDenormalizerManager
*/
protected $schemaDenormalizerManager;
/**
* Creates a new denormalizer drush command.
*
* @param \Drupal\denormalizer\Service\DenormalizerManagerInterface $denormalizerManager
* The denormalizer manager service.
* @param \Drupal\denormalizer\Plugin\Denormalizer\SchemaDenormalizerManager $schemaDenormalizerManager
* The schema denormalizer plugin manager.
*/
public function __construct(DenormalizerManagerInterface $denormalizerManager, SchemaDenormalizerManager $schemaDenormalizerManager) {
$this->denormalizerManager = $denormalizerManager;
$this->schemaDenormalizerManager = $schemaDenormalizerManager;
}
/**
* Denormalize tables. Makes a delicious denormalized schema.
*
* @command denormalizer:denormalize
* @aliases dnz
* @options reset Resets tables.
* @usage drush denormalizer:denormalize --reset
* Resets tables.
*/
public function denormalize($options = ['reset' => FALSE]) {
$entityId = 'node';
$bundle = 'tags';
// $schema = $this->denormalizerManager->getContentEntityFieldSchema(.
// $entityId, $bundle);.
$types = $this->denormalizerManager->getContentEntityTypes();
$instance = $this->schemaDenormalizerManager->createInstance($entityId);
// $instance->schemas();
print_r($instance->schemas('page'));
// $this->denormalizerManager->createDenormalizedTable($entityId.'_'.
// $bundle.'_denormalize', $schema, 'denormalizer');.
// $this->denormalizerManager->createDatabase('denormalizer');.
}
}
This diff is collapsed.
<?php
namespace Drupal\denormalizer\Exception;
use Exception;
/**
* Defines an exception thrown when the database being created already exists.
*
* Class DatabaseCreationNotSupportedException.
*
* @package Drupal\denormalizer\Exception
*/
class DatabaseCreationNotSupportedException extends Exception {
}
<?php
namespace Drupal\denormalizer\Form;
use Drupal\denormalizer\Denormalizer;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
/**
* Defines a confirmation form to confirm denormalization.
*/
class DenormalizerCreateForm extends ConfirmFormBase {
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$denormalizer = new Denormalizer();
$denormalizer->build();
$denormalizer->execute();
$config = \Drupal::service('config.factory')->getEditable('denormalizer.settings');
$config->set('denormalizer_last_run', \Drupal::time()->getRequestTime());
\Drupal::logger('denormalizer')->info('Ran denormalizer.');
$form_state->setRedirect('denormalizer.settings');
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return "denormalizer_create_form";
}
/**
* {@inheritdoc}
*/
public function getCancelUrl() {
// Todo this URL needs to be updated.
return new Url('denormalizer.settings');
}
/**
* {@inheritdoc}
*/
public function getQuestion() {
return $this->t('Ready? This will create database views of normalized data.');
}
}
<?php
namespace Drupal\denormalizer\Form;
use Drupal\denormalizer\Denormalizer;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Defines a confirmation form to confirm denormalization.
*/
class DenormalizerExportForm extends FormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return "denormalizer_export_form";
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['header']['#markup'] = t('You can use the SQL below to generate database views of denormalized data on a copy of this database. This uses the entity property and field metadata from the current site, so queries may fail if the data is different.');
$denormalizer = new Denormalizer();
$denormalizer->build();
$form['sql']['#markup'] = $denormalizer->getSql();
$form['actions'] = [
'#type' => 'actions',
];
// Add a submit button that handles the submission of the form.
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Submit'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$messenger = \Drupal::messenger();
$messenger->addMessage(' SQL exported');
$form_state->setRedirect('denormalizer.settings');
}
}
......@@ -74,7 +74,6 @@ class DenormalizerSettingsForm extends ConfigFormBase {
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('denormalizer.settings');
$form['cron_enabled'] = [
......@@ -130,24 +129,4 @@ class DenormalizerSettingsForm extends ConfigFormBase {
parent::submitForm($form, $form_state);
}
/**
* Check bundles.
*
* @param string $entityId
* The entity id.
*
* @return array
* Return bundles.
*/
private function checkBundles($entityId) {
$bundles = $this->bundleInfo->getBundleInfo($entityId);
if (array_key_exists($entityId, $bundles)) {
return [];
}
return array_keys($bundles);
}
}
......@@ -82,7 +82,7 @@ class DenormalizerTableForm extends EntityForm {
'#title' => $this->t('Status'),
'#options' => [
0 => $this->t('Disabled'),
1 => $this->t('Enabled'),
1 => $this->t('Enabled'),
],
'#default_value' => (int) $table->status(),
];
......@@ -122,7 +122,8 @@ class DenormalizerTableForm extends EntityForm {
$this->entity->save();
if ($this->entity->getSourceId() !== 'entity') {
$this->messenger()->addWarning($this->t('Only @entity config entity was created! None entity source are\'t currently supported!'));
$this->messenger()
->addWarning($this->t('Only @entity config entity was created! None entity source are\'t currently supported!'));
$form_state->setRedirect('entity.denormalizer_table.collection');
return;
}
......@@ -134,7 +135,7 @@ class DenormalizerTableForm extends EntityForm {
$class = get_class($this->entity);
$operations[] = [
[$class, 'initBatch'],
[$this->entity, $entity_type_id]
[$this->entity, $entity_type_id],
];
$entity_type_definition = $this->entityTypeManager->getDefinition($entity_type_id);
......@@ -143,7 +144,7 @@ class DenormalizerTableForm extends EntityForm {
foreach ($entity_ids_chunks as $entity_ids_chunk) {
$operations[] = [
[$class, 'populateTableBatch'],
[$entity_ids_chunk]
[$entity_ids_chunk],
];
}
......@@ -165,7 +166,10 @@ class DenormalizerTableForm extends EntityForm {
if ($source_id === 'entity') {
/** @var \Drupal\Core\Entity\EntityTypeRepositoryInterface $entity_type_repository */
$entity_type_repository = \Drupal::service('entity_type.repository');
$entity_type = $form_state->getValue(['configuration', 'entity_type'], '');
$entity_type = $form_state->getValue([
'configuration',
'entity_type',
], '');
if (!$entity_type) {
$entity_type = $configuration['entity_type'] ?? '';
}
......@@ -269,7 +273,7 @@ class DenormalizerTableForm extends EntityForm {
if (!$entity_type) {
return [];
}
return array_map(function ($bundle_info) {
return array_map(function($bundle_info) {
return $bundle_info['label'];
}, \Drupal::service('entity_type.bundle.info')->getBundleInfo($entity_type));
}
......@@ -282,13 +286,7 @@ class DenormalizerTableForm extends EntityForm {
->getBaseFieldDefinitions($entity_type_id);
$options = [];
foreach ($base_fields as $field) {
$field_type = $field->getType();
if ($changed_key && ($field_type === 'changed' || $field_type === 'timestamp')) {
$options[$field->getName()] = $field->getLabel();
}
else {
$options[$field->getName()] = $field->getLabel();
}
$options[$field->getName()] = $field->getLabel();
}
return $options;
}
......@@ -297,28 +295,23 @@ class DenormalizerTableForm extends EntityForm {
if (!$entity_type_id || !$bundle) {
return [];
}
$options = [];
if ($bundle) {
if ($entity_type_id !== 'webform_submission') {
$entity_field_manager = $this->entityFieldManager();
$field_definitions = $entity_field_manager->getFieldDefinitions($entity_type_id, $bundle);
foreach ($field_definitions as $field) {
if ($field->getTargetBundle()) {
$options[$field->getName()] = $field->getLabel();
}
}
if ($entity_type_id === 'webform_submission' && ($webform = $this->getWebform($bundle))) {
foreach ($webform->getElementsInitializedFlattenedAndHasValue() as $key => $element) {
$title = isset($element['#title']) ? $this->t('@title', [
'@title' => $element['#title'],
]) : $key;
$options[$key] = $title;
}
else {
$webform = $this->entityTypeManager->getStorage('webform')
->load($bundle);
if ($webform instanceof WebformInterface) {
foreach ($webform->getElementsInitializedFlattenedAndHasValue() as $key => $element) {
$title = isset($element['#title']) ? $this->t('@title', [
'@title' => $element['#title'],
]) : $key;
$options[$key] = $title;
}
}
return $options;
}
$entity_field_manager = $this->entityFieldManager();
$field_definitions = $entity_field_manager->getFieldDefinitions($entity_type_id, $bundle);
foreach ($field_definitions as $field) {
if ($field->getTargetBundle()) {
$options[$field->getName()] = $field->getLabel();
}
}
return $options;
......@@ -363,4 +356,10 @@ class DenormalizerTableForm extends EntityForm {
return $query->execute();
}
private function getWebform(string $webform_id): ?WebformInterface {
/** @var \Drupal\webform\WebformEntityStorageInterface $webform_storage */
$webform_storage = $this->entityTypeManager->getStorage('webform');
return $webform_storage->load($webform_id);
}
}
<?php
namespace Drupal\denormalizer\Plugin\Denormalizer;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\denormalizer\Service\DenormalizerManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* The base class for content entity schema denormailzer plugins.
*
* @package Drupal\denormalizer\Plugin\Denormalizer
*/
abstract class AbstractSchemaDenormalizer extends PluginBase implements SchemaDenormalizerInterface, ContainerFactoryPluginInterface {
/*
* {@inheritdoc}
*/
use StringTranslationTrait;
/**
* The denormalizer manager.
*
* @var \Drupal\denormalizer\Service\DenormalizerManagerInterface
*/
protected $denormalizerManager;
/**
* AbstractSchemaDenormalizer constructor.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\denormalizer\Service\DenormalizerManagerInterface $denormalizerManager
* The denormalizer plugin manager.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, DenormalizerManagerInterface $denormalizerManager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->denormalizerManager = $denormalizerManager;
}
/**
* Create denormalizer schema.
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* The container.
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
*
* @return \Drupal\Core\Plugin\ContainerFactoryPluginInterface|\Drupal\denormalizer\Plugin\Denormalizer\AbstractSchemaDenormalizer
* The denormalizer schema.
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration, $plugin_id, $plugin_definition,
$container->get('denormalizer.manager')
);
}
/**
* {@inheritdoc}
*/
public function getMachineName() {
return $this->pluginDefinition['id'];
}
/**
* {@inheritdoc}
*/
public function hasBundle() {
return $this->pluginDefinition['hasBundle'];
}
/**
* {@inheritdoc}
*/
public function schemas(string $bundle = NULL) {
if ($this->hasBundle() && !isset($bundle)) {
throw new \Exception("Missing bundle name for '" . $this->getMachineName() . "' content entity.");
}
return $this->denormalizerManager->getContentEntityFieldSchema($this->getMachineName(), $bundle);
}
}
<?php
namespace Drupal\denormalizer\Plugin\Denormalizer;
/**
* Define a concrete class for a node content entity.
*
* @SchemaDenormalizer (
* id = "node",
* name = @Translation("Node"),
* hasBundle = TRUE,
* )
*/
class Node extends AbstractSchemaDenormalizer {
// /**
// * {@inheritdoc}
// */
/* public function schemas(string $bundle = NULL) {
if ($this->hasBundle() && !isset($bundle)){
throw new \Exception("Missing bundle name for '".$this->getMachineName()."'.
ontent entity.");
}
return $this->denormalizerManager->getContentEntityFieldSchema($this
->getMachineName(), $bundle);.
} */
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment