Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
|
@ -6,5 +6,5 @@ dependencies:
|
|||
id: node_delete_action
|
||||
label: 'Delete content'
|
||||
type: node
|
||||
plugin: node_delete_action
|
||||
plugin: entity:delete_action:node
|
||||
configuration: { }
|
||||
|
|
|
@ -6,5 +6,5 @@ dependencies:
|
|||
id: node_publish_action
|
||||
label: 'Publish content'
|
||||
type: node
|
||||
plugin: node_publish_action
|
||||
plugin: entity:publish_action:node
|
||||
configuration: { }
|
||||
|
|
|
@ -6,5 +6,5 @@ dependencies:
|
|||
id: node_save_action
|
||||
label: 'Save content'
|
||||
type: node
|
||||
plugin: node_save_action
|
||||
plugin: entity:save_action:node
|
||||
configuration: { }
|
||||
|
|
|
@ -6,5 +6,5 @@ dependencies:
|
|||
id: node_unpublish_action
|
||||
label: 'Unpublish content'
|
||||
type: node
|
||||
plugin: node_unpublish_action
|
||||
plugin: entity:unpublish_action:node
|
||||
configuration: { }
|
||||
|
|
|
@ -28,7 +28,7 @@ display:
|
|||
empty:
|
||||
area_text_custom:
|
||||
admin_label: ''
|
||||
content: 'No front page content has been created yet.'
|
||||
content: 'No front page content has been created yet.<br/>Follow the <a target="_blank" href="https://www.drupal.org/docs/user_guide/en/index.html">User Guide</a> to start building your site.'
|
||||
empty: true
|
||||
field: area_text_custom
|
||||
group_type: group
|
||||
|
|
|
@ -62,18 +62,26 @@ action.configuration.node_promote_action:
|
|||
type: action_configuration_default
|
||||
label: 'Promote selected content from front page configuration'
|
||||
|
||||
# @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0.
|
||||
# @see https://www.drupal.org/node/2919303
|
||||
action.configuration.node_publish_action:
|
||||
type: action_configuration_default
|
||||
label: 'Publish selected content configuration'
|
||||
|
||||
# @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0.
|
||||
# @see https://www.drupal.org/node/2919303
|
||||
action.configuration.node_unpublish_action:
|
||||
type: action_configuration_default
|
||||
label: 'Unpublish selected content configuration'
|
||||
|
||||
# @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0.
|
||||
# @see https://www.drupal.org/node/2919303
|
||||
action.configuration.node_save_action:
|
||||
type: action_configuration_default
|
||||
label: 'Save content configuration'
|
||||
|
||||
# @deprecated in Drupal 8.6.x, to be removed before Drupal 9.0.0.
|
||||
# @see https://www.drupal.org/node/2934349
|
||||
action.configuration.node_delete_action:
|
||||
type: action_configuration_default
|
||||
label: 'Delete content configuration'
|
||||
|
|
81
web/core/modules/node/content_types.es6.js
Normal file
81
web/core/modules/node/content_types.es6.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* @file
|
||||
* Javascript for the node content editing form.
|
||||
*/
|
||||
|
||||
(function($, Drupal) {
|
||||
/**
|
||||
* Behaviors for setting summaries on content type form.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches summary behaviors on content type edit forms.
|
||||
*/
|
||||
Drupal.behaviors.contentTypes = {
|
||||
attach(context) {
|
||||
const $context = $(context);
|
||||
// Provide the vertical tab summaries.
|
||||
$context.find('#edit-submission').drupalSetSummary(context => {
|
||||
const vals = [];
|
||||
vals.push(
|
||||
Drupal.checkPlain(
|
||||
$(context)
|
||||
.find('#edit-title-label')
|
||||
.val(),
|
||||
) || Drupal.t('Requires a title'),
|
||||
);
|
||||
return vals.join(', ');
|
||||
});
|
||||
$context.find('#edit-workflow').drupalSetSummary(context => {
|
||||
const vals = [];
|
||||
$(context)
|
||||
.find('input[name^="options"]:checked')
|
||||
.next('label')
|
||||
.each(function() {
|
||||
vals.push(Drupal.checkPlain($(this).text()));
|
||||
});
|
||||
if (
|
||||
!$(context)
|
||||
.find('#edit-options-status')
|
||||
.is(':checked')
|
||||
) {
|
||||
vals.unshift(Drupal.t('Not published'));
|
||||
}
|
||||
return vals.join(', ');
|
||||
});
|
||||
$('#edit-language', context).drupalSetSummary(context => {
|
||||
const vals = [];
|
||||
|
||||
vals.push(
|
||||
$(
|
||||
'.js-form-item-language-configuration-langcode select option:selected',
|
||||
context,
|
||||
).text(),
|
||||
);
|
||||
|
||||
$('input:checked', context)
|
||||
.next('label')
|
||||
.each(function() {
|
||||
vals.push(Drupal.checkPlain($(this).text()));
|
||||
});
|
||||
|
||||
return vals.join(', ');
|
||||
});
|
||||
$context.find('#edit-display').drupalSetSummary(context => {
|
||||
const vals = [];
|
||||
const $editContext = $(context);
|
||||
$editContext
|
||||
.find('input:checked')
|
||||
.next('label')
|
||||
.each(function() {
|
||||
vals.push(Drupal.checkPlain($(this).text()));
|
||||
});
|
||||
if (!$editContext.find('#edit-display-submitted').is(':checked')) {
|
||||
vals.unshift(Drupal.t("Don't display post information"));
|
||||
}
|
||||
return vals.join(', ');
|
||||
});
|
||||
},
|
||||
};
|
||||
})(jQuery, Drupal);
|
|
@ -1,24 +1,15 @@
|
|||
/**
|
||||
* @file
|
||||
* Javascript for the node content editing form.
|
||||
*/
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* See the following change record for more information,
|
||||
* https://www.drupal.org/node/2815083
|
||||
* @preserve
|
||||
**/
|
||||
|
||||
(function ($, Drupal) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Behaviors for setting summaries on content type form.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches summary behaviors on content type edit forms.
|
||||
*/
|
||||
Drupal.behaviors.contentTypes = {
|
||||
attach: function (context) {
|
||||
attach: function attach(context) {
|
||||
var $context = $(context);
|
||||
// Provide the vertical tab summaries.
|
||||
|
||||
$context.find('#edit-submission').drupalSetSummary(function (context) {
|
||||
var vals = [];
|
||||
vals.push(Drupal.checkPlain($(context).find('#edit-title-label').val()) || Drupal.t('Requires a title'));
|
||||
|
@ -26,7 +17,7 @@
|
|||
});
|
||||
$context.find('#edit-workflow').drupalSetSummary(function (context) {
|
||||
var vals = [];
|
||||
$(context).find('input[name^="options"]:checked').parent().each(function () {
|
||||
$(context).find('input[name^="options"]:checked').next('label').each(function () {
|
||||
vals.push(Drupal.checkPlain($(this).text()));
|
||||
});
|
||||
if (!$(context).find('#edit-options-status').is(':checked')) {
|
||||
|
@ -58,5 +49,4 @@
|
|||
});
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery, Drupal);
|
||||
})(jQuery, Drupal);
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
/* Narrow screens */
|
||||
.layout-region {
|
||||
box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Wide screens */
|
||||
|
@ -51,7 +51,7 @@
|
|||
.layout-region-node-secondary .form-number,
|
||||
.layout-region-node-secondary .form-color,
|
||||
.layout-region-node-secondary textarea {
|
||||
box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
id: d6_node_translation
|
||||
label: Node translations
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
deriver: Drupal\node\Plugin\migrate\D6NodeDeriver
|
||||
source:
|
||||
plugin: d6_node
|
||||
translations: true
|
||||
process:
|
||||
# If you are using this file to build a custom migration consider removing
|
||||
# the nid field to allow incremental migrations.
|
||||
nid: tnid
|
||||
type: type
|
||||
langcode:
|
||||
plugin: default_value
|
||||
source: language
|
||||
default_value: "und"
|
||||
title: title
|
||||
uid: node_uid
|
||||
status: status
|
||||
created: created
|
||||
changed: changed
|
||||
promote: promote
|
||||
sticky: sticky
|
||||
'body/format':
|
||||
plugin: migration_lookup
|
||||
migration: d6_filter_format
|
||||
source: format
|
||||
'body/value': body
|
||||
'body/summary': teaser
|
||||
revision_uid: revision_uid
|
||||
revision_log: log
|
||||
revision_timestamp: timestamp
|
||||
content_translation_source: source_langcode
|
||||
|
||||
# unmapped d6 fields.
|
||||
# translate
|
||||
# moderate
|
||||
# comment
|
||||
|
||||
destination:
|
||||
plugin: entity:node
|
||||
translations: true
|
||||
migration_dependencies:
|
||||
required:
|
||||
- d6_user
|
||||
- d6_node_type
|
||||
- d6_node_settings
|
||||
- d6_filter_format
|
||||
- language
|
||||
optional:
|
||||
- d6_field_instance_widget_settings
|
||||
- d6_field_formatter_settings
|
||||
- d6_upload_field_instance
|
||||
provider: migrate_drupal
|
|
@ -1,42 +0,0 @@
|
|||
id: d7_node_translation
|
||||
label: Node translations
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- translation
|
||||
deriver: Drupal\node\Plugin\migrate\D7NodeDeriver
|
||||
source:
|
||||
plugin: d7_node
|
||||
translations: true
|
||||
process:
|
||||
# If you are using this file to build a custom migration consider removing
|
||||
# the nid field to allow incremental migrations.
|
||||
nid: tnid
|
||||
type: type
|
||||
langcode:
|
||||
plugin: default_value
|
||||
source: language
|
||||
default_value: "und"
|
||||
title: title
|
||||
uid: node_uid
|
||||
status: status
|
||||
created: created
|
||||
changed: changed
|
||||
promote: promote
|
||||
sticky: sticky
|
||||
revision_uid: revision_uid
|
||||
revision_log: log
|
||||
revision_timestamp: timestamp
|
||||
content_translation_source: source_langcode
|
||||
destination:
|
||||
plugin: entity:node
|
||||
translations: true
|
||||
content_translation_update_definitions:
|
||||
- node
|
||||
migration_dependencies:
|
||||
required:
|
||||
- d7_user
|
||||
- d7_node_type
|
||||
- language
|
||||
optional:
|
||||
- d7_field_instance
|
||||
provider: migrate_drupal
|
|
@ -1,7 +1,9 @@
|
|||
id: d6_node
|
||||
label: Nodes
|
||||
audit: true
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Content
|
||||
deriver: Drupal\node\Plugin\migrate\D6NodeDeriver
|
||||
source:
|
||||
plugin: d6_node
|
|
@ -1,7 +1,9 @@
|
|||
id: d6_node_revision
|
||||
label: Node revisions
|
||||
audit: true
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Content
|
||||
deriver: Drupal\node\Plugin\migrate\D6NodeDeriver
|
||||
source:
|
||||
plugin: d6_node_revision
|
|
@ -2,6 +2,7 @@ id: d6_node_setting_promote
|
|||
label: Node type 'promote' setting
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: d6_node_type
|
||||
constants:
|
|
@ -2,6 +2,7 @@ id: d6_node_setting_status
|
|||
label: Node type 'status' setting
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: d6_node_type
|
||||
constants:
|
|
@ -2,6 +2,7 @@ id: d6_node_setting_sticky
|
|||
label: Node type 'sticky' setting
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: d6_node_type
|
||||
constants:
|
|
@ -2,10 +2,12 @@ id: d6_node_settings
|
|||
label: Node configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- node_admin_theme
|
||||
source_module: node
|
||||
process:
|
||||
use_admin_theme: node_admin_theme
|
||||
destination:
|
|
@ -2,6 +2,7 @@ id: d6_node_type
|
|||
label: Node type configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: d6_node_type
|
||||
constants:
|
|
@ -2,6 +2,7 @@ id: d6_view_modes
|
|||
label: View modes
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: d6_view_mode
|
||||
constants:
|
|
@ -1,7 +1,9 @@
|
|||
id: d7_node
|
||||
label: Nodes
|
||||
audit: true
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Content
|
||||
deriver: Drupal\node\Plugin\migrate\D7NodeDeriver
|
||||
source:
|
||||
plugin: d7_node
|
||||
|
@ -35,3 +37,4 @@ migration_dependencies:
|
|||
- d7_node_type
|
||||
optional:
|
||||
- d7_field_instance
|
||||
- d7_comment_field_instance
|
|
@ -1,7 +1,9 @@
|
|||
id: d7_node_revision
|
||||
label: Node revisions
|
||||
audit: true
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Content
|
||||
deriver: Drupal\node\Plugin\migrate\D7NodeDeriver
|
||||
source:
|
||||
plugin: d7_node_revision
|
|
@ -2,10 +2,12 @@ id: d7_node_settings
|
|||
label: Node configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- node_admin_theme
|
||||
source_module: node
|
||||
process:
|
||||
use_admin_theme: node_admin_theme
|
||||
destination:
|
|
@ -2,6 +2,7 @@ id: d7_node_title_label
|
|||
label: Node title label
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: d7_node_type
|
||||
constants:
|
|
@ -2,6 +2,7 @@ id: d7_node_type
|
|||
label: Node type configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: d7_node_type
|
||||
constants:
|
|
@ -35,7 +35,7 @@ function node_mass_update(array $nodes, array $updates, $langcode = NULL, $load
|
|||
if (count($nodes) > 10) {
|
||||
$batch = [
|
||||
'operations' => [
|
||||
['_node_mass_update_batch_process', [$nodes, $updates, $langcode, $load, $revisions]]
|
||||
['_node_mass_update_batch_process', [$nodes, $updates, $langcode, $load, $revisions]],
|
||||
],
|
||||
'finished' => '_node_mass_update_batch_finished',
|
||||
'title' => t('Processing'),
|
||||
|
@ -60,7 +60,7 @@ function node_mass_update(array $nodes, array $updates, $langcode = NULL, $load
|
|||
}
|
||||
_node_mass_update_helper($node, $updates, $langcode);
|
||||
}
|
||||
drupal_set_message(t('The update has been performed.'));
|
||||
\Drupal::messenger()->addStatus(t('The update has been performed.'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,16 +164,16 @@ function _node_mass_update_batch_process(array $nodes, array $updates, $langcode
|
|||
*/
|
||||
function _node_mass_update_batch_finished($success, $results, $operations) {
|
||||
if ($success) {
|
||||
drupal_set_message(t('The update has been performed.'));
|
||||
\Drupal::messenger()->addStatus(t('The update has been performed.'));
|
||||
}
|
||||
else {
|
||||
drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
|
||||
\Drupal::messenger()->addError(t('An error occurred and processing did not complete.'));
|
||||
$message = \Drupal::translation()->formatPlural(count($results), '1 item successfully processed:', '@count items successfully processed:');
|
||||
$item_list = [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $results,
|
||||
];
|
||||
$message .= drupal_render($item_list);
|
||||
drupal_set_message($message);
|
||||
$message .= \Drupal::service('renderer')->render($item_list);
|
||||
\Drupal::messenger()->addStatus($message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,7 +169,7 @@ function hook_node_access_records(\Drupal\node\NodeInterface $node) {
|
|||
'grant_view' => 1,
|
||||
'grant_update' => 0,
|
||||
'grant_delete' => 0,
|
||||
'langcode' => 'ca'
|
||||
'langcode' => 'ca',
|
||||
];
|
||||
}
|
||||
// For the example_author array, the GID is equivalent to a UID, which
|
||||
|
@ -183,7 +183,7 @@ function hook_node_access_records(\Drupal\node\NodeInterface $node) {
|
|||
'grant_view' => 1,
|
||||
'grant_update' => 1,
|
||||
'grant_delete' => 1,
|
||||
'langcode' => 'ca'
|
||||
'langcode' => 'ca',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -297,11 +297,17 @@ function hook_node_grants_alter(&$grants, \Drupal\Core\Session\AccountInterface
|
|||
* permission may always view and edit content through the administrative
|
||||
* interface.
|
||||
*
|
||||
* Note that not all modules will want to influence access on all node types. If
|
||||
* your module does not want to explicitly allow or forbid access, return an
|
||||
* AccessResultInterface object with neither isAllowed() nor isForbidden()
|
||||
* equaling TRUE. Blindly returning an object with isForbidden() equaling TRUE
|
||||
* will break other node access modules.
|
||||
* The access to a node can be influenced in several ways:
|
||||
* - To explicitly allow access, return an AccessResultInterface object with
|
||||
* isAllowed() returning TRUE. Other modules can override this access by
|
||||
* returning TRUE for isForbidden().
|
||||
* - To explicitly forbid access, return an AccessResultInterface object with
|
||||
* isForbidden() returning TRUE. Access will be forbidden even if your module
|
||||
* (or another module) also returns TRUE for isNeutral() or isAllowed().
|
||||
* - To neither allow nor explicitly forbid access, return an
|
||||
* AccessResultInterface object with isNeutral() returning TRUE.
|
||||
* - If your module does not return an AccessResultInterface object, neutral
|
||||
* access will be assumed.
|
||||
*
|
||||
* Also note that this function isn't called for node listings (e.g., RSS feeds,
|
||||
* the default home page at path 'node', a recent content block, etc.) See
|
||||
|
@ -320,7 +326,7 @@ function hook_node_grants_alter(&$grants, \Drupal\Core\Session\AccountInterface
|
|||
* The user object to perform the access check operation on.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
* The access result.
|
||||
*
|
||||
* @ingroup node_access
|
||||
*/
|
||||
|
|
56
web/core/modules/node/node.es6.js
Normal file
56
web/core/modules/node/node.es6.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* @file
|
||||
* Defines Javascript behaviors for the node module.
|
||||
*/
|
||||
|
||||
(function($, Drupal, drupalSettings) {
|
||||
/**
|
||||
* Behaviors for tabs in the node edit form.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches summary behavior for tabs in the node edit form.
|
||||
*/
|
||||
Drupal.behaviors.nodeDetailsSummaries = {
|
||||
attach(context) {
|
||||
const $context = $(context);
|
||||
|
||||
$context.find('.node-form-author').drupalSetSummary(context => {
|
||||
const $authorContext = $(context);
|
||||
const name = $authorContext.find('.field--name-uid input').val();
|
||||
const date = $authorContext.find('.field--name-created input').val();
|
||||
|
||||
if (name && date) {
|
||||
return Drupal.t('By @name on @date', {
|
||||
'@name': name,
|
||||
'@date': date,
|
||||
});
|
||||
}
|
||||
if (name) {
|
||||
return Drupal.t('By @name', { '@name': name });
|
||||
}
|
||||
if (date) {
|
||||
return Drupal.t('Authored on @date', { '@date': date });
|
||||
}
|
||||
});
|
||||
|
||||
$context.find('.node-form-options').drupalSetSummary(context => {
|
||||
const $optionsContext = $(context);
|
||||
const vals = [];
|
||||
|
||||
if ($optionsContext.find('input').is(':checked')) {
|
||||
$optionsContext
|
||||
.find('input:checked')
|
||||
.next('label')
|
||||
.each(function() {
|
||||
vals.push(Drupal.checkPlain($.trim($(this).text())));
|
||||
});
|
||||
return vals.join(', ');
|
||||
}
|
||||
|
||||
return Drupal.t('Not promoted');
|
||||
});
|
||||
},
|
||||
};
|
||||
})(jQuery, Drupal, drupalSettings);
|
|
@ -6,4 +6,4 @@ version: VERSION
|
|||
core: 8.x
|
||||
configure: entity.node_type.collection
|
||||
dependencies:
|
||||
- text
|
||||
- drupal:text
|
||||
|
|
|
@ -74,7 +74,7 @@ function node_schema() {
|
|||
'default' => 0,
|
||||
],
|
||||
'realm' => [
|
||||
'description' => 'The realm in which the user must possess the grant ID. Each node access node can define one or more realms.',
|
||||
'description' => 'The realm in which the user must possess the grant ID. Modules can define one or more realms by implementing hook_node_grants().',
|
||||
'type' => 'varchar_ascii',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
|
@ -246,3 +246,24 @@ function node_update_8301() {
|
|||
$entity_type->set('entity_keys', $keys);
|
||||
$definition_update_manager->updateEntityType($entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix realm column description on the node_access table.
|
||||
*/
|
||||
function node_update_8400() {
|
||||
$schema = drupal_get_module_schema('node', 'node_access');
|
||||
$schema['fields']['realm']['description'] = 'The realm in which the user must possess the grant ID. Modules can define one or more realms by implementing hook_node_grants().';
|
||||
Database::getConnection()->schema()->changeField('node_access', 'realm', 'realm', $schema['fields']['realm']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a node access rebuild, if required.
|
||||
*/
|
||||
function node_update_8401() {
|
||||
// Get the list of node access modules.
|
||||
$modules = \Drupal::moduleHandler()->getImplementations('node_grants');
|
||||
// If multilingual usage, then rebuild node access.
|
||||
if (count($modules) > 0 && \Drupal::languageManager()->isMultilingual()) {
|
||||
node_access_needs_rebuild(TRUE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,13 @@
|
|||
/**
|
||||
* @file
|
||||
* Defines Javascript behaviors for the node module.
|
||||
*/
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* See the following change record for more information,
|
||||
* https://www.drupal.org/node/2815083
|
||||
* @preserve
|
||||
**/
|
||||
|
||||
(function ($, Drupal, drupalSettings) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Behaviors for tabs in the node edit form.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches summary behavior for tabs in the node edit form.
|
||||
*/
|
||||
Drupal.behaviors.nodeDetailsSummaries = {
|
||||
attach: function (context) {
|
||||
attach: function attach(context) {
|
||||
var $context = $(context);
|
||||
|
||||
$context.find('.node-form-author').drupalSetSummary(function (context) {
|
||||
|
@ -25,13 +16,16 @@
|
|||
var date = $authorContext.find('.field--name-created input').val();
|
||||
|
||||
if (name && date) {
|
||||
return Drupal.t('By @name on @date', {'@name': name, '@date': date});
|
||||
return Drupal.t('By @name on @date', {
|
||||
'@name': name,
|
||||
'@date': date
|
||||
});
|
||||
}
|
||||
else if (name) {
|
||||
return Drupal.t('By @name', {'@name': name});
|
||||
if (name) {
|
||||
return Drupal.t('By @name', { '@name': name });
|
||||
}
|
||||
else if (date) {
|
||||
return Drupal.t('Authored on @date', {'@date': date});
|
||||
if (date) {
|
||||
return Drupal.t('Authored on @date', { '@date': date });
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -45,11 +39,9 @@
|
|||
});
|
||||
return vals.join(', ');
|
||||
}
|
||||
else {
|
||||
return Drupal.t('Not promoted');
|
||||
}
|
||||
|
||||
return Drupal.t('Not promoted');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery, Drupal, drupalSettings);
|
||||
})(jQuery, Drupal, drupalSettings);
|
|
@ -20,6 +20,7 @@ drupal.node.preview:
|
|||
- core/jquery
|
||||
- core/jquery.once
|
||||
- core/drupal
|
||||
- core/drupal.dialog
|
||||
- core/drupal.form
|
||||
|
||||
drupal.content_types:
|
||||
|
|
|
@ -28,12 +28,15 @@ use Drupal\node\Entity\Node;
|
|||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\node\NodeInterface;
|
||||
use Drupal\node\NodeTypeInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
* Denotes that the node is not published.
|
||||
*
|
||||
* @deprecated Scheduled for removal in Drupal 9.0.x.
|
||||
* Use \Drupal\node\NodeInterface::NOT_PUBLISHED instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2316145
|
||||
*/
|
||||
const NODE_NOT_PUBLISHED = 0;
|
||||
|
||||
|
@ -42,6 +45,8 @@ const NODE_NOT_PUBLISHED = 0;
|
|||
*
|
||||
* @deprecated Scheduled for removal in Drupal 9.0.x.
|
||||
* Use \Drupal\node\NodeInterface::PUBLISHED instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2316145
|
||||
*/
|
||||
const NODE_PUBLISHED = 1;
|
||||
|
||||
|
@ -50,6 +55,8 @@ const NODE_PUBLISHED = 1;
|
|||
*
|
||||
* @deprecated Scheduled for removal in Drupal 9.0.x.
|
||||
* Use \Drupal\node\NodeInterface::NOT_PROMOTED instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2316145
|
||||
*/
|
||||
const NODE_NOT_PROMOTED = 0;
|
||||
|
||||
|
@ -58,6 +65,8 @@ const NODE_NOT_PROMOTED = 0;
|
|||
*
|
||||
* @deprecated Scheduled for removal in Drupal 9.0.x.
|
||||
* Use \Drupal\node\NodeInterface::PROMOTED instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2316145
|
||||
*/
|
||||
const NODE_PROMOTED = 1;
|
||||
|
||||
|
@ -66,6 +75,8 @@ const NODE_PROMOTED = 1;
|
|||
*
|
||||
* @deprecated Scheduled for removal in Drupal 9.0.x.
|
||||
* Use \Drupal\node\NodeInterface::NOT_STICKY instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2316145
|
||||
*/
|
||||
const NODE_NOT_STICKY = 0;
|
||||
|
||||
|
@ -74,6 +85,8 @@ const NODE_NOT_STICKY = 0;
|
|||
*
|
||||
* @deprecated Scheduled for removal in Drupal 9.0.x.
|
||||
* Use \Drupal\node\NodeInterface::STICKY instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2316145
|
||||
*/
|
||||
const NODE_STICKY = 1;
|
||||
|
||||
|
@ -92,7 +105,7 @@ function node_help($route_name, RouteMatchInterface $route_match) {
|
|||
else {
|
||||
$message = t('The content access permissions need to be rebuilt. <a href=":node_access_rebuild">Rebuild permissions</a>.', [':node_access_rebuild' => \Drupal::url('node.configure_rebuild_confirm')]);
|
||||
}
|
||||
drupal_set_message($message, 'error');
|
||||
\Drupal::messenger()->addError($message);
|
||||
}
|
||||
|
||||
switch ($route_name) {
|
||||
|
@ -121,7 +134,7 @@ function node_help($route_name, RouteMatchInterface $route_match) {
|
|||
case 'entity.entity_form_display.node.default':
|
||||
case 'entity.entity_form_display.node.form_mode':
|
||||
$type = $route_match->getParameter('node_type');
|
||||
return '<p>' . t('Content items can be edited using different form modes. Here, you can define which fields are shown and hidden when %type content is edited in each form mode, and define how the field form widgets are displayed in each form mode.', ['%type' => $type->label()]) . '</p>' ;
|
||||
return '<p>' . t('Content items can be edited using different form modes. Here, you can define which fields are shown and hidden when %type content is edited in each form mode, and define how the field form widgets are displayed in each form mode.', ['%type' => $type->label()]) . '</p>';
|
||||
|
||||
case 'entity.entity_view_display.node.default':
|
||||
case 'entity.entity_view_display.node.view_mode':
|
||||
|
@ -535,9 +548,12 @@ function template_preprocess_node_add_list(&$variables) {
|
|||
* Implements hook_preprocess_HOOK() for HTML document templates.
|
||||
*/
|
||||
function node_preprocess_html(&$variables) {
|
||||
// If on an individual node page, add the node type to body classes.
|
||||
if (($node = \Drupal::routeMatch()->getParameter('node')) && $node instanceof NodeInterface) {
|
||||
$variables['node_type'] = $node->getType();
|
||||
// If on an individual node page or node preview page, add the node type to
|
||||
// the body classes.
|
||||
if (($node = \Drupal::routeMatch()->getParameter('node')) || ($node = \Drupal::routeMatch()->getParameter('node_preview'))) {
|
||||
if ($node instanceof NodeInterface) {
|
||||
$variables['node_type'] = $node->getType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -593,9 +609,9 @@ function template_preprocess_node(&$variables) {
|
|||
$variables['node'] = $variables['elements']['#node'];
|
||||
/** @var \Drupal\node\NodeInterface $node */
|
||||
$node = $variables['node'];
|
||||
$variables['date'] = drupal_render($variables['elements']['created']);
|
||||
$variables['date'] = \Drupal::service('renderer')->render($variables['elements']['created']);
|
||||
unset($variables['elements']['created']);
|
||||
$variables['author_name'] = drupal_render($variables['elements']['uid']);
|
||||
$variables['author_name'] = \Drupal::service('renderer')->render($variables['elements']['uid']);
|
||||
unset($variables['elements']['uid']);
|
||||
|
||||
$variables['url'] = $node->url('canonical', [
|
||||
|
@ -698,7 +714,7 @@ function node_ranking() {
|
|||
/**
|
||||
* Implements hook_user_cancel().
|
||||
*/
|
||||
function node_user_cancel($edit, $account, $method) {
|
||||
function node_user_cancel($edit, UserInterface $account, $method) {
|
||||
switch ($method) {
|
||||
case 'user_cancel_block_unpublish':
|
||||
// Unpublish nodes (current revisions).
|
||||
|
@ -794,7 +810,7 @@ function node_get_recent($number = 10) {
|
|||
* the global content language of the current request.
|
||||
*
|
||||
* @return array
|
||||
* An array as expected by drupal_render().
|
||||
* An array as expected by \Drupal\Core\Render\RendererInterface::render().
|
||||
*/
|
||||
function node_view(NodeInterface $node, $view_mode = 'full', $langcode = NULL) {
|
||||
return entity_view($node, $view_mode, $langcode);
|
||||
|
@ -812,7 +828,8 @@ function node_view(NodeInterface $node, $view_mode = 'full', $langcode = NULL) {
|
|||
* content language of the current request.
|
||||
*
|
||||
* @return array
|
||||
* An array in the format expected by drupal_render().
|
||||
* An array in the format expected by
|
||||
* \Drupal\Core\Render\RendererInterface::render().
|
||||
*/
|
||||
function node_view_multiple($nodes, $view_mode = 'teaser', $langcode = NULL) {
|
||||
return entity_view_multiple($nodes, $view_mode, $langcode);
|
||||
|
@ -828,7 +845,7 @@ function node_page_top(array &$page) {
|
|||
$page['page_top']['node_preview'] = [
|
||||
'#type' => 'container',
|
||||
'#attributes' => [
|
||||
'class' => ['node-preview-container', 'container-inline']
|
||||
'class' => ['node-preview-container', 'container-inline'],
|
||||
],
|
||||
];
|
||||
|
||||
|
@ -1022,7 +1039,6 @@ function node_access_view_all_nodes($account = NULL) {
|
|||
return $access[$account->id()];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements hook_query_TAG_alter().
|
||||
*
|
||||
|
@ -1099,7 +1115,7 @@ function node_query_node_access_alter(AlterableInterface $query) {
|
|||
// context.
|
||||
$request = \Drupal::requestStack()->getCurrentRequest();
|
||||
$renderer = \Drupal::service('renderer');
|
||||
if ($request->isMethodSafe() && $renderer->hasRenderContext()) {
|
||||
if ($request->isMethodCacheable() && $renderer->hasRenderContext()) {
|
||||
$build = ['#cache' => ['contexts' => ['user.node_grants:' . $op]]];
|
||||
$renderer->render($build);
|
||||
}
|
||||
|
@ -1173,7 +1189,7 @@ function node_access_rebuild($batch_mode = FALSE) {
|
|||
'operations' => [
|
||||
['_node_access_rebuild_batch_operation', []],
|
||||
],
|
||||
'finished' => '_node_access_rebuild_batch_finished'
|
||||
'finished' => '_node_access_rebuild_batch_finished',
|
||||
];
|
||||
batch_set($batch);
|
||||
}
|
||||
|
@ -1209,7 +1225,7 @@ function node_access_rebuild($batch_mode = FALSE) {
|
|||
}
|
||||
|
||||
if (!isset($batch)) {
|
||||
drupal_set_message(t('Content permissions have been rebuilt.'));
|
||||
\Drupal::messenger()->addStatus(t('Content permissions have been rebuilt.'));
|
||||
node_access_needs_rebuild(FALSE);
|
||||
}
|
||||
}
|
||||
|
@ -1282,11 +1298,11 @@ function _node_access_rebuild_batch_operation(&$context) {
|
|||
*/
|
||||
function _node_access_rebuild_batch_finished($success, $results, $operations) {
|
||||
if ($success) {
|
||||
drupal_set_message(t('The content access permissions have been rebuilt.'));
|
||||
\Drupal::messenger()->addStatus(t('The content access permissions have been rebuilt.'));
|
||||
node_access_needs_rebuild(FALSE);
|
||||
}
|
||||
else {
|
||||
drupal_set_message(t('The content access permissions have not been properly rebuilt.'), 'error');
|
||||
\Drupal::messenger()->addError(t('The content access permissions have not been properly rebuilt.'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,18 +12,17 @@ administer nodes:
|
|||
restrict access: true
|
||||
access content overview:
|
||||
title: 'Access the Content overview page'
|
||||
access content:
|
||||
title: 'View published content'
|
||||
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 <em>view revisions</em> and <em>edit rights</em> for nodes in question or <em>administer nodes</em>.'
|
||||
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 <em>view revisions</em> and <em>delete rights</em> for nodes in question or <em>administer nodes</em>.'
|
||||
description: 'To delete a revision, you also need permission to delete the content item.'
|
||||
|
||||
permission_callbacks:
|
||||
- \Drupal\node\NodePermissions::nodeTypePermissions
|
||||
|
|
29
web/core/modules/node/node.post_update.php
Normal file
29
web/core/modules/node/node.post_update.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Post update functions for Node.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityFormDisplay;
|
||||
|
||||
/**
|
||||
* Load all form displays for nodes, add status with these settings, save.
|
||||
*/
|
||||
function node_post_update_configure_status_field_widget() {
|
||||
$query = \Drupal::entityQuery('entity_form_display')->condition('targetEntityType', 'node');
|
||||
$ids = $query->execute();
|
||||
$form_displays = EntityFormDisplay::loadMultiple($ids);
|
||||
|
||||
// Assign status settings for each 'node' target entity types with 'default'
|
||||
// form mode.
|
||||
foreach ($form_displays as $id => $form_display) {
|
||||
/** @var \Drupal\Core\Entity\Display\EntityDisplayInterface $form_display */
|
||||
$form_display->setComponent('status', [
|
||||
'type' => 'boolean_checkbox',
|
||||
'settings' => [
|
||||
'display_label' => TRUE,
|
||||
],
|
||||
])->save();
|
||||
}
|
||||
}
|
112
web/core/modules/node/node.preview.es6.js
Normal file
112
web/core/modules/node/node.preview.es6.js
Normal file
|
@ -0,0 +1,112 @@
|
|||
/**
|
||||
* @file
|
||||
* Preview behaviors.
|
||||
*/
|
||||
|
||||
(function($, Drupal) {
|
||||
/**
|
||||
* Disables all non-relevant links in node previews.
|
||||
*
|
||||
* Destroys links (except local fragment identifiers such as href="#frag") in
|
||||
* node previews to prevent users from leaving the page.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches confirmation prompt for clicking links in node preview mode.
|
||||
* @prop {Drupal~behaviorDetach} detach
|
||||
* Detaches confirmation prompt for clicking links in node preview mode.
|
||||
*/
|
||||
Drupal.behaviors.nodePreviewDestroyLinks = {
|
||||
attach(context) {
|
||||
function clickPreviewModal(event) {
|
||||
// Only confirm leaving previews when left-clicking and user is not
|
||||
// pressing the ALT, CTRL, META (Command key on the Macintosh keyboard)
|
||||
// or SHIFT key.
|
||||
if (
|
||||
event.button === 0 &&
|
||||
!event.altKey &&
|
||||
!event.ctrlKey &&
|
||||
!event.metaKey &&
|
||||
!event.shiftKey
|
||||
) {
|
||||
event.preventDefault();
|
||||
const $previewDialog = $(
|
||||
`<div>${Drupal.theme('nodePreviewModal')}</div>`,
|
||||
).appendTo('body');
|
||||
Drupal.dialog($previewDialog, {
|
||||
title: Drupal.t('Leave preview?'),
|
||||
buttons: [
|
||||
{
|
||||
text: Drupal.t('Cancel'),
|
||||
click() {
|
||||
$(this).dialog('close');
|
||||
},
|
||||
},
|
||||
{
|
||||
text: Drupal.t('Leave preview'),
|
||||
click() {
|
||||
window.top.location.href = event.target.href;
|
||||
},
|
||||
},
|
||||
],
|
||||
}).showModal();
|
||||
}
|
||||
}
|
||||
|
||||
const $preview = $(context).once('node-preview');
|
||||
if ($(context).find('.node-preview-container').length) {
|
||||
$preview.on(
|
||||
'click.preview',
|
||||
'a:not([href^="#"], .node-preview-container a)',
|
||||
clickPreviewModal,
|
||||
);
|
||||
}
|
||||
},
|
||||
detach(context, settings, trigger) {
|
||||
if (trigger === 'unload') {
|
||||
const $preview = $(context)
|
||||
.find('.content')
|
||||
.removeOnce('node-preview');
|
||||
if ($preview.length) {
|
||||
$preview.off('click.preview');
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Switch view mode.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches automatic submit on `formUpdated.preview` events.
|
||||
*/
|
||||
Drupal.behaviors.nodePreviewSwitchViewMode = {
|
||||
attach(context) {
|
||||
const $autosubmit = $(context)
|
||||
.find('[data-drupal-autosubmit]')
|
||||
.once('autosubmit');
|
||||
if ($autosubmit.length) {
|
||||
$autosubmit.on('formUpdated.preview', function() {
|
||||
$(this.form).trigger('submit');
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Theme function for node preview modal.
|
||||
*
|
||||
* @return {string}
|
||||
* Markup for the node preview modal.
|
||||
*/
|
||||
Drupal.theme.nodePreviewModal = function() {
|
||||
return `<p>${Drupal.t(
|
||||
'Leaving the preview will cause unsaved changes to be lost. Are you sure you want to leave the preview?',
|
||||
)}</p><small class="description">${Drupal.t(
|
||||
'CTRL+Left click will prevent this dialog from showing and proceed to the clicked link.',
|
||||
)}</small>`;
|
||||
};
|
||||
})(jQuery, Drupal);
|
|
@ -1,60 +1,40 @@
|
|||
/**
|
||||
* @file
|
||||
* Preview behaviors.
|
||||
*/
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* See the following change record for more information,
|
||||
* https://www.drupal.org/node/2815083
|
||||
* @preserve
|
||||
**/
|
||||
|
||||
(function ($, Drupal) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Disables all non-relevant links in node previews.
|
||||
*
|
||||
* Destroys links (except local fragment identifiers such as href="#frag") in
|
||||
* node previews to prevent users from leaving the page.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches confirmation prompt for clicking links in node preview mode.
|
||||
* @prop {Drupal~behaviorDetach} detach
|
||||
* Detaches confirmation prompt for clicking links in node preview mode.
|
||||
*/
|
||||
Drupal.behaviors.nodePreviewDestroyLinks = {
|
||||
attach: function (context) {
|
||||
|
||||
attach: function attach(context) {
|
||||
function clickPreviewModal(event) {
|
||||
// Only confirm leaving previews when left-clicking and user is not
|
||||
// pressing the ALT, CTRL, META (Command key on the Macintosh keyboard)
|
||||
// or SHIFT key.
|
||||
if (event.button === 0 && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey) {
|
||||
event.preventDefault();
|
||||
var $previewDialog = $('<div>' + Drupal.theme('nodePreviewModal') + '</div>').appendTo('body');
|
||||
Drupal.dialog($previewDialog, {
|
||||
title: Drupal.t('Leave preview?'),
|
||||
buttons: [
|
||||
{
|
||||
text: Drupal.t('Cancel'),
|
||||
click: function () {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
}, {
|
||||
text: Drupal.t('Leave preview'),
|
||||
click: function () {
|
||||
window.top.location.href = event.target.href;
|
||||
}
|
||||
buttons: [{
|
||||
text: Drupal.t('Cancel'),
|
||||
click: function click() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
]
|
||||
}, {
|
||||
text: Drupal.t('Leave preview'),
|
||||
click: function click() {
|
||||
window.top.location.href = event.target.href;
|
||||
}
|
||||
}]
|
||||
}).showModal();
|
||||
}
|
||||
}
|
||||
|
||||
var $preview = $(context).find('.content').once('node-preview');
|
||||
var $preview = $(context).once('node-preview');
|
||||
if ($(context).find('.node-preview-container').length) {
|
||||
$preview.on('click.preview', 'a:not([href^=#], #edit-backlink, #toolbar-administration a)', clickPreviewModal);
|
||||
$preview.on('click.preview', 'a:not([href^="#"], .node-preview-container a)', clickPreviewModal);
|
||||
}
|
||||
},
|
||||
detach: function (context, settings, trigger) {
|
||||
detach: function detach(context, settings, trigger) {
|
||||
if (trigger === 'unload') {
|
||||
var $preview = $(context).find('.content').removeOnce('node-preview');
|
||||
if ($preview.length) {
|
||||
|
@ -64,16 +44,8 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Switch view mode.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches automatic submit on `formUpdated.preview` events.
|
||||
*/
|
||||
Drupal.behaviors.nodePreviewSwitchViewMode = {
|
||||
attach: function (context) {
|
||||
attach: function attach(context) {
|
||||
var $autosubmit = $(context).find('[data-drupal-autosubmit]').once('autosubmit');
|
||||
if ($autosubmit.length) {
|
||||
$autosubmit.on('formUpdated.preview', function () {
|
||||
|
@ -83,17 +55,7 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Theme function for node preview modal.
|
||||
*
|
||||
* @return {string}
|
||||
* Markup for the node preview modal.
|
||||
*/
|
||||
Drupal.theme.nodePreviewModal = function () {
|
||||
return '<p>' +
|
||||
Drupal.t('Leaving the preview will cause unsaved changes to be lost. Are you sure you want to leave the preview?') +
|
||||
'</p><small class="description">' +
|
||||
Drupal.t('CTRL+Left click will prevent this dialog from showing and proceed to the clicked link.') + '</small>';
|
||||
return '<p>' + Drupal.t('Leaving the preview will cause unsaved changes to be lost. Are you sure you want to leave the preview?') + '</p><small class="description">' + Drupal.t('CTRL+Left click will prevent this dialog from showing and proceed to the clicked link.') + '</small>';
|
||||
};
|
||||
|
||||
})(jQuery, Drupal);
|
||||
})(jQuery, Drupal);
|
|
@ -2,8 +2,17 @@ node.multiple_delete_confirm:
|
|||
path: '/admin/content/node/delete'
|
||||
defaults:
|
||||
_form: '\Drupal\node\Form\DeleteMultiple'
|
||||
entity_type_id: 'node'
|
||||
requirements:
|
||||
_permission: 'administer nodes'
|
||||
_entity_delete_multiple_access: 'node'
|
||||
|
||||
entity.node.delete_multiple_form:
|
||||
path: '/admin/content/node/delete'
|
||||
defaults:
|
||||
_form: '\Drupal\node\Form\DeleteMultiple'
|
||||
entity_type_id: 'node'
|
||||
requirements:
|
||||
_entity_delete_multiple_access: 'node'
|
||||
|
||||
node.add_page:
|
||||
path: '/node/add'
|
||||
|
|
|
@ -30,7 +30,7 @@ services:
|
|||
- { name: event_subscriber }
|
||||
node_preview:
|
||||
class: Drupal\node\ParamConverter\NodePreviewConverter
|
||||
arguments: ['@user.private_tempstore']
|
||||
arguments: ['@tempstore.private']
|
||||
tags:
|
||||
- { name: paramconverter }
|
||||
lazy: true
|
||||
|
|
|
@ -4,8 +4,9 @@ namespace Drupal\node\ContextProvider;
|
|||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\Plugin\Context\ContextProviderInterface;
|
||||
use Drupal\Core\Plugin\Context\EntityContext;
|
||||
use Drupal\Core\Plugin\Context\EntityContextDefinition;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
|
@ -39,7 +40,7 @@ class NodeRouteContext implements ContextProviderInterface {
|
|||
*/
|
||||
public function getRuntimeContexts(array $unqualified_context_ids) {
|
||||
$result = [];
|
||||
$context_definition = new ContextDefinition('entity:node', NULL, FALSE);
|
||||
$context_definition = EntityContextDefinition::create('node')->setRequired(FALSE);
|
||||
$value = NULL;
|
||||
if (($route_object = $this->routeMatch->getRouteObject()) && ($route_contexts = $route_object->getOption('parameters')) && isset($route_contexts['node'])) {
|
||||
if ($node = $this->routeMatch->getParameter('node')) {
|
||||
|
@ -65,7 +66,7 @@ class NodeRouteContext implements ContextProviderInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAvailableContexts() {
|
||||
$context = new Context(new ContextDefinition('entity:node', $this->t('Node from URL')));
|
||||
$context = EntityContext::fromEntityTypeId('node', $this->t('Node from URL'));
|
||||
return ['node' => $context];
|
||||
}
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
|
|||
* The node revision ID.
|
||||
*
|
||||
* @return array
|
||||
* An array suitable for drupal_render().
|
||||
* An array suitable for \Drupal\Core\Render\RendererInterface::render().
|
||||
*/
|
||||
public function revisionShow($node_revision) {
|
||||
$node = $this->entityManager()->getStorage('node')->loadRevision($node_revision);
|
||||
|
@ -154,7 +154,7 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
|
|||
* A node object.
|
||||
*
|
||||
* @return array
|
||||
* An array as expected by drupal_render().
|
||||
* An array as expected by \Drupal\Core\Render\RendererInterface::render().
|
||||
*/
|
||||
public function revisionOverview(NodeInterface $node) {
|
||||
$account = $this->currentUser();
|
||||
|
@ -173,6 +173,7 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
|
|||
|
||||
$rows = [];
|
||||
$default_revision = $node->getRevisionId();
|
||||
$current_revision_displayed = FALSE;
|
||||
|
||||
foreach ($this->getRevisionIds($node, $node_storage) as $vid) {
|
||||
/** @var \Drupal\node\NodeInterface $revision */
|
||||
|
@ -187,11 +188,18 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
|
|||
|
||||
// Use revision link to link to revisions that are not active.
|
||||
$date = $this->dateFormatter->format($revision->revision_timestamp->value, 'short');
|
||||
if ($vid != $node->getRevisionId()) {
|
||||
|
||||
// We treat also the latest translation-affecting revision as current
|
||||
// revision, if it was the default revision, as its values for the
|
||||
// current language will be the same of the current default revision in
|
||||
// this case.
|
||||
$is_current_revision = $vid == $default_revision || (!$current_revision_displayed && $revision->wasDefaultRevision());
|
||||
if (!$is_current_revision) {
|
||||
$link = $this->l($date, new Url('entity.node.revision', ['node' => $node->id(), 'node_revision' => $vid]));
|
||||
}
|
||||
else {
|
||||
$link = $node->link($date);
|
||||
$current_revision_displayed = TRUE;
|
||||
}
|
||||
|
||||
$row = [];
|
||||
|
@ -210,7 +218,7 @@ class NodeController extends ControllerBase implements ContainerInjectionInterfa
|
|||
$this->renderer->addCacheableDependency($column['data'], $username);
|
||||
$row[] = $column;
|
||||
|
||||
if ($vid == $default_revision) {
|
||||
if ($is_current_revision) {
|
||||
$row[] = [
|
||||
'data' => [
|
||||
'#prefix' => '<em>',
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
namespace Drupal\node\Entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityBase;
|
||||
use Drupal\Core\Entity\EntityChangedTrait;
|
||||
use Drupal\Core\Entity\EntityPublishedTrait;
|
||||
use Drupal\Core\Entity\EditorialContentEntityBase;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
@ -35,7 +33,8 @@ use Drupal\user\UserInterface;
|
|||
* "form" = {
|
||||
* "default" = "Drupal\node\NodeForm",
|
||||
* "delete" = "Drupal\node\Form\NodeDeleteForm",
|
||||
* "edit" = "Drupal\node\NodeForm"
|
||||
* "edit" = "Drupal\node\NodeForm",
|
||||
* "delete-multiple-confirm" = "Drupal\node\Form\DeleteMultiple"
|
||||
* },
|
||||
* "route_provider" = {
|
||||
* "html" = "Drupal\node\Entity\NodeRouteProvider",
|
||||
|
@ -61,6 +60,11 @@ use Drupal\user\UserInterface;
|
|||
* "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,
|
||||
|
@ -68,16 +72,15 @@ use Drupal\user\UserInterface;
|
|||
* links = {
|
||||
* "canonical" = "/node/{node}",
|
||||
* "delete-form" = "/node/{node}/delete",
|
||||
* "delete-multiple-form" = "/admin/content/node/delete",
|
||||
* "edit-form" = "/node/{node}/edit",
|
||||
* "version-history" = "/node/{node}/revisions",
|
||||
* "revision" = "/node/{node}/revisions/{node_revision}/view",
|
||||
* "create" = "/node",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Node extends ContentEntityBase implements NodeInterface {
|
||||
|
||||
use EntityChangedTrait;
|
||||
use EntityPublishedTrait;
|
||||
class Node extends EditorialContentEntityBase implements NodeInterface {
|
||||
|
||||
/**
|
||||
* Whether the node is being previewed or not.
|
||||
|
@ -209,7 +212,6 @@ class Node extends ContentEntityBase implements NodeInterface {
|
|||
return $this->get('created')->value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -278,21 +280,6 @@ class Node extends ContentEntityBase implements NodeInterface {
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRevisionCreationTime() {
|
||||
return $this->get('revision_timestamp')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRevisionCreationTime($timestamp) {
|
||||
$this->set('revision_timestamp', $timestamp);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -300,13 +287,6 @@ class Node extends ContentEntityBase implements NodeInterface {
|
|||
return $this->getRevisionUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRevisionUser() {
|
||||
return $this->get('revision_uid')->entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -315,50 +295,11 @@ class Node extends ContentEntityBase implements NodeInterface {
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRevisionUser(UserInterface $user) {
|
||||
$this->set('revision_uid', $user);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRevisionUserId() {
|
||||
return $this->get('revision_uid')->entity->id();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRevisionUserId($user_id) {
|
||||
$this->set('revision_uid', $user_id);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRevisionLogMessage() {
|
||||
return $this->get('revision_log')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRevisionLogMessage($revision_log_message) {
|
||||
$this->set('revision_log', $revision_log_message);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
$fields += static::publishedBaseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['title'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(t('Title'))
|
||||
|
@ -400,6 +341,16 @@ class Node extends ContentEntityBase implements NodeInterface {
|
|||
])
|
||||
->setDisplayConfigurable('form', TRUE);
|
||||
|
||||
$fields['status']
|
||||
->setDisplayOptions('form', [
|
||||
'type' => 'boolean_checkbox',
|
||||
'settings' => [
|
||||
'display_label' => TRUE,
|
||||
],
|
||||
'weight' => 120,
|
||||
])
|
||||
->setDisplayConfigurable('form', TRUE);
|
||||
|
||||
$fields['created'] = BaseFieldDefinition::create('created')
|
||||
->setLabel(t('Authored on'))
|
||||
->setDescription(t('The time that the node was created.'))
|
||||
|
@ -450,39 +401,6 @@ class Node extends ContentEntityBase implements NodeInterface {
|
|||
])
|
||||
->setDisplayConfigurable('form', TRUE);
|
||||
|
||||
$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')
|
||||
->setLabel(t('Revision log message'))
|
||||
->setDescription(t('Briefly describe the changes you have made.'))
|
||||
->setRevisionable(TRUE)
|
||||
->setDefaultValue('')
|
||||
->setDisplayOptions('form', [
|
||||
'type' => 'string_textarea',
|
||||
'weight' => 25,
|
||||
'settings' => [
|
||||
'rows' => 4,
|
||||
],
|
||||
]);
|
||||
|
||||
$fields['revision_translation_affected'] = BaseFieldDefinition::create('boolean')
|
||||
->setLabel(t('Revision translation affected'))
|
||||
->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
|
||||
->setReadOnly(TRUE)
|
||||
->setRevisionable(TRUE)
|
||||
->setTranslatable(TRUE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ class NodeRouteProvider implements EntityRouteProviderInterface {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRoutes( EntityTypeInterface $entity_type) {
|
||||
public function getRoutes(EntityTypeInterface $entity_type) {
|
||||
$route_collection = new RouteCollection();
|
||||
$route = (new Route('/node/{node}'))
|
||||
->addDefaults([
|
||||
|
|
|
@ -12,6 +12,13 @@ use Drupal\node\NodeTypeInterface;
|
|||
* @ConfigEntityType(
|
||||
* id = "node_type",
|
||||
* label = @Translation("Content type"),
|
||||
* label_collection = @Translation("Content types"),
|
||||
* label_singular = @Translation("content type"),
|
||||
* label_plural = @Translation("content types"),
|
||||
* label_count = @PluralTranslation(
|
||||
* singular = "@count content type",
|
||||
* plural = "@count content types",
|
||||
* ),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\node\NodeTypeAccessControlHandler",
|
||||
* "form" = {
|
||||
|
@ -179,7 +186,7 @@ class NodeType extends ConfigEntityBundleBase implements NodeTypeInterface {
|
|||
if ($update && $this->getOriginalId() != $this->id()) {
|
||||
$update_count = node_type_update_nodes($this->getOriginalId(), $this->id());
|
||||
if ($update_count) {
|
||||
drupal_set_message(\Drupal::translation()->formatPlural($update_count,
|
||||
\Drupal::messenger()->addStatus(\Drupal::translation()->formatPlural($update_count,
|
||||
'Changed the content type of 1 post from %old-type to %type.',
|
||||
'Changed the content type of @count posts from %old-type to %type.',
|
||||
[
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\node\EventSubscriber;
|
||||
|
||||
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\ParamConverter\ParamNotConvertedException;
|
||||
use Drupal\Core\Routing\UrlGeneratorInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
* Redirect node translations that have been consolidated by migration.
|
||||
*
|
||||
* If we migrated node translations from Drupal 6 or 7, these nodes are now
|
||||
* combined with their source language node. Since there still might be
|
||||
* references to the URLs of these now consolidated nodes, this service catches
|
||||
* the 404s and try to redirect them to the right node in the right language.
|
||||
*
|
||||
* The mapping of the old nids to the new ones is made by the
|
||||
* NodeTranslationMigrateSubscriber class during the migration and is stored
|
||||
* in the "node_translation_redirect" key/value collection.
|
||||
*
|
||||
* @see \Drupal\node\NodeServiceProvider
|
||||
* @see \Drupal\node\EventSubscriber\NodeTranslationMigrateSubscriber
|
||||
*/
|
||||
class NodeTranslationExceptionSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The key value factory.
|
||||
*
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueFactoryInterface
|
||||
*/
|
||||
protected $keyValue;
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The URL generator.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\UrlGeneratorInterface
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
|
||||
/**
|
||||
* The state service.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Constructs the NodeTranslationExceptionSubscriber.
|
||||
*
|
||||
* @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value
|
||||
* The key value factory.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
|
||||
* The URL generator.
|
||||
* @param \Drupal\Core\State\StateInterface $state
|
||||
* The state service.
|
||||
*/
|
||||
public function __construct(KeyValueFactoryInterface $key_value, LanguageManagerInterface $language_manager, UrlGeneratorInterface $url_generator, StateInterface $state) {
|
||||
$this->keyValue = $key_value;
|
||||
$this->languageManager = $language_manager;
|
||||
$this->urlGenerator = $url_generator;
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects not found node translations using the key value collection.
|
||||
*
|
||||
* @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
|
||||
* The exception event.
|
||||
*/
|
||||
public function onException(GetResponseForExceptionEvent $event) {
|
||||
$exception = $event->getException();
|
||||
|
||||
// If this is not a 404, we don't need to check for a redirection.
|
||||
if (!($exception instanceof NotFoundHttpException)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$previous_exception = $exception->getPrevious();
|
||||
if ($previous_exception instanceof ParamNotConvertedException) {
|
||||
$route_name = $previous_exception->getRouteName();
|
||||
$parameters = $previous_exception->getRawParameters();
|
||||
if ($route_name === 'entity.node.canonical' && isset($parameters['node'])) {
|
||||
// If the node_translation_redirect state is not set, we don't need to check
|
||||
// for a redirection.
|
||||
if (!$this->state->get('node_translation_redirect')) {
|
||||
return;
|
||||
}
|
||||
$old_nid = $parameters['node'];
|
||||
$collection = $this->keyValue->get('node_translation_redirect');
|
||||
if ($old_nid && $value = $collection->get($old_nid)) {
|
||||
list($nid, $langcode) = $value;
|
||||
$language = $this->languageManager->getLanguage($langcode);
|
||||
$url = $this->urlGenerator->generateFromRoute('entity.node.canonical', ['node' => $nid], ['language' => $language]);
|
||||
$response = new RedirectResponse($url, 301);
|
||||
$event->setResponse($response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events = [];
|
||||
|
||||
$events[KernelEvents::EXCEPTION] = ['onException'];
|
||||
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\node\EventSubscriber;
|
||||
|
||||
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\migrate\Event\EventBase;
|
||||
use Drupal\migrate\Event\MigrateEvents;
|
||||
use Drupal\migrate\Event\MigrateImportEvent;
|
||||
use Drupal\migrate\Event\MigratePostRowSaveEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Creates a key value collection for migrated node translation redirections.
|
||||
*
|
||||
* If we are migrating node translations from Drupal 6 or 7, these nodes will be
|
||||
* combined with their source node. Since there still might be references to the
|
||||
* URLs of these now consolidated nodes, this service saves the mapping between
|
||||
* the old nids to the new ones to be able to redirect them to the right node in
|
||||
* the right language.
|
||||
*
|
||||
* The mapping is stored in the "node_translation_redirect" key/value collection
|
||||
* and the redirection is made by the NodeTranslationExceptionSubscriber class.
|
||||
*
|
||||
* @see \Drupal\node\NodeServiceProvider
|
||||
* @see \Drupal\node\EventSubscriber\NodeTranslationExceptionSubscriber
|
||||
*/
|
||||
class NodeTranslationMigrateSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The key value factory.
|
||||
*
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueFactoryInterface
|
||||
*/
|
||||
protected $keyValue;
|
||||
|
||||
/**
|
||||
* The state service.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Constructs the NodeTranslationMigrateSubscriber.
|
||||
*
|
||||
* @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value
|
||||
* The key value factory.
|
||||
* @param \Drupal\Core\State\StateInterface $state
|
||||
* The state service.
|
||||
*/
|
||||
public function __construct(KeyValueFactoryInterface $key_value, StateInterface $state) {
|
||||
$this->keyValue = $key_value;
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to check if we are migrating translated nodes.
|
||||
*
|
||||
* @param \Drupal\migrate\Event\EventBase $event
|
||||
* The migrate event.
|
||||
*
|
||||
* @return bool
|
||||
* True if we are migrating translated nodes, false otherwise.
|
||||
*/
|
||||
protected function isNodeTranslationsMigration(EventBase $event) {
|
||||
$migration = $event->getMigration();
|
||||
$source_configuration = $migration->getSourceConfiguration();
|
||||
$destination_configuration = $migration->getDestinationConfiguration();
|
||||
return !empty($source_configuration['translations']) && $destination_configuration['plugin'] === 'entity:node';
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the old nid to the new one in the key value collection.
|
||||
*
|
||||
* @param \Drupal\migrate\Event\MigratePostRowSaveEvent $event
|
||||
* The migrate post row save event.
|
||||
*/
|
||||
public function onPostRowSave(MigratePostRowSaveEvent $event) {
|
||||
if ($this->isNodeTranslationsMigration($event)) {
|
||||
$row = $event->getRow();
|
||||
$source = $row->getSource();
|
||||
$destination = $row->getDestination();
|
||||
$collection = $this->keyValue->get('node_translation_redirect');
|
||||
$collection->set($source['nid'], [$destination['nid'], $destination['langcode']]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the node_translation_redirect state to enable the redirections.
|
||||
*
|
||||
* @param \Drupal\migrate\Event\MigrateImportEvent $event
|
||||
* The migrate import event.
|
||||
*/
|
||||
public function onPostImport(MigrateImportEvent $event) {
|
||||
if ($this->isNodeTranslationsMigration($event)) {
|
||||
$this->state->set('node_translation_redirect', TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events = [];
|
||||
|
||||
$events[MigrateEvents::POST_ROW_SAVE] = ['onPostRowSave'];
|
||||
$events[MigrateEvents::POST_IMPORT] = ['onPostImport'];
|
||||
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,76 +2,15 @@
|
|||
|
||||
namespace Drupal\node\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Entity\Form\DeleteMultipleForm as EntityDeleteMultipleForm;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\user\PrivateTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
||||
/**
|
||||
* Provides a node deletion confirmation form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class DeleteMultiple extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
* The array of nodes to delete.
|
||||
*
|
||||
* @var string[][]
|
||||
*/
|
||||
protected $nodeInfo = [];
|
||||
|
||||
/**
|
||||
* The tempstore factory.
|
||||
*
|
||||
* @var \Drupal\user\PrivateTempStoreFactory
|
||||
*/
|
||||
protected $tempStoreFactory;
|
||||
|
||||
/**
|
||||
* The node storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* Constructs a DeleteMultiple form object.
|
||||
*
|
||||
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
|
||||
* The tempstore factory.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $manager
|
||||
* The entity manager.
|
||||
*/
|
||||
public function __construct(PrivateTempStoreFactory $temp_store_factory, EntityManagerInterface $manager) {
|
||||
$this->tempStoreFactory = $temp_store_factory;
|
||||
$this->storage = $manager->getStorage('node');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('user.private_tempstore'),
|
||||
$container->get('entity.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'node_multiple_delete_confirm';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQuestion() {
|
||||
return $this->formatPlural(count($this->nodeInfo), 'Are you sure you want to delete this item?', 'Are you sure you want to delete these items?');
|
||||
}
|
||||
class DeleteMultiple extends EntityDeleteMultipleForm {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -83,117 +22,15 @@ class DeleteMultiple extends ConfirmFormBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfirmText() {
|
||||
return t('Delete');
|
||||
protected function getDeletedMessage($count) {
|
||||
return $this->formatPlural($count, 'Deleted @count content item.', 'Deleted @count content items.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$this->nodeInfo = $this->tempStoreFactory->get('node_multiple_delete_confirm')->get(\Drupal::currentUser()->id());
|
||||
if (empty($this->nodeInfo)) {
|
||||
return new RedirectResponse($this->getCancelUrl()->setAbsolute()->toString());
|
||||
}
|
||||
/** @var \Drupal\node\NodeInterface[] $nodes */
|
||||
$nodes = $this->storage->loadMultiple(array_keys($this->nodeInfo));
|
||||
|
||||
$items = [];
|
||||
foreach ($this->nodeInfo as $id => $langcodes) {
|
||||
foreach ($langcodes as $langcode) {
|
||||
$node = $nodes[$id]->getTranslation($langcode);
|
||||
$key = $id . ':' . $langcode;
|
||||
$default_key = $id . ':' . $node->getUntranslated()->language()->getId();
|
||||
|
||||
// If we have a translated entity we build a nested list of translations
|
||||
// that will be deleted.
|
||||
$languages = $node->getTranslationLanguages();
|
||||
if (count($languages) > 1 && $node->isDefaultTranslation()) {
|
||||
$names = [];
|
||||
foreach ($languages as $translation_langcode => $language) {
|
||||
$names[] = $language->getName();
|
||||
unset($items[$id . ':' . $translation_langcode]);
|
||||
}
|
||||
$items[$default_key] = [
|
||||
'label' => [
|
||||
'#markup' => $this->t('@label (Original translation) - <em>The following content translations will be deleted:</em>', ['@label' => $node->label()]),
|
||||
],
|
||||
'deleted_translations' => [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $names,
|
||||
],
|
||||
];
|
||||
}
|
||||
elseif (!isset($items[$default_key])) {
|
||||
$items[$key] = $node->label();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$form['nodes'] = [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $items,
|
||||
];
|
||||
$form = parent::buildForm($form, $form_state);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
if ($form_state->getValue('confirm') && !empty($this->nodeInfo)) {
|
||||
$total_count = 0;
|
||||
$delete_nodes = [];
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface[][] $delete_translations */
|
||||
$delete_translations = [];
|
||||
/** @var \Drupal\node\NodeInterface[] $nodes */
|
||||
$nodes = $this->storage->loadMultiple(array_keys($this->nodeInfo));
|
||||
|
||||
foreach ($this->nodeInfo as $id => $langcodes) {
|
||||
foreach ($langcodes as $langcode) {
|
||||
$node = $nodes[$id]->getTranslation($langcode);
|
||||
if ($node->isDefaultTranslation()) {
|
||||
$delete_nodes[$id] = $node;
|
||||
unset($delete_translations[$id]);
|
||||
$total_count += count($node->getTranslationLanguages());
|
||||
}
|
||||
elseif (!isset($delete_nodes[$id])) {
|
||||
$delete_translations[$id][] = $node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($delete_nodes) {
|
||||
$this->storage->delete($delete_nodes);
|
||||
$this->logger('content')->notice('Deleted @count posts.', ['@count' => count($delete_nodes)]);
|
||||
}
|
||||
|
||||
if ($delete_translations) {
|
||||
$count = 0;
|
||||
foreach ($delete_translations as $id => $translations) {
|
||||
$node = $nodes[$id]->getUntranslated();
|
||||
foreach ($translations as $translation) {
|
||||
$node->removeTranslation($translation->language()->getId());
|
||||
}
|
||||
$node->save();
|
||||
$count += count($translations);
|
||||
}
|
||||
if ($count) {
|
||||
$total_count += $count;
|
||||
$this->logger('content')->notice('Deleted @count content translations.', ['@count' => $count]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($total_count) {
|
||||
drupal_set_message($this->formatPlural($total_count, 'Deleted 1 post.', 'Deleted @count posts.'));
|
||||
}
|
||||
|
||||
$this->tempStoreFactory->get('node_multiple_delete_confirm')->delete(\Drupal::currentUser()->id());
|
||||
}
|
||||
|
||||
$form_state->setRedirect('system.admin_content');
|
||||
protected function getInaccessibleMessage($count) {
|
||||
return $this->formatPlural($count, "@count content item has not been deleted because you do not have the necessary permissions.", "@count content items have not been deleted because you do not have the necessary permissions.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ use Drupal\Core\Entity\ContentEntityDeleteForm;
|
|||
|
||||
/**
|
||||
* Provides a form for deleting a node.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class NodeDeleteForm extends ContentEntityDeleteForm {
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* Contains a form for switching the view mode of a node during preview.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class NodePreviewForm extends FormBase {
|
||||
|
||||
|
@ -105,7 +107,7 @@ class NodePreviewForm extends FormBase {
|
|||
'#default_value' => $view_mode,
|
||||
'#attributes' => [
|
||||
'data-drupal-autosubmit' => TRUE,
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
$form['submit'] = [
|
||||
|
|
|
@ -11,6 +11,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* Provides a form for reverting a node revision.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class NodeRevisionDeleteForm extends ConfirmFormBase {
|
||||
|
||||
|
@ -116,7 +118,12 @@ class NodeRevisionDeleteForm extends ConfirmFormBase {
|
|||
|
||||
$this->logger('content')->notice('@type: deleted %title revision %revision.', ['@type' => $this->revision->bundle(), '%title' => $this->revision->label(), '%revision' => $this->revision->getRevisionId()]);
|
||||
$node_type = $this->nodeTypeStorage->load($this->revision->bundle())->label();
|
||||
drupal_set_message(t('Revision from %revision-date of @type %title has been deleted.', ['%revision-date' => format_date($this->revision->getRevisionCreationTime()), '@type' => $node_type, '%title' => $this->revision->label()]));
|
||||
$this->messenger()
|
||||
->addStatus($this->t('Revision from %revision-date of @type %title has been deleted.', [
|
||||
'%revision-date' => format_date($this->revision->getRevisionCreationTime()),
|
||||
'@type' => $node_type,
|
||||
'%title' => $this->revision->label(),
|
||||
]));
|
||||
$form_state->setRedirect(
|
||||
'entity.node.canonical',
|
||||
['node' => $this->revision->id()]
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\node\Form;
|
||||
|
||||
use Drupal\Component\Datetime\TimeInterface;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
|
@ -12,6 +13,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* Provides a form for reverting a node revision.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class NodeRevisionRevertForm extends ConfirmFormBase {
|
||||
|
||||
|
@ -25,7 +28,7 @@ class NodeRevisionRevertForm extends ConfirmFormBase {
|
|||
/**
|
||||
* The node storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
* @var \Drupal\node\NodeStorageInterface
|
||||
*/
|
||||
protected $nodeStorage;
|
||||
|
||||
|
@ -50,11 +53,13 @@ class NodeRevisionRevertForm extends ConfirmFormBase {
|
|||
* The node storage.
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
|
||||
* The date formatter service.
|
||||
* @param \Drupal\Component\Datetime\TimeInterface $time
|
||||
* The time service.
|
||||
*/
|
||||
public function __construct(EntityStorageInterface $node_storage, DateFormatterInterface $date_formatter) {
|
||||
public function __construct(EntityStorageInterface $node_storage, DateFormatterInterface $date_formatter, TimeInterface $time) {
|
||||
$this->nodeStorage = $node_storage;
|
||||
$this->dateFormatter = $date_formatter;
|
||||
$this->time = \Drupal::service('datetime.time');
|
||||
$this->time = $time;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,7 +68,8 @@ class NodeRevisionRevertForm extends ConfirmFormBase {
|
|||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.manager')->getStorage('node'),
|
||||
$container->get('date.formatter')
|
||||
$container->get('date.formatter'),
|
||||
$container->get('datetime.time')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -122,12 +128,18 @@ class NodeRevisionRevertForm extends ConfirmFormBase {
|
|||
|
||||
$this->revision = $this->prepareRevertedRevision($this->revision, $form_state);
|
||||
$this->revision->revision_log = t('Copy of the revision from %date.', ['%date' => $this->dateFormatter->format($original_revision_timestamp)]);
|
||||
$this->revision->setRevisionUserId($this->currentUser()->id());
|
||||
$this->revision->setRevisionCreationTime($this->time->getRequestTime());
|
||||
$this->revision->setChangedTime($this->time->getRequestTime());
|
||||
$this->revision->save();
|
||||
|
||||
$this->logger('content')->notice('@type: reverted %title revision %revision.', ['@type' => $this->revision->bundle(), '%title' => $this->revision->label(), '%revision' => $this->revision->getRevisionId()]);
|
||||
drupal_set_message(t('@type %title has been reverted to the revision from %revision-date.', ['@type' => node_get_type_label($this->revision), '%title' => $this->revision->label(), '%revision-date' => $this->dateFormatter->format($original_revision_timestamp)]));
|
||||
$this->messenger()
|
||||
->addStatus($this->t('@type %title has been reverted to the revision from %revision-date.', [
|
||||
'@type' => node_get_type_label($this->revision),
|
||||
'%title' => $this->revision->label(),
|
||||
'%revision-date' => $this->dateFormatter->format($original_revision_timestamp),
|
||||
]));
|
||||
$form_state->setRedirect(
|
||||
'entity.node.version_history',
|
||||
['node' => $this->revision->id()]
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\node\Form;
|
||||
|
||||
use Drupal\Component\Datetime\TimeInterface;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
@ -11,6 +12,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* Provides a form for reverting a node revision for a single translation.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class NodeRevisionRevertTranslationForm extends NodeRevisionRevertForm {
|
||||
|
||||
|
@ -37,9 +40,11 @@ class NodeRevisionRevertTranslationForm extends NodeRevisionRevertForm {
|
|||
* The date formatter service.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Component\Datetime\TimeInterface $time
|
||||
* The time service.
|
||||
*/
|
||||
public function __construct(EntityStorageInterface $node_storage, DateFormatterInterface $date_formatter, LanguageManagerInterface $language_manager) {
|
||||
parent::__construct($node_storage, $date_formatter);
|
||||
public function __construct(EntityStorageInterface $node_storage, DateFormatterInterface $date_formatter, LanguageManagerInterface $language_manager, TimeInterface $time) {
|
||||
parent::__construct($node_storage, $date_formatter, $time);
|
||||
$this->languageManager = $language_manager;
|
||||
}
|
||||
|
||||
|
@ -50,7 +55,8 @@ class NodeRevisionRevertTranslationForm extends NodeRevisionRevertForm {
|
|||
return new static(
|
||||
$container->get('entity.manager')->getStorage('node'),
|
||||
$container->get('date.formatter'),
|
||||
$container->get('language_manager')
|
||||
$container->get('language_manager'),
|
||||
$container->get('datetime.time')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -82,10 +88,15 @@ class NodeRevisionRevertTranslationForm extends NodeRevisionRevertForm {
|
|||
$this->langcode = $langcode;
|
||||
$form = parent::buildForm($form, $form_state, $node_revision);
|
||||
|
||||
// Unless untranslatable fields are configured to affect only the default
|
||||
// translation, we need to ask the user whether they should be included in
|
||||
// the revert process.
|
||||
$default_translation_affected = $this->revision->isDefaultTranslationAffectedOnly();
|
||||
$form['revert_untranslated_fields'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Revert content shared among translations'),
|
||||
'#default_value' => FALSE,
|
||||
'#default_value' => $default_translation_affected && $this->revision->getTranslation($this->langcode)->isDefaultTranslation(),
|
||||
'#access' => !$default_translation_affected,
|
||||
];
|
||||
|
||||
return $form;
|
||||
|
@ -95,24 +106,9 @@ class NodeRevisionRevertTranslationForm extends NodeRevisionRevertForm {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
protected function prepareRevertedRevision(NodeInterface $revision, FormStateInterface $form_state) {
|
||||
$revert_untranslated_fields = $form_state->getValue('revert_untranslated_fields');
|
||||
|
||||
/** @var \Drupal\node\NodeInterface $default_revision */
|
||||
$latest_revision = $this->nodeStorage->load($revision->id());
|
||||
$latest_revision_translation = $latest_revision->getTranslation($this->langcode);
|
||||
|
||||
$revision_translation = $revision->getTranslation($this->langcode);
|
||||
|
||||
foreach ($latest_revision_translation->getFieldDefinitions() as $field_name => $definition) {
|
||||
if ($definition->isTranslatable() || $revert_untranslated_fields) {
|
||||
$latest_revision_translation->set($field_name, $revision_translation->get($field_name)->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
$latest_revision_translation->setNewRevision();
|
||||
$latest_revision_translation->isDefaultRevision(TRUE);
|
||||
|
||||
return $latest_revision_translation;
|
||||
$revert_untranslated_fields = (bool) $form_state->getValue('revert_untranslated_fields');
|
||||
$translation = $revision->getTranslation($this->langcode);
|
||||
return $this->nodeStorage->createRevision($translation, TRUE, $revert_untranslated_fields);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
|
||||
/**
|
||||
* Provides a form for content type deletion.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class NodeTypeDeleteConfirm extends EntityDeleteForm {
|
||||
|
||||
|
|
|
@ -6,6 +6,11 @@ use Drupal\Core\Form\ConfirmFormBase;
|
|||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Form for rebuilding permissions.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class RebuildPermissionsForm extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
|
|
|
@ -50,7 +50,6 @@ class NodeAccessControlHandler extends EntityAccessControlHandler implements Nod
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -4,39 +4,52 @@ namespace Drupal\node;
|
|||
|
||||
use Drupal\Component\Datetime\TimeInterface;
|
||||
use Drupal\Core\Entity\ContentEntityForm;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityRepositoryInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\user\PrivateTempStoreFactory;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\TempStore\PrivateTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Form handler for the node edit forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class NodeForm extends ContentEntityForm {
|
||||
|
||||
/**
|
||||
* The tempstore factory.
|
||||
*
|
||||
* @var \Drupal\user\PrivateTempStoreFactory
|
||||
* @var \Drupal\Core\TempStore\PrivateTempStoreFactory
|
||||
*/
|
||||
protected $tempStoreFactory;
|
||||
|
||||
/**
|
||||
* The Current User object.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* Constructs a NodeForm object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
|
||||
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
|
||||
* The entity repository.
|
||||
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
|
||||
* The factory for the temp store object.
|
||||
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
|
||||
* The entity type bundle service.
|
||||
* @param \Drupal\Component\Datetime\TimeInterface $time
|
||||
* The time service.
|
||||
* @param \Drupal\Core\Session\AccountInterface $current_user
|
||||
* The current user.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, PrivateTempStoreFactory $temp_store_factory, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) {
|
||||
parent::__construct($entity_manager, $entity_type_bundle_info, $time);
|
||||
public function __construct(EntityRepositoryInterface $entity_repository, PrivateTempStoreFactory $temp_store_factory, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, AccountInterface $current_user) {
|
||||
parent::__construct($entity_repository, $entity_type_bundle_info, $time);
|
||||
$this->tempStoreFactory = $temp_store_factory;
|
||||
$this->currentUser = $current_user;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,10 +57,11 @@ class NodeForm extends ContentEntityForm {
|
|||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.manager'),
|
||||
$container->get('user.private_tempstore'),
|
||||
$container->get('entity.repository'),
|
||||
$container->get('tempstore.private'),
|
||||
$container->get('entity_type.bundle.info'),
|
||||
$container->get('datetime.time')
|
||||
$container->get('datetime.time'),
|
||||
$container->get('current_user')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -86,7 +100,10 @@ class NodeForm extends ContentEntityForm {
|
|||
$node = $this->entity;
|
||||
|
||||
if ($this->operation == 'edit') {
|
||||
$form['#title'] = $this->t('<em>Edit @type</em> @title', ['@type' => node_get_type_label($node), '@title' => $node->label()]);
|
||||
$form['#title'] = $this->t('<em>Edit @type</em> @title', [
|
||||
'@type' => node_get_type_label($node),
|
||||
'@title' => $node->label(),
|
||||
]);
|
||||
}
|
||||
|
||||
// Changed must be sent to the client, for later overwrite error checking.
|
||||
|
@ -99,6 +116,36 @@ class NodeForm extends ContentEntityForm {
|
|||
|
||||
$form['advanced']['#attributes']['class'][] = 'entity-meta';
|
||||
|
||||
$form['meta'] = [
|
||||
'#type' => 'details',
|
||||
'#group' => 'advanced',
|
||||
'#weight' => -10,
|
||||
'#title' => $this->t('Status'),
|
||||
'#attributes' => ['class' => ['entity-meta__header']],
|
||||
'#tree' => TRUE,
|
||||
'#access' => $this->currentUser->hasPermission('administer nodes'),
|
||||
];
|
||||
$form['meta']['published'] = [
|
||||
'#type' => 'item',
|
||||
'#markup' => $node->isPublished() ? $this->t('Published') : $this->t('Not published'),
|
||||
'#access' => !$node->isNew(),
|
||||
'#wrapper_attributes' => ['class' => ['entity-meta__title']],
|
||||
];
|
||||
$form['meta']['changed'] = [
|
||||
'#type' => 'item',
|
||||
'#title' => $this->t('Last saved'),
|
||||
'#markup' => !$node->isNew() ? format_date($node->getChangedTime(), 'short') : $this->t('Not saved yet'),
|
||||
'#wrapper_attributes' => ['class' => ['entity-meta__last-saved']],
|
||||
];
|
||||
$form['meta']['author'] = [
|
||||
'#type' => 'item',
|
||||
'#title' => $this->t('Author'),
|
||||
'#markup' => $node->getOwner()->getUsername(),
|
||||
'#wrapper_attributes' => ['class' => ['entity-meta__author']],
|
||||
];
|
||||
|
||||
$form['status']['#group'] = 'footer';
|
||||
|
||||
// Node author information for administrators.
|
||||
$form['author'] = [
|
||||
'#type' => 'details',
|
||||
|
@ -147,8 +194,6 @@ class NodeForm extends ContentEntityForm {
|
|||
|
||||
$form['#attached']['library'][] = 'node/form';
|
||||
|
||||
$form['#entity_builders']['update_status'] = '::updateStatus';
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
@ -165,11 +210,14 @@ class NodeForm extends ContentEntityForm {
|
|||
* The current state of the form.
|
||||
*
|
||||
* @see \Drupal\node\NodeForm::form()
|
||||
*
|
||||
* @deprecated in Drupal 8.4.x, will be removed before Drupal 9.0.0.
|
||||
* The "Publish" button was removed.
|
||||
*/
|
||||
public function updateStatus($entity_type_id, NodeInterface $node, array $form, FormStateInterface $form_state) {
|
||||
$element = $form_state->getTriggeringElement();
|
||||
if (isset($element['#published_status'])) {
|
||||
$node->setPublished($element['#published_status']);
|
||||
$element['#published_status'] ? $node->setPublished() : $node->setUnpublished();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,59 +231,6 @@ class NodeForm extends ContentEntityForm {
|
|||
|
||||
$element['submit']['#access'] = $preview_mode != DRUPAL_REQUIRED || $form_state->get('has_been_previewed');
|
||||
|
||||
// If saving is an option, privileged users get dedicated form submit
|
||||
// buttons to adjust the publishing status while saving in one go.
|
||||
// @todo This adjustment makes it close to impossible for contributed
|
||||
// modules to integrate with "the Save operation" of this form. Modules
|
||||
// need a way to plug themselves into 1) the ::submit() step, and
|
||||
// 2) the ::save() step, both decoupled from the pressed form button.
|
||||
if ($element['submit']['#access'] && \Drupal::currentUser()->hasPermission('administer nodes')) {
|
||||
// isNew | prev status » default & publish label & unpublish label
|
||||
// 1 | 1 » publish & Save and publish & Save as unpublished
|
||||
// 1 | 0 » unpublish & Save and publish & Save as unpublished
|
||||
// 0 | 1 » publish & Save and keep published & Save and unpublish
|
||||
// 0 | 0 » unpublish & Save and keep unpublished & Save and publish
|
||||
|
||||
// Add a "Publish" button.
|
||||
$element['publish'] = $element['submit'];
|
||||
// If the "Publish" button is clicked, we want to update the status to "published".
|
||||
$element['publish']['#published_status'] = TRUE;
|
||||
$element['publish']['#dropbutton'] = 'save';
|
||||
if ($node->isNew()) {
|
||||
$element['publish']['#value'] = t('Save and publish');
|
||||
}
|
||||
else {
|
||||
$element['publish']['#value'] = $node->isPublished() ? t('Save and keep published') : t('Save and publish');
|
||||
}
|
||||
$element['publish']['#weight'] = 0;
|
||||
|
||||
// Add a "Unpublish" button.
|
||||
$element['unpublish'] = $element['submit'];
|
||||
// If the "Unpublish" button is clicked, we want to update the status to "unpublished".
|
||||
$element['unpublish']['#published_status'] = FALSE;
|
||||
$element['unpublish']['#dropbutton'] = 'save';
|
||||
if ($node->isNew()) {
|
||||
$element['unpublish']['#value'] = t('Save as unpublished');
|
||||
}
|
||||
else {
|
||||
$element['unpublish']['#value'] = !$node->isPublished() ? t('Save and keep unpublished') : t('Save and unpublish');
|
||||
}
|
||||
$element['unpublish']['#weight'] = 10;
|
||||
|
||||
// If already published, the 'publish' button is primary.
|
||||
if ($node->isPublished()) {
|
||||
unset($element['unpublish']['#button_type']);
|
||||
}
|
||||
// Otherwise, the 'unpublish' button is primary and should come first.
|
||||
else {
|
||||
unset($element['publish']['#button_type']);
|
||||
$element['unpublish']['#weight'] = -10;
|
||||
}
|
||||
|
||||
// Remove the "Save" button.
|
||||
$element['submit']['#access'] = FALSE;
|
||||
}
|
||||
|
||||
$element['preview'] = [
|
||||
'#type' => 'submit',
|
||||
'#access' => $preview_mode != DRUPAL_DISABLED && ($node->access('create') || $node->access('update')),
|
||||
|
@ -290,11 +285,11 @@ class NodeForm extends ContentEntityForm {
|
|||
|
||||
if ($insert) {
|
||||
$this->logger('content')->notice('@type: added %title.', $context);
|
||||
drupal_set_message(t('@type %title has been created.', $t_args));
|
||||
$this->messenger()->addStatus($this->t('@type %title has been created.', $t_args));
|
||||
}
|
||||
else {
|
||||
$this->logger('content')->notice('@type: updated %title.', $context);
|
||||
drupal_set_message(t('@type %title has been updated.', $t_args));
|
||||
$this->messenger()->addStatus($this->t('@type %title has been updated.', $t_args));
|
||||
}
|
||||
|
||||
if ($node->id()) {
|
||||
|
@ -317,7 +312,7 @@ class NodeForm extends ContentEntityForm {
|
|||
else {
|
||||
// In the unlikely case something went wrong on save, the node will be
|
||||
// rebuilt and node form redisplayed the same way as in preview.
|
||||
drupal_set_message(t('The post could not be saved.'), 'error');
|
||||
$this->messenger()->addError($this->t('The post could not be saved.'));
|
||||
$form_state->setRebuild();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ class NodeGrantDatabaseStorage implements NodeGrantDatabaseStorageInterface {
|
|||
|
||||
$grants = static::buildGrantsQueryCondition(node_access_grants('view', $account));
|
||||
|
||||
if (count($grants) > 0 ) {
|
||||
if (count($grants) > 0) {
|
||||
$query->condition($grants);
|
||||
}
|
||||
return $query->execute()->fetchField();
|
||||
|
@ -211,6 +211,7 @@ class NodeGrantDatabaseStorage implements NodeGrantDatabaseStorageInterface {
|
|||
$query = $this->database->insert('node_access')->fields(['nid', 'langcode', 'fallback', 'realm', 'gid', 'grant_view', 'grant_update', 'grant_delete']);
|
||||
// If we have defined a granted langcode, use it. But if not, add a grant
|
||||
// for every language this node is translated to.
|
||||
$fallback_langcode = $node->getUntranslated()->language()->getId();
|
||||
foreach ($grants as $grant) {
|
||||
if ($realm && $realm != $grant['realm']) {
|
||||
continue;
|
||||
|
@ -227,7 +228,7 @@ class NodeGrantDatabaseStorage implements NodeGrantDatabaseStorageInterface {
|
|||
$grant['nid'] = $node->id();
|
||||
$grant['langcode'] = $grant_langcode;
|
||||
// The record with the original langcode is used as the fallback.
|
||||
if ($grant['langcode'] == $node->language()->getId()) {
|
||||
if ($grant['langcode'] == $fallback_langcode) {
|
||||
$grant['fallback'] = 1;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -31,11 +31,11 @@ interface NodeGrantDatabaseStorageInterface {
|
|||
* @param array $tables
|
||||
* A list of tables that need to be part of the alter.
|
||||
* @param string $op
|
||||
* The operation to be performed on the node. Possible values are:
|
||||
* - "view"
|
||||
* - "update"
|
||||
* - "delete"
|
||||
* - "create"
|
||||
* The operation to be performed on the node. Possible values are:
|
||||
* - "view"
|
||||
* - "update"
|
||||
* - "delete"
|
||||
* - "create"
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* A user object representing the user for whom the operation is to be
|
||||
* performed.
|
||||
|
|
|
@ -25,13 +25,6 @@ class NodeListBuilder extends EntityListBuilder {
|
|||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
/**
|
||||
* The redirect destination service.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RedirectDestinationInterface
|
||||
*/
|
||||
protected $redirectDestination;
|
||||
|
||||
/**
|
||||
* Constructs a new NodeListBuilder object.
|
||||
*
|
||||
|
@ -110,7 +103,7 @@ class NodeListBuilder extends EntityListBuilder {
|
|||
$row['title']['data'] = [
|
||||
'#type' => 'link',
|
||||
'#title' => $entity->label(),
|
||||
'#suffix' => ' ' . drupal_render($mark),
|
||||
'#suffix' => ' ' . \Drupal::service('renderer')->render($mark),
|
||||
'#url' => $uri,
|
||||
];
|
||||
$row['type'] = node_get_type_label($entity);
|
||||
|
@ -128,17 +121,4 @@ class NodeListBuilder extends EntityListBuilder {
|
|||
return $row + parent::buildRow($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getDefaultOperations(EntityInterface $entity) {
|
||||
$operations = parent::getDefaultOperations($entity);
|
||||
|
||||
$destination = $this->redirectDestination->getAsArray();
|
||||
foreach ($operations as $key => $operation) {
|
||||
$operations[$key]['query'] = $destination;
|
||||
}
|
||||
return $operations;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -62,14 +62,15 @@ class NodePermissions {
|
|||
],
|
||||
"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 <em>view revisions</em> and <em>edit rights</em> for nodes in question, or <em>administer nodes</em>.'),
|
||||
'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 <em>view revisions</em> and <em>delete rights</em> for nodes in question, or <em>administer nodes</em>.'),
|
||||
'description' => $this->t('To delete a revision, you also need permission to delete the content item.'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
|
42
web/core/modules/node/src/NodeServiceProvider.php
Normal file
42
web/core/modules/node/src/NodeServiceProvider.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\node;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceProviderInterface;
|
||||
use Drupal\node\EventSubscriber\NodeTranslationExceptionSubscriber;
|
||||
use Drupal\node\EventSubscriber\NodeTranslationMigrateSubscriber;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Registers services in the container.
|
||||
*/
|
||||
class NodeServiceProvider implements ServiceProviderInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function register(ContainerBuilder $container) {
|
||||
// Register the node.node_translation_migrate service in the container if
|
||||
// the migrate and language modules are enabled.
|
||||
$modules = $container->getParameter('container.modules');
|
||||
if (isset($modules['migrate']) && isset($modules['language'])) {
|
||||
$container->register('node.node_translation_migrate', NodeTranslationMigrateSubscriber::class)
|
||||
->addTag('event_subscriber')
|
||||
->addArgument(new Reference('keyvalue'))
|
||||
->addArgument(new Reference('state'));
|
||||
}
|
||||
|
||||
// Register the node.node_translation_exception service in the container if
|
||||
// the language module is enabled.
|
||||
if (isset($modules['language'])) {
|
||||
$container->register('node.node_translation_exception', NodeTranslationExceptionSubscriber::class)
|
||||
->addTag('event_subscriber')
|
||||
->addArgument(new Reference('keyvalue'))
|
||||
->addArgument(new Reference('language_manager'))
|
||||
->addArgument(new Reference('url_generator'))
|
||||
->addArgument(new Reference('state'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -19,7 +19,7 @@ class NodeStorage extends SqlContentEntityStorage implements NodeStorageInterfac
|
|||
*/
|
||||
public function revisionIds(NodeInterface $node) {
|
||||
return $this->database->query(
|
||||
'SELECT vid FROM {node_revision} WHERE nid=:nid ORDER BY vid',
|
||||
'SELECT vid FROM {' . $this->getRevisionTable() . '} WHERE nid=:nid ORDER BY vid',
|
||||
[':nid' => $node->id()]
|
||||
)->fetchCol();
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class NodeStorage extends SqlContentEntityStorage implements NodeStorageInterfac
|
|||
*/
|
||||
public function userRevisionIds(AccountInterface $account) {
|
||||
return $this->database->query(
|
||||
'SELECT vid FROM {node_field_revision} WHERE uid = :uid ORDER BY vid',
|
||||
'SELECT vid FROM {' . $this->getRevisionDataTable() . '} WHERE uid = :uid ORDER BY vid',
|
||||
[':uid' => $account->id()]
|
||||
)->fetchCol();
|
||||
}
|
||||
|
@ -38,14 +38,14 @@ class NodeStorage extends SqlContentEntityStorage implements NodeStorageInterfac
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function countDefaultLanguageRevisions(NodeInterface $node) {
|
||||
return $this->database->query('SELECT COUNT(*) FROM {node_field_revision} WHERE nid = :nid AND default_langcode = 1', [':nid' => $node->id()])->fetchField();
|
||||
return $this->database->query('SELECT COUNT(*) FROM {' . $this->getRevisionDataTable() . '} WHERE nid = :nid AND default_langcode = 1', [':nid' => $node->id()])->fetchField();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function updateType($old_type, $new_type) {
|
||||
return $this->database->update('node')
|
||||
return $this->database->update($this->getBaseTable())
|
||||
->fields(['type' => $new_type])
|
||||
->condition('type', $old_type)
|
||||
->execute();
|
||||
|
@ -55,7 +55,7 @@ class NodeStorage extends SqlContentEntityStorage implements NodeStorageInterfac
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function clearRevisionsLanguage(LanguageInterface $language) {
|
||||
return $this->database->update('node_revision')
|
||||
return $this->database->update($this->getRevisionTable())
|
||||
->fields(['langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED])
|
||||
->condition('langcode', $language->getId())
|
||||
->execute();
|
||||
|
|
|
@ -17,10 +17,12 @@ class NodeStorageSchema extends SqlContentEntityStorageSchema {
|
|||
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
|
||||
$schema = parent::getEntitySchema($entity_type, $reset);
|
||||
|
||||
$schema['node_field_data']['indexes'] += [
|
||||
'node__frontpage' => ['promote', 'status', 'sticky', 'created'],
|
||||
'node__title_type' => ['title', ['type', 4]],
|
||||
];
|
||||
if ($data_table = $this->storage->getDataTable()) {
|
||||
$schema[$data_table]['indexes'] += [
|
||||
'node__frontpage' => ['promote', 'status', 'sticky', 'created'],
|
||||
'node__title_type' => ['title', ['type', 4]],
|
||||
];
|
||||
}
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
|
|
@ -39,10 +39,8 @@ class NodeTranslationHandler extends ContentTranslationHandler {
|
|||
}
|
||||
}
|
||||
if (isset($status_translatable)) {
|
||||
foreach (['publish', 'unpublish', 'submit'] as $button) {
|
||||
if (isset($form['actions'][$button])) {
|
||||
$form['actions'][$button]['#value'] .= ' ' . ($status_translatable ? t('(this translation)') : t('(all translations)'));
|
||||
}
|
||||
if (isset($form['actions']['submit'])) {
|
||||
$form['actions']['submit']['#value'] .= ' ' . ($status_translatable ? t('(this translation)') : t('(all translations)'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* Form handler for node type forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class NodeTypeForm extends BundleEntityFormBase {
|
||||
|
||||
|
@ -122,7 +124,7 @@ class NodeTypeForm extends BundleEntityFormBase {
|
|||
DRUPAL_REQUIRED => t('Required'),
|
||||
],
|
||||
];
|
||||
$form['submission']['help'] = [
|
||||
$form['submission']['help'] = [
|
||||
'#type' => 'textarea',
|
||||
'#title' => t('Explanation or submission guidelines'),
|
||||
'#default_value' => $type->getHelp(),
|
||||
|
@ -223,11 +225,11 @@ class NodeTypeForm extends BundleEntityFormBase {
|
|||
$t_args = ['%name' => $type->label()];
|
||||
|
||||
if ($status == SAVED_UPDATED) {
|
||||
drupal_set_message(t('The content type %name has been updated.', $t_args));
|
||||
$this->messenger()->addStatus($this->t('The content type %name has been updated.', $t_args));
|
||||
}
|
||||
elseif ($status == SAVED_NEW) {
|
||||
node_add_body_field($type);
|
||||
drupal_set_message(t('The content type %name has been added.', $t_args));
|
||||
$this->messenger()->addStatus($this->t('The content type %name has been added.', $t_args));
|
||||
$context = array_merge($t_args, ['link' => $type->link($this->t('View'), 'collection')]);
|
||||
$this->logger('node')->notice('Added content type %name.', $context);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ class NodeTypeListBuilder extends ConfigEntityListBuilder {
|
|||
public function render() {
|
||||
$build = parent::render();
|
||||
$build['table']['#empty'] = $this->t('No content types available. <a href=":link">Add content type</a>.', [
|
||||
':link' => Url::fromRoute('node.type_add')->toString()
|
||||
':link' => Url::fromRoute('node.type_add')->toString(),
|
||||
]);
|
||||
return $build;
|
||||
}
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
|
||||
namespace Drupal\node;
|
||||
|
||||
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityViewBuilder;
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* View builder handler for nodes.
|
||||
|
@ -29,12 +27,15 @@ class NodeViewBuilder extends EntityViewBuilder {
|
|||
|
||||
if ($display->getComponent('links')) {
|
||||
$build[$id]['links'] = [
|
||||
'#lazy_builder' => [get_called_class() . '::renderLinks', [
|
||||
$entity->id(),
|
||||
$view_mode,
|
||||
$entity->language()->getId(),
|
||||
!empty($entity->in_preview),
|
||||
]],
|
||||
'#lazy_builder' => [
|
||||
get_called_class() . '::renderLinks', [
|
||||
$entity->id(),
|
||||
$view_mode,
|
||||
$entity->language()->getId(),
|
||||
!empty($entity->in_preview),
|
||||
$entity->isDefaultRevision() ? NULL : $entity->getLoadedRevisionId(),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -45,7 +46,7 @@ class NodeViewBuilder extends EntityViewBuilder {
|
|||
'#title' => t('Language'),
|
||||
'#markup' => $entity->language()->getName(),
|
||||
'#prefix' => '<div id="field-language-display">',
|
||||
'#suffix' => '</div>'
|
||||
'#suffix' => '</div>',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -76,11 +77,14 @@ class NodeViewBuilder extends EntityViewBuilder {
|
|||
* The language in which the node entity is being viewed.
|
||||
* @param bool $is_in_preview
|
||||
* Whether the node is currently being previewed.
|
||||
* @param $revision_id
|
||||
* (optional) The identifier of the node revision to be loaded. If none
|
||||
* is provided, the default revision will be loaded.
|
||||
*
|
||||
* @return array
|
||||
* A renderable array representing the node links.
|
||||
*/
|
||||
public static function renderLinks($node_entity_id, $view_mode, $langcode, $is_in_preview) {
|
||||
public static function renderLinks($node_entity_id, $view_mode, $langcode, $is_in_preview, $revision_id = NULL) {
|
||||
$links = [
|
||||
'#theme' => 'links__node',
|
||||
'#pre_render' => ['drupal_pre_render_links'],
|
||||
|
@ -88,7 +92,10 @@ class NodeViewBuilder extends EntityViewBuilder {
|
|||
];
|
||||
|
||||
if (!$is_in_preview) {
|
||||
$entity = Node::load($node_entity_id)->getTranslation($langcode);
|
||||
$storage = \Drupal::entityTypeManager()->getStorage('node');
|
||||
/** @var \Drupal\node\NodeInterface $revision */
|
||||
$revision = !isset($revision_id) ? $storage->load($node_entity_id) : $storage->loadRevision($revision_id);
|
||||
$entity = $revision->getTranslation($langcode);
|
||||
$links['node'] = static::buildLinks($entity, $view_mode);
|
||||
|
||||
// Allow other modules to alter the node links.
|
||||
|
@ -139,29 +146,4 @@ class NodeViewBuilder extends EntityViewBuilder {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function alterBuild(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
|
||||
/** @var \Drupal\node\NodeInterface $entity */
|
||||
parent::alterBuild($build, $entity, $display, $view_mode);
|
||||
if ($entity->id()) {
|
||||
if ($entity->isDefaultRevision()) {
|
||||
$build['#contextual_links']['node'] = [
|
||||
'route_parameters' => ['node' => $entity->id()],
|
||||
'metadata' => ['changed' => $entity->getChangedTime()],
|
||||
];
|
||||
}
|
||||
else {
|
||||
$build['#contextual_links']['node_revision'] = [
|
||||
'route_parameters' => [
|
||||
'node' => $entity->id(),
|
||||
'node_revision' => $entity->getRevisionId(),
|
||||
],
|
||||
'metadata' => ['changed' => $entity->getChangedTime()],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -58,14 +58,6 @@ class NodeViewsData extends EntityViewsData {
|
|||
$data['node_field_data']['sticky']['filter']['type'] = 'yes-no';
|
||||
$data['node_field_data']['sticky']['sort']['help'] = $this->t('Whether or not the content is sticky. To list sticky content first, set this to descending.');
|
||||
|
||||
$data['node']['path'] = [
|
||||
'field' => [
|
||||
'title' => $this->t('Path'),
|
||||
'help' => $this->t('The aliased path to this content.'),
|
||||
'id' => 'node_path',
|
||||
],
|
||||
];
|
||||
|
||||
$data['node']['node_bulk_form'] = [
|
||||
'title' => $this->t('Node operations bulk form'),
|
||||
'help' => $this->t('Add a form element that lets you run operations on multiple nodes.'),
|
||||
|
@ -288,7 +280,7 @@ class NodeViewsData extends EntityViewsData {
|
|||
|
||||
// Define the base group of this table. Fields that don't have a group defined
|
||||
// will go into this field by default.
|
||||
$data['node_access']['table']['group'] = $this->t('Content access');
|
||||
$data['node_access']['table']['group'] = $this->t('Content access');
|
||||
|
||||
// For other base tables, explain how we join.
|
||||
$data['node_access']['table']['join'] = [
|
||||
|
@ -330,7 +322,7 @@ class NodeViewsData extends EntityViewsData {
|
|||
'field' => 'sid',
|
||||
'table' => 'search_index',
|
||||
'extra' => "node_search_index.type = 'node_search' AND node_search_index.langcode = node_field_data.langcode",
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
$data['node_search_total']['table']['join'] = [
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Drupal\node\ParamConverter;
|
||||
|
||||
use Drupal\user\PrivateTempStoreFactory;
|
||||
use Drupal\Core\TempStore\PrivateTempStoreFactory;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Drupal\Core\ParamConverter\ParamConverterInterface;
|
||||
|
||||
|
@ -14,14 +14,14 @@ class NodePreviewConverter implements ParamConverterInterface {
|
|||
/**
|
||||
* Stores the tempstore factory.
|
||||
*
|
||||
* @var \Drupal\user\PrivateTempStoreFactory
|
||||
* @var \Drupal\Core\TempStore\PrivateTempStoreFactory
|
||||
*/
|
||||
protected $tempStoreFactory;
|
||||
|
||||
/**
|
||||
* Constructs a new NodePreviewConverter.
|
||||
*
|
||||
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
|
||||
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
|
||||
* The factory for the temp store object.
|
||||
*/
|
||||
public function __construct(PrivateTempStoreFactory $temp_store_factory) {
|
||||
|
|
|
@ -2,98 +2,33 @@
|
|||
|
||||
namespace Drupal\node\Plugin\Action;
|
||||
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Action\Plugin\Action\DeleteAction;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\user\PrivateTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\Core\TempStore\PrivateTempStoreFactory;
|
||||
|
||||
/**
|
||||
* Redirects to a node deletion form.
|
||||
*
|
||||
* @deprecated in Drupal 8.6.x, to be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Core\Action\Plugin\Action\DeleteAction instead.
|
||||
*
|
||||
* @see \Drupal\Core\Action\Plugin\Action\DeleteAction
|
||||
* @see https://www.drupal.org/node/2934349
|
||||
*
|
||||
* @Action(
|
||||
* id = "node_delete_action",
|
||||
* label = @Translation("Delete content"),
|
||||
* type = "node",
|
||||
* confirm_form_route_name = "node.multiple_delete_confirm"
|
||||
* label = @Translation("Delete content")
|
||||
* )
|
||||
*/
|
||||
class DeleteNode extends ActionBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The tempstore object.
|
||||
*
|
||||
* @var \Drupal\user\SharedTempStore
|
||||
*/
|
||||
protected $tempStore;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* Constructs a new DeleteNode object.
|
||||
*
|
||||
* @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\user\PrivateTempStoreFactory $temp_store_factory
|
||||
* The tempstore factory.
|
||||
* @param AccountInterface $current_user
|
||||
* Current user.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, PrivateTempStoreFactory $temp_store_factory, AccountInterface $current_user) {
|
||||
$this->currentUser = $current_user;
|
||||
$this->tempStore = $temp_store_factory->get('node_multiple_delete_confirm');
|
||||
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
}
|
||||
class DeleteNode extends DeleteAction {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('user.private_tempstore'),
|
||||
$container->get('current_user')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function executeMultiple(array $entities) {
|
||||
$info = [];
|
||||
/** @var \Drupal\node\NodeInterface $node */
|
||||
foreach ($entities as $node) {
|
||||
$langcode = $node->language()->getId();
|
||||
$info[$node->id()][$langcode] = $langcode;
|
||||
}
|
||||
$this->tempStore->set($this->currentUser->id(), $info);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($object = NULL) {
|
||||
$this->executeMultiple([$object]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
/** @var \Drupal\node\NodeInterface $object */
|
||||
return $object->access('delete', $account, $return_as_object);
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $temp_store_factory, AccountInterface $current_user) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $temp_store_factory, $current_user);
|
||||
@trigger_error(__NAMESPACE__ . '\DeleteNode is deprecated in Drupal 8.6.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\DeleteAction instead. See https://www.drupal.org/node/2934349.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Drupal\node\Plugin\Action;
|
||||
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Field\FieldUpdateActionBase;
|
||||
use Drupal\node\NodeInterface;
|
||||
|
||||
/**
|
||||
* Demotes a node.
|
||||
|
@ -14,25 +14,13 @@ use Drupal\Core\Session\AccountInterface;
|
|||
* type = "node"
|
||||
* )
|
||||
*/
|
||||
class DemoteNode extends ActionBase {
|
||||
class DemoteNode extends FieldUpdateActionBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($entity = NULL) {
|
||||
$entity->setPromoted(FALSE);
|
||||
$entity->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
/** @var \Drupal\node\NodeInterface $object */
|
||||
$result = $object->access('update', $account, TRUE)
|
||||
->andIf($object->promote->access('edit', $account, TRUE));
|
||||
|
||||
return $return_as_object ? $result : $result->isAllowed();
|
||||
protected function getFieldsToUpdate() {
|
||||
return ['promote' => NodeInterface::NOT_PROMOTED];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Drupal\node\Plugin\Action;
|
||||
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Field\FieldUpdateActionBase;
|
||||
use Drupal\node\NodeInterface;
|
||||
|
||||
/**
|
||||
* Promotes a node.
|
||||
|
@ -14,24 +14,13 @@ use Drupal\Core\Session\AccountInterface;
|
|||
* type = "node"
|
||||
* )
|
||||
*/
|
||||
class PromoteNode extends ActionBase {
|
||||
class PromoteNode extends FieldUpdateActionBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($entity = NULL) {
|
||||
$entity->setPromoted(TRUE);
|
||||
$entity->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
/** @var \Drupal\node\NodeInterface $object */
|
||||
$access = $object->access('update', $account, TRUE)
|
||||
->andif($object->promote->access('edit', $account, TRUE));
|
||||
return $return_as_object ? $access : $access->isAllowed();
|
||||
protected function getFieldsToUpdate() {
|
||||
return ['promote' => NodeInterface::PROMOTED];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,36 +2,32 @@
|
|||
|
||||
namespace Drupal\node\Plugin\Action;
|
||||
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Action\Plugin\Action\PublishAction;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
|
||||
/**
|
||||
* Publishes a node.
|
||||
*
|
||||
* @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Core\Action\Plugin\Action\PublishAction instead.
|
||||
*
|
||||
* @see \Drupal\Core\Action\Plugin\Action\PublishAction
|
||||
* @see https://www.drupal.org/node/2919303
|
||||
*
|
||||
* @Action(
|
||||
* id = "node_publish_action",
|
||||
* label = @Translation("Publish selected content"),
|
||||
* type = "node"
|
||||
* )
|
||||
*/
|
||||
class PublishNode extends ActionBase {
|
||||
class PublishNode extends PublishAction {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($entity = NULL) {
|
||||
$entity->setPublished()->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
/** @var \Drupal\node\NodeInterface $object */
|
||||
$result = $object->access('update', $account, TRUE)
|
||||
->andIf($object->status->access('edit', $account, TRUE));
|
||||
|
||||
return $return_as_object ? $result : $result->isAllowed();
|
||||
public function __construct($configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager);
|
||||
@trigger_error(__NAMESPACE__ . '\PublishNode is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\PublishAction instead. See https://www.drupal.org/node/2919303.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,36 +2,33 @@
|
|||
|
||||
namespace Drupal\node\Plugin\Action;
|
||||
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Component\Datetime\TimeInterface;
|
||||
use Drupal\Core\Action\Plugin\Action\SaveAction;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
|
||||
/**
|
||||
* Provides an action that can save any entity.
|
||||
*
|
||||
* @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Core\Action\Plugin\Action\SaveAction instead.
|
||||
*
|
||||
* @see \Drupal\Core\Action\Plugin\Action\SaveAction
|
||||
* @see https://www.drupal.org/node/2919303
|
||||
*
|
||||
* @Action(
|
||||
* id = "node_save_action",
|
||||
* label = @Translation("Save content"),
|
||||
* type = "node"
|
||||
* )
|
||||
*/
|
||||
class SaveNode extends ActionBase {
|
||||
class SaveNode extends SaveAction {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($entity = NULL) {
|
||||
// We need to change at least one value, otherwise the changed timestamp
|
||||
// will not be updated.
|
||||
$entity->changed = 0;
|
||||
$entity->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
/** @var \Drupal\node\NodeInterface $object */
|
||||
return $object->access('update', $account, $return_as_object);
|
||||
public function __construct($configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, TimeInterface $time) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $time);
|
||||
@trigger_error(__NAMESPACE__ . '\SaveNode is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\SaveAction instead. See https://www.drupal.org/node/2919303.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Drupal\node\Plugin\Action;
|
||||
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Field\FieldUpdateActionBase;
|
||||
use Drupal\node\NodeInterface;
|
||||
|
||||
/**
|
||||
* Makes a node sticky.
|
||||
|
@ -14,23 +14,13 @@ use Drupal\Core\Session\AccountInterface;
|
|||
* type = "node"
|
||||
* )
|
||||
*/
|
||||
class StickyNode extends ActionBase {
|
||||
class StickyNode extends FieldUpdateActionBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($entity = NULL) {
|
||||
$entity->setSticky(TRUE)->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
/** @var \Drupal\node\NodeInterface $object */
|
||||
$access = $object->access('update', $account, TRUE)
|
||||
->andif($object->sticky->access('edit', $account, TRUE));
|
||||
return $return_as_object ? $access : $access->isAllowed();
|
||||
protected function getFieldsToUpdate() {
|
||||
return ['sticky' => NodeInterface::STICKY];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ class UnpublishByKeywordNode extends ConfigurableActionBase {
|
|||
public function execute($node = NULL) {
|
||||
foreach ($this->configuration['keywords'] as $keyword) {
|
||||
$elements = node_view(clone $node);
|
||||
if (strpos(drupal_render($elements), $keyword) !== FALSE || strpos($node->label(), $keyword) !== FALSE) {
|
||||
$node->setPublished(FALSE);
|
||||
if (strpos(\Drupal::service('renderer')->render($elements), $keyword) !== FALSE || strpos($node->label(), $keyword) !== FALSE) {
|
||||
$node->setUnpublished();
|
||||
$node->save();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2,36 +2,32 @@
|
|||
|
||||
namespace Drupal\node\Plugin\Action;
|
||||
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Action\Plugin\Action\UnpublishAction;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
|
||||
/**
|
||||
* Unpublishes a node.
|
||||
*
|
||||
* @deprecated in Drupal 8.5.x, to be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Core\Action\Plugin\Action\UnpublishAction instead.
|
||||
*
|
||||
* @see \Drupal\Core\Action\Plugin\Action\UnpublishAction
|
||||
* @see https://www.drupal.org/node/2919303
|
||||
*
|
||||
* @Action(
|
||||
* id = "node_unpublish_action",
|
||||
* label = @Translation("Unpublish selected content"),
|
||||
* type = "node"
|
||||
* )
|
||||
*/
|
||||
class UnpublishNode extends ActionBase {
|
||||
class UnpublishNode extends UnpublishAction {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($entity = NULL) {
|
||||
$entity->setUnpublished()->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
/** @var \Drupal\node\NodeInterface $object */
|
||||
$access = $object->access('update', $account, TRUE)
|
||||
->andIf($object->status->access('edit', $account, TRUE));
|
||||
|
||||
return $return_as_object ? $access : $access->isAllowed();
|
||||
public function __construct($configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager);
|
||||
@trigger_error(__NAMESPACE__ . '\UnpublishNode is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\Core\Action\Plugin\Action\UnpublishAction instead. See https://www.drupal.org/node/2919303.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Drupal\node\Plugin\Action;
|
||||
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Field\FieldUpdateActionBase;
|
||||
use Drupal\node\NodeInterface;
|
||||
|
||||
/**
|
||||
* Makes a node not sticky.
|
||||
|
@ -14,24 +14,13 @@ use Drupal\Core\Session\AccountInterface;
|
|||
* type = "node"
|
||||
* )
|
||||
*/
|
||||
class UnstickyNode extends ActionBase {
|
||||
class UnstickyNode extends FieldUpdateActionBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($entity = NULL) {
|
||||
$entity->setSticky(FALSE)->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
/** @var \Drupal\node\NodeInterface $object */
|
||||
$access = $object->access('update', $account, TRUE)
|
||||
->andIf($object->sticky->access('edit', $account, TRUE));
|
||||
|
||||
return $return_as_object ? $access : $access->isAllowed();
|
||||
protected function getFieldsToUpdate() {
|
||||
return ['sticky' => NodeInterface::NOT_STICKY];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
namespace Drupal\node\Plugin\EntityReferenceSelection;
|
||||
|
||||
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\node\NodeInterface;
|
||||
|
||||
/**
|
||||
|
@ -19,15 +18,6 @@ use Drupal\node\NodeInterface;
|
|||
*/
|
||||
class NodeSelection extends DefaultSelection {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$form = parent::buildConfigurationForm($form, $form_state);
|
||||
$form['target_bundles']['#title'] = $this->t('Content types');
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -52,7 +42,7 @@ class NodeSelection extends DefaultSelection {
|
|||
|
||||
// In order to create a referenceable node, it needs to published.
|
||||
/** @var \Drupal\node\NodeInterface $node */
|
||||
$node->setPublished(TRUE);
|
||||
$node->setPublished();
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface;
|
|||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Access\AccessibleInterface;
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
|
@ -114,10 +115,17 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
*/
|
||||
const ADVANCED_FORM = 'advanced-form';
|
||||
|
||||
/**
|
||||
* The messenger.
|
||||
*
|
||||
* @var \Drupal\Core\Messenger\MessengerInterface
|
||||
*/
|
||||
protected $messenger;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
static public function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
|
@ -128,6 +136,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
$container->get('config.factory')->get('search.settings'),
|
||||
$container->get('language_manager'),
|
||||
$container->get('renderer'),
|
||||
$container->get('messenger'),
|
||||
$container->get('current_user')
|
||||
);
|
||||
}
|
||||
|
@ -153,16 +162,19 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
* The language manager.
|
||||
* @param \Drupal\Core\Render\RendererInterface $renderer
|
||||
* The renderer.
|
||||
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
|
||||
* The messenger.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The $account object to use for checking for access to advanced search.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, Config $search_settings, LanguageManagerInterface $language_manager, RendererInterface $renderer, AccountInterface $account = NULL) {
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, Config $search_settings, LanguageManagerInterface $language_manager, RendererInterface $renderer, MessengerInterface $messenger, AccountInterface $account = NULL) {
|
||||
$this->database = $database;
|
||||
$this->entityManager = $entity_manager;
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->searchSettings = $search_settings;
|
||||
$this->languageManager = $language_manager;
|
||||
$this->renderer = $renderer;
|
||||
$this->messenger = $messenger;
|
||||
$this->account = $account;
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
||||
|
@ -289,15 +301,15 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
$status = $query->getStatus();
|
||||
|
||||
if ($status & SearchQuery::EXPRESSIONS_IGNORED) {
|
||||
drupal_set_message($this->t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', ['@count' => $this->searchSettings->get('and_or_limit')]), 'warning');
|
||||
$this->messenger->addWarning($this->t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', ['@count' => $this->searchSettings->get('and_or_limit')]));
|
||||
}
|
||||
|
||||
if ($status & SearchQuery::LOWER_CASE_OR) {
|
||||
drupal_set_message($this->t('Search for either of the two terms with uppercase <strong>OR</strong>. For example, <strong>cats OR dogs</strong>.'), 'warning');
|
||||
$this->messenger->addWarning($this->t('Search for either of the two terms with uppercase <strong>OR</strong>. For example, <strong>cats OR dogs</strong>.'));
|
||||
}
|
||||
|
||||
if ($status & SearchQuery::NO_POSITIVE_KEYWORDS) {
|
||||
drupal_set_message($this->formatPlural($this->searchSettings->get('index.minimum_word_size'), 'You must include at least one keyword to match in the content, and punctuation is ignored.', 'You must include at least one keyword to match in the content. Keywords must be at least @count characters, and punctuation is ignored.'), 'warning');
|
||||
$this->messenger->addWarning($this->formatPlural($this->searchSettings->get('index.minimum_word_size'), 'You must include at least one keyword to match in the content, and punctuation is ignored.', 'You must include at least one keyword to match in the content. Keywords must be at least @count characters, and punctuation is ignored.'));
|
||||
}
|
||||
|
||||
return $find;
|
||||
|
@ -475,7 +487,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
'#prefix' => '<h1>',
|
||||
'#plain_text' => $node->label(),
|
||||
'#suffix' => '</h1>',
|
||||
'#weight' => -1000
|
||||
'#weight' => -1000,
|
||||
];
|
||||
$text = $this->renderer->renderPlain($build);
|
||||
|
||||
|
@ -781,7 +793,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
'#open' => TRUE,
|
||||
];
|
||||
$form['content_ranking']['info'] = [
|
||||
'#markup' => '<p><em>' . $this->t('Influence is a numeric multiplier used in ordering search results. A higher number means the corresponding factor has more influence on search results; zero means the factor is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') . '</em></p>'
|
||||
'#markup' => '<p><em>' . $this->t('Influence is a numeric multiplier used in ordering search results. A higher number means the corresponding factor has more influence on search results; zero means the factor is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') . '</em></p>',
|
||||
];
|
||||
// Prepare table.
|
||||
$header = [$this->t('Factor'), $this->t('Influence')];
|
||||
|
|
|
@ -165,7 +165,7 @@ class D6NodeDeriver extends DeriverBase implements ContainerDeriverInterface {
|
|||
$this->fieldPluginCache[$field_type] = $this->fieldPluginManager->createInstance($plugin_id, ['core' => 6], $migration);
|
||||
}
|
||||
$this->fieldPluginCache[$field_type]
|
||||
->processFieldValues($migration, $field_name, $info);
|
||||
->defineValueProcessPipeline($migration, $field_name, $info);
|
||||
}
|
||||
catch (PluginNotFoundException $ex) {
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\node\Plugin\migrate;
|
||||
|
||||
use Drupal\migrate\Plugin\Migration;
|
||||
use Drupal\migrate_drupal\Plugin\MigrationWithFollowUpInterface;
|
||||
|
||||
/**
|
||||
* Migration plugin for the Drupal 6 node translations.
|
||||
*/
|
||||
class D6NodeTranslation extends Migration implements MigrationWithFollowUpInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function generateFollowUpMigrations() {
|
||||
$this->migrationPluginManager->clearCachedDefinitions();
|
||||
return $this->migrationPluginManager->createInstances('d6_entity_reference_translation');
|
||||
}
|
||||
|
||||
}
|
|
@ -141,6 +141,16 @@ class D7NodeDeriver extends DeriverBase implements ContainerDeriverInterface {
|
|||
$values['source']['node_type'] = $node_type;
|
||||
$values['destination']['default_bundle'] = $node_type;
|
||||
|
||||
// Comment status must be mapped to correct comment type.
|
||||
// Comment type migration creates a separate comment type for each
|
||||
// node type except for Forum which uses 'comment_forum'.
|
||||
$comment_type = 'comment_node_' . $node_type;
|
||||
if ($node_type == 'forum') {
|
||||
$comment_type = 'comment_forum';
|
||||
}
|
||||
$nested_key = $comment_type . '/0/status';
|
||||
$values['process'][$nested_key] = 'comment';
|
||||
|
||||
// If this migration is based on the d7_node_revision migration or
|
||||
// is for translations of nodes, it should explicitly depend on the
|
||||
// corresponding d7_node variant.
|
||||
|
@ -158,7 +168,7 @@ class D7NodeDeriver extends DeriverBase implements ContainerDeriverInterface {
|
|||
$this->fieldPluginCache[$field_type] = $this->fieldPluginManager->createInstance($plugin_id, ['core' => 7], $migration);
|
||||
}
|
||||
$this->fieldPluginCache[$field_type]
|
||||
->processFieldValues($migration, $field_name, $info);
|
||||
->defineValueProcessPipeline($migration, $field_name, $info);
|
||||
}
|
||||
catch (PluginNotFoundException $ex) {
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\node\Plugin\migrate;
|
||||
|
||||
use Drupal\migrate\Plugin\Migration;
|
||||
use Drupal\migrate_drupal\Plugin\MigrationWithFollowUpInterface;
|
||||
|
||||
/**
|
||||
* Migration plugin for the Drupal 7 node translations.
|
||||
*/
|
||||
class D7NodeTranslation extends Migration implements MigrationWithFollowUpInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function generateFollowUpMigrations() {
|
||||
$this->migrationPluginManager->clearCachedDefinitions();
|
||||
return $this->migrationPluginManager->createInstances('d7_entity_reference_translation');
|
||||
}
|
||||
|
||||
}
|
|
@ -15,7 +15,9 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
* Drupal 6 node source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_node"
|
||||
* id = "d6_node",
|
||||
* source_module = "node"
|
||||
*
|
||||
* )
|
||||
*/
|
||||
class Node extends DrupalSqlBase {
|
||||
|
@ -176,24 +178,24 @@ class Node extends DrupalSqlBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets CCK field values for a node.
|
||||
* Gets field values for a node.
|
||||
*
|
||||
* @param \Drupal\migrate\Row $node
|
||||
* The node.
|
||||
*
|
||||
* @return array
|
||||
* CCK field values, keyed by field name.
|
||||
* Field values, keyed by field name.
|
||||
*/
|
||||
protected function getFieldValues(Row $node) {
|
||||
$values = [];
|
||||
foreach ($this->getFieldInfo($node->getSourceProperty('type')) as $field => $info) {
|
||||
$values[$field] = $this->getCckData($info, $node);
|
||||
$values[$field] = $this->getFieldData($info, $node);
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets CCK field and instance definitions from the database.
|
||||
* Gets field and instance definitions from the database.
|
||||
*
|
||||
* @param string $node_type
|
||||
* The node type for which to get field info.
|
||||
|
@ -205,14 +207,14 @@ class Node extends DrupalSqlBase {
|
|||
if (!isset($this->fieldInfo)) {
|
||||
$this->fieldInfo = [];
|
||||
|
||||
// Query the database directly for all CCK field info.
|
||||
// Query the database directly for all field info.
|
||||
$query = $this->select('content_node_field_instance', 'cnfi');
|
||||
$query->join('content_node_field', 'cnf', 'cnf.field_name = cnfi.field_name');
|
||||
$query->fields('cnfi');
|
||||
$query->fields('cnf');
|
||||
|
||||
foreach ($query->execute() as $field) {
|
||||
$this->fieldInfo[ $field['type_name'] ][ $field['field_name'] ] = $field;
|
||||
$this->fieldInfo[$field['type_name']][$field['field_name']] = $field;
|
||||
}
|
||||
|
||||
foreach ($this->fieldInfo as $type => $fields) {
|
||||
|
@ -230,7 +232,7 @@ class Node extends DrupalSqlBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieves raw CCK field data for a node.
|
||||
* Retrieves raw field data for a node.
|
||||
*
|
||||
* @param array $field
|
||||
* A field and instance definition from getFieldInfo().
|
||||
|
@ -240,7 +242,7 @@ class Node extends DrupalSqlBase {
|
|||
* @return array
|
||||
* The field values, keyed by delta.
|
||||
*/
|
||||
protected function getCckData(array $field, Row $node) {
|
||||
protected function getFieldData(array $field, Row $node) {
|
||||
$field_table = 'content_' . $field['field_name'];
|
||||
$node_table = 'content_type_' . $node->getSourceProperty('type');
|
||||
|
||||
|
@ -276,10 +278,9 @@ class Node extends DrupalSqlBase {
|
|||
|
||||
return $query
|
||||
// This call to isNotNull() is a kludge which relies on the convention
|
||||
// that CCK field schemas usually define their most important
|
||||
// column first. A better way would be to allow cckfield plugins to
|
||||
// alter the query directly before it's run, but this will do for
|
||||
// the time being.
|
||||
// that field schemas usually define their most important column first.
|
||||
// A better way would be to allow field plugins to alter the query
|
||||
// directly before it's run, but this will do for the time being.
|
||||
->isNotNull($field['field_name'] . '_' . $columns[0])
|
||||
->condition('nid', $node->getSourceProperty('nid'))
|
||||
->condition('vid', $node->getSourceProperty('vid'))
|
||||
|
@ -291,6 +292,24 @@ class Node extends DrupalSqlBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves raw field data for a node.
|
||||
*
|
||||
* @deprecated in Drupal 8.2.x, to be removed in Drupal 9.0.x. Use
|
||||
* getFieldData() instead.
|
||||
*
|
||||
* @param array $field
|
||||
* A field and instance definition from getFieldInfo().
|
||||
* @param \Drupal\migrate\Row $node
|
||||
* The node.
|
||||
*
|
||||
* @return array
|
||||
* The field values, keyed by delta.
|
||||
*/
|
||||
protected function getCckData(array $field, Row $node) {
|
||||
return $this->getFieldData($field, $node);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\node\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Core\Database\Query\SelectInterface;
|
||||
|
||||
/**
|
||||
* Drupal 6 node revision source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_node_revision"
|
||||
* id = "d6_node_revision",
|
||||
* source_module = "node"
|
||||
* )
|
||||
*/
|
||||
class NodeRevision extends Node {
|
||||
|
|
|
@ -9,7 +9,8 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
|||
* Drupal 6 Node types source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_node_type"
|
||||
* id = "d6_node_type",
|
||||
* source_module = "node"
|
||||
* )
|
||||
*/
|
||||
class NodeType extends DrupalSqlBase {
|
||||
|
@ -62,7 +63,7 @@ class NodeType extends DrupalSqlBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
$fields = [
|
||||
'type' => $this->t('Machine name of the node type.'),
|
||||
'name' => $this->t('Human name of the node type.'),
|
||||
'module' => $this->t('The module providing the node type.'),
|
||||
|
@ -78,6 +79,28 @@ class NodeType extends DrupalSqlBase {
|
|||
'orig_type' => $this->t('The original type.'),
|
||||
'teaser_length' => $this->t('Teaser length'),
|
||||
];
|
||||
if ($this->moduleExists('comment')) {
|
||||
$fields += $this->getCommentFields();
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fields containing comment settings for each node type.
|
||||
*
|
||||
* @return string[]
|
||||
* An associative array of field descriptions, keyed by field.
|
||||
*/
|
||||
protected function getCommentFields() {
|
||||
return [
|
||||
'comment' => $this->t('Default comment setting'),
|
||||
'comment_default_mode' => $this->t('Default display mode'),
|
||||
'comment_default_per_page' => $this->t('Default comments per page'),
|
||||
'comment_anonymous' => $this->t('Anonymous commenting'),
|
||||
'comment_subject_field' => $this->t('Comment subject field'),
|
||||
'comment_preview' => $this->t('Preview comment'),
|
||||
'comment_form_location' => $this->t('Location of comment submission form'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,6 +134,13 @@ class NodeType extends DrupalSqlBase {
|
|||
$row->setSourceProperty('available_menus', [$default_node_menu]);
|
||||
$row->setSourceProperty('parent', $default_node_menu . ':');
|
||||
}
|
||||
|
||||
if ($this->moduleExists('comment')) {
|
||||
foreach (array_keys($this->getCommentFields()) as $field) {
|
||||
$row->setSourceProperty($field, $this->variableGet($field . '_' . $type, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Drupal\node\Plugin\migrate\source\d6;
|
|||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_view_mode",
|
||||
* source_provider = "content"
|
||||
* source_module = "content"
|
||||
* )
|
||||
*/
|
||||
class ViewMode extends ViewModeBase {
|
||||
|
|
|
@ -12,7 +12,7 @@ abstract class ViewModeBase extends DrupalSqlBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function count() {
|
||||
public function count($refresh = FALSE) {
|
||||
return count($this->initializeIterator());
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_node",
|
||||
* source_provider = "node"
|
||||
* source_module = "node"
|
||||
* )
|
||||
*/
|
||||
class Node extends FieldableEntity {
|
||||
|
@ -104,17 +104,40 @@ class Node extends FieldableEntity {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$nid = $row->getSourceProperty('nid');
|
||||
$vid = $row->getSourceProperty('vid');
|
||||
$type = $row->getSourceProperty('type');
|
||||
|
||||
// If this entity was translated using Entity Translation, we need to get
|
||||
// its source language to get the field values in the right language.
|
||||
// The translations will be migrated by the d7_node_entity_translation
|
||||
// migration.
|
||||
$entity_translatable = $this->isEntityTranslatable('node') && (int) $this->variableGet('language_content_type_' . $type, 0) === 4;
|
||||
$source_language = $this->getEntityTranslationSourceLanguage('node', $nid);
|
||||
$language = $entity_translatable && $source_language ? $source_language : $row->getSourceProperty('language');
|
||||
|
||||
// Get Field API field values.
|
||||
foreach (array_keys($this->getFields('node', $row->getSourceProperty('type'))) as $field) {
|
||||
$nid = $row->getSourceProperty('nid');
|
||||
$vid = $row->getSourceProperty('vid');
|
||||
$row->setSourceProperty($field, $this->getFieldValues('node', $field, $nid, $vid));
|
||||
foreach ($this->getFields('node', $type) as $field_name => $field) {
|
||||
// Ensure we're using the right language if the entity and the field are
|
||||
// translatable.
|
||||
$field_language = $entity_translatable && $field['translatable'] ? $language : NULL;
|
||||
$row->setSourceProperty($field_name, $this->getFieldValues('node', $field_name, $nid, $vid, $field_language));
|
||||
}
|
||||
|
||||
// Make sure we always have a translation set.
|
||||
if ($row->getSourceProperty('tnid') == 0) {
|
||||
$row->setSourceProperty('tnid', $row->getSourceProperty('nid'));
|
||||
}
|
||||
|
||||
// If the node title was replaced by a real field using the Drupal 7 Title
|
||||
// module, use the field value instead of the node title.
|
||||
if ($this->moduleExists('title')) {
|
||||
$title_field = $row->getSourceProperty('title_field');
|
||||
if (isset($title_field[0]['value'])) {
|
||||
$row->setSourceProperty('title', $title_field[0]['value']);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\node\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
|
||||
|
||||
/**
|
||||
* Provides Drupal 7 node entity translations source plugin.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_node_entity_translation",
|
||||
* source_module = "entity_translation"
|
||||
* )
|
||||
*/
|
||||
class NodeEntityTranslation extends FieldableEntity {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
$query = $this->select('entity_translation', 'et')
|
||||
->fields('et')
|
||||
->fields('n', [
|
||||
'title',
|
||||
'type',
|
||||
'promote',
|
||||
'sticky',
|
||||
])
|
||||
->fields('nr', [
|
||||
'log',
|
||||
'timestamp',
|
||||
])
|
||||
->condition('et.entity_type', 'node')
|
||||
->condition('et.source', '', '<>');
|
||||
|
||||
$query->addField('nr', 'uid', 'revision_uid');
|
||||
|
||||
$query->innerJoin('node', 'n', 'n.nid = et.entity_id');
|
||||
$query->innerJoin('node_revision', 'nr', 'nr.vid = et.revision_id');
|
||||
|
||||
if (isset($this->configuration['node_type'])) {
|
||||
$query->condition('n.type', $this->configuration['node_type']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$nid = $row->getSourceProperty('entity_id');
|
||||
$vid = $row->getSourceProperty('revision_id');
|
||||
$type = $row->getSourceProperty('type');
|
||||
$language = $row->getSourceProperty('language');
|
||||
|
||||
// Get Field API field values.
|
||||
foreach ($this->getFields('node', $type) as $field_name => $field) {
|
||||
// Ensure we're using the right language if the entity is translatable.
|
||||
$field_language = $field['translatable'] ? $language : NULL;
|
||||
$row->setSourceProperty($field_name, $this->getFieldValues('node', $field_name, $nid, $vid, $field_language));
|
||||
}
|
||||
|
||||
// If the node title was replaced by a real field using the Drupal 7 Title
|
||||
// module, use the field value instead of the node title.
|
||||
if ($this->moduleExists('title')) {
|
||||
$title_field = $row->getSourceProperty('title_field');
|
||||
if (isset($title_field[0]['value'])) {
|
||||
$row->setSourceProperty('title', $title_field[0]['value']);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'entity_type' => $this->t('The entity type this translation relates to'),
|
||||
'entity_id' => $this->t('The entity ID this translation relates to'),
|
||||
'revision_id' => $this->t('The entity revision ID this translation relates to'),
|
||||
'language' => $this->t('The target language for this translation.'),
|
||||
'source' => $this->t('The source language from which this translation was created.'),
|
||||
'uid' => $this->t('The author of this translation.'),
|
||||
'status' => $this->t('Boolean indicating whether the translation is published (visible to non-administrators).'),
|
||||
'translate' => $this->t('A boolean indicating whether this translation needs to be updated.'),
|
||||
'created' => $this->t('The Unix timestamp when the translation was created.'),
|
||||
'changed' => $this->t('The Unix timestamp when the translation was most recently saved.'),
|
||||
'title' => $this->t('Node title'),
|
||||
'type' => $this->t('Node type'),
|
||||
'promote' => $this->t('Promoted to front page'),
|
||||
'sticky' => $this->t('Sticky at top of lists'),
|
||||
'log' => $this->t('Revision log'),
|
||||
'timestamp' => $this->t('The timestamp the latest revision of this node was created.'),
|
||||
'revision_uid' => $this->t('Revision authored by (uid)'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
return [
|
||||
'entity_id' => [
|
||||
'type' => 'integer',
|
||||
'alias' => 'et',
|
||||
],
|
||||
'language' => [
|
||||
'type' => 'string',
|
||||
'alias' => 'et',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -7,7 +7,7 @@ namespace Drupal\node\Plugin\migrate\source\d7;
|
|||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_node_revision",
|
||||
* source_provider = "node"
|
||||
* source_module = "node"
|
||||
* )
|
||||
*/
|
||||
class NodeRevision extends Node {
|
||||
|
|
|
@ -10,7 +10,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
|||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_node_type",
|
||||
* source_provider = "node"
|
||||
* source_module = "node"
|
||||
* )
|
||||
*/
|
||||
class NodeType extends DrupalSqlBase {
|
||||
|
@ -54,6 +54,28 @@ class NodeType extends DrupalSqlBase {
|
|||
'orig_type' => $this->t('The original type.'),
|
||||
'teaser_length' => $this->t('Teaser length'),
|
||||
];
|
||||
if ($this->moduleExists('comment')) {
|
||||
$fields += $this->getCommentFields();
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fields containing comment settings for each node type.
|
||||
*
|
||||
* @return string[]
|
||||
* An associative array of field descriptions, keyed by field.
|
||||
*/
|
||||
protected function getCommentFields() {
|
||||
return [
|
||||
'comment' => $this->t('Default comment setting'),
|
||||
'comment_default_mode' => $this->t('Default display mode'),
|
||||
'comment_default_per_page' => $this->t('Default comments per page'),
|
||||
'comment_anonymous' => $this->t('Anonymous commenting'),
|
||||
'comment_subject_field' => $this->t('Comment subject field'),
|
||||
'comment_preview' => $this->t('Preview comment'),
|
||||
'comment_form_location' => $this->t('Location of comment submission form'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,6 +129,13 @@ class NodeType extends DrupalSqlBase {
|
|||
if ($parent = $this->variableGet('menu_parent_' . $type, NULL)) {
|
||||
$row->setSourceProperty('parent', $parent . ':');
|
||||
}
|
||||
|
||||
if ($this->moduleExists('comment')) {
|
||||
foreach (array_keys($this->getCommentFields()) as $field) {
|
||||
$row->setSourceProperty($field, $this->variableGet($field . '_' . $type, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ class Nid extends NumericArgument {
|
|||
* The plugin_id for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param NodeStorageInterface $node_storage
|
||||
* @param \Drupal\node\NodeStorageInterface $node_storage
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, NodeStorageInterface $node_storage) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
|
|
@ -29,7 +29,7 @@ class Type extends StringArgument {
|
|||
* The plugin_id for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $node_type_storage
|
||||
* The entity storage class.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityStorageInterface $node_type_storage) {
|
||||
|
|
|
@ -29,7 +29,7 @@ class Vid extends NumericArgument {
|
|||
protected $nodeStorage;
|
||||
|
||||
/**
|
||||
* Constructs a Drupal\Component\Plugin\PluginBase object.
|
||||
* Constructs a \Drupal\node\Plugin\views\argument\Vid object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Drupal\node\Plugin\views\field;
|
||||
|
||||
use Drupal\system\Plugin\views\field\BulkForm;
|
||||
use Drupal\views\Plugin\views\field\BulkForm;
|
||||
|
||||
/**
|
||||
* Defines a node operations bulk form element.
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Drupal\node\Plugin\views\field;
|
||||
|
||||
@trigger_error('Drupal\node\Plugin\views\field\Path is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Use @ViewsField("entity_link") with \'output_url_as_text\' set.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\views\Plugin\views\field\FieldPluginBase;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
|
@ -14,6 +16,9 @@ use Drupal\views\ViewExecutable;
|
|||
* @ingroup views_field_handlers
|
||||
*
|
||||
* @ViewsField("node_path")
|
||||
*
|
||||
* @deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0.
|
||||
* Use @ViewsField("entity_link") with 'output_url_as_text' set.
|
||||
*/
|
||||
class Path extends FieldPluginBase {
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -14,8 +15,10 @@ use Drupal\views\Plugin\views\filter\FilterPluginBase;
|
|||
*/
|
||||
class Access extends FilterPluginBase {
|
||||
|
||||
public function adminSummary() { }
|
||||
protected function operatorForm(&$form, FormStateInterface $form_state) { }
|
||||
public function adminSummary() {}
|
||||
|
||||
protected function operatorForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
public function canExpose() {
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -27,10 +30,10 @@ class Access extends FilterPluginBase {
|
|||
$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)
|
||||
);
|
||||
|
|
|
@ -14,11 +14,13 @@ use Drupal\views\Plugin\views\filter\FilterPluginBase;
|
|||
*/
|
||||
class Status extends FilterPluginBase {
|
||||
|
||||
public function adminSummary() { }
|
||||
public function adminSummary() {}
|
||||
|
||||
protected function operatorForm(&$form, FormStateInterface $form_state) { }
|
||||
protected function operatorForm(&$form, FormStateInterface $form_state) {}
|
||||
|
||||
public function canExpose() { return FALSE; }
|
||||
public function canExpose() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
public function query() {
|
||||
$table = $this->ensureMyTable();
|
||||
|
|
|
@ -22,23 +22,11 @@ class Node extends WizardPluginBase {
|
|||
|
||||
/**
|
||||
* Set the created column.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $createdColumn = 'node_field_data-created';
|
||||
|
||||
/**
|
||||
* Set default values for the filters.
|
||||
*/
|
||||
protected $filters = [
|
||||
'status' => [
|
||||
'value' => TRUE,
|
||||
'table' => 'node_field_data',
|
||||
'field' => 'status',
|
||||
'plugin_id' => 'boolean',
|
||||
'entity_type' => 'node',
|
||||
'entity_field' => 'status',
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* Overrides Drupal\views\Plugin\views\wizard\WizardPluginBase::getAvailableSorts().
|
||||
*
|
||||
|
@ -49,7 +37,7 @@ class Node extends WizardPluginBase {
|
|||
public function getAvailableSorts() {
|
||||
// You can't execute functions in properties, so override the method
|
||||
return [
|
||||
'node_field_data-title:ASC' => $this->t('Title')
|
||||
'node_field_data-title:ASC' => $this->t('Title'),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue