updated contrib modules : pathauto, token, entity_api, search_api, redirect, features

This commit is contained in:
2018-09-12 15:05:44 +02:00
parent b8e8cc8cee
commit a4746432c7
281 changed files with 4839 additions and 2453 deletions
@@ -6,5 +6,12 @@
"require": { "require": {
"drupal/config_update": "^1.4" "drupal/config_update": "^1.4"
}, },
"type": "drupal-module" "type": "drupal-module",
"extra": {
"drush": {
"services": {
"drush.services.yml": "^9"
}
}
}
} }
@@ -6,6 +6,7 @@
*/ */
use Drupal\features\ConfigurationItem; use Drupal\features\ConfigurationItem;
use Drupal\features\FeaturesBundleInterface;
use Drupal\features\FeaturesManagerInterface; use Drupal\features\FeaturesManagerInterface;
use Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationWrite; use Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationWrite;
use Drupal\Component\Diff\DiffFormatter; use Drupal\Component\Diff\DiffFormatter;
@@ -14,118 +15,118 @@ use Drupal\Component\Diff\DiffFormatter;
* Implements hook_drush_command(). * Implements hook_drush_command().
*/ */
function features_drush_command() { function features_drush_command() {
$items = array(); $items = [];
$items['features-status'] = array( $items['features-status'] = [
'description' => 'Display current Features settings.', 'description' => 'Display current Features settings.',
'aliases' => array('fs'), 'aliases' => ['fs'],
); ];
$items['features-list-packages'] = array( $items['features-list-packages'] = [
'description' => 'Display a list of all existing features and packages available to be generated. If a package name is provided as an argument, then all of the configuration objects assigned to that package will be listed.', 'description' => 'Display a list of all existing features and packages available to be generated. If a package name is provided as an argument, then all of the configuration objects assigned to that package will be listed.',
'examples' => array( 'examples' => [
"drush features-list-packages" => 'Display a list of all existing featurea and packages available to be generated.', "drush features-list-packages" => 'Display a list of all existing featurea and packages available to be generated.',
"drush features-list-packages 'example_article'" => "Display a list of all configuration objects assigned to the 'example_article' package.", "drush features-list-packages 'example_article'" => "Display a list of all configuration objects assigned to the 'example_article' package.",
), ],
'arguments' => array( 'arguments' => [
'package' => 'The package to list. Optional; if specified, lists all configuration objects assigned to that package. If no package is specified, lists all of the features.', 'package' => 'The package to list. Optional; if specified, lists all configuration objects assigned to that package. If no package is specified, lists all of the features.',
), ],
'outputformat' => array( 'outputformat' => [
'default' => 'table', 'default' => 'table',
'pipe-format' => 'list', 'pipe-format' => 'list',
'field-labels' => array( 'field-labels' => [
'name' => 'Name', 'name' => 'Name',
'machine_name' => 'Machine name', 'machine_name' => 'Machine name',
'status' => 'Status', 'status' => 'Status',
'version' => 'Version', 'version' => 'Version',
'state' => 'State', 'state' => 'State',
'object' => 'Configuration object', 'object' => 'Configuration object',
), ],
'output-data-type' => 'format-table', 'output-data-type' => 'format-table',
), ],
'aliases' => array('fl'), 'aliases' => ['fl'],
); ];
$items['features-import-all'] = array( $items['features-import-all'] = [
'description' => 'Import module config from all installed features.', 'description' => 'Import module config from all installed features.',
'examples' => array( 'examples' => [
"drush features-import-all" => 'Import module config from all installed features.', "drush features-import-all" => 'Import module config from all installed features.',
), ],
'aliases' => array('fra', 'fia', 'fim-all'), 'aliases' => ['fra', 'fia', 'fim-all'],
); ];
$items['features-export'] = array( $items['features-export'] = [
'description' => "Export the configuration on your site into a custom module.", 'description' => "Export the configuration on your site into a custom module.",
'arguments' => array( 'arguments' => [
'package' => 'A space delimited list of features to export.', 'package' => 'A space delimited list of features to export.',
), ],
'options' => array( 'options' => [
'add-profile' => 'Package features into an install profile.', 'add-profile' => 'Package features into an install profile.',
), ],
'examples' => array( 'examples' => [
"drush features-export" => 'Export all available packages.', "drush features-export" => 'Export all available packages.',
"drush features-export example_article example_page" => "Export the example_article and example_page packages.", "drush features-export example_article example_page" => "Export the example_article and example_page packages.",
"drush features-export --add-profile" => "Export all available packages and add them to an install profile.", "drush features-export --add-profile" => "Export all available packages and add them to an install profile.",
), ],
// Add previous "fu" alias for compatibility. // Add previous "fu" alias for compatibility.
'aliases' => array('fex', 'fu', 'fua', 'fu-all'), 'aliases' => ['fex', 'fu', 'fua', 'fu-all'],
); ];
$items['features-add'] = array( $items['features-add'] = [
'description' => "Add a config item to a feature package.", 'description' => "Add a config item to a feature package.",
'arguments' => array( 'arguments' => [
'feature' => 'Feature package to export and add config to.', 'feature' => 'Feature package to export and add config to.',
'components' => 'Patterns of config to add, see features-components for the format of patterns.', 'components' => 'Patterns of config to add, see features-components for the format of patterns.',
), ],
'aliases' => array('fa', 'fe'), 'aliases' => ['fa', 'fe'],
); ];
$items['features-components'] = array( $items['features-components'] = [
'description' => 'List features components.', 'description' => 'List features components.',
'arguments' => array( 'arguments' => [
'patterns' => 'The features components type to list. Omit this argument to list all components.', 'patterns' => 'The features components type to list. Omit this argument to list all components.',
), ],
'options' => array( 'options' => [
'exported' => array( 'exported' => [
'description' => 'Show only components that have been exported.', 'description' => 'Show only components that have been exported.',
), ],
'not-exported' => array( 'not-exported' => [
'description' => 'Show only components that have not been exported.', 'description' => 'Show only components that have not been exported.',
), ],
), ],
'aliases' => array('fc'), 'aliases' => ['fc'],
); ];
$items['features-diff'] = array( $items['features-diff'] = [
'description' => "Show the difference between the active config and the default config stored in a feature package.", 'description' => "Show the difference between the active config and the default config stored in a feature package.",
'arguments' => array( 'arguments' => [
'feature' => 'The feature in question.', 'feature' => 'The feature in question.',
), ],
'options' => array( 'options' => [
'ctypes' => 'Comma separated list of component types to limit the output to. Defaults to all types.', 'ctypes' => 'Comma separated list of component types to limit the output to. Defaults to all types.',
'lines' => 'Generate diffs with <n> lines of context instead of the usual two.', 'lines' => 'Generate diffs with <n> lines of context instead of the usual two.',
), ],
'aliases' => array('fd'), 'aliases' => ['fd'],
); ];
$items['features-import'] = array( $items['features-import'] = [
'description' => "Import a module config into your site.", 'description' => "Import a module config into your site.",
'arguments' => array( 'arguments' => [
'feature' => 'A space delimited list of features or feature:component pairs to import.', 'feature' => 'A space delimited list of features or feature:component pairs to import.',
), ],
'options' => array( 'options' => [
'force' => "Force import even if config is not overridden.", 'force' => "Force import even if config is not overridden.",
), ],
'examples' => array( 'examples' => [
'drush features-import foo:node.type.page foo:taxonomy.vocabulary.tags bar' => 'Import node and taxonomy config of feature "foo". Import all config of feature "bar".', 'drush features-import foo:node.type.page foo:taxonomy.vocabulary.tags bar' => 'Import node and taxonomy config of feature "foo". Import all config of feature "bar".',
), ],
'aliases' => array('fim', 'fr'), 'aliases' => ['fim', 'fr'],
); ];
foreach ($items as $name => &$item) { foreach ($items as $name => &$item) {
$item['options']['bundle'] = array( $item['options']['bundle'] = [
'description' => 'Use a specific bundle namespace.', 'description' => 'Use a specific bundle namespace.',
); ];
} }
return $items; return $items;
@@ -145,7 +146,7 @@ function _drush_features_options() {
if (!empty($bundle_name)) { if (!empty($bundle_name)) {
$bundle = $assigner->applyBundle($bundle_name); $bundle = $assigner->applyBundle($bundle_name);
if ($bundle->getMachineName() != $bundle_name) { if ($bundle->getMachineName() != $bundle_name) {
drush_log(dt('Bundle @name not found. Using default.', array('@name' => $bundle_name)), 'warning'); drush_log(dt('Bundle @name not found. Using default.', ['@name' => $bundle_name]), 'warning');
} }
} }
else { else {
@@ -172,13 +173,13 @@ function drush_features_status() {
} }
else { else {
drush_print(dt('Current bundle: @name (@machine_name)', drush_print(dt('Current bundle: @name (@machine_name)',
array( [
'@name' => $current_bundle->getName(), '@name' => $current_bundle->getName(),
'@machine_name' => $current_bundle->getMachineName(), '@machine_name' => $current_bundle->getMachineName(),
))); ]));
} }
drush_print(dt('Export folder: @folder', array('@folder' => $export_settings['folder']))); drush_print(dt('Export folder: @folder', ['@folder' => $export_settings['folder']]));
$dt_args = array('@methods' => implode(', ', array_keys($methods))); $dt_args = ['@methods' => implode(', ', array_keys($methods))];
drush_print(dt('The following assignment methods are enabled:')); drush_print(dt('The following assignment methods are enabled:'));
drush_print(dt(' @methods', $dt_args)); drush_print(dt(' @methods', $dt_args));
@@ -204,18 +205,18 @@ function drush_features_status() {
function drush_features_list_packages($package_name = '') { function drush_features_list_packages($package_name = '') {
$assigner = _drush_features_options(); $assigner = _drush_features_options();
$current_bundle = $assigner->getBundle(); $current_bundle = $assigner->getBundle();
$namespace = $current_bundle->isDefault() ? '' : $current_bundle->getMachineName(); $namespace = $current_bundle->isDefault() ? FeaturesBundleInterface::DEFAULT_BUNDLE : $current_bundle->getMachineName();
/** @var \Drupal\features\FeaturesManagerInterface $manager */ /** @var \Drupal\features\FeaturesManagerInterface $manager */
$manager = \Drupal::service('features.manager'); $manager = \Drupal::service('features.manager');
$packages = $manager->getPackages(); $packages = $manager->getPackages();
$packages = $manager->filterPackages($packages, $namespace); $packages = $manager->filterPackages($packages, $namespace);
$result = array(); $result = [];
// If no package was specified, list all packages. // If no package was specified, list all packages.
if (empty($package_name)) { if (empty($package_name)) {
drush_hide_output_fields(array('object')); drush_hide_output_fields(['object']);
foreach ($packages as $package) { foreach ($packages as $package) {
$overrides = $manager->detectOverrides($package); $overrides = $manager->detectOverrides($package);
$state = $package->getState(); $state = $package->getState();
@@ -223,7 +224,7 @@ function drush_features_list_packages($package_name = '') {
$state = FeaturesManagerInterface::STATE_OVERRIDDEN; $state = FeaturesManagerInterface::STATE_OVERRIDDEN;
} }
$result[$package->getMachineName()] = array( $result[$package->getMachineName()] = [
'name' => $package->getName(), 'name' => $package->getName(),
'machine_name' => $package->getMachineName(), 'machine_name' => $package->getMachineName(),
'status' => $manager->statusLabel($package->getStatus()), 'status' => $manager->statusLabel($package->getStatus()),
@@ -231,7 +232,7 @@ function drush_features_list_packages($package_name = '') {
'state' => ($state != FeaturesManagerInterface::STATE_DEFAULT) 'state' => ($state != FeaturesManagerInterface::STATE_DEFAULT)
? $manager->stateLabel($state) ? $manager->stateLabel($state)
: '', : '',
); ];
} }
return $result; return $result;
} }
@@ -239,17 +240,17 @@ function drush_features_list_packages($package_name = '') {
else { else {
foreach ($packages as $package) { foreach ($packages as $package) {
if ($package->getMachineName() == $package_name) { if ($package->getMachineName() == $package_name) {
drush_hide_output_fields(array( drush_hide_output_fields([
'machine_name', 'machine_name',
'name', 'name',
'status', 'status',
'version', 'version',
'state', 'state',
)); ]);
foreach ($package->getConfig() as $item_name) { foreach ($package->getConfig() as $item_name) {
$result[$item_name] = array( $result[$item_name] = [
'object' => $item_name, 'object' => $item_name,
); ];
} }
return $result; return $result;
} }
@@ -258,7 +259,7 @@ function drush_features_list_packages($package_name = '') {
} }
// If no matching package found, return an error. // If no matching package found, return an error.
drush_log(dt('Package "@package" not found.', array('@package' => $package_name)), 'warning'); drush_log(dt('Package "@package" not found.', ['@package' => $package_name]), 'warning');
return FALSE; return FALSE;
} }
@@ -269,13 +270,13 @@ function drush_features_list_packages($package_name = '') {
function drush_features_import_all() { function drush_features_import_all() {
$assigner = _drush_features_options(); $assigner = _drush_features_options();
$current_bundle = $assigner->getBundle(); $current_bundle = $assigner->getBundle();
$namespace = $current_bundle->isDefault() ? '' : $current_bundle->getMachineName(); $namespace = $current_bundle->isDefault() ? FeaturesBundleInterface::DEFAULT_BUNDLE : $current_bundle->getMachineName();
/** @var \Drupal\features\FeaturesManagerInterface $manager */ /** @var \Drupal\features\FeaturesManagerInterface $manager */
$manager = \Drupal::service('features.manager'); $manager = \Drupal::service('features.manager');
$packages = $manager->getPackages(); $packages = $manager->getPackages();
$packages = $manager->filterPackages($packages, $namespace); $packages = $manager->filterPackages($packages, $namespace);
$overridden = array(); $overridden = [];
foreach ($packages as $package) { foreach ($packages as $package) {
$overrides = $manager->detectOverrides($package); $overrides = $manager->detectOverrides($package);
@@ -317,13 +318,13 @@ function drush_features_export($packages = NULL) {
$all_packages = $manager->getPackages(); $all_packages = $manager->getPackages();
foreach ($packages as $name) { foreach ($packages as $name) {
if (!isset($all_packages[$name])) { if (!isset($all_packages[$name])) {
return drush_set_error('', dt("The package @name does not exist.", array('@name' => $name))); return drush_set_error('', dt("The package @name does not exist.", ['@name' => $name]));
} }
} }
if (empty($packages)) { if (empty($packages)) {
$packages = $all_packages; $packages = $all_packages;
$dt_args = array('@modules' => implode(', ', array_keys($packages))); $dt_args = ['@modules' => implode(', ', array_keys($packages))];
drush_print(dt('The following extensions will be exported: @modules', $dt_args)); drush_print(dt('The following extensions will be exported: @modules', $dt_args));
if (!drush_confirm(dt('Do you really want to continue?'))) { if (!drush_confirm(dt('Do you really want to continue?'))) {
return drush_user_abort('Aborting.'); return drush_user_abort('Aborting.');
@@ -333,7 +334,7 @@ function drush_features_export($packages = NULL) {
// If any packages exist, confirm before overwriting. // If any packages exist, confirm before overwriting.
if ($existing_packages = $manager->listPackageDirectories($packages, $current_bundle)) { if ($existing_packages = $manager->listPackageDirectories($packages, $current_bundle)) {
foreach ($existing_packages as $name => $directory) { foreach ($existing_packages as $name => $directory) {
drush_print(dt("The extension @name already exists at @directory.", array('@name' => $name, '@directory' => $directory))); drush_print(dt("The extension @name already exists at @directory.", ['@name' => $name, '@directory' => $directory]));
} }
// Apparently, format_plural is not always available. // Apparently, format_plural is not always available.
if (count($existing_packages) == 1) { if (count($existing_packages) == 1) {
@@ -379,9 +380,9 @@ function drush_features_add() {
return drush_set_error('', 'No components supplied.'); return drush_set_error('', 'No components supplied.');
} }
$components = _drush_features_component_list(); $components = _drush_features_component_list();
$options = array( $options = [
'exported' => FALSE, 'exported' => FALSE,
); ];
$filtered_components = _drush_features_component_filter($components, $args, $options); $filtered_components = _drush_features_component_filter($components, $args, $options);
$items = $filtered_components['components']; $items = $filtered_components['components'];
@@ -390,11 +391,11 @@ function drush_features_add() {
return drush_set_error('', 'No components to add.'); return drush_set_error('', 'No components to add.');
} }
$packages = array($module); $packages = [$module];
// If any packages exist, confirm before overwriting. // If any packages exist, confirm before overwriting.
if ($existing_packages = $manager->listPackageDirectories($packages)) { if ($existing_packages = $manager->listPackageDirectories($packages)) {
foreach ($existing_packages as $name => $directory) { foreach ($existing_packages as $name => $directory) {
drush_print(dt("The extension @name already exists at @directory.", array('@name' => $name, '@directory' => $directory))); drush_print(dt("The extension @name already exists at @directory.", ['@name' => $name, '@directory' => $directory]));
} }
// Apparently, format_plural is not always available. // Apparently, format_plural is not always available.
if (count($existing_packages) == 1) { if (count($existing_packages) == 1) {
@@ -410,7 +411,7 @@ function drush_features_add() {
else { else {
$package = $manager->initPackage($module, NULL, '', 'module', $current_bundle); $package = $manager->initPackage($module, NULL, '', 'module', $current_bundle);
list($full_name, $path) = $manager->getExportInfo($package, $current_bundle); list($full_name, $path) = $manager->getExportInfo($package, $current_bundle);
drush_print(dt('Will create a new extension @name in @directory', array('@name' => $full_name, '@directory' => $path))); drush_print(dt('Will create a new extension @name in @directory', ['@name' => $full_name, '@directory' => $path]));
if (!drush_confirm(dt('Do you really want to continue?'))) { if (!drush_confirm(dt('Do you really want to continue?'))) {
drush_die('Aborting.'); drush_die('Aborting.');
} }
@@ -452,15 +453,15 @@ function drush_features_components() {
return; return;
} }
$args = ($choice == 0) ? array('*') : array($types[$choice]); $args = ($choice == 0) ? ['*'] : [$types[$choice]];
} }
$options = array( $options = [
'provided by' => TRUE, 'provided by' => TRUE,
); ];
if (drush_get_option(array('exported', 'e'), NULL)) { if (drush_get_option(['exported', 'e'], NULL)) {
$options['not exported'] = FALSE; $options['not exported'] = FALSE;
} }
elseif (drush_get_option(array('not-exported', 'o'), NULL)) { elseif (drush_get_option(['not-exported', 'o'], NULL)) {
$options['exported'] = FALSE; $options['exported'] = FALSE;
} }
@@ -496,7 +497,7 @@ function drush_features_diff() {
$feature = $manager->loadPackage($module, TRUE); $feature = $manager->loadPackage($module, TRUE);
if (empty($feature)) { if (empty($feature)) {
drush_log(dt('No such feature is available: @module', array('@module' => $module)), 'error'); drush_log(dt('No such feature is available: @module', ['@module' => $module]), 'error');
return; return;
} }
@@ -521,7 +522,7 @@ function drush_features_diff() {
$overrides = array_merge($overrides, $missing); $overrides = array_merge($overrides, $missing);
if (empty($overrides)) { if (empty($overrides)) {
drush_print(dt('Active config matches stored config for @module.', array('@module' => $module))); drush_print(dt('Active config matches stored config for @module.', ['@module' => $module]));
} }
else { else {
/** @var \Drupal\config_update\ConfigDiffInterface $config_diff */ /** @var \Drupal\config_update\ConfigDiffInterface $config_diff */
@@ -538,20 +539,20 @@ function drush_features_diff() {
$message = ''; $message = '';
if (in_array($name, $missing)) { if (in_array($name, $missing)) {
$message = sprintf($red, t('(missing from active)')); $message = sprintf($red, t('(missing from active)'));
$extension = array(); $extension = [];
} }
else { else {
$active = $manager->getActiveStorage()->read($name); $active = $manager->getActiveStorage()->read($name);
$extension = $manager->getExtensionStorages()->read($name); $extension = $manager->getExtensionStorages()->read($name);
if (empty($extension)) { if (empty($extension)) {
$extension = array(); $extension = [];
$message = sprintf($green, t('(not exported)')); $message = sprintf($green, t('(not exported)'));
} }
$diff = $config_diff->diff($extension, $active); $diff = $config_diff->diff($extension, $active);
$rows = explode("\n", $formatter->format($diff)); $rows = explode("\n", $formatter->format($diff));
} }
drush_print(); drush_print();
drush_print(dt("Config @name @message", array('@name' => $name, '@message' => $message))); drush_print(dt("Config @name @message", ['@name' => $name, '@message' => $message]));
if (!empty($extension)) { if (!empty($extension)) {
foreach ($rows as $row) { foreach ($rows as $row) {
if (strpos($row, '>') === 0) { if (strpos($row, '>') === 0) {
@@ -588,7 +589,7 @@ function drush_features_import() {
$manager = \Drupal::service('features.manager'); $manager = \Drupal::service('features.manager');
// Parse list of arguments. // Parse list of arguments.
$modules = array(); $modules = [];
foreach ($args as $arg) { foreach ($args as $arg) {
$arg = explode(':', $arg); $arg = explode(':', $arg);
$module = array_shift($arg); $module = array_shift($arg);
@@ -602,7 +603,7 @@ function drush_features_import() {
} }
elseif ($modules[$module] !== TRUE) { elseif ($modules[$module] !== TRUE) {
if (!isset($modules[$module])) { if (!isset($modules[$module])) {
$modules[$module] = array(); $modules[$module] = [];
} }
$modules[$module][] = $component; $modules[$module][] = $component;
} }
@@ -692,7 +693,7 @@ function drush_features_import() {
function _drush_features_build_config(array $items) { function _drush_features_build_config(array $items) {
/** @var \Drupal\features\FeaturesManagerInterface $manager */ /** @var \Drupal\features\FeaturesManagerInterface $manager */
$manager = \Drupal::service('features.manager'); $manager = \Drupal::service('features.manager');
$result = array(); $result = [];
foreach ($items as $config_type => $item) { foreach ($items as $config_type => $item) {
foreach ($item as $item_name => $title) { foreach ($item as $item_name => $title) {
$result[] = $manager->getFullName($config_type, $item_name); $result[] = $manager->getFullName($config_type, $item_name);
@@ -705,7 +706,7 @@ function _drush_features_build_config(array $items) {
* Returns a listing of all known components, indexed by source. * Returns a listing of all known components, indexed by source.
*/ */
function _drush_features_component_list() { function _drush_features_component_list() {
$result = array(); $result = [];
/** @var \Drupal\features\FeaturesManagerInterface $manager */ /** @var \Drupal\features\FeaturesManagerInterface $manager */
$manager = \Drupal::service('features.manager'); $manager = \Drupal::service('features.manager');
$config = $manager->getConfigCollection(); $config = $manager->getConfigCollection();
@@ -718,13 +719,13 @@ function _drush_features_component_list() {
/** /**
* Filters components by patterns. * Filters components by patterns.
*/ */
function _drush_features_component_filter($all_components, $patterns = array(), $options = array()) { function _drush_features_component_filter($all_components, $patterns = [], $options = []) {
$options += array( $options += [
'exported' => TRUE, 'exported' => TRUE,
'not exported' => TRUE, 'not exported' => TRUE,
'provided by' => FALSE, 'provided by' => FALSE,
); ];
$pool = array(); $pool = [];
// Maps exported components to feature modules. // Maps exported components to feature modules.
$components_map = _drush_features_get_component_map(); $components_map = _drush_features_get_component_map();
// First filter on exported state. // First filter on exported state.
@@ -753,11 +754,11 @@ function _drush_features_component_filter($all_components, $patterns = array(),
$state_string = 'exported'; $state_string = 'exported';
} }
$selected = array(); $selected = [];
foreach ($patterns as $pattern) { foreach ($patterns as $pattern) {
// Rewrite * to %. Let users use both as wildcard. // Rewrite * to %. Let users use both as wildcard.
$pattern = strtr($pattern, array('*' => '%')); $pattern = strtr($pattern, ['*' => '%']);
$sources = array(); $sources = [];
list($source_pattern, $component_pattern) = explode(':', $pattern, 2); list($source_pattern, $component_pattern) = explode(':', $pattern, 2);
// If source is empty, use a pattern. // If source is empty, use a pattern.
if ($source_pattern == '') { if ($source_pattern == '') {
@@ -767,8 +768,8 @@ function _drush_features_component_filter($all_components, $patterns = array(),
$component_pattern = '%'; $component_pattern = '%';
} }
$preg_source_pattern = strtr(preg_quote($source_pattern, '/'), array('%' => '.*')); $preg_source_pattern = strtr(preg_quote($source_pattern, '/'), ['%' => '.*']);
$preg_component_pattern = strtr(preg_quote($component_pattern, '/'), array('%' => '.*')); $preg_component_pattern = strtr(preg_quote($component_pattern, '/'), ['%' => '.*']);
// If it isn't a pattern, but a simple string, we don't anchor the // If it isn't a pattern, but a simple string, we don't anchor the
// pattern. This allows for abbreviating. Otherwise, we do, as this seems // pattern. This allows for abbreviating. Otherwise, we do, as this seems
// more natural for patterns. // more natural for patterns.
@@ -778,7 +779,7 @@ function _drush_features_component_filter($all_components, $patterns = array(),
if (strpos($component_pattern, '%') !== FALSE) { if (strpos($component_pattern, '%') !== FALSE) {
$preg_component_pattern = '^' . $preg_component_pattern . '$'; $preg_component_pattern = '^' . $preg_component_pattern . '$';
} }
$matches = array(); $matches = [];
// Find the sources. // Find the sources.
$all_sources = array_keys($pool); $all_sources = array_keys($pool);
@@ -789,20 +790,20 @@ function _drush_features_component_filter($all_components, $patterns = array(),
// use that, or error out. // use that, or error out.
if (count($matches) > 1 and $preg_source_pattern[0] != '^') { if (count($matches) > 1 and $preg_source_pattern[0] != '^') {
if (in_array($source_pattern, $matches)) { if (in_array($source_pattern, $matches)) {
$matches = array($source_pattern); $matches = [$source_pattern];
} }
else { else {
return drush_set_error('', dt('Ambiguous source "@source", matches @matches', array( return drush_set_error('', dt('Ambiguous source "@source", matches @matches', [
'@source' => $source_pattern, '@source' => $source_pattern,
'@matches' => implode(', ', $matches), '@matches' => implode(', ', $matches),
))); ]));
} }
} }
// Loose the indexes preg_grep preserved. // Loose the indexes preg_grep preserved.
$sources = array_values($matches); $sources = array_values($matches);
} }
else { else {
return drush_set_error('', dt('No @state sources match "@source"', array('@state' => $state_string, '@source' => $source_pattern))); return drush_set_error('', dt('No @state sources match "@source"', ['@state' => $state_string, '@source' => $source_pattern]));
} }
// Now find the components. // Now find the components.
@@ -817,17 +818,17 @@ function _drush_features_component_filter($all_components, $patterns = array(),
// use that, or error out. // use that, or error out.
if (count($matches) > 1 and $preg_component_pattern[0] != '^') { if (count($matches) > 1 and $preg_component_pattern[0] != '^') {
if (in_array($component_pattern, $matches)) { if (in_array($component_pattern, $matches)) {
$matches = array($component_pattern); $matches = [$component_pattern];
} }
else { else {
return drush_set_error('', dt('Ambiguous component "@component", matches @matches', array( return drush_set_error('', dt('Ambiguous component "@component", matches @matches', [
'@component' => $component_pattern, '@component' => $component_pattern,
'@matches' => implode(', ', $matches), '@matches' => implode(', ', $matches),
))); ]));
} }
} }
if (!is_array($selected[$source])) { if (!is_array($selected[$source])) {
$selected[$source] = array(); $selected[$source] = [];
} }
$selected[$source] += array_intersect_key($pool[$source], array_flip($matches)); $selected[$source] += array_intersect_key($pool[$source], array_flip($matches));
} }
@@ -835,11 +836,11 @@ function _drush_features_component_filter($all_components, $patterns = array(),
// No matches. If the source was a pattern, just carry on, else // No matches. If the source was a pattern, just carry on, else
// error out. Allows for patterns like :*field* // error out. Allows for patterns like :*field*
if ($preg_source_pattern[0] != '^') { if ($preg_source_pattern[0] != '^') {
return drush_set_error('', dt('No @state @source components match "@component"', array( return drush_set_error('', dt('No @state @source components match "@component"', [
'@state' => $state_string, '@state' => $state_string,
'@component' => $component_pattern, '@component' => $component_pattern,
'@source' => $source, '@source' => $source,
))); ]));
} }
} }
} }
@@ -847,7 +848,7 @@ function _drush_features_component_filter($all_components, $patterns = array(),
// Lastly, provide feature module information on the selected components, if // Lastly, provide feature module information on the selected components, if
// requested. // requested.
$provided_by = array(); $provided_by = [];
if ($options['provided by'] && $options['exported']) { if ($options['provided by'] && $options['exported']) {
foreach ($selected as $source => $components) { foreach ($selected as $source => $components) {
foreach ($components as $name => $title) { foreach ($components as $name => $title) {
@@ -859,17 +860,17 @@ function _drush_features_component_filter($all_components, $patterns = array(),
} }
} }
return array( return [
'components' => $selected, 'components' => $selected,
'sources' => $provided_by, 'sources' => $provided_by,
); ];
} }
/** /**
* Provides a component to feature map (port of features_get_component_map). * Provides a component to feature map (port of features_get_component_map).
*/ */
function _drush_features_get_component_map() { function _drush_features_get_component_map() {
$result = array(); $result = [];
/** @var \Drupal\features\FeaturesManagerInterface $manager */ /** @var \Drupal\features\FeaturesManagerInterface $manager */
$manager = \Drupal::service('features.manager'); $manager = \Drupal::service('features.manager');
// Recalc full config list without running assignments. // Recalc full config list without running assignments.
@@ -881,7 +882,7 @@ function _drush_features_get_component_map() {
$short_name = $item->getShortName(); $short_name = $item->getShortName();
$name = $item->getName(); $name = $item->getName();
if (!isset($result[$type][$short_name])) { if (!isset($result[$type][$short_name])) {
$result[$type][$short_name] = array(); $result[$type][$short_name] = [];
} }
if (!empty($item->getPackage())) { if (!empty($item->getPackage())) {
$package = $packages[$item->getPackage()]; $package = $packages[$item->getPackage()];
@@ -896,10 +897,10 @@ function _drush_features_get_component_map() {
* Prints a list of filtered components. * Prints a list of filtered components.
*/ */
function _drush_features_component_print($filtered_components) { function _drush_features_component_print($filtered_components) {
$rows = array(array(dt('Available sources'))); $rows = [[dt('Available sources')]];
foreach ($filtered_components['components'] as $source => $components) { foreach ($filtered_components['components'] as $source => $components) {
foreach ($components as $name => $value) { foreach ($components as $name => $value) {
$row = array($source . ':' . $name); $row = [$source . ':' . $name];
if (isset($filtered_components['sources'][$source . ':' . $name])) { if (isset($filtered_components['sources'][$source . ':' . $name])) {
$row[] = dt('Provided by') . ': ' . $filtered_components['sources'][$source . ':' . $name]; $row[] = dt('Provided by') . ': ' . $filtered_components['sources'][$source . ':' . $name];
} }
@@ -4,11 +4,11 @@ description: 'Enables administrators to package configuration into modules.'
package: Development package: Development
# core: 8.x # core: 8.x
dependencies: dependencies:
- config - drupal:config
- config_update - config_update:config_update
# Information added by Drupal.org packaging script on 2018-02-27 # Information added by Drupal.org packaging script on 2018-09-09
version: '8.x-3.7' version: '8.x-3.8'
core: '8.x' core: '8.x'
project: 'features' project: 'features'
datestamp: 1519763291 datestamp: 1536512288
@@ -15,9 +15,9 @@ function features_help($route_name, RouteMatchInterface $route_match) {
case 'help.page.features': case 'help.page.features':
$output = ''; $output = '';
$output .= '<h3>' . t('About') . '</h3>'; $output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Features module provides a user interface for exporting bundles of configuration into modules. For more information, see the online documentation for <a href=":url">Features module</a>', array( $output .= '<p>' . t('The Features module provides a user interface for exporting bundles of configuration into modules. For more information, see the online documentation for <a href=":url">Features module</a>', [
':url' => 'http://drupal.org/node/2404427', ':url' => 'http://drupal.org/node/2404427',
)) . '</p>'; ]) . '</p>';
return $output; return $output;
} }
} }
@@ -37,9 +37,9 @@ function features_file_download($uri) {
// "export configuration" permission, token is validated by the controller. // "export configuration" permission, token is validated by the controller.
// @see \Drupal\features\Controller\FeaturesController::downloadExport() // @see \Drupal\features\Controller\FeaturesController::downloadExport()
if ($route == 'features.export_download') { if ($route == 'features.export_download') {
return array( return [
'Content-disposition' => 'attachment; filename="' . $target . '"', 'Content-disposition' => 'attachment; filename="' . $target . '"',
); ];
} }
} }
} }
@@ -143,8 +143,7 @@ span.features-component-list span {
margin-right:5px; margin-right:5px;
padding:2px 5px; padding:2px 5px;
background:#eee; background:#eee;
-moz-border-radius:5px; border-radius:5px;
-webkit-border-radius:5px;
} }
div.features-export-empty { div.features-export-empty {
@@ -172,8 +171,7 @@ span.features-component-list .features-dependency {
display: inline-block; display: inline-block;
background: transparent; background: transparent;
border: 1px solid #DDD; border: 1px solid #DDD;
-moz-border-radius: 5px; border-radius: 5px;
-webkit-border-radius: 5px;
white-space: nowrap; white-space: nowrap;
padding: 0 8px; padding: 0 8px;
margin: 0 10px 0 0; margin: 0 10px 0 0;
@@ -238,8 +236,7 @@ span.features-component-list .features-dependency {
padding: 0 5px; padding: 0 5px;
background: transparent; background: transparent;
background: #EEE; background: #EEE;
-moz-border-radius: 5px; border-radius: 5px;
-webkit-border-radius: 5px;
cursor: pointer; cursor: pointer;
} }
#features-filter span:hover { #features-filter span:hover {
@@ -23,60 +23,60 @@ function theme_features_listing(array $variables) {
$renderer = \Drupal::service('renderer'); $renderer = \Drupal::service('renderer');
// Individual table headers. // Individual table headers.
$rows = array(); $rows = [];
// Iterate through all the features, which are children of this element. // Iterate through all the features, which are children of this element.
foreach (Element::children($form) as $key) { foreach (Element::children($form) as $key) {
// Stick the key into $module for easier access. // Stick the key into $module for easier access.
$element = $form[$key]; $element = $form[$key];
// Create the row for the table. // Create the row for the table.
$row = array(); $row = [];
// Add the checkbox into the first cell. // Add the checkbox into the first cell.
unset($element['enable']['#title']); unset($element['enable']['#title']);
$row[] = array('class' => array('checkbox'), 'data' => $renderer->render($element['enable'])); $row[] = ['class' => ['checkbox'], 'data' => $renderer->render($element['enable'])];
// Add the module label and expand/collapse functionalty. // Add the module label and expand/collapse functionalty.
$id = Html::getUniqueId('feature-' . $key); $id = Html::getUniqueId('feature-' . $key);
$col2 = new FormattableMarkup('<label id="@id" for="@for" class="module-name table-filter-text-source">@name</label>', $col2 = new FormattableMarkup('<label id="@id" for="@for" class="module-name table-filter-text-source">@name</label>',
array( [
'@id' => $id, '@id' => $id,
'@for' => $element['enable']['#id'], '@for' => $element['enable']['#id'],
'@name' => $renderer->render($element['name']), '@name' => $renderer->render($element['name']),
) ]
); );
$row[] = array('class' => array('module'), 'data' => $col2); $row[] = ['class' => ['module'], 'data' => $col2];
$row[] = array('class' => array('machine_name'), 'data' => $renderer->render($element['machine_name'])); $row[] = ['class' => ['machine_name'], 'data' => $renderer->render($element['machine_name'])];
$description = t('@details', array('@details' => $renderer->render($element['details']))); $description = t('@details', ['@details' => $renderer->render($element['details'])]);
$details = array( $details = [
'#type' => 'details', '#type' => 'details',
'#title' => new FormattableMarkup('<span class="text">@desc</span>', array( '@desc' => $renderer->render($element['description']))), '#title' => new FormattableMarkup('<span class="text">@desc</span>', [ '@desc' => $renderer->render($element['description'])]),
'#attributes' => array('id' => $element['enable']['#id'] . '-description'), '#attributes' => ['id' => $element['enable']['#id'] . '-description'],
'#description' => $description, '#description' => $description,
); ];
$row[] = array( $row[] = [
'class' => array('description', 'expand'), 'class' => ['description', 'expand'],
'data' => $renderer->render($details), 'data' => $renderer->render($details),
); ];
$row[] = array( $row[] = [
'class' => array('feature-version'), 'class' => ['feature-version'],
'data' => $renderer->render($element['version']), 'data' => $renderer->render($element['version']),
); ];
$row[] = array( $row[] = [
'class' => array('feature-state'), 'class' => ['feature-state'],
'data' => $renderer->render($element['state']), 'data' => $renderer->render($element['state']),
); ];
$rows[] = array('data' => $row); $rows[] = ['data' => $row];
} }
$table = array( $table = [
'#type' => 'tableselect', '#type' => 'tableselect',
'#header' => $form['#header'], '#header' => $form['#header'],
'#options' => $rows, '#options' => $rows,
'#empty' => t('No Features packages available.'), '#empty' => t('No Features packages available.'),
); ];
return $renderer->render($table); return $renderer->render($table);
} }
@@ -90,31 +90,31 @@ function theme_features_listing(array $variables) {
function template_preprocess_features_assignment_configure_form(&$variables) { function template_preprocess_features_assignment_configure_form(&$variables) {
$form =& $variables['form']; $form =& $variables['form'];
$header = array( $header = [
t('Assignment method'), t('Assignment method'),
t('Description'), t('Description'),
t('Enabled'), t('Enabled'),
t('Weight'), t('Weight'),
); ];
// If there is at least one operation enabled, show the operation column. // If there is at least one operation enabled, show the operation column.
if ($form['#show_operations']) { if ($form['#show_operations']) {
$header[] = t('Operations'); $header[] = t('Operations');
} }
$table = array( $table = [
'#type' => 'table', '#type' => 'table',
'#weight' => 5, '#weight' => 5,
'#header' => $header, '#header' => $header,
'#attributes' => array('id' => 'features-assignment-methods'), '#attributes' => ['id' => 'features-assignment-methods'],
'#tabledrag' => array( '#tabledrag' => [
array( [
'action' => 'order', 'action' => 'order',
'relationship' => 'sibling', 'relationship' => 'sibling',
'group' => 'assignment-method-weight', 'group' => 'assignment-method-weight',
), ],
), ],
); ];
foreach ($form['title'] as $id => $element) { foreach ($form['title'] as $id => $element) {
// Do not take form control structures. // Do not take form control structures.
@@ -122,11 +122,11 @@ function template_preprocess_features_assignment_configure_form(&$variables) {
$table[$id]['#attributes']['class'][] = 'draggable'; $table[$id]['#attributes']['class'][] = 'draggable';
$table[$id]['#weight'] = $element['#weight']; $table[$id]['#weight'] = $element['#weight'];
$table[$id]['title'] = array( $table[$id]['title'] = [
'#prefix' => '<strong>', '#prefix' => '<strong>',
$form['title'][$id], $form['title'][$id],
'#suffix' => '</strong>', '#suffix' => '</strong>',
); ];
$table[$id]['description'] = $form['description'][$id]; $table[$id]['description'] = $form['description'][$id];
$table[$id]['enabled'] = $form['enabled'][$id]; $table[$id]['enabled'] = $form['enabled'][$id];
$table[$id]['weight'] = $form['weight'][$id]; $table[$id]['weight'] = $form['weight'][$id];
@@ -157,7 +157,7 @@ function template_preprocess_features_assignment_configure_form(&$variables) {
function theme_features_items(array $variables) { function theme_features_items(array $variables) {
$items = $variables['items']; $items = $variables['items'];
$list = array(); $list = [];
foreach ($items as $item) { foreach ($items as $item) {
$class = !empty($item['class']) ? $item['class'] : ''; $class = !empty($item['class']) ? $item['class'] : '';
$list[] = '<span class="features-item ' . $class . '" title="' . $item['name'] . '">' . $item['label'] . '</span>'; $list[] = '<span class="features-item ' . $class . '" title="' . $item['name'] . '">' . $item['label'] . '</span>';
@@ -5,10 +5,10 @@ package: Development
# core: 8.x # core: 8.x
configure: features.assignment configure: features.assignment
dependencies: dependencies:
- features - features:features
# Information added by Drupal.org packaging script on 2018-02-27 # Information added by Drupal.org packaging script on 2018-09-09
version: '8.x-3.7' version: '8.x-3.8'
core: '8.x' core: '8.x'
project: 'features' project: 'features'
datestamp: 1519763291 datestamp: 1536512288
@@ -14,10 +14,10 @@ function features_ui_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) { switch ($route_name) {
case 'features.assignment': case 'features.assignment':
$output = ''; $output = '';
$output .= '<p>' . t('Bundles are used to collect together groups of features. A bundle provides a shared <a href=":namespace">namespace</a> for all features included in it, which prevents conflicts and helps distinguish your features from those produced for other purposes. Common uses of bundles include:', array(':namespace' => 'http://en.wikipedia.org/wiki/Namespace')); $output .= '<p>' . t('Bundles are used to collect together groups of features. A bundle provides a shared <a href=":namespace">namespace</a> for all features included in it, which prevents conflicts and helps distinguish your features from those produced for other purposes. Common uses of bundles include:', [':namespace' => 'http://en.wikipedia.org/wiki/Namespace']);
$output .= '<ul>'; $output .= '<ul>';
$output .= '<li>' . t('Custom features for use on a particular site.') . '</li>'; $output .= '<li>' . t('Custom features for use on a particular site.') . '</li>';
$output .= '<li>' . t('The features of a given <a href=":distributions">distribution</a>.', array(':distributions' => 'https://www.drupal.org/documentation/build/distributions')) . '</li>'; $output .= '<li>' . t('The features of a given <a href=":distributions">distribution</a>.', [':distributions' => 'https://www.drupal.org/documentation/build/distributions']) . '</li>';
$output .= '</ul></p>'; $output .= '</ul></p>';
$output .= '<p>' . t('Use the form below to manage bundles. Each bundle comes with a set of assignment methods. By configuring and ordering the assignment methods, you can set the defaults for what does and doesn\'t get packaged into features for your bundle. Use the <em>Bundle</em> select to choose which bundle to edit, or chose <em>--New--</em> to create a new bundle. The <em>Default</em> bundle does not include a namespace and cannot be deleted.') . '</p>'; $output .= '<p>' . t('Use the form below to manage bundles. Each bundle comes with a set of assignment methods. By configuring and ordering the assignment methods, you can set the defaults for what does and doesn\'t get packaged into features for your bundle. Use the <em>Bundle</em> select to choose which bundle to edit, or chose <em>--New--</em> to create a new bundle. The <em>Default</em> bundle does not include a namespace and cannot be deleted.') . '</p>';
return $output; return $output;
@@ -33,23 +33,23 @@ function features_ui_help($route_name, RouteMatchInterface $route_match) {
* Implements hook_theme(). * Implements hook_theme().
*/ */
function features_ui_theme() { function features_ui_theme() {
return array( return [
'features_listing' => array( 'features_listing' => [
'render element' => 'form', 'render element' => 'form',
'file' => 'features_ui.admin.inc', 'file' => 'features_ui.admin.inc',
'function' => 'theme_features_listing', 'function' => 'theme_features_listing',
), ],
'features_assignment_configure_form' => array( 'features_assignment_configure_form' => [
'render element' => 'form', 'render element' => 'form',
'file' => 'features_ui.admin.inc', 'file' => 'features_ui.admin.inc',
'function' => 'theme_assignment_form', 'function' => 'theme_assignment_form',
), ],
'features_items' => array( 'features_items' => [
'variables' => array( 'variables' => [
'items' => array(), 'items' => [],
), ],
'file' => 'features_ui.admin.inc', 'file' => 'features_ui.admin.inc',
'function' => 'theme_features_items', 'function' => 'theme_features_items',
), ],
); ];
} }
@@ -58,14 +58,14 @@ class FeaturesUIController implements ContainerInjectionInterface {
* List of auto-detected config items, keyed by type and short name. * List of auto-detected config items, keyed by type and short name.
*/ */
public function detect($name) { public function detect($name) {
$detected = array(); $detected = [];
$this->assigner->assignConfigPackages(); $this->assigner->assignConfigPackages();
$config_collection = $this->featuresManager->getConfigCollection(); $config_collection = $this->featuresManager->getConfigCollection();
$items = $_POST['items']; $items = $_POST['items'];
if (!empty($items)) { if (!empty($items)) {
$excluded = (!empty($_POST['excluded'])) ? $_POST['excluded'] : array(); $excluded = (!empty($_POST['excluded'])) ? $_POST['excluded'] : [];
$selected = array(); $selected = [];
foreach ($items as $key) { foreach ($items as $key) {
preg_match('/^([^\[]+)(\[.+\])?\[(.+)\]\[(.+)\]$/', $key, $matches); preg_match('/^([^\[]+)(\[.+\])?\[(.+)\]\[(.+)\]$/', $key, $matches);
if (!empty($matches[1]) && !empty($matches[4])) { if (!empty($matches[1]) && !empty($matches[4])) {
@@ -76,7 +76,7 @@ class FeaturesUIController implements ContainerInjectionInterface {
} }
} }
} }
$detected = !empty($selected) ? $this->getConfigDependents($selected, $name) : array(); $detected = !empty($selected) ? $this->getConfigDependents($selected, $name) : [];
$detected = array_merge($detected, $selected); $detected = array_merge($detected, $selected);
} }
@@ -112,7 +112,7 @@ class FeaturesUIController implements ContainerInjectionInterface {
// Add any existing auto-detected items already in the package config // Add any existing auto-detected items already in the package config
$this->package = $packages[$package_name]; $this->package = $packages[$package_name];
$package_config = isset($this->package) ? $this->package->getConfig() : array(); $package_config = isset($this->package) ? $this->package->getConfig() : [];
$package_config = !empty($package_config) ? array_unique(array_merge($package_config, $item_names)) : $item_names; $package_config = !empty($package_config) ? array_unique(array_merge($package_config, $item_names)) : $item_names;
foreach ($package_config as $config_name) { foreach ($package_config as $config_name) {
if (!$config_collection[$config_name]->getPackageExcluded()) { if (!$config_collection[$config_name]->getPackageExcluded()) {
@@ -177,7 +177,7 @@ class FeaturesUIController implements ContainerInjectionInterface {
* An encoding map. * An encoding map.
*/ */
protected function domEncodeMap() { protected function domEncodeMap() {
return array( return [
':' => '__' . ord(':') . '__', ':' => '__' . ord(':') . '__',
'/' => '__' . ord('/') . '__', '/' => '__' . ord('/') . '__',
',' => '__' . ord(',') . '__', ',' => '__' . ord(',') . '__',
@@ -187,7 +187,7 @@ class FeaturesUIController implements ContainerInjectionInterface {
'%' => '__' . ord('%') . '__', '%' => '__' . ord('%') . '__',
')' => '__' . ord(')') . '__', ')' => '__' . ord(')') . '__',
'(' => '__' . ord('(') . '__', '(' => '__' . ord('(') . '__',
); ];
} }
} }
@@ -29,26 +29,26 @@ class AssignmentAlterForm extends AssignmentFormBase {
$uuid_setting = $settings['uuid']; $uuid_setting = $settings['uuid'];
$user_permissions_setting = $settings['user_permissions']; $user_permissions_setting = $settings['user_permissions'];
$form['core'] = array( $form['core'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Strip out <em>_core</em> property.'), '#title' => $this->t('Strip out <em>_core</em> property.'),
'#default_value' => $core_setting, '#default_value' => $core_setting,
'#description' => $this->t('Select this option to remove the <em>_core</em> configuration property on export. This property is added by Drupal core when configuration is installed.'), '#description' => $this->t('Select this option to remove the <em>_core</em> configuration property on export. This property is added by Drupal core when configuration is installed.'),
); ];
$form['uuid'] = array( $form['uuid'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Strip out <em>uuid</em> property.'), '#title' => $this->t('Strip out <em>uuid</em> property.'),
'#default_value' => $uuid_setting, '#default_value' => $uuid_setting,
'#description' => $this->t('Select this option to remove the <em>uuid</em> configuration property on export. This property is added by Drupal core when configuration is installed.'), '#description' => $this->t('Select this option to remove the <em>uuid</em> configuration property on export. This property is added by Drupal core when configuration is installed.'),
); ];
$form['user_permissions'] = array( $form['user_permissions'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Strip out user permissions.'), '#title' => $this->t('Strip out user permissions.'),
'#default_value' => $user_permissions_setting, '#default_value' => $user_permissions_setting,
'#description' => $this->t('Select this option to remove permissions from user roles on export.'), '#description' => $this->t('Select this option to remove permissions from user roles on export.'),
); ];
$this->setActions($form, self::METHOD_ID); $this->setActions($form, self::METHOD_ID);
@@ -132,7 +132,7 @@ class AssignmentConfigureForm extends FormBase {
$load_values = TRUE; $load_values = TRUE;
} }
elseif ($trigger['#name'] == 'bundle[bundle_select]') { elseif ($trigger['#name'] == 'bundle[bundle_select]') {
$bundle_name = $form_state->getValue(array('bundle', 'bundle_select')); $bundle_name = $form_state->getValue(['bundle', 'bundle_select']);
if ($bundle_name != self::NEW_BUNDLE_SELECT_VALUE) { if ($bundle_name != self::NEW_BUNDLE_SELECT_VALUE) {
$this->assigner->setCurrent($this->assigner->getBundle($bundle_name)); $this->assigner->setCurrent($this->assigner->getBundle($bundle_name));
} }
@@ -142,7 +142,7 @@ class AssignmentConfigureForm extends FormBase {
$current_bundle = $this->assigner->loadBundle($bundle_name); $current_bundle = $this->assigner->loadBundle($bundle_name);
$bundle_name = $current_bundle->getMachineName(); $bundle_name = $current_bundle->getMachineName();
$this->assigner->removeBundle($bundle_name); $this->assigner->removeBundle($bundle_name);
return $this->redirect('features.assignment', array('')); return $this->redirect('features.assignment', ['']);
} }
if (!isset($current_bundle)) { if (!isset($current_bundle)) {
switch ($bundle_name) { switch ($bundle_name) {
@@ -177,28 +177,28 @@ class AssignmentConfigureForm extends FormBase {
$this->loadBundleValues($bundle_name, $form_state, $current_bundle, $enabled_methods, $methods_weight); $this->loadBundleValues($bundle_name, $form_state, $current_bundle, $enabled_methods, $methods_weight);
} }
$form = array( $form = [
'#attached' => array( '#attached' => [
'library' => array( 'library' => [
// Provides the copyFieldValue behavior invoked below. // Provides the copyFieldValue behavior invoked below.
'system/drupal.system', 'system/drupal.system',
'features_ui/drupal.features_ui.admin', 'features_ui/drupal.features_ui.admin',
), ],
), ],
// '#attributes' => array('class' => 'edit-bundles-wrapper'), // '#attributes' => array('class' => 'edit-bundles-wrapper'),
'#tree' => TRUE, '#tree' => TRUE,
'#show_operations' => FALSE, '#show_operations' => FALSE,
'weight' => array('#tree' => TRUE), 'weight' => ['#tree' => TRUE],
'#prefix' => '<div id="edit-bundles-wrapper">', '#prefix' => '<div id="edit-bundles-wrapper">',
'#suffix' => '</div>', '#suffix' => '</div>',
); ];
$form['bundle'] = array( $form['bundle'] = [
'#type' => 'fieldset', '#type' => 'fieldset',
'#title' => $this->t('Bundle'), '#title' => $this->t('Bundle'),
'#tree' => TRUE, '#tree' => TRUE,
'#weight' => -9, '#weight' => -9,
); ];
if ($bundle_name == self::NEW_BUNDLE_SELECT_VALUE) { if ($bundle_name == self::NEW_BUNDLE_SELECT_VALUE) {
$default_values = [ $default_values = [
@@ -220,86 +220,86 @@ class AssignmentConfigureForm extends FormBase {
'profile_name' => $current_bundle->getProfileName(), 'profile_name' => $current_bundle->getProfileName(),
]; ];
} }
$form['bundle']['bundle_select'] = array( $form['bundle']['bundle_select'] = [
'#title' => $this->t('Bundle'), '#title' => $this->t('Bundle'),
'#title_display' => 'invisible', '#title_display' => 'invisible',
'#type' => 'select', '#type' => 'select',
'#options' => [self::NEW_BUNDLE_SELECT_VALUE => $this->t('--New--')] + $this->assigner->getBundleOptions(), '#options' => [self::NEW_BUNDLE_SELECT_VALUE => $this->t('--New--')] + $this->assigner->getBundleOptions(),
'#default_value' => $default_values['bundle_select'], '#default_value' => $default_values['bundle_select'],
'#ajax' => array( '#ajax' => [
'callback' => '::updateForm', 'callback' => '::updateForm',
'wrapper' => 'edit-bundles-wrapper', 'wrapper' => 'edit-bundles-wrapper',
), ],
); ];
// Don't show the remove button for the default bundle or when adding a new // Don't show the remove button for the default bundle or when adding a new
// bundle. // bundle.
if ($bundle_name != self::NEW_BUNDLE_SELECT_VALUE && !$current_bundle->isDefault()) { if ($bundle_name != self::NEW_BUNDLE_SELECT_VALUE && !$current_bundle->isDefault()) {
$form['bundle']['remove'] = array( $form['bundle']['remove'] = [
'#type' => 'button', '#type' => 'button',
'#name' => 'removebundle', '#name' => 'removebundle',
'#value' => $this->t('Remove bundle'), '#value' => $this->t('Remove bundle'),
); ];
} }
$form['bundle']['name'] = array( $form['bundle']['name'] = [
'#title' => $this->t('Bundle name'), '#title' => $this->t('Bundle name'),
'#type' => 'textfield', '#type' => 'textfield',
'#description' => $this->t('A unique human-readable name of this bundle.'), '#description' => $this->t('A unique human-readable name of this bundle.'),
'#default_value' => $default_values['name'], '#default_value' => $default_values['name'],
'#required' => TRUE, '#required' => TRUE,
'#disabled' => $bundle_name == FeaturesBundleInterface::DEFAULT_BUNDLE, '#disabled' => $bundle_name == FeaturesBundleInterface::DEFAULT_BUNDLE,
); ];
// Don't allow changing the default bundle machine name. // Don't allow changing the default bundle machine name.
if ($bundle_name == FeaturesBundleInterface::DEFAULT_BUNDLE) { if ($bundle_name == FeaturesBundleInterface::DEFAULT_BUNDLE) {
$form['bundle']['machine_name'] = array( $form['bundle']['machine_name'] = [
'#type' => 'value', '#type' => 'value',
'#value' => $default_values['machine_name'], '#value' => $default_values['machine_name'],
); ];
} }
else { else {
$form['bundle']['machine_name'] = array( $form['bundle']['machine_name'] = [
'#title' => $this->t('Machine name'), '#title' => $this->t('Machine name'),
'#type' => 'machine_name', '#type' => 'machine_name',
'#required' => TRUE, '#required' => TRUE,
'#default_value' => $default_values['machine_name'], '#default_value' => $default_values['machine_name'],
'#description' => $this->t('A unique machine-readable name of this bundle. Used to prefix exported packages. It must only contain lowercase letters, numbers, and underscores.'), '#description' => $this->t('A unique machine-readable name of this bundle. Used to prefix exported packages. It must only contain lowercase letters, numbers, and underscores.'),
'#machine_name' => array( '#machine_name' => [
'source' => array('bundle', 'name'), 'source' => ['bundle', 'name'],
'exists' => array($this, 'bundleExists'), 'exists' => [$this, 'bundleExists'],
), ],
); ];
} }
$form['bundle']['description'] = array( $form['bundle']['description'] = [
'#title' => $this->t('Distribution description'), '#title' => $this->t('Distribution description'),
'#type' => 'textfield', '#type' => 'textfield',
'#default_value' => $default_values['description'], '#default_value' => $default_values['description'],
'#description' => $this->t('A description of the bundle.'), '#description' => $this->t('A description of the bundle.'),
'#size' => 80, '#size' => 80,
); ];
$form['bundle']['is_profile'] = array( $form['bundle']['is_profile'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Include install profile'), '#title' => $this->t('Include install profile'),
'#default_value' => $default_values['is_profile'], '#default_value' => $default_values['is_profile'],
'#description' => $this->t('Select this option to have your features packaged into an install profile.'), '#description' => $this->t('Select this option to have your features packaged into an install profile.'),
'#attributes' => array( '#attributes' => [
'data-add-profile' => 'status', 'data-add-profile' => 'status',
), ],
); ];
$show_and_require_if_profile_checked = array( $show_and_require_if_profile_checked = [
'visible' => array( 'visible' => [
':input[data-add-profile="status"]' => array('checked' => TRUE), ':input[data-add-profile="status"]' => ['checked' => TRUE],
), ],
'required' => array( 'required' => [
':input[data-add-profile="status"]' => array('checked' => TRUE), ':input[data-add-profile="status"]' => ['checked' => TRUE],
), ],
); ];
$form['bundle']['profile_name'] = array( $form['bundle']['profile_name'] = [
'#title' => $this->t('Profile name'), '#title' => $this->t('Profile name'),
'#type' => 'textfield', '#type' => 'textfield',
'#default_value' => $default_values['profile_name'], '#default_value' => $default_values['profile_name'],
@@ -307,7 +307,7 @@ class AssignmentConfigureForm extends FormBase {
'#size' => 30, '#size' => 30,
// Show and require only if the profile.add option is selected. // Show and require only if the profile.add option is selected.
'#states' => $show_and_require_if_profile_checked, '#states' => $show_and_require_if_profile_checked,
); ];
// Attach the copyFieldValue behavior to the profile_name field. In // Attach the copyFieldValue behavior to the profile_name field. In
// practice this only works if a user tabs through the bundle machine name // practice this only works if a user tabs through the bundle machine name
@@ -327,48 +327,48 @@ class AssignmentConfigureForm extends FormBase {
$method_name = Html::escape($method['name']); $method_name = Html::escape($method['name']);
$form['weight'][$method_id] = array( $form['weight'][$method_id] = [
'#type' => 'weight', '#type' => 'weight',
'#title' => $this->t('Weight for @title package assignment method', array('@title' => Unicode::strtolower($method_name))), '#title' => $this->t('Weight for @title package assignment method', ['@title' => Unicode::strtolower($method_name)]),
'#title_display' => 'invisible', '#title_display' => 'invisible',
'#default_value' => $weight, '#default_value' => $weight,
'#attributes' => array('class' => array('assignment-method-weight')), '#attributes' => ['class' => ['assignment-method-weight']],
'#delta' => 20, '#delta' => 20,
); ];
$form['title'][$method_id] = array('#markup' => $method_name); $form['title'][$method_id] = ['#markup' => $method_name];
$form['enabled'][$method_id] = array( $form['enabled'][$method_id] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Enable @title package assignment method', array('@title' => Unicode::strtolower($method_name))), '#title' => $this->t('Enable @title package assignment method', ['@title' => Unicode::strtolower($method_name)]),
'#title_display' => 'invisible', '#title_display' => 'invisible',
'#default_value' => $enabled, '#default_value' => $enabled,
); ];
$form['description'][$method_id] = array('#markup' => $method['description']); $form['description'][$method_id] = ['#markup' => $method['description']];
$config_op = array(); $config_op = [];
if (isset($method['config_route_name'])) { if (isset($method['config_route_name'])) {
$config_op['configure'] = array( $config_op['configure'] = [
'title' => $this->t('Configure'), 'title' => $this->t('Configure'),
'url' => Url::fromRoute($method['config_route_name'], array('bundle_name' => $current_bundle->getMachineName())), 'url' => Url::fromRoute($method['config_route_name'], ['bundle_name' => $current_bundle->getMachineName()]),
); ];
// If there is at least one operation enabled, show the operation // If there is at least one operation enabled, show the operation
// column. // column.
$form['#show_operations'] = TRUE; $form['#show_operations'] = TRUE;
} }
$form['operation'][$method_id] = array( $form['operation'][$method_id] = [
'#type' => 'operations', '#type' => 'operations',
'#links' => $config_op, '#links' => $config_op,
); ];
} }
$form['actions'] = array('#type' => 'actions', '#weight' => 9); $form['actions'] = ['#type' => 'actions', '#weight' => 9];
$form['actions']['submit'] = array( $form['actions']['submit'] = [
'#type' => 'submit', '#type' => 'submit',
'#button_type' => 'primary', '#button_type' => 'primary',
'#value' => $this->t('Save settings'), '#value' => $this->t('Save settings'),
); ];
return $form; return $form;
} }
@@ -384,7 +384,7 @@ class AssignmentConfigureForm extends FormBase {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function validateForm(array &$form, FormStateInterface $form_state) { public function validateForm(array &$form, FormStateInterface $form_state) {
if ($form_state->getValue(array('bundle', 'is_profile')) && empty($form_state->getValue(array('bundle', 'profile_name')))) { if ($form_state->getValue(['bundle', 'is_profile']) && empty($form_state->getValue(['bundle', 'profile_name']))) {
$form_state->setErrorByName('bundle][profile_name', $this->t('To create a profile, please enter a profile name.')); $form_state->setErrorByName('bundle][profile_name', $this->t('To create a profile, please enter a profile name.'));
} }
@@ -400,28 +400,28 @@ class AssignmentConfigureForm extends FormBase {
$method_weights = $form_state->getValue('weight'); $method_weights = $form_state->getValue('weight');
ksort($method_weights); ksort($method_weights);
$machine_name = $form_state->getValue(array('bundle', 'machine_name')); $machine_name = $form_state->getValue(['bundle', 'machine_name']);
// If this is a new bundle, create it. // If this is a new bundle, create it.
if ($form_state->getValue(array('bundle', 'bundle_select')) == self::NEW_BUNDLE_SELECT_VALUE) { if ($form_state->getValue(['bundle', 'bundle_select']) == self::NEW_BUNDLE_SELECT_VALUE) {
$bundle = $this->assigner->createBundleFromDefault($machine_name); $bundle = $this->assigner->createBundleFromDefault($machine_name);
} }
// Otherwise, load the current bundle and rename if needed. // Otherwise, load the current bundle and rename if needed.
else { else {
$bundle = $this->assigner->loadBundle(); $bundle = $this->assigner->loadBundle();
$old_name = $bundle->getMachineName(); $old_name = $bundle->getMachineName();
$new_name = $form_state->getValue(array('bundle', 'machine_name')); $new_name = $form_state->getValue(['bundle', 'machine_name']);
if ($old_name != $new_name) { if ($old_name != $new_name) {
$bundle = $this->assigner->renameBundle($old_name, $new_name); $bundle = $this->assigner->renameBundle($old_name, $new_name);
} }
} }
$bundle->setName($form_state->getValue(array('bundle', 'name'))); $bundle->setName($form_state->getValue(['bundle', 'name']));
$bundle->setDescription($form_state->getValue(array('bundle', 'description'))); $bundle->setDescription($form_state->getValue(['bundle', 'description']));
$bundle->setEnabledAssignments(array_keys($enabled_methods)); $bundle->setEnabledAssignments(array_keys($enabled_methods));
$bundle->setAssignmentWeights($method_weights); $bundle->setAssignmentWeights($method_weights);
$bundle->setIsProfile($form_state->getValue(array('bundle', 'is_profile'))); $bundle->setIsProfile($form_state->getValue(['bundle', 'is_profile']));
$bundle->setProfileName($form_state->getValue(array('bundle', 'profile_name'))); $bundle->setProfileName($form_state->getValue(['bundle', 'profile_name']));
$bundle->save(); $bundle->save();
$this->assigner->setBundle($bundle); $this->assigner->setBundle($bundle);
$this->assigner->setCurrent($bundle); $this->assigner->setCurrent($bundle);
@@ -31,72 +31,72 @@ class AssignmentExcludeForm extends AssignmentFormBase {
$this->setConfigTypeSelect($form, $settings['types']['config'], $this->t('exclude'), FALSE, $this->setConfigTypeSelect($form, $settings['types']['config'], $this->t('exclude'), FALSE,
$this->t("Select types of configuration that should be excluded from packaging.")); $this->t("Select types of configuration that should be excluded from packaging."));
$form['curated'] = array( $form['curated'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Exclude designated site-specific configuration'), '#title' => $this->t('Exclude designated site-specific configuration'),
'#default_value' => $curated_settings, '#default_value' => $curated_settings,
'#description' => $this->t('Select this option to exclude a curated list of site-specific configuration from packaging.'), '#description' => $this->t('Select this option to exclude a curated list of site-specific configuration from packaging.'),
); ];
$form['module'] = array( $form['module'] = [
'#type' => 'fieldset', '#type' => 'fieldset',
'#tree' => TRUE, '#tree' => TRUE,
'#title' => $this->t('Exclude configuration provided by modules'), '#title' => $this->t('Exclude configuration provided by modules'),
); ];
$form['module']['installed'] = array( $form['module']['installed'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Exclude installed module-provided entity configuration'), '#title' => $this->t('Exclude installed module-provided entity configuration'),
'#default_value' => $module_settings['installed'], '#default_value' => $module_settings['installed'],
'#description' => $this->t('Select this option to exclude configuration provided by INSTALLED modules from reassignment.'), '#description' => $this->t('Select this option to exclude configuration provided by INSTALLED modules from reassignment.'),
'#attributes' => array( '#attributes' => [
'data-module-installed' => 'status', 'data-module-installed' => 'status',
), ],
); ];
$show_if_module_installed_checked = array( $show_if_module_installed_checked = [
'visible' => array( 'visible' => [
':input[data-module-installed="status"]' => array('checked' => TRUE), ':input[data-module-installed="status"]' => ['checked' => TRUE],
), ],
); ];
$info = system_get_info('module', drupal_get_profile()); $info = system_get_info('module', drupal_get_profile());
$form['module']['profile'] = array( $form['module']['profile'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t("Don't exclude install profile's configuration"), '#title' => $this->t("Don't exclude install profile's configuration"),
'#default_value' => $module_settings['profile'], '#default_value' => $module_settings['profile'],
'#description' => $this->t("Select this option to allow configuration provided by the site's install profile (%profile) to be reassigned.", array('%profile' => $info['name'])), '#description' => $this->t("Select this option to allow configuration provided by the site's install profile (%profile) to be reassigned.", ['%profile' => $info['name']]),
'#states' => $show_if_module_installed_checked, '#states' => $show_if_module_installed_checked,
); ];
$bundle_name = $this->currentBundle->getMachineName(); $bundle_name = $this->currentBundle->getMachineName();
$bundle_name = !empty($bundle_name) ? $bundle_name : $this->t('none'); $bundle_name = !empty($bundle_name) ? $bundle_name : $this->t('none');
$form['module']['namespace'] = array( $form['module']['namespace'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t("Don't exclude non-installed configuration by namespace"), '#title' => $this->t("Don't exclude non-installed configuration by namespace"),
'#default_value' => $module_settings['namespace'], '#default_value' => $module_settings['namespace'],
'#description' => $this->t("Select this option to allow configuration provided by uninstalled modules with the bundle namespace (%namespace_*) to be reassigned.", array('%namespace' => $bundle_name)), '#description' => $this->t("Select this option to allow configuration provided by uninstalled modules with the bundle namespace (%namespace_*) to be reassigned.", ['%namespace' => $bundle_name]),
'#states' => $show_if_module_installed_checked, '#states' => $show_if_module_installed_checked,
'#attributes' => array( '#attributes' => [
'data-namespace' => 'status', 'data-namespace' => 'status',
), ],
); ];
$show_if_namespace_checked = array( $show_if_namespace_checked = [
'visible' => array( 'visible' => [
':input[data-namespace="status"]' => array('checked' => TRUE), ':input[data-namespace="status"]' => ['checked' => TRUE],
':input[data-module-installed="status"]' => array('checked' => TRUE), ':input[data-module-installed="status"]' => ['checked' => TRUE],
), ],
); ];
$form['module']['namespace_any'] = array( $form['module']['namespace_any'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t("Don't exclude ANY configuration by namespace"), '#title' => $this->t("Don't exclude ANY configuration by namespace"),
'#default_value' => $module_settings['namespace_any'], '#default_value' => $module_settings['namespace_any'],
'#description' => $this->t("Select this option to allow configuration provided by ANY modules with the bundle namespace (%namespace_*) to be reassigned. '#description' => $this->t("Select this option to allow configuration provided by ANY modules with the bundle namespace (%namespace_*) to be reassigned.
Warning: Can cause installed configuration to be reassigned to different packages.", array('%namespace' => $bundle_name)), Warning: Can cause installed configuration to be reassigned to different packages.", ['%namespace' => $bundle_name]),
'#states' => $show_if_namespace_checked, '#states' => $show_if_namespace_checked,
); ];
$this->setActions($form, self::METHOD_ID); $this->setActions($form, self::METHOD_ID);
@@ -77,19 +77,19 @@ abstract class AssignmentFormBase extends FormBase {
$options = $this->featuresManager->listConfigTypes($bundles_only); $options = $this->featuresManager->listConfigTypes($bundles_only);
if (!isset($form['types'])) { if (!isset($form['types'])) {
$form['types'] = array( $form['types'] = [
'#type' => 'container', '#type' => 'container',
'#tree' => TRUE, '#tree' => TRUE,
); ];
} }
$form['types']['config'] = array( $form['types']['config'] = [
'#type' => 'checkboxes', '#type' => 'checkboxes',
'#title' => $this->t('Configuration types'), '#title' => $this->t('Configuration types'),
'#description' => !empty($description) ? $description : $this->t('Select types of configuration that should be considered @type types.', array('@type' => $type)), '#description' => !empty($description) ? $description : $this->t('Select types of configuration that should be considered @type types.', ['@type' => $type]),
'#options' => $options, '#options' => $options,
'#default_value' => $defaults, '#default_value' => $defaults,
); ];
} }
/** /**
@@ -98,13 +98,13 @@ abstract class AssignmentFormBase extends FormBase {
protected function setContentTypeSelect(&$form, $defaults, $type, $exclude_has_config_bundles = TRUE) { protected function setContentTypeSelect(&$form, $defaults, $type, $exclude_has_config_bundles = TRUE) {
$entity_types = $this->entityTypeManager->getDefinitions(); $entity_types = $this->entityTypeManager->getDefinitions();
$has_config_bundle = array(); $has_config_bundle = [];
foreach ($entity_types as $definition) { foreach ($entity_types as $definition) {
if ($entity_type_id = $definition->getBundleOf()) { if ($entity_type_id = $definition->getBundleOf()) {
$has_config_bundle[] = $entity_type_id; $has_config_bundle[] = $entity_type_id;
} }
} }
$options = array(); $options = [];
foreach ($entity_types as $entity_type_id => $entity_type) { foreach ($entity_types as $entity_type_id => $entity_type) {
if (!$entity_type instanceof ContentEntityTypeInterface) { if (!$entity_type instanceof ContentEntityTypeInterface) {
@@ -120,19 +120,19 @@ abstract class AssignmentFormBase extends FormBase {
uasort($options, 'strnatcasecmp'); uasort($options, 'strnatcasecmp');
if (!isset($form['types'])) { if (!isset($form['types'])) {
$form['types'] = array( $form['types'] = [
'#type' => 'container', '#type' => 'container',
'#tree' => TRUE, '#tree' => TRUE,
); ];
} }
$form['types']['content'] = array( $form['types']['content'] = [
'#type' => 'checkboxes', '#type' => 'checkboxes',
'#title' => $this->t('Content entity types'), '#title' => $this->t('Content entity types'),
'#description' => $this->t('Select content entity types that should be considered @type types.', array('@type' => $type)), '#description' => $this->t('Select content entity types that should be considered @type types.', ['@type' => $type]),
'#options' => $options, '#options' => $options,
'#default_value' => $defaults, '#default_value' => $defaults,
); ];
} }
/** /**
@@ -142,25 +142,25 @@ abstract class AssignmentFormBase extends FormBase {
$assignment_info = $this->assigner->getAssignmentMethods(); $assignment_info = $this->assigner->getAssignmentMethods();
if (isset($method_id) && isset($assignment_info[$method_id])) { if (isset($method_id) && isset($assignment_info[$method_id])) {
$method = $assignment_info[$method_id]; $method = $assignment_info[$method_id];
$form['help_text'] = array( $form['help_text'] = [
'#markup' => $method['description'], '#markup' => $method['description'],
'#prefix' => '<p class="messages messages--status">', '#prefix' => '<p class="messages messages--status">',
'#suffix' => '</p>', '#suffix' => '</p>',
'#weight' => -99, '#weight' => -99,
); ];
} }
$form['actions'] = array('#type' => 'actions'); $form['actions'] = ['#type' => 'actions'];
$form['actions']['submit'] = array( $form['actions']['submit'] = [
'#type' => 'submit', '#type' => 'submit',
'#button_type' => 'primary', '#button_type' => 'primary',
'#value' => $this->t('Save settings'), '#value' => $this->t('Save settings'),
); ];
$form['#attributes']['class'][] = 'features-assignment-settings-form'; $form['#attributes']['class'][] = 'features-assignment-settings-form';
$form['#attached'] = array( $form['#attached'] = [
'library' => array( 'library' => [
'features_ui/drupal.features_ui.admin', 'features_ui/drupal.features_ui.admin',
)); ]];
} }
/** /**
@@ -170,7 +170,7 @@ abstract class AssignmentFormBase extends FormBase {
* The form state. * The form state.
*/ */
protected function setRedirect(FormStateInterface $form_state) { protected function setRedirect(FormStateInterface $form_state) {
$form_state->setRedirect('features.assignment', array('bundle_name' => $this->currentBundle->getMachineName())); $form_state->setRedirect('features.assignment', ['bundle_name' => $this->currentBundle->getMachineName()]);
} }
} }
@@ -27,32 +27,32 @@ class AssignmentProfileForm extends AssignmentFormBase {
$this->setConfigTypeSelect($form, $settings['types']['config'], $this->t('profile')); $this->setConfigTypeSelect($form, $settings['types']['config'], $this->t('profile'));
$form['curated'] = array( $form['curated'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Add commonly-needed configuration'), '#title' => $this->t('Add commonly-needed configuration'),
'#default_value' => $settings['curated'], '#default_value' => $settings['curated'],
'#description' => $this->t('Select this option to add a curated list of commonly-needed configuration including cron- and theme-related settings to the install profile.'), '#description' => $this->t('Select this option to add a curated list of commonly-needed configuration including cron- and theme-related settings to the install profile.'),
); ];
$standard_settings = $settings['standard']; $standard_settings = $settings['standard'];
$form['standard'] = array( $form['standard'] = [
'#type' => 'fieldset', '#type' => 'fieldset',
'#title' => $this->t('Crib from the Standard profile'), '#title' => $this->t('Crib from the Standard profile'),
'#tree' => TRUE, '#tree' => TRUE,
); ];
$form['standard']['files'] = array( $form['standard']['files'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Crib code'), '#title' => $this->t('Crib code'),
'#default_value' => $standard_settings['files'], '#default_value' => $standard_settings['files'],
'#description' => $this->t('Select this option to add configuration and other files to the optional install profile from the Drupal core Standard install profile. Without these additions, a generated install profile will be missing some important initial setup.'), '#description' => $this->t('Select this option to add configuration and other files to the optional install profile from the Drupal core Standard install profile. Without these additions, a generated install profile will be missing some important initial setup.'),
); ];
$form['standard']['dependencies'] = array( $form['standard']['dependencies'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Crib dependencies'), '#title' => $this->t('Crib dependencies'),
'#default_value' => $standard_settings['dependencies'], '#default_value' => $standard_settings['dependencies'],
'#description' => $this->t('Select this option to add module and theme dependencies from the Standard install profile.'), '#description' => $this->t('Select this option to add module and theme dependencies from the Standard install profile.'),
); ];
$this->setActions($form, self::METHOD_ID); $this->setActions($form, self::METHOD_ID);
@@ -99,70 +99,70 @@ class FeaturesDiffForm extends FormBase {
public function buildForm(array $form, FormStateInterface $form_state, $featurename = '') { public function buildForm(array $form, FormStateInterface $form_state, $featurename = '') {
$current_bundle = $this->assigner->applyBundle(); $current_bundle = $this->assigner->applyBundle();
$packages = $this->featuresManager->getPackages(); $packages = $this->featuresManager->getPackages();
$form = array(); $form = [];
$machine_name = ''; $machine_name = '';
if (!empty($featurename) && empty($packages[$featurename])) { if (!empty($featurename) && empty($packages[$featurename])) {
drupal_set_message($this->t('Feature @name does not exist.', array('@name' => $featurename)), 'error'); drupal_set_message($this->t('Feature @name does not exist.', ['@name' => $featurename]), 'error');
return array(); return [];
} }
elseif (!empty($featurename)) { elseif (!empty($featurename)) {
$machine_name = $packages[$featurename]->getMachineName(); $machine_name = $packages[$featurename]->getMachineName();
$packages = array($packages[$featurename]); $packages = [$packages[$featurename]];
} }
else { else {
$packages = $this->featuresManager->filterPackages($packages, $current_bundle->getMachineName()); $packages = $this->featuresManager->filterPackages($packages, $current_bundle->getMachineName());
} }
$header = array( $header = [
'row' => array( 'row' => [
'data' => !empty($machine_name) 'data' => !empty($machine_name)
? $this->t('Differences in @name', array('@name' => $machine_name)) ? $this->t('Differences in @name', ['@name' => $machine_name])
: ($current_bundle->isDefault() ? $this->t('All differences') : $this->t('All differences in bundle: @bundle', array('@bundle' => $current_bundle->getName()))), : ($current_bundle->isDefault() ? $this->t('All differences') : $this->t('All differences in bundle: @bundle', ['@bundle' => $current_bundle->getName()])),
), ],
); ];
$options = array(); $options = [];
foreach ($packages as $package) { foreach ($packages as $package) {
if ($package->getStatus() != FeaturesManagerInterface::STATUS_NO_EXPORT) { if ($package->getStatus() != FeaturesManagerInterface::STATUS_NO_EXPORT) {
$missing = $this->featuresManager->reorderMissing($this->featuresManager->detectMissing($package)); $missing = $this->featuresManager->reorderMissing($this->featuresManager->detectMissing($package));
$overrides = $this->featuresManager->detectOverrides($package, TRUE); $overrides = $this->featuresManager->detectOverrides($package, TRUE);
if (!empty($overrides) || !empty($missing)) { if (!empty($overrides) || !empty($missing)) {
$options += array( $options += [
$package->getMachineName() => array( $package->getMachineName() => [
'row' => array( 'row' => [
'data' => array( 'data' => [
'#type' => 'html_tag', '#type' => 'html_tag',
'#tag' => 'h2', '#tag' => 'h2',
'#value' => Html::escape($package->getName()), '#value' => Html::escape($package->getName()),
), ],
), ],
'#attributes' => array( '#attributes' => [
'class' => 'features-diff-header', 'class' => 'features-diff-header',
), ],
), ],
); ];
$options += $this->diffOutput($package, $overrides, $missing); $options += $this->diffOutput($package, $overrides, $missing);
} }
} }
} }
$form['diff'] = array( $form['diff'] = [
'#type' => 'tableselect', '#type' => 'tableselect',
'#header' => $header, '#header' => $header,
'#options' => $options, '#options' => $options,
'#attributes' => array('class' => array('features-diff-listing')), '#attributes' => ['class' => ['features-diff-listing']],
'#empty' => $this->t('No differences exist in exported features.'), '#empty' => $this->t('No differences exist in exported features.'),
); ];
$form['actions'] = array('#type' => 'actions', '#tree' => TRUE); $form['actions'] = ['#type' => 'actions', '#tree' => TRUE];
$form['actions']['revert'] = array( $form['actions']['revert'] = [
'#type' => 'submit', '#type' => 'submit',
'#value' => $this->t('Import changes'), '#value' => $this->t('Import changes'),
); ];
$form['actions']['help'] = array( $form['actions']['help'] = [
'#markup' => $this->t('Import the selected changes above into the active configuration.'), '#markup' => $this->t('Import the selected changes above into the active configuration.'),
); ];
$form['#attached']['library'][] = 'system/diff'; $form['#attached']['library'][] = 'system/diff';
$form['#attached']['library'][] = 'features_ui/drupal.features_ui.admin'; $form['#attached']['library'][] = 'features_ui/drupal.features_ui.admin';
@@ -192,7 +192,7 @@ class FeaturesDiffForm extends FormBase {
$type = ConfigurationItem::fromConfigStringToConfigType($item['type']); $type = ConfigurationItem::fromConfigStringToConfigType($item['type']);
$this->configRevert->import($type, $item['name_short']); $this->configRevert->import($type, $item['name_short']);
} }
drupal_set_message($this->t('Imported @name', array('@name' => $config_name))); drupal_set_message($this->t('Imported @name', ['@name' => $config_name]));
} }
} }
@@ -209,59 +209,59 @@ class FeaturesDiffForm extends FormBase {
* @return array * @return array
* A form element. * A form element.
*/ */
protected function diffOutput(Package $package, $overrides, $missing = array()) { protected function diffOutput(Package $package, $overrides, $missing = []) {
$element = array(); $element = [];
$config = $this->featuresManager->getConfigCollection(); $config = $this->featuresManager->getConfigCollection();
$components = array_merge($missing, $overrides); $components = array_merge($missing, $overrides);
$header = array( $header = [
array('data' => '', 'class' => 'diff-marker'), ['data' => '', 'class' => 'diff-marker'],
array('data' => $this->t('Active site config'), 'class' => 'diff-context'), ['data' => $this->t('Active site config'), 'class' => 'diff-context'],
array('data' => '', 'class' => 'diff-marker'), ['data' => '', 'class' => 'diff-marker'],
array('data' => $this->t('Feature code config'), 'class' => 'diff-context'), ['data' => $this->t('Feature code config'), 'class' => 'diff-context'],
); ];
foreach ($components as $name) { foreach ($components as $name) {
$rows[] = array(array('data' => $name, 'colspan' => 4, 'header' => TRUE)); $rows[] = [['data' => $name, 'colspan' => 4, 'header' => TRUE]];
if (!isset($config[$name])) { if (!isset($config[$name])) {
$details = array( $details = [
'#markup' => $this->t('Component in feature missing from active config.'), '#markup' => $this->t('Component in feature missing from active config.'),
); ];
} }
else { else {
$active = $this->featuresManager->getActiveStorage()->read($name); $active = $this->featuresManager->getActiveStorage()->read($name);
$extension = $this->featuresManager->getExtensionStorages()->read($name); $extension = $this->featuresManager->getExtensionStorages()->read($name);
if (empty($extension)) { if (empty($extension)) {
$details = array( $details = [
'#markup' => $this->t('Dependency detected in active config but not exported to the feature.'), '#markup' => $this->t('Dependency detected in active config but not exported to the feature.'),
); ];
} }
else { else {
$diff = $this->configDiff->diff($active, $extension); $diff = $this->configDiff->diff($active, $extension);
$details = array( $details = [
'#type' => 'table', '#type' => 'table',
'#header' => $header, '#header' => $header,
'#rows' => $this->diffFormatter->format($diff), '#rows' => $this->diffFormatter->format($diff),
'#attributes' => array('class' => array('diff', 'features-diff')), '#attributes' => ['class' => ['diff', 'features-diff']],
); ];
} }
} }
$element[$name] = array( $element[$name] = [
'row' => array( 'row' => [
'data' => array( 'data' => [
'#type' => 'details', '#type' => 'details',
'#title' => Html::escape($name), '#title' => Html::escape($name),
'#open' => TRUE, '#open' => TRUE,
'#description' => array( '#description' => [
'data' => $details, 'data' => $details,
), ],
), ],
), ],
'#attributes' => array( '#attributes' => [
'class' => 'diff-' . $package->getMachineName(), 'class' => 'diff-' . $package->getMachineName(),
), ],
); ];
} }
return $element; return $element;
@@ -180,7 +180,7 @@ class FeaturesEditForm extends FormBase {
$packages = $this->featuresManager->getPackages(); $packages = $this->featuresManager->getPackages();
if (empty($packages[$featurename])) { if (empty($packages[$featurename])) {
$featurename = str_replace(array('-', ' '), '_', $featurename); $featurename = str_replace(['-', ' '], '_', $featurename);
$this->package = $this->featuresManager->initPackage($featurename, NULL, '', 'module', $bundle); $this->package = $this->featuresManager->initPackage($featurename, NULL, '', 'module', $bundle);
} }
else { else {
@@ -202,107 +202,107 @@ class FeaturesEditForm extends FormBase {
$this->package = $packages[$featurename]; $this->package = $packages[$featurename];
} }
$form = array( $form = [
'#show_operations' => FALSE, '#show_operations' => FALSE,
'#prefix' => '<div id="features-edit-wrapper">', '#prefix' => '<div id="features-edit-wrapper">',
'#suffix' => '</div>', '#suffix' => '</div>',
); ];
$form['info'] = array( $form['info'] = [
'#type' => 'fieldset', '#type' => 'fieldset',
'#title' => $this->t('General Information'), '#title' => $this->t('General Information'),
'#tree' => FALSE, '#tree' => FALSE,
'#weight' => 2, '#weight' => 2,
'#prefix' => "<div id='features-export-info'>", '#prefix' => "<div id='features-export-info'>",
'#suffix' => '</div>', '#suffix' => '</div>',
); ];
$form['info']['name'] = array( $form['info']['name'] = [
'#title' => $this->t('Name'), '#title' => $this->t('Name'),
'#description' => $this->t('Example: Image gallery') . ' (' . $this->t('Do not begin name with numbers.') . ')', '#description' => $this->t('Example: Image gallery') . ' (' . $this->t('Do not begin name with numbers.') . ')',
'#type' => 'textfield', '#type' => 'textfield',
'#default_value' => $this->package->getName(), '#default_value' => $this->package->getName(),
); ];
if (!$bundle->isDefault()) { if (!$bundle->isDefault()) {
$form['info']['name']['#description'] .= '<br/>' . $form['info']['name']['#description'] .= '<br/>' .
$this->t('The namespace "@name_" will be prepended to the machine name', array('@name' => $bundle->getMachineName())); $this->t('The namespace "@name_" will be prepended to the machine name', ['@name' => $bundle->getMachineName()]);
} }
$form['info']['machine_name'] = array( $form['info']['machine_name'] = [
'#type' => 'machine_name', '#type' => 'machine_name',
'#title' => $this->t('Machine-readable name'), '#title' => $this->t('Machine-readable name'),
'#description' => $this->t('Example: image_gallery') . ' ' . $this->t('May only contain lowercase letters, numbers and underscores.'), '#description' => $this->t('Example: image_gallery') . ' ' . $this->t('May only contain lowercase letters, numbers and underscores.'),
'#required' => TRUE, '#required' => TRUE,
'#default_value' => $bundle->getShortName($this->package->getMachineName()), '#default_value' => $bundle->getShortName($this->package->getMachineName()),
'#machine_name' => array( '#machine_name' => [
'source' => array('info', 'name'), 'source' => ['info', 'name'],
'exists' => array($this, 'featureExists'), 'exists' => [$this, 'featureExists'],
), ],
); ];
if (!$bundle->isDefault()) { if (!$bundle->isDefault()) {
$form['info']['machine_name']['#description'] .= '<br/>' . $form['info']['machine_name']['#description'] .= '<br/>' .
$this->t('NOTE: Do NOT include the namespace prefix "@name_"; it will be added automatically.', array('@name' => $bundle->getMachineName())); $this->t('NOTE: Do NOT include the namespace prefix "@name_"; it will be added automatically.', ['@name' => $bundle->getMachineName()]);
} }
$form['info']['description'] = array( $form['info']['description'] = [
'#title' => $this->t('Description'), '#title' => $this->t('Description'),
'#description' => $this->t('Provide a short description of what users should expect when they install your feature.'), '#description' => $this->t('Provide a short description of what users should expect when they install your feature.'),
'#type' => 'textarea', '#type' => 'textarea',
'#rows' => 3, '#rows' => 3,
'#default_value' => $this->package->getDescription(), '#default_value' => $this->package->getDescription(),
); ];
$form['info']['package'] = array( $form['info']['package'] = [
'#title' => $this->t('Bundle'), '#title' => $this->t('Bundle'),
'#type' => 'select', '#type' => 'select',
'#options' => $this->assigner->getBundleOptions(), '#options' => $this->assigner->getBundleOptions(),
'#default_value' => $bundle->getMachineName(), '#default_value' => $bundle->getMachineName(),
'#ajax' => array( '#ajax' => [
'callback' => '::updateBundle', 'callback' => '::updateBundle',
'wrapper' => 'features-export-info', 'wrapper' => 'features-export-info',
), ],
); ];
$form['info']['version'] = array( $form['info']['version'] = [
'#title' => $this->t('Version'), '#title' => $this->t('Version'),
'#description' => $this->t('Examples: 8.x-1.0, 8.x-1.0-beta1'), '#description' => $this->t('Examples: 8.x-1.0, 8.x-1.0-beta1'),
'#type' => 'textfield', '#type' => 'textfield',
'#required' => FALSE, '#required' => FALSE,
'#default_value' => $this->package->getVersion(), '#default_value' => $this->package->getVersion(),
'#size' => 30, '#size' => 30,
); ];
list($full_name, $path) = $this->featuresManager->getExportInfo($this->package, $bundle); list($full_name, $path) = $this->featuresManager->getExportInfo($this->package, $bundle);
$form['info']['directory'] = array( $form['info']['directory'] = [
'#title' => $this->t('Path'), '#title' => $this->t('Path'),
'#description' => $this->t('Path to export package using Write action, relative to root directory.'), '#description' => $this->t('Path to export package using Write action, relative to root directory.'),
'#type' => 'textfield', '#type' => 'textfield',
'#required' => FALSE, '#required' => FALSE,
'#default_value' => $path, '#default_value' => $path,
'#size' => 30, '#size' => 30,
); ];
$require_all = $this->package->getRequiredAll(); $require_all = $this->package->getRequiredAll();
$form['info']['require_all'] = array( $form['info']['require_all'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Mark all config as required'), '#title' => $this->t('Mark all config as required'),
'#default_value' => $this->package->getRequiredAll(), '#default_value' => $this->package->getRequiredAll(),
'#description' => $this->t('Required config will be assigned to this feature regardless of other assignment plugins.'), '#description' => $this->t('Required config will be assigned to this feature regardless of other assignment plugins.'),
); ];
$form['conflicts'] = array( $form['conflicts'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => $this->t('Allow conflicts'), '#title' => $this->t('Allow conflicts'),
'#default_value' => $this->allowConflicts, '#default_value' => $this->allowConflicts,
'#description' => $this->t('Allow configuration to be exported to more than one feature.'), '#description' => $this->t('Allow configuration to be exported to more than one feature.'),
'#weight' => 8, '#weight' => 8,
'#ajax' => array( '#ajax' => [
'callback' => '::updateForm', 'callback' => '::updateForm',
'wrapper' => 'features-edit-wrapper', 'wrapper' => 'features-edit-wrapper',
), ],
); ];
$generation_info = array(); $generation_info = [];
if (\Drupal::currentUser()->hasPermission('export configuration')) { if (\Drupal::currentUser()->hasPermission('export configuration')) {
// Offer available generation methods. // Offer available generation methods.
$generation_info = $this->generator->getGenerationMethods(); $generation_info = $this->generator->getGenerationMethods();
@@ -310,16 +310,16 @@ class FeaturesEditForm extends FormBase {
uasort($generation_info, '\Drupal\Component\Utility\SortArray::sortByWeightElement'); uasort($generation_info, '\Drupal\Component\Utility\SortArray::sortByWeightElement');
} }
$form['actions'] = array('#type' => 'actions', '#tree' => TRUE); $form['actions'] = ['#type' => 'actions', '#tree' => TRUE];
foreach ($generation_info as $method_id => $method) { foreach ($generation_info as $method_id => $method) {
$form['actions'][$method_id] = array( $form['actions'][$method_id] = [
'#type' => 'submit', '#type' => 'submit',
'#name' => $method_id, '#name' => $method_id,
'#value' => $this->t('@name', array('@name' => $method['name'])), '#value' => $this->t('@name', ['@name' => $method['name']]),
'#attributes' => array( '#attributes' => [
'title' => Html::escape($method['description']), 'title' => Html::escape($method['description']),
), ],
); ];
} }
// Build the Component Listing panel on the right. // Build the Component Listing panel on the right.
@@ -342,29 +342,29 @@ class FeaturesEditForm extends FormBase {
$this->t('Or, enable the Allow Conflicts option above.') . $this->t('Or, enable the Allow Conflicts option above.') .
'</strong>'; '</strong>';
} }
$form['actions']['import_missing'] = array( $form['actions']['import_missing'] = [
'#type' => 'submit', '#type' => 'submit',
'#name' => 'import_missing', '#name' => 'import_missing',
'#value' => $this->t('Import Missing'), '#value' => $this->t('Import Missing'),
'#attributes' => array( '#attributes' => [
'title' => $this->t('Import only the missing configuration items.'), 'title' => $this->t('Import only the missing configuration items.'),
), ],
); ];
} }
$form['#attached'] = array( $form['#attached'] = [
'library' => array( 'library' => [
'features_ui/drupal.features_ui.admin', 'features_ui/drupal.features_ui.admin',
), ],
'drupalSettings' => array( 'drupalSettings' => [
'features' => array( 'features' => [
'excluded' => $this->excluded, 'excluded' => $this->excluded,
'required' => $this->required, 'required' => $this->required,
'conflicts' => $this->conflicts, 'conflicts' => $this->conflicts,
'autodetect' => TRUE, 'autodetect' => TRUE,
), ],
), ],
); ];
return $form; return $form;
} }
@@ -414,7 +414,7 @@ class FeaturesEditForm extends FormBase {
* form. * form.
*/ */
protected function buildComponentList(FormStateInterface $form_state) { protected function buildComponentList(FormStateInterface $form_state) {
$element = array( $element = [
'#type' => 'fieldset', '#type' => 'fieldset',
'#title' => $this->t('Components'), '#title' => $this->t('Components'),
'#description' => $this->t('Expand each component section and select which items should be included in this feature export.'), '#description' => $this->t('Expand each component section and select which items should be included in this feature export.'),
@@ -422,35 +422,35 @@ class FeaturesEditForm extends FormBase {
'#prefix' => "<div id='features-export-wrapper'>", '#prefix' => "<div id='features-export-wrapper'>",
'#suffix' => '</div>', '#suffix' => '</div>',
'#weight' => 1, '#weight' => 1,
); ];
// Filter field used in javascript, so javascript will unhide it. // Filter field used in javascript, so javascript will unhide it.
$element['features_filter_wrapper'] = array( $element['features_filter_wrapper'] = [
'#type' => 'fieldset', '#type' => 'fieldset',
'#title' => $this->t('Filters'), '#title' => $this->t('Filters'),
'#tree' => FALSE, '#tree' => FALSE,
'#prefix' => "<div id='features-filter' class='element-invisible'>", '#prefix' => "<div id='features-filter' class='element-invisible'>",
'#suffix' => '</div>', '#suffix' => '</div>',
'#weight' => -10, '#weight' => -10,
); ];
$element['features_filter_wrapper']['features_filter'] = array( $element['features_filter_wrapper']['features_filter'] = [
'#type' => 'textfield', '#type' => 'textfield',
'#title' => $this->t('Search'), '#title' => $this->t('Search'),
'#hidden' => TRUE, '#hidden' => TRUE,
'#default_value' => '', '#default_value' => '',
'#suffix' => "<span class='features-filter-clear'>" . $this->t('Clear') . "</span>", '#suffix' => "<span class='features-filter-clear'>" . $this->t('Clear') . "</span>",
); ];
$element['features_filter_wrapper']['checkall'] = array( $element['features_filter_wrapper']['checkall'] = [
'#type' => 'checkbox', '#type' => 'checkbox',
'#default_value' => FALSE, '#default_value' => FALSE,
'#hidden' => TRUE, '#hidden' => TRUE,
'#title' => $this->t('Select all'), '#title' => $this->t('Select all'),
'#attributes' => array( '#attributes' => [
'class' => array('features-checkall'), 'class' => ['features-checkall'],
), ],
); ];
$sections = array('included', 'detected', 'added'); $sections = ['included', 'detected', 'added'];
$config_types = $this->featuresManager->listConfigTypes(); $config_types = $this->featuresManager->listConfigTypes();
// Generate the export array for the current feature and user selections. // Generate the export array for the current feature and user selections.
@@ -460,10 +460,10 @@ class FeaturesEditForm extends FormBase {
$component_items_count = count($component_info['_features_options']['sources']); $component_items_count = count($component_info['_features_options']['sources']);
$label = new FormattableMarkup('@component (<span class="component-count">@count</span>)', $label = new FormattableMarkup('@component (<span class="component-count">@count</span>)',
array( [
'@component' => $config_types[$component], '@component' => $config_types[$component],
'@count' => $component_items_count, '@count' => $component_items_count,
) ]
); );
$count = 0; $count = 0;
@@ -474,76 +474,76 @@ class FeaturesEditForm extends FormBase {
$component_name = str_replace('_', '-', Html::escape($component)); $component_name = str_replace('_', '-', Html::escape($component));
if ($count + $component_items_count > 0) { if ($count + $component_items_count > 0) {
$element[$component] = array( $element[$component] = [
'#markup' => '', '#markup' => '',
'#tree' => TRUE, '#tree' => TRUE,
); ];
$element[$component]['sources'] = array( $element[$component]['sources'] = [
'#type' => 'details', '#type' => 'details',
'#title' => $label, '#title' => $label,
'#tree' => TRUE, '#tree' => TRUE,
'#open' => FALSE, '#open' => FALSE,
'#attributes' => array('class' => array('features-export-component')), '#attributes' => ['class' => ['features-export-component']],
'#prefix' => "<div class='features-export-parent component-$component'>", '#prefix' => "<div class='features-export-parent component-$component'>",
); ];
$element[$component]['sources']['selected'] = array( $element[$component]['sources']['selected'] = [
'#type' => 'checkboxes', '#type' => 'checkboxes',
'#id' => "edit-sources-$component_name", '#id' => "edit-sources-$component_name",
'#options' => $this->domDecodeOptions($component_info['_features_options']['sources']), '#options' => $this->domDecodeOptions($component_info['_features_options']['sources']),
'#default_value' => $this->domDecodeOptions($component_info['_features_selected']['sources'], FALSE), '#default_value' => $this->domDecodeOptions($component_info['_features_selected']['sources'], FALSE),
'#attributes' => array('class' => array('component-select')), '#attributes' => ['class' => ['component-select']],
'#prefix' => "<span class='component-select'>", '#prefix' => "<span class='component-select'>",
'#suffix' => '</span>', '#suffix' => '</span>',
); ];
$element[$component]['before-list'] = array( $element[$component]['before-list'] = [
'#markup' => "<div class='component-list features-export-list $extra_class'>", '#markup' => "<div class='component-list features-export-list $extra_class'>",
); ];
foreach ($sections as $section) { foreach ($sections as $section) {
$element[$component][$section] = array( $element[$component][$section] = [
'#type' => 'checkboxes', '#type' => 'checkboxes',
'#options' => !empty($component_info['_features_options'][$section]) ? '#options' => !empty($component_info['_features_options'][$section]) ?
$this->domDecodeOptions($component_info['_features_options'][$section]) : array(), $this->domDecodeOptions($component_info['_features_options'][$section]) : [],
'#default_value' => !empty($component_info['_features_selected'][$section]) ? '#default_value' => !empty($component_info['_features_selected'][$section]) ?
$this->domDecodeOptions($component_info['_features_selected'][$section], FALSE) : array(), $this->domDecodeOptions($component_info['_features_selected'][$section], FALSE) : [],
'#attributes' => array('class' => array('component-' . $section)), '#attributes' => ['class' => ['component-' . $section]],
'#prefix' => "<span class='component-$section'>", '#prefix' => "<span class='component-$section'>",
'#suffix' => '</span>', '#suffix' => '</span>',
); ];
} }
// Close both the before-list as well as the sources div. // Close both the before-list as well as the sources div.
$element[$component]['after-list'] = array( $element[$component]['after-list'] = [
'#markup' => "</div></div>", '#markup' => "</div></div>",
); ];
} }
} }
$element['features_missing'] = array( $element['features_missing'] = [
'#theme' => 'item_list', '#theme' => 'item_list',
'#items' => $export['missing'], '#items' => $export['missing'],
'#title' => $this->t('Configuration missing from active site:'), '#title' => $this->t('Configuration missing from active site:'),
'#suffix' => '<div class="description">' . '#suffix' => '<div class="description">' .
$this->t('Import the feature to create the missing config listed above.') . $this->t('Import the feature to create the missing config listed above.') .
'</div>', '</div>',
); ];
$element['features_legend'] = array( $element['features_legend'] = [
'#type' => 'fieldset', '#type' => 'fieldset',
'#title' => $this->t('Legend'), '#title' => $this->t('Legend'),
'#tree' => FALSE, '#tree' => FALSE,
'#prefix' => "<div id='features-legend'>", '#prefix' => "<div id='features-legend'>",
'#suffix' => '</div>', '#suffix' => '</div>',
); ];
$element['features_legend']['legend'] = array( $element['features_legend']['legend'] = [
'#markup' => '#markup' =>
"<span class='component-included'>" . $this->t('Normal') . "</span> " . "<span class='component-included'>" . $this->t('Normal') . "</span> " .
"<span class='component-added'>" . $this->t('Added') . "</span> " . "<span class='component-added'>" . $this->t('Added') . "</span> " .
"<span class='component-detected'>" . $this->t('Auto detected') . "</span> " . "<span class='component-detected'>" . $this->t('Auto detected') . "</span> " .
"<span class='component-conflict'>" . $this->t('Conflict') . "</span> ", "<span class='component-conflict'>" . $this->t('Conflict') . "</span> ",
); ];
return $element; return $element;
} }
@@ -604,8 +604,8 @@ class FeaturesEditForm extends FormBase {
$this->package = $packages[$package_name]; $this->package = $packages[$package_name];
// Make a map of all config data. // Make a map of all config data.
$components = array(); $components = [];
$this->conflicts = array(); $this->conflicts = [];
foreach ($config as $item_name => $item) { foreach ($config as $item_name => $item) {
if (($item->getPackage() != $package_name) && if (($item->getPackage() != $package_name) &&
!empty($packages[$item->getPackage()]) && ($packages[$item->getPackage()]->getStatus() != FeaturesManagerInterface::STATUS_NO_EXPORT)) { !empty($packages[$item->getPackage()]) && ($packages[$item->getPackage()]->getStatus() != FeaturesManagerInterface::STATUS_NO_EXPORT)) {
@@ -619,8 +619,8 @@ class FeaturesEditForm extends FormBase {
} }
// Make a map of the config data already exported to the Feature. // Make a map of the config data already exported to the Feature.
$this->missing = array(); $this->missing = [];
$exported_features_info = array(); $exported_features_info = [];
foreach ($this->package->getConfigOrig() as $item_name) { foreach ($this->package->getConfigOrig() as $item_name) {
// Make sure the extension provided item exists in the active // Make sure the extension provided item exists in the active
// configuration storage. // configuration storage.
@@ -638,9 +638,9 @@ class FeaturesEditForm extends FormBase {
$exported_features_info['dependencies'] = $this->package->getDependencyInfo(); $exported_features_info['dependencies'] = $this->package->getDependencyInfo();
// Make a map of any config specifically excluded and/or required. // Make a map of any config specifically excluded and/or required.
foreach (array('excluded', 'required') as $constraint) { foreach (['excluded', 'required'] as $constraint) {
$this->{$constraint} = array(); $this->{$constraint} = [];
$info = !empty($this->package->{'get' . $constraint}()) ? $this->package->{'get' . $constraint}() : array(); $info = !empty($this->package->{'get' . $constraint}()) ? $this->package->{'get' . $constraint}() : [];
// $info may be boolean. // $info may be boolean.
if (is_array($info)) { if (is_array($info)) {
foreach ($info as $item_name) { foreach ($info as $item_name) {
@@ -654,7 +654,7 @@ class FeaturesEditForm extends FormBase {
} }
// Make a map of the config data to be exported within the Feature. // Make a map of the config data to be exported within the Feature.
$new_features_info = array(); $new_features_info = [];
foreach ($this->package->getConfig() as $item_name) { foreach ($this->package->getConfig() as $item_name) {
$item = $config[$item_name]; $item = $config[$item_name];
$new_features_info[$item->getType()][$item->getShortName()] = $item->getLabel(); $new_features_info[$item->getType()][$item->getShortName()] = $item->getLabel();
@@ -662,29 +662,29 @@ class FeaturesEditForm extends FormBase {
$new_features_info['dependencies'] = $this->package->getDependencies(); $new_features_info['dependencies'] = $this->package->getDependencies();
// Assemble the combined component list. // Assemble the combined component list.
$config_new = array(); $config_new = [];
$sections = array('sources', 'included', 'detected', 'added'); $sections = ['sources', 'included', 'detected', 'added'];
// Generate list of config to be exported. // Generate list of config to be exported.
$config_count = array(); $config_count = [];
foreach ($components as $component => $component_info) { foreach ($components as $component => $component_info) {
// User-selected components take precedence. // User-selected components take precedence.
$config_new[$component] = array(); $config_new[$component] = [];
$config_count[$component] = 0; $config_count[$component] = 0;
// Add selected items from Sources checkboxes. // Add selected items from Sources checkboxes.
if (!$form_state->isValueEmpty(array($component, 'sources', 'selected'))) { if (!$form_state->isValueEmpty([$component, 'sources', 'selected'])) {
$config_new[$component] = array_merge($config_new[$component], $this->domDecodeOptions(array_filter($form_state->getValue(array( $config_new[$component] = array_merge($config_new[$component], $this->domDecodeOptions(array_filter($form_state->getValue([
$component, $component,
'sources', 'sources',
'selected', 'selected',
))))); ]))));
$config_count[$component]++; $config_count[$component]++;
} }
// Add selected items from already Included, newly Added, auto-detected // Add selected items from already Included, newly Added, auto-detected
// checkboxes. // checkboxes.
foreach (array('included', 'added', 'detected') as $section) { foreach (['included', 'added', 'detected'] as $section) {
if (!$form_state->isValueEmpty(array($component, $section))) { if (!$form_state->isValueEmpty([$component, $section])) {
$config_new[$component] = array_merge($config_new[$component], $this->domDecodeOptions(array_filter($form_state->getValue(array($component, $section))))); $config_new[$component] = array_merge($config_new[$component], $this->domDecodeOptions(array_filter($form_state->getValue([$component, $section]))));
$config_count[$component]++; $config_count[$component]++;
} }
} }
@@ -710,19 +710,19 @@ class FeaturesEditForm extends FormBase {
foreach ($components as $component => $component_info) { foreach ($components as $component => $component_info) {
$component_export = $component_info; $component_export = $component_info;
foreach ($sections as $section) { foreach ($sections as $section) {
$component_export['_features_options'][$section] = array(); $component_export['_features_options'][$section] = [];
$component_export['_features_selected'][$section] = array(); $component_export['_features_selected'][$section] = [];
} }
if (!empty($component_info)) { if (!empty($component_info)) {
$exported_components = !empty($exported_features_info[$component]) ? $exported_features_info[$component] : array(); $exported_components = !empty($exported_features_info[$component]) ? $exported_features_info[$component] : [];
$new_components = !empty($new_features_info[$component]) ? $new_features_info[$component] : array(); $new_components = !empty($new_features_info[$component]) ? $new_features_info[$component] : [];
foreach ($component_info as $key => $label) { foreach ($component_info as $key => $label) {
$config_name = $this->featuresManager->getFullName($component, $key); $config_name = $this->featuresManager->getFullName($component, $key);
// If checkbox in Sources is checked, move it to Added section. // If checkbox in Sources is checked, move it to Added section.
if (!$form_state->isValueEmpty(array($component, 'sources', 'selected', $key))) { if (!$form_state->isValueEmpty([$component, 'sources', 'selected', $key])) {
$form_state->setValue(array($component, 'sources', 'selected', $key), FALSE); $form_state->setValue([$component, 'sources', 'selected', $key], FALSE);
$form_state->setValue(array($component, 'added', $key), 1); $form_state->setValue([$component, 'added', $key], 1);
$component_export['_features_options']['added'][$key] = $this->configLabel($component, $key, $label); $component_export['_features_options']['added'][$key] = $this->configLabel($component, $key, $label);
$component_export['_features_selected']['added'][$key] = $key; $component_export['_features_selected']['added'][$key] = $key;
// If this was previously excluded, we don't need to set it as // If this was previously excluded, we don't need to set it as
@@ -746,8 +746,8 @@ class FeaturesEditForm extends FormBase {
// means it was an auto-detect that was previously part of the // means it was an auto-detect that was previously part of the
// export and is now de-selected in UI. // export and is now de-selected in UI.
if ($form_state->isSubmitted() && if ($form_state->isSubmitted() &&
($form_state->hasValue(array($component, 'included', $key)) || ($form_state->hasValue([$component, 'included', $key]) ||
($form_state->isValueEmpty(array($component, 'detected', $key)))) && ($form_state->isValueEmpty([$component, 'detected', $key]))) &&
empty($config_new[$component][$key])) { empty($config_new[$component][$key])) {
$section = 'detected'; $section = 'detected';
$default_value = FALSE; $default_value = FALSE;
@@ -755,9 +755,9 @@ class FeaturesEditForm extends FormBase {
// Unless it's unchecked in the form, then move it to Newly // Unless it's unchecked in the form, then move it to Newly
// disabled item. // disabled item.
elseif ($form_state->isSubmitted() && elseif ($form_state->isSubmitted() &&
$form_state->isValueEmpty(array($component, 'added', $key)) && $form_state->isValueEmpty([$component, 'added', $key]) &&
$form_state->isValueEmpty(array($component, 'detected', $key)) && $form_state->isValueEmpty([$component, 'detected', $key]) &&
$form_state->isValueEmpty(array($component, 'included', $key))) { $form_state->isValueEmpty([$component, 'included', $key])) {
$section = 'added'; $section = 'added';
$default_value = FALSE; $default_value = FALSE;
} }
@@ -777,16 +777,16 @@ class FeaturesEditForm extends FormBase {
// If it's already checked in Added or Sources, leave it in Added // If it's already checked in Added or Sources, leave it in Added
// as checked. // as checked.
if ($form_state->isSubmitted() && if ($form_state->isSubmitted() &&
(!$form_state->isValueEmpty(array($component, 'added', $key)) || (!$form_state->isValueEmpty([$component, 'added', $key]) ||
!$form_state->isValueEmpty(array($component, 'sources', 'selected', $key)))) { !$form_state->isValueEmpty([$component, 'sources', 'selected', $key]))) {
$section = 'added'; $section = 'added';
$default_value = $key; $default_value = $key;
} }
// If it's already been unchecked, leave it unchecked. // If it's already been unchecked, leave it unchecked.
elseif ($form_state->isSubmitted() && elseif ($form_state->isSubmitted() &&
$form_state->isValueEmpty(array($component, 'sources', 'selected', $key)) && $form_state->isValueEmpty([$component, 'sources', 'selected', $key]) &&
$form_state->isValueEmpty(array($component, 'detected', $key)) && $form_state->isValueEmpty([$component, 'detected', $key]) &&
!$form_state->hasValue(array($component, 'added', $key))) { !$form_state->hasValue([$component, 'added', $key])) {
$section = 'detected'; $section = 'detected';
$default_value = FALSE; $default_value = FALSE;
} }
@@ -817,10 +817,10 @@ class FeaturesEditForm extends FormBase {
// at 'input'. // at 'input'.
if ($form_state->isSubmitted()) { if ($form_state->isSubmitted()) {
if (!$default_value) { if (!$default_value) {
$form_state->setValue(array($component, $section, $key), FALSE); $form_state->setValue([$component, $section, $key], FALSE);
} }
else { else {
$form_state->setValue(array($component, $section, $key), 1); $form_state->setValue([$component, $section, $key], 1);
} }
} }
} }
@@ -833,9 +833,9 @@ class FeaturesEditForm extends FormBase {
else { else {
// Option was not part of the new export. // Option was not part of the new export.
$added = FALSE; $added = FALSE;
foreach (array('included', 'added') as $section) { foreach (['included', 'added'] as $section) {
// Restore any user-selected checkboxes. // Restore any user-selected checkboxes.
if (!$form_state->isValueEmpty(array($component, $section, $key))) { if (!$form_state->isValueEmpty([$component, $section, $key])) {
$component_export['_features_options'][$section][$key] = $this->configLabel($component, $key, $label); $component_export['_features_options'][$section][$key] = $this->configLabel($component, $key, $label);
$component_export['_features_selected'][$section][$key] = $key; $component_export['_features_selected'][$section][$key] = $key;
$added = TRUE; $added = TRUE;
@@ -927,12 +927,12 @@ class FeaturesEditForm extends FormBase {
} }
// Set default redirect, but allow generators to change it later. // Set default redirect, but allow generators to change it later.
$form_state->setRedirect('features.edit', array('featurename' => $this->package->getMachineName())); $form_state->setRedirect('features.edit', ['featurename' => $this->package->getMachineName()]);
if ($method_id == 'import_missing') { if ($method_id == 'import_missing') {
$this->importMissing(); $this->importMissing();
} }
elseif (!empty($method_id)) { elseif (!empty($method_id)) {
$packages = array($this->package->getMachineName()); $packages = [$this->package->getMachineName()];
$this->generator->generatePackages($method_id, $bundle, $packages); $this->generator->generatePackages($method_id, $bundle, $packages);
$this->generator->applyExportFormSubmit($method_id, $form, $form_state); $this->generator->applyExportFormSubmit($method_id, $form, $form_state);
} }
@@ -947,7 +947,7 @@ class FeaturesEditForm extends FormBase {
* Config array to be exported. * Config array to be exported.
*/ */
protected function updatePackageConfig(FormStateInterface $form_state) { protected function updatePackageConfig(FormStateInterface $form_state) {
$config = array(); $config = [];
$components = $this->getComponentList($form_state); $components = $this->getComponentList($form_state);
foreach ($components['config_new'] as $config_type => $items) { foreach ($components['config_new'] as $config_type => $items) {
foreach ($items as $name) { foreach ($items as $name) {
@@ -969,10 +969,10 @@ class FeaturesEditForm extends FormBase {
$type = ConfigurationItem::fromConfigStringToConfigType($item['type']); $type = ConfigurationItem::fromConfigStringToConfigType($item['type']);
try { try {
$this->configRevert->import($type, $item['name_short']); $this->configRevert->import($type, $item['name_short']);
drupal_set_message($this->t('Imported @name', array('@name' => $config_name))); drupal_set_message($this->t('Imported @name', ['@name' => $config_name]));
} catch (\Exception $e) { } catch (\Exception $e) {
drupal_set_message($this->t('Error importing @name : @message', drupal_set_message($this->t('Error importing @name : @message',
array('@name' => $config_name, '@message' => $e->getMessage())), 'error'); ['@name' => $config_name, '@message' => $e->getMessage()]), 'error');
} }
} }
} }
@@ -1010,7 +1010,7 @@ class FeaturesEditForm extends FormBase {
* suitable for storing in the info.yml file. * suitable for storing in the info.yml file.
*/ */
protected function updateConstrained($constraint) { protected function updateConstrained($constraint) {
$constrained = array(); $constrained = [];
foreach ($this->{$constraint} as $type => $item) { foreach ($this->{$constraint} as $type => $item) {
foreach ($item as $name => $value) { foreach ($item as $name => $value) {
$constrained[] = $this->featuresManager->getFullName($type, $name); $constrained[] = $this->featuresManager->getFullName($type, $name);
@@ -1061,7 +1061,7 @@ class FeaturesEditForm extends FormBase {
*/ */
protected function domDecodeOptions(array $options, $keys_only = FALSE) { protected function domDecodeOptions(array $options, $keys_only = FALSE) {
$replacements = array_flip($this->domEncodeMap()); $replacements = array_flip($this->domEncodeMap());
$encoded = array(); $encoded = [];
foreach ($options as $key => $value) { foreach ($options as $key => $value) {
$encoded[strtr($key, $replacements)] = $keys_only ? $value : strtr($value, $replacements); $encoded[strtr($key, $replacements)] = $keys_only ? $value : strtr($value, $replacements);
} }
@@ -1075,7 +1075,7 @@ class FeaturesEditForm extends FormBase {
* An encoding map. * An encoding map.
*/ */
protected function domEncodeMap() { protected function domEncodeMap() {
return array( return [
':' => '__' . ord(':') . '__', ':' => '__' . ord(':') . '__',
'/' => '__' . ord('/') . '__', '/' => '__' . ord('/') . '__',
',' => '__' . ord(',') . '__', ',' => '__' . ord(',') . '__',
@@ -1085,7 +1085,7 @@ class FeaturesEditForm extends FormBase {
'%' => '__' . ord('%') . '__', '%' => '__' . ord('%') . '__',
')' => '__' . ord(')') . '__', ')' => '__' . ord(')') . '__',
'(' => '__' . ord('(') . '__', '(' => '__' . ord('(') . '__',
); ];
} }
} }
@@ -139,10 +139,10 @@ class FeaturesExportForm extends FormBase {
// callback. // callback.
$form['#packages'] = $packages; $form['#packages'] = $packages;
$form['#profile_package'] = $current_bundle->getProfileName(); $form['#profile_package'] = $current_bundle->getProfileName();
$form['header'] = array( $form['header'] = [
'#type' => 'container', '#type' => 'container',
'#attributes' => array('class' => 'features-header'), '#attributes' => ['class' => 'features-header'],
); ];
$bundle_options = $this->assigner->getBundleOptions(); $bundle_options = $this->assigner->getBundleOptions();
@@ -153,29 +153,29 @@ class FeaturesExportForm extends FormBase {
$form['#prefix'] = '<div id="edit-features-wrapper">'; $form['#prefix'] = '<div id="edit-features-wrapper">';
$form['#suffix'] = '</div>'; $form['#suffix'] = '</div>';
$form['header']['bundle'] = array( $form['header']['bundle'] = [
'#title' => $this->t('Bundle'), '#title' => $this->t('Bundle'),
'#type' => 'select', '#type' => 'select',
'#options' => $bundle_options, '#options' => $bundle_options,
'#default_value' => $current_bundle->getMachineName(), '#default_value' => $current_bundle->getMachineName(),
'#prefix' => '<div id="edit-package-set-wrapper">', '#prefix' => '<div id="edit-package-set-wrapper">',
'#suffix' => '</div>', '#suffix' => '</div>',
'#ajax' => array( '#ajax' => [
'callback' => '::updatePreview', 'callback' => '::updatePreview',
'wrapper' => 'edit-features-preview-wrapper', 'wrapper' => 'edit-features-preview-wrapper',
), ],
'#attributes' => array( '#attributes' => [
'data-new-package-set' => 'status', 'data-new-package-set' => 'status',
), ],
); ];
$form['preview'] = $this->buildListing($packages, $current_bundle); $form['preview'] = $this->buildListing($packages, $current_bundle);
$form['#attached'] = array( $form['#attached'] = [
'library' => array( 'library' => [
'features_ui/drupal.features_ui.admin', 'features_ui/drupal.features_ui.admin',
), ],
); ];
if (\Drupal::currentUser()->hasPermission('export configuration')) { if (\Drupal::currentUser()->hasPermission('export configuration')) {
// Offer available generation methods. // Offer available generation methods.
@@ -183,24 +183,24 @@ class FeaturesExportForm extends FormBase {
// Sort generation methods by weight. // Sort generation methods by weight.
uasort($generation_info, '\Drupal\Component\Utility\SortArray::sortByWeightElement'); uasort($generation_info, '\Drupal\Component\Utility\SortArray::sortByWeightElement');
$form['description'] = array( $form['description'] = [
'#markup' => '<p>' . $this->t('Use an export method button below to generate the selected features.') . '</p>', '#markup' => '<p>' . $this->t('Use an export method button below to generate the selected features.') . '</p>',
); ];
$form['actions'] = array('#type' => 'actions', '#tree' => TRUE); $form['actions'] = ['#type' => 'actions', '#tree' => TRUE];
foreach ($generation_info as $method_id => $method) { foreach ($generation_info as $method_id => $method) {
$form['actions'][$method_id] = array( $form['actions'][$method_id] = [
'#type' => 'submit', '#type' => 'submit',
'#name' => $method_id, '#name' => $method_id,
'#value' => $this->t('@name', array('@name' => $method['name'])), '#value' => $this->t('@name', ['@name' => $method['name']]),
'#attributes' => array( '#attributes' => [
'title' => Html::escape($method['description']), 'title' => Html::escape($method['description']),
), ],
); ];
} }
} }
$form['#pre_render'][] = array(get_class($this), 'preRenderRemoveInvalidCheckboxes'); $form['#pre_render'][] = [get_class($this), 'preRenderRemoveInvalidCheckboxes'];
return $form; return $form;
} }
@@ -230,16 +230,16 @@ class FeaturesExportForm extends FormBase {
*/ */
protected function buildListing(array $packages, FeaturesBundleInterface $bundle) { protected function buildListing(array $packages, FeaturesBundleInterface $bundle) {
$header = array( $header = [
'name' => array('data' => $this->t('Feature')), 'name' => ['data' => $this->t('Feature')],
'machine_name' => array('data' => $this->t('')), 'machine_name' => ['data' => $this->t('')],
'details' => array('data' => $this->t('Description'), 'class' => array(RESPONSIVE_PRIORITY_LOW)), 'details' => ['data' => $this->t('Description'), 'class' => [RESPONSIVE_PRIORITY_LOW]],
'version' => array('data' => $this->t('Version'), 'class' => array(RESPONSIVE_PRIORITY_LOW)), 'version' => ['data' => $this->t('Version'), 'class' => [RESPONSIVE_PRIORITY_LOW]],
'status' => array('data' => $this->t('Status'), 'class' => array(RESPONSIVE_PRIORITY_LOW)), 'status' => ['data' => $this->t('Status'), 'class' => [RESPONSIVE_PRIORITY_LOW]],
'state' => array('data' => $this->t('State'), 'class' => array(RESPONSIVE_PRIORITY_LOW)), 'state' => ['data' => $this->t('State'), 'class' => [RESPONSIVE_PRIORITY_LOW]],
); ];
$options = array(); $options = [];
$first = TRUE; $first = TRUE;
foreach ($packages as $package) { foreach ($packages as $package) {
if ($first && $package->getStatus() == FeaturesManagerInterface::STATUS_NO_EXPORT) { if ($first && $package->getStatus() == FeaturesManagerInterface::STATUS_NO_EXPORT) {
@@ -250,25 +250,25 @@ class FeaturesExportForm extends FormBase {
continue; continue;
} }
$first = FALSE; $first = FALSE;
$options[] = array( $options[] = [
'name' => array( 'name' => [
'data' => $this->t('The following packages are not exported.'), 'data' => $this->t('The following packages are not exported.'),
'class' => 'features-export-header-row', 'class' => 'features-export-header-row',
'colspan' => 6, 'colspan' => 6,
), ],
); ];
} }
$options[$package->getMachineName()] = $this->buildPackageDetail($package, $bundle); $options[$package->getMachineName()] = $this->buildPackageDetail($package, $bundle);
} }
$element = array( $element = [
'#type' => 'tableselect', '#type' => 'tableselect',
'#header' => $header, '#header' => $header,
'#options' => $options, '#options' => $options,
'#attributes' => array('class' => array('features-listing')), '#attributes' => ['class' => ['features-listing']],
'#prefix' => '<div id="edit-features-preview-wrapper">', '#prefix' => '<div id="edit-features-preview-wrapper">',
'#suffix' => '</div>', '#suffix' => '</div>',
); ];
return $element; return $element;
} }
@@ -287,12 +287,12 @@ class FeaturesExportForm extends FormBase {
protected function buildPackageDetail(Package $package, FeaturesBundleInterface $bundle) { protected function buildPackageDetail(Package $package, FeaturesBundleInterface $bundle) {
$config_collection = $this->featuresManager->getConfigCollection(); $config_collection = $this->featuresManager->getConfigCollection();
$url = Url::fromRoute('features.edit', array('featurename' => $package->getMachineName())); $url = Url::fromRoute('features.edit', ['featurename' => $package->getMachineName()]);
$element['name'] = array( $element['name'] = [
'data' => \Drupal::l($package->getName(), $url), 'data' => \Drupal::l($package->getName(), $url),
'class' => array('feature-name'), 'class' => ['feature-name'],
); ];
$machine_name = $package->getMachineName(); $machine_name = $package->getMachineName();
// Except for the 'unpackaged' pseudo-package, display the full name, since // Except for the 'unpackaged' pseudo-package, display the full name, since
// that's what will be generated. // that's what will be generated.
@@ -300,128 +300,128 @@ class FeaturesExportForm extends FormBase {
$machine_name = $bundle->getFullName($machine_name); $machine_name = $bundle->getFullName($machine_name);
} }
$element['machine_name'] = $machine_name; $element['machine_name'] = $machine_name;
$element['status'] = array( $element['status'] = [
'data' => $this->featuresManager->statusLabel($package->getStatus()), 'data' => $this->featuresManager->statusLabel($package->getStatus()),
'class' => array('column-nowrap'), 'class' => ['column-nowrap'],
); ];
// Use 'data' instead of plain string value so a blank version doesn't // Use 'data' instead of plain string value so a blank version doesn't
// remove column from table. // remove column from table.
$element['version'] = array( $element['version'] = [
'data' => Html::escape($package->getVersion()), 'data' => Html::escape($package->getVersion()),
'class' => array('column-nowrap'), 'class' => ['column-nowrap'],
); ];
$overrides = $this->featuresManager->detectOverrides($package); $overrides = $this->featuresManager->detectOverrides($package);
$new_config = $this->featuresManager->detectNew($package); $new_config = $this->featuresManager->detectNew($package);
$conflicts = array(); $conflicts = [];
$missing = array(); $missing = [];
$moved = array(); $moved = [];
if ($package->getStatus() == FeaturesManagerInterface::STATUS_NO_EXPORT) { if ($package->getStatus() == FeaturesManagerInterface::STATUS_NO_EXPORT) {
$overrides = array(); $overrides = [];
$new_config = array(); $new_config = [];
} }
// Bundle package configuration by type. // Bundle package configuration by type.
$package_config = array(); $package_config = [];
foreach ($package->getConfig() as $item_name) { foreach ($package->getConfig() as $item_name) {
if (isset($config_collection[$item_name])) { if (isset($config_collection[$item_name])) {
$item = $config_collection[$item_name]; $item = $config_collection[$item_name];
$package_config[$item->getType()][] = array( $package_config[$item->getType()][] = [
'name' => Html::escape($item_name), 'name' => Html::escape($item_name),
'label' => Html::escape($item->getLabel()), 'label' => Html::escape($item->getLabel()),
'class' => in_array($item_name, $overrides) ? 'features-override' : 'class' => in_array($item_name, $overrides) ? 'features-override' :
(in_array($item_name, $new_config) ? 'features-detected' : ''), (in_array($item_name, $new_config) ? 'features-detected' : ''),
); ];
} }
} }
// Conflict config from other modules. // Conflict config from other modules.
foreach ($package->getConfigOrig() as $item_name) { foreach ($package->getConfigOrig() as $item_name) {
if (!isset($config_collection[$item_name])) { if (!isset($config_collection[$item_name])) {
$missing[] = $item_name; $missing[] = $item_name;
$package_config['missing'][] = array( $package_config['missing'][] = [
'name' => Html::escape($item_name), 'name' => Html::escape($item_name),
'label' => Html::escape($item_name), 'label' => Html::escape($item_name),
'class' => 'features-missing', 'class' => 'features-missing',
); ];
} }
elseif (!in_array($item_name, $package->getConfig())) { elseif (!in_array($item_name, $package->getConfig())) {
$item = $config_collection[$item_name]; $item = $config_collection[$item_name];
if (empty($item->getProvider())) { if (empty($item->getProvider())) {
$conflicts[] = $item_name; $conflicts[] = $item_name;
$package_name = !empty($item->getPackage()) ? $item->getPackage() : $this->t('PACKAGE NOT ASSIGNED'); $package_name = !empty($item->getPackage()) ? $item->getPackage() : $this->t('PACKAGE NOT ASSIGNED');
$package_config[$item->getType()][] = array( $package_config[$item->getType()][] = [
'name' => Html::escape($package_name), 'name' => Html::escape($package_name),
'label' => Html::escape($item->getLabel()), 'label' => Html::escape($item->getLabel()),
'class' => 'features-conflict', 'class' => 'features-conflict',
); ];
} }
else { else {
$moved[] = $item_name; $moved[] = $item_name;
$package_name = !empty($item->getPackage()) ? $item->getPackage() : $this->t('PACKAGE NOT ASSIGNED'); $package_name = !empty($item->getPackage()) ? $item->getPackage() : $this->t('PACKAGE NOT ASSIGNED');
$package_config[$item->getType()][] = array( $package_config[$item->getType()][] = [
'name' => $this->t('Moved to @package', array('@package' => $package_name)), 'name' => $this->t('Moved to @package', ['@package' => $package_name]),
'label' => Html::escape($item->getLabel()), 'label' => Html::escape($item->getLabel()),
'class' => 'features-moved', 'class' => 'features-moved',
); ];
} }
} }
} }
// Add dependencies. // Add dependencies.
$package_config['dependencies'] = array(); $package_config['dependencies'] = [];
foreach ($package->getDependencies() as $dependency) { foreach ($package->getDependencies() as $dependency) {
$package_config['dependencies'][] = array( $package_config['dependencies'][] = [
'name' => $dependency, 'name' => $dependency,
'label' => $this->moduleHandler->getName($dependency), 'label' => $this->moduleHandler->moduleExists($dependency) ? $this->moduleHandler->getName($dependency) : $dependency,
'class' => '', 'class' => '',
); ];
} }
$class = ''; $class = '';
$state_links = []; $state_links = [];
if (!empty($conflicts)) { if (!empty($conflicts)) {
$state_links[] = array( $state_links[] = [
'#type' => 'link', '#type' => 'link',
'#title' => $this->t('Conflicts'), '#title' => $this->t('Conflicts'),
'#url' => Url::fromRoute('features.edit', array('featurename' => $package->getMachineName())), '#url' => Url::fromRoute('features.edit', ['featurename' => $package->getMachineName()]),
'#attributes' => array('class' => array('features-conflict')), '#attributes' => ['class' => ['features-conflict']],
); ];
} }
if (!empty($overrides)) { if (!empty($overrides)) {
$state_links[] = array( $state_links[] = [
'#type' => 'link', '#type' => 'link',
'#title' => $this->featuresManager->stateLabel(FeaturesManagerInterface::STATE_OVERRIDDEN), '#title' => $this->featuresManager->stateLabel(FeaturesManagerInterface::STATE_OVERRIDDEN),
'#url' => Url::fromRoute('features.diff', array('featurename' => $package->getMachineName())), '#url' => Url::fromRoute('features.diff', ['featurename' => $package->getMachineName()]),
'#attributes' => array('class' => array('features-override')), '#attributes' => ['class' => ['features-override']],
); ];
} }
if (!empty($new_config)) { if (!empty($new_config)) {
$state_links[] = array( $state_links[] = [
'#type' => 'link', '#type' => 'link',
'#title' => $this->t('New detected'), '#title' => $this->t('New detected'),
'#url' => Url::fromRoute('features.diff', array('featurename' => $package->getMachineName())), '#url' => Url::fromRoute('features.diff', ['featurename' => $package->getMachineName()]),
'#attributes' => array('class' => array('features-detected')), '#attributes' => ['class' => ['features-detected']],
); ];
} }
if (!empty($missing) && ($package->getStatus() == FeaturesManagerInterface::STATUS_INSTALLED)) { if (!empty($missing) && ($package->getStatus() == FeaturesManagerInterface::STATUS_INSTALLED)) {
$state_links[] = array( $state_links[] = [
'#type' => 'link', '#type' => 'link',
'#title' => $this->t('Missing'), '#title' => $this->t('Missing'),
'#url' => Url::fromRoute('features.edit', array('featurename' => $package->getMachineName())), '#url' => Url::fromRoute('features.edit', ['featurename' => $package->getMachineName()]),
'#attributes' => array('class' => array('features-missing')), '#attributes' => ['class' => ['features-missing']],
); ];
} }
if (!empty($moved)) { if (!empty($moved)) {
$state_links[] = array( $state_links[] = [
'#type' => 'link', '#type' => 'link',
'#title' => $this->t('Moved'), '#title' => $this->t('Moved'),
'#url' => Url::fromRoute('features.edit', array('featurename' => $package->getMachineName())), '#url' => Url::fromRoute('features.edit', ['featurename' => $package->getMachineName()]),
'#attributes' => array('class' => array('features-moved')), '#attributes' => ['class' => ['features-moved']],
); ];
} }
if (!empty($state_links)) { if (!empty($state_links)) {
$element['state'] = array( $element['state'] = [
'data' => $state_links, 'data' => $state_links,
'class' => array('column-nowrap'), 'class' => ['column-nowrap'],
); ];
} }
else { else {
$element['state'] = ''; $element['state'] = '';
@@ -473,7 +473,7 @@ class FeaturesExportForm extends FormBase {
); );
$details['table'] = array( $details['table'] = array(
'#type' => 'details', '#type' => 'details',
'#title' => array('#markup' => $this->t('Included configuration')), '#title' => $this->t('Included configuration'),
'#description' => array('data' => $element['table']), '#description' => array('data' => $element['table']),
); );
$element['details'] = array( $element['details'] = array(
@@ -34,7 +34,7 @@ class FeaturesUITest extends WebTestBase {
$this->assertText($this->t('You have not yet created any bundles. Before generating features, you may wish to create a bundle to group your features within.')); $this->assertText($this->t('You have not yet created any bundles. Before generating features, you may wish to create a bundle to group your features within.'));
// Creating custom bundle. // Creating custom bundle.
$this->drupalGet('admin/config/development/features/bundle'); $this->drupalGet('admin/config/development/features/bundle');
$this->drupalPostAjaxForm(NULL, array('bundle[bundle_select]' => 'new'), 'bundle[bundle_select]'); $this->drupalPostAjaxForm(NULL, ['bundle[bundle_select]' => 'new'], 'bundle[bundle_select]');
$edit = [ $edit = [
'bundle[name]' => 'foo', 'bundle[name]' => 'foo',
'bundle[machine_name]' => 'foo', 'bundle[machine_name]' => 'foo',
@@ -9,6 +9,7 @@ use Drupal\Core\Config\StorageInterface;
use Drupal\features\Exception\DomainException; use Drupal\features\Exception\DomainException;
use Drupal\features\Exception\InvalidArgumentException; use Drupal\features\Exception\InvalidArgumentException;
use Drupal\features\FeaturesAssignerInterface; use Drupal\features\FeaturesAssignerInterface;
use Drupal\features\FeaturesBundleInterface;
use Drupal\features\FeaturesGeneratorInterface; use Drupal\features\FeaturesGeneratorInterface;
use Drupal\features\FeaturesManagerInterface; use Drupal\features\FeaturesManagerInterface;
use Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationWrite; use Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationWrite;
@@ -246,7 +247,7 @@ class FeaturesCommands extends DrushCommands {
public function listPackages($package_name = NULL, $options = self::OPTIONS_LIST) { public function listPackages($package_name = NULL, $options = self::OPTIONS_LIST) {
$assigner = $this->featuresOptions($options); $assigner = $this->featuresOptions($options);
$current_bundle = $assigner->getBundle(); $current_bundle = $assigner->getBundle();
$namespace = $current_bundle->isDefault() ? '' : $current_bundle->getMachineName(); $namespace = $current_bundle->isDefault() ? FeaturesBundleInterface::DEFAULT_BUNDLE : $current_bundle->getMachineName();
$manager = $this->manager; $manager = $this->manager;
$packages = $manager->getPackages(); $packages = $manager->getPackages();
@@ -312,7 +313,7 @@ class FeaturesCommands extends DrushCommands {
public function importAll($options = self::OPTIONS_IMPORT_ALL) { public function importAll($options = self::OPTIONS_IMPORT_ALL) {
$assigner = $this->featuresOptions($options); $assigner = $this->featuresOptions($options);
$currentBundle = $assigner->getBundle(); $currentBundle = $assigner->getBundle();
$namespace = $currentBundle->isDefault() ? '' : $currentBundle->getMachineName(); $namespace = $currentBundle->isDefault() ? FeaturesBundleInterface::DEFAULT_BUNDLE : $currentBundle->getMachineName();
$manager = $this->manager; $manager = $this->manager;
$packages = $manager->getPackages(); $packages = $manager->getPackages();
@@ -69,7 +69,7 @@ class FeaturesController implements ContainerInjectionInterface {
throw new AccessDeniedHttpException(); throw new AccessDeniedHttpException();
} }
$request = new Request(array('file' => $uri)); $request = new Request(['file' => $uri]);
return $this->fileDownloadController->download($request, 'temporary'); return $this->fileDownloadController->download($request, 'temporary');
} }
} }
@@ -193,7 +193,7 @@ class FeaturesBundle extends ConfigEntityBase implements FeaturesBundleInterface
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getEnabledAssignments() { public function getEnabledAssignments() {
$list = array(); $list = [];
foreach ($this->assignments as $method_id => $method) { foreach ($this->assignments as $method_id => $method) {
if ($method['enabled']) { if ($method['enabled']) {
$list[$method_id] = $method_id; $list[$method_id] = $method_id;
@@ -221,7 +221,7 @@ class FeaturesBundle extends ConfigEntityBase implements FeaturesBundleInterface
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getAssignmentWeights() { public function getAssignmentWeights() {
$list = array(); $list = [];
foreach ($this->assignments as $method_id => $method) { foreach ($this->assignments as $method_id => $method) {
$list[$method_id] = $method['weight']; $list[$method_id] = $method['weight'];
} }
@@ -275,7 +275,7 @@ class FeaturesBundle extends ConfigEntityBase implements FeaturesBundleInterface
} }
} }
else { else {
$list = array(); $list = [];
foreach (array_keys($this->assignments) as $method_id) { foreach (array_keys($this->assignments) as $method_id) {
$list[$method_id] = $this->getAssignmentSettings($method_id); $list[$method_id] = $this->getAssignmentSettings($method_id);
} }
@@ -113,7 +113,7 @@ class FeaturesAssigner implements FeaturesAssignerInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function reset() { public function reset() {
$this->methods = array(); $this->methods = [];
$this->featuresManager->reset(); $this->featuresManager->reset();
} }
@@ -181,7 +181,7 @@ class FeaturesAssigner implements FeaturesAssignerInterface {
*/ */
protected function getAssignmentMethodInstance($method_id) { protected function getAssignmentMethodInstance($method_id) {
if (!isset($this->methods[$method_id])) { if (!isset($this->methods[$method_id])) {
$instance = $this->assignerManager->createInstance($method_id, array()); $instance = $this->assignerManager->createInstance($method_id, []);
$instance->setFeaturesManager($this->featuresManager); $instance->setFeaturesManager($this->featuresManager);
$instance->setAssigner($this); $instance->setAssigner($this);
$instance->setEntityTypeManager($this->entityTypeManager); $instance->setEntityTypeManager($this->entityTypeManager);
@@ -261,7 +261,7 @@ class FeaturesAssigner implements FeaturesAssignerInterface {
*/ */
public function getBundleList() { public function getBundleList() {
if (empty($this->bundles)) { if (empty($this->bundles)) {
$this->bundles = array(); $this->bundles = [];
foreach ($this->entityTypeManager->getStorage('features_bundle')->loadMultiple() as $machine_name => $bundle) { foreach ($this->entityTypeManager->getStorage('features_bundle')->loadMultiple() as $machine_name => $bundle) {
$this->bundles[$machine_name] = $bundle; $this->bundles[$machine_name] = $bundle;
} }
@@ -279,7 +279,7 @@ class FeaturesAssigner implements FeaturesAssignerInterface {
return $bundle; return $bundle;
} }
} }
$machine_name = strtolower(str_replace(array(' ', '-'), '_', $name)); $machine_name = strtolower(str_replace([' ', '-'], '_', $name));
if (isset($bundles[$machine_name])) { if (isset($bundles[$machine_name])) {
return $bundles[$machine_name]; return $bundles[$machine_name];
} }
@@ -311,7 +311,7 @@ class FeaturesAssigner implements FeaturesAssignerInterface {
$bundle->setDescription($description); $bundle->setDescription($description);
} }
else { else {
$bundle->setDescription(t('Auto-generated bundle from package @name', array('@name' => $name))); $bundle->setDescription(t('Auto-generated bundle from package @name', ['@name' => $name]));
} }
$bundle->setIsProfile($is_profile); $bundle->setIsProfile($is_profile);
if (isset($profile_name)) { if (isset($profile_name)) {
@@ -374,7 +374,7 @@ class FeaturesAssigner implements FeaturesAssignerInterface {
*/ */
public function getBundleOptions() { public function getBundleOptions() {
$list = $this->getBundleList(); $list = $this->getBundleList();
$result = array(); $result = [];
foreach ($list as $machine_name => $bundle) { foreach ($list as $machine_name => $bundle) {
$result[$machine_name] = $bundle->getName(); $result[$machine_name] = $bundle->getName();
} }
@@ -17,9 +17,9 @@ class FeaturesConfigDependencyManager extends ConfigDependencyManager{
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getDependentEntities($type, $name) { public function getDependentEntities($type, $name) {
$dependent_entities = array(); $dependent_entities = [];
$entities_to_check = array(); $entities_to_check = [];
if ($type == 'config') { if ($type == 'config') {
$entities_to_check[] = $name; $entities_to_check[] = $name;
} }
@@ -42,7 +42,7 @@ class FeaturesConfigDependencyManager extends ConfigDependencyManager{
// always after field storages. This is because field storages need to be // always after field storages. This is because field storages need to be
// created before a field. // created before a field.
$this->sorted_graph = $this->getGraph(); $this->sorted_graph = $this->getGraph();
uasort($this->sorted_graph, array($this, 'sortGraph')); uasort($this->sorted_graph, [$this, 'sortGraph']);
} }
return array_replace(array_intersect_key($this->sorted_graph, $dependencies), $dependencies); return array_replace(array_intersect_key($this->sorted_graph, $dependencies), $dependencies);
} }
@@ -75,7 +75,7 @@ class FeaturesConfigInstaller extends ConfigInstaller {
$features_config = array_keys($this->featuresManager->listExistingConfig()); $features_config = array_keys($this->featuresManager->listExistingConfig());
// Map array so we can use isset instead of in_array for faster access. // Map array so we can use isset instead of in_array for faster access.
$features_config = array_combine($features_config, $features_config); $features_config = array_combine($features_config, $features_config);
$existing_configuration = array(); $existing_configuration = [];
// Gather information about all the supported collections. // Gather information about all the supported collections.
$collection_info = $this->configManager->getConfigCollectionInfo(); $collection_info = $this->configManager->getConfigCollectionInfo();
@@ -0,0 +1,24 @@
<?php
namespace Drupal\features;
/**
* Wraps FeaturesInstallStorage to support multiple configuration
* directories.
*/
class FeaturesExtensionStoragesByDirectory extends FeaturesExtensionStorages implements FeaturesExtensionStoragesByDirectoryInterface {
/**
* {@inheritdoc}
*/
public function listAllByDirectory($prefix = '') {
if (!isset($this->configurationLists[$prefix])) {
$this->configurationLists[$prefix] = [];
foreach ($this->extensionStorages as $directory => $extension_storage) {
$this->configurationLists[$prefix] += array_fill_keys($extension_storage->listAll($prefix), $directory);
}
}
return $this->configurationLists[$prefix];
}
}
@@ -0,0 +1,26 @@
<?php
namespace Drupal\features;
/**
* Defines an extended interface for extension storages.
*/
interface FeaturesExtensionStoragesByDirectoryInterface extends FeaturesExtensionStoragesInterface {
/**
* Returns a list of all configuration available from extensions.
*
* This method was made public late in the 8.x-3.x cycle and so is not
* included in the interface.
*
* @param string $prefix
* (optional) The prefix to search for. If omitted, all configuration object
* names that exist are returned.
*
* @return array
* An array with configuration item names as keys and configuration
* directories as values.
*/
public function listAllByDirectory($prefix = '');
}
@@ -65,7 +65,7 @@ abstract class FeaturesGenerationMethodBase implements FeaturesGenerationMethodI
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function prepare(array &$packages = array(), FeaturesBundleInterface $bundle = NULL) { public function prepare(array &$packages = [], FeaturesBundleInterface $bundle = NULL) {
// If no packages were specified, get all packages. // If no packages were specified, get all packages.
if (empty($packages)) { if (empty($packages)) {
$packages = $this->featuresManager->getPackages(); $packages = $this->featuresManager->getPackages();
@@ -37,7 +37,7 @@ interface FeaturesGenerationMethodInterface {
* @return array * @return array
* An array of packages data. * An array of packages data.
*/ */
public function prepare(array &$packages = array(), FeaturesBundleInterface $bundle = NULL); public function prepare(array &$packages = [], FeaturesBundleInterface $bundle = NULL);
/** /**
* Performs package generation. * Performs package generation.
@@ -56,7 +56,7 @@ interface FeaturesGenerationMethodInterface {
* - 'message': a message about the result of the operation. * - 'message': a message about the result of the operation.
* - 'variables': an array of substitutions to be used in the message. * - 'variables': an array of substitutions to be used in the message.
*/ */
public function generate(array $packages = array(), FeaturesBundleInterface $bundle = NULL); public function generate(array $packages = [], FeaturesBundleInterface $bundle = NULL);
/** /**
* Responds to the submission of * Responds to the submission of
@@ -69,13 +69,13 @@ class FeaturesGenerator implements FeaturesGeneratorInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function reset() { public function reset() {
$this->methods = array(); $this->methods = [];
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function applyGenerationMethod($method_id, array $packages = array(), FeaturesBundleInterface $bundle = NULL) { public function applyGenerationMethod($method_id, array $packages = [], FeaturesBundleInterface $bundle = NULL) {
$method = $this->getGenerationMethodInstance($method_id); $method = $this->getGenerationMethodInstance($method_id);
$method->prepare($packages, $bundle); $method->prepare($packages, $bundle);
return $method->generate($packages, $bundle); return $method->generate($packages, $bundle);
@@ -107,7 +107,7 @@ class FeaturesGenerator implements FeaturesGeneratorInterface {
*/ */
protected function getGenerationMethodInstance($method_id) { protected function getGenerationMethodInstance($method_id) {
if (!isset($this->methods[$method_id])) { if (!isset($this->methods[$method_id])) {
$instance = $this->generatorManager->createInstance($method_id, array()); $instance = $this->generatorManager->createInstance($method_id, []);
$instance->setFeaturesManager($this->featuresManager); $instance->setFeaturesManager($this->featuresManager);
$instance->setAssigner($this->assigner); $instance->setAssigner($this->assigner);
$this->methods[$method_id] = $instance; $this->methods[$method_id] = $instance;
@@ -118,7 +118,7 @@ class FeaturesGenerator implements FeaturesGeneratorInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function generatePackages($method_id, FeaturesBundleInterface $bundle, array $package_names = array()) { public function generatePackages($method_id, FeaturesBundleInterface $bundle, array $package_names = []) {
$this->featuresManager->setPackageBundleNames($bundle, $package_names); $this->featuresManager->setPackageBundleNames($bundle, $package_names);
return $this->generate($method_id, $bundle, $package_names); return $this->generate($method_id, $bundle, $package_names);
} }
@@ -144,7 +144,7 @@ class FeaturesGenerator implements FeaturesGeneratorInterface {
* - 'message': a message about the result of the operation. * - 'message': a message about the result of the operation.
* - 'variables': an array of substitutions to be used in the message. * - 'variables': an array of substitutions to be used in the message.
*/ */
protected function generate($method_id, FeaturesBundleInterface $bundle, array $package_names = array()) { protected function generate($method_id, FeaturesBundleInterface $bundle, array $package_names = []) {
$packages = $this->featuresManager->getPackages(); $packages = $this->featuresManager->getPackages();
// Filter out the packages that weren't requested. // Filter out the packages that weren't requested.
@@ -71,7 +71,7 @@ interface FeaturesGeneratorInterface {
* - 'message': a message about the result of the operation. * - 'message': a message about the result of the operation.
* - 'variables': an array of substitutions to be used in the message. * - 'variables': an array of substitutions to be used in the message.
*/ */
public function applyGenerationMethod($method_id, array $packages = array(), FeaturesBundleInterface $bundle = NULL); public function applyGenerationMethod($method_id, array $packages = [], FeaturesBundleInterface $bundle = NULL);
/** /**
* Responds to the submission of * Responds to the submission of
@@ -98,6 +98,6 @@ interface FeaturesGeneratorInterface {
* Array of names of packages to be generated. If none are specified, all * Array of names of packages to be generated. If none are specified, all
* available packages will be added. * available packages will be added.
*/ */
public function generatePackages($method_id, FeaturesBundleInterface $bundle, array $package_names = array()); public function generatePackages($method_id, FeaturesBundleInterface $bundle, array $package_names = []);
} }
@@ -66,7 +66,7 @@ class FeaturesInstallStorage extends ExtensionInstallStorage {
*/ */
public function getAllFolders() { public function getAllFolders() {
if (!isset($this->folders)) { if (!isset($this->folders)) {
$this->folders = array(); $this->folders = [];
$this->folders += $this->getCoreNames(); $this->folders += $this->getCoreNames();
$install_profile = Settings::get('install_profile'); $install_profile = Settings::get('install_profile');
@@ -117,8 +117,8 @@ class FeaturesInstallStorage extends ExtensionInstallStorage {
// CHANGED START: Put Features modules first in list returned. // CHANGED START: Put Features modules first in list returned.
// to allow features to override config provided by other extensions. // to allow features to override config provided by other extensions.
$featuresManager = \Drupal::service('features.manager'); $featuresManager = \Drupal::service('features.manager');
$features_list = array(); $features_list = [];
$module_list = array(); $module_list = [];
foreach (array_keys($module_list_scan) as $module) { foreach (array_keys($module_list_scan) as $module) {
if ($featuresManager->isFeatureModule($module_list_scan[$module])) { if ($featuresManager->isFeatureModule($module_list_scan[$module])) {
$features_list[$module] = $module_list_scan[$module]; $features_list[$module] = $module_list_scan[$module];
@@ -150,7 +150,7 @@ class FeaturesInstallStorage extends ExtensionInstallStorage {
$profile_list = $listing->scan('profile'); $profile_list = $listing->scan('profile');
} }
if (isset($profile_list[$profile])) { if (isset($profile_list[$profile])) {
$profile_folders = $this->getComponentNames(array($profile_list[$profile])); $profile_folders = $this->getComponentNames([$profile_list[$profile]]);
$this->folders = $profile_folders + $this->folders; $this->folders = $profile_folders + $this->folders;
} }
} }
@@ -39,7 +39,7 @@ class FeaturesManager implements FeaturesManagerInterface {
/** /**
* The extension storages. * The extension storages.
* *
* @var \Drupal\features\FeaturesExtensionStoragesInterface * @var \Drupal\features\FeaturesExtensionStoragesByDirectoryInterface
*/ */
protected $extensionStorages; protected $extensionStorages;
@@ -148,7 +148,7 @@ class FeaturesManager implements FeaturesManagerInterface {
$this->configFactory = $config_factory; $this->configFactory = $config_factory;
$this->configReverter = $config_reverter; $this->configReverter = $config_reverter;
$this->settings = $config_factory->getEditable('features.settings'); $this->settings = $config_factory->getEditable('features.settings');
$this->extensionStorages = new FeaturesExtensionStorages($this->configStorage); $this->extensionStorages = new FeaturesExtensionStoragesByDirectory($this->configStorage);
$this->extensionStorages->addStorage(InstallStorage::CONFIG_INSTALL_DIRECTORY); $this->extensionStorages->addStorage(InstallStorage::CONFIG_INSTALL_DIRECTORY);
$this->extensionStorages->addStorage(InstallStorage::CONFIG_OPTIONAL_DIRECTORY); $this->extensionStorages->addStorage(InstallStorage::CONFIG_OPTIONAL_DIRECTORY);
$this->packages = []; $this->packages = [];
@@ -196,10 +196,10 @@ class FeaturesManager implements FeaturesManagerInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getConfigType($fullname) { public function getConfigType($fullname) {
$result = array( $result = [
'type' => '', 'type' => '',
'name_short' => '', 'name_short' => '',
); ];
$prefix = FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG . '.'; $prefix = FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG . '.';
if (strpos($fullname, $prefix) !== FALSE) { if (strpos($fullname, $prefix) !== FALSE) {
$result['type'] = FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG; $result['type'] = FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG;
@@ -320,7 +320,7 @@ class FeaturesManager implements FeaturesManagerInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function filterPackages(array $packages, $namespace = '', $only_exported = FALSE) { public function filterPackages(array $packages, $namespace = '', $only_exported = FALSE) {
$result = array(); $result = [];
/** @var \Drupal\features\Package $package */ /** @var \Drupal\features\Package $package */
foreach ($packages as $key => $package) { foreach ($packages as $key => $package) {
// A package matches the namespace if: // A package matches the namespace if:
@@ -417,7 +417,7 @@ class FeaturesManager implements FeaturesManagerInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function listPackageDirectories(array $machine_names = array(), FeaturesBundleInterface $bundle = NULL) { public function listPackageDirectories(array $machine_names = [], FeaturesBundleInterface $bundle = NULL) {
if (empty($machine_names)) { if (empty($machine_names)) {
$machine_names = array_keys($this->getPackages()); $machine_names = array_keys($this->getPackages());
} }
@@ -438,7 +438,7 @@ class FeaturesManager implements FeaturesManagerInterface {
return in_array($module->getName(), $machine_names); return in_array($module->getName(), $machine_names);
}); });
$directories = array(); $directories = [];
foreach ($modules as $module) { foreach ($modules as $module) {
$directories[$module->getName()] = $module->getPath(); $directories[$module->getName()] = $module->getPath();
} }
@@ -546,7 +546,7 @@ class FeaturesManager implements FeaturesManagerInterface {
* @param array $module_list * @param array $module_list
* @return array $dependencies * @return array $dependencies
*/ */
protected function getConfigDependency(ConfigurationItem $config, $module_list = array()) { protected function getConfigDependency(ConfigurationItem $config, $module_list = []) {
$dependencies = []; $dependencies = [];
$type = $config->getType(); $type = $config->getType();
@@ -737,7 +737,7 @@ class FeaturesManager implements FeaturesManagerInterface {
$packages = $this->getPackages(); $packages = $this->getPackages();
} }
else { else {
$packages = array($package); $packages = [$package];
} }
$module_list = $this->moduleHandler->getModuleList(); $module_list = $this->moduleHandler->getModuleList();
$config_collection = $this->getConfigCollection(); $config_collection = $this->getConfigCollection();
@@ -940,7 +940,7 @@ class FeaturesManager implements FeaturesManagerInterface {
} }
if ($package->getConfig()) { if ($package->getConfig()) {
foreach (array('excluded', 'required') as $constraint) { foreach (['excluded', 'required'] as $constraint) {
if (!empty($package->{'get' . $constraint}())) { if (!empty($package->{'get' . $constraint}())) {
$features_info[$constraint] = $package->{'get' . $constraint}(); $features_info[$constraint] = $package->{'get' . $constraint}();
} }
@@ -957,7 +957,7 @@ class FeaturesManager implements FeaturesManagerInterface {
// The name and description need to be cast as strings from the // The name and description need to be cast as strings from the
// TranslatableMarkup objects returned by t() to avoid raising an // TranslatableMarkup objects returned by t() to avoid raising an
// InvalidDataTypeException on Yaml serialization. // InvalidDataTypeException on Yaml serialization.
foreach (array('name', 'description') as $key) { foreach (['name', 'description'] as $key) {
$info[$key] = (string) $info[$key]; $info[$key] = (string) $info[$key];
} }
@@ -1008,7 +1008,7 @@ class FeaturesManager implements FeaturesManagerInterface {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mergeInfoArray(array $info1, array $info2, array $keys = array()) { public function mergeInfoArray(array $info1, array $info2, array $keys = []) {
// If keys were specified, use only those. // If keys were specified, use only those.
if (!empty($keys)) { if (!empty($keys)) {
$info2 = array_intersect_key($info2, array_fill_keys($keys, NULL)); $info2 = array_intersect_key($info2, array_fill_keys($keys, NULL));
@@ -1061,7 +1061,7 @@ class FeaturesManager implements FeaturesManagerInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function listExistingConfig($installed = FALSE, FeaturesBundleInterface $bundle = NULL) { public function listExistingConfig($installed = FALSE, FeaturesBundleInterface $bundle = NULL) {
$config = array(); $config = [];
$existing = $this->getFeaturesModules($bundle, $installed); $existing = $this->getFeaturesModules($bundle, $installed);
foreach ($existing as $extension) { foreach ($existing as $extension) {
// Keys are configuration item names and values are providing extension // Keys are configuration item names and values are providing extension
@@ -1150,6 +1150,7 @@ class FeaturesManager implements FeaturesManagerInterface {
$dependency_manager = $this->getFeaturesConfigDependencyManager(); $dependency_manager = $this->getFeaturesConfigDependencyManager();
// List configuration provided by installed features. // List configuration provided by installed features.
$existing_config = $this->listExistingConfig(NULL); $existing_config = $this->listExistingConfig(NULL);
$existing_config_by_directory = $this->extensionStorages->listAllByDirectory();
foreach (array_keys($config_types) as $config_type) { foreach (array_keys($config_types) as $config_type) {
$config = $this->listConfigByType($config_type); $config = $this->listConfigByType($config_type);
foreach ($config as $item_name => $label) { foreach ($config as $item_name => $label) {
@@ -1162,7 +1163,7 @@ class FeaturesManager implements FeaturesManagerInterface {
'type' => $config_type, 'type' => $config_type,
'dependents' => array_keys($dependency_manager->getDependentEntities('config', $name)), 'dependents' => array_keys($dependency_manager->getDependentEntities('config', $name)),
// Default to the install directory. // Default to the install directory.
'subdirectory' => InstallStorage::CONFIG_INSTALL_DIRECTORY, 'subdirectory' => isset($existing_config_by_directory[$name]) ? $existing_config_by_directory[$name] : InstallStorage::CONFIG_INSTALL_DIRECTORY,
'package' => '', 'package' => '',
'providerExcluded' => NULL, 'providerExcluded' => NULL,
'provider' => isset($existing_config[$name]) ? $existing_config[$name] : NULL, 'provider' => isset($existing_config[$name]) ? $existing_config[$name] : NULL,
@@ -1211,7 +1212,7 @@ class FeaturesManager implements FeaturesManagerInterface {
$path = dirname($extension_path); $path = dirname($extension_path);
} }
return array($full_name, $path); return [$full_name, $path];
} }
/** /**
@@ -1221,11 +1222,11 @@ class FeaturesManager implements FeaturesManagerInterface {
/** @var \Drupal\config_update\ConfigDiffInterface $config_diff */ /** @var \Drupal\config_update\ConfigDiffInterface $config_diff */
$config_diff = \Drupal::service('config_update.config_diff'); $config_diff = \Drupal::service('config_update.config_diff');
$different = array(); $different = [];
foreach ($feature->getConfig() as $name) { foreach ($feature->getConfig() as $name) {
$active = $this->configStorage->read($name); $active = $this->configStorage->read($name);
$extension = $this->extensionStorages->read($name); $extension = $this->extensionStorages->read($name);
$extension = !empty($extension) ? $extension : array(); $extension = !empty($extension) ? $extension : [];
if (($include_new || !empty($extension)) && !$config_diff->same($extension, $active)) { if (($include_new || !empty($extension)) && !$config_diff->same($extension, $active)) {
$different[] = $name; $different[] = $name;
} }
@@ -1241,7 +1242,7 @@ class FeaturesManager implements FeaturesManagerInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function detectNew(Package $feature) { public function detectNew(Package $feature) {
$result = array(); $result = [];
foreach ($feature->getConfig() as $name) { foreach ($feature->getConfig() as $name) {
$extension = $this->extensionStorages->read($name); $extension = $this->extensionStorages->read($name);
if (empty($extension)) { if (empty($extension)) {
@@ -1256,7 +1257,7 @@ class FeaturesManager implements FeaturesManagerInterface {
*/ */
public function detectMissing(Package $feature) { public function detectMissing(Package $feature) {
$config = $this->getConfigCollection(); $config = $this->getConfigCollection();
$result = array(); $result = [];
foreach ($feature->getConfigOrig() as $name) { foreach ($feature->getConfigOrig() as $name) {
if (!isset($config[$name])) { if (!isset($config[$name])) {
$result[] = $name; $result[] = $name;
@@ -1269,8 +1270,8 @@ class FeaturesManager implements FeaturesManagerInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function reorderMissing(array $missing) { public function reorderMissing(array $missing) {
$list = array(); $list = [];
$result = array(); $result = [];
foreach ($missing as $full_name) { foreach ($missing as $full_name) {
$this->addConfigList($full_name, $list); $this->addConfigList($full_name, $list);
} }
@@ -328,7 +328,7 @@ interface FeaturesManagerInterface {
* @return array * @return array
* Array of package directories keyed by package machine name. * Array of package directories keyed by package machine name.
*/ */
public function listPackageDirectories(array $machine_names = array(), FeaturesBundleInterface $bundle = NULL); public function listPackageDirectories(array $machine_names = [], FeaturesBundleInterface $bundle = NULL);
/** /**
* Assigns a set of configuration items to a given package or profile. * Assigns a set of configuration items to a given package or profile.
@@ -414,7 +414,7 @@ interface FeaturesManagerInterface {
* *
* @fixme Should this be moved to the package object or a related helper? * @fixme Should this be moved to the package object or a related helper?
*/ */
public function mergeInfoArray(array $info1, array $info2, array $keys = array()); public function mergeInfoArray(array $info1, array $info2, array $keys = []);
/** /**
* Lists the types of configuration available on the site. * Lists the types of configuration available on the site.
@@ -429,7 +429,7 @@ class Package {
$this->setBundle($features_info['bundle']); $this->setBundle($features_info['bundle']);
} }
$this->setRequired(isset($features_info['required']) ? $features_info['required'] : false); $this->setRequired(isset($features_info['required']) ? $features_info['required'] : false);
$this->setExcluded(isset($features_info['excluded']) ? $features_info['excluded'] : array()); $this->setExcluded(isset($features_info['excluded']) ? $features_info['excluded'] : []);
return $this; return $this;
} }
@@ -2,7 +2,7 @@
namespace Drupal\features\Plugin\FeaturesAssignment; namespace Drupal\features\Plugin\FeaturesAssignment;
use Drupal\component\Utility\Unicode; use Drupal\Component\Utility\Unicode;
use Drupal\features\FeaturesAssignmentMethodBase; use Drupal\features\FeaturesAssignmentMethodBase;
/** /**
@@ -37,7 +37,7 @@ class FeaturesAssignmentBaseType extends FeaturesAssignmentMethodBase {
foreach ($config_collection as $item_name => $item) { foreach ($config_collection as $item_name => $item) {
if (in_array($item->getType(), $config_base_types)) { if (in_array($item->getType(), $config_base_types)) {
if (is_null($this->featuresManager->findPackage($item->getShortName())) && !$item->getPackage()) { if (is_null($this->featuresManager->findPackage($item->getShortName())) && !$item->getPackage()) {
$description = $this->t('Provides @label @type and related configuration.', array('@label' => $item->getLabel(), '@type' => Unicode::strtolower($config_types[$item->getType()]))); $description = $this->t('Provides @label @type and related configuration.', ['@label' => $item->getLabel(), '@type' => Unicode::strtolower($config_types[$item->getType()])]);
if (isset($item->getData()['description'])) { if (isset($item->getData()['description'])) {
$description .= ' ' . $item->getData()['description']; $description .= ' ' . $item->getData()['description'];
} }
@@ -59,7 +59,7 @@ class FeaturesAssignmentBaseType extends FeaturesAssignmentMethodBase {
foreach ($content_base_types as $entity_type_id) { foreach ($content_base_types as $entity_type_id) {
if (!isset($packages[$entity_type_id]) && isset($entity_types[$entity_type_id])) { if (!isset($packages[$entity_type_id]) && isset($entity_types[$entity_type_id])) {
$label = $entity_types[$entity_type_id]->getLabel(); $label = $entity_types[$entity_type_id]->getLabel();
$description = $this->t('Provide @label related configuration.', array('@label' => $label)); $description = $this->t('Provide @label related configuration.', ['@label' => $label]);
$this->featuresManager->initPackage($entity_type_id, $label, $description, 'module', $current_bundle); $this->featuresManager->initPackage($entity_type_id, $label, $description, 'module', $current_bundle);
} }
} }
@@ -71,7 +71,7 @@ class FeaturesAssignmentProfile extends FeaturesAssignmentMethodBase {
// Only read in from the Standard profile if this profile doesn't already // Only read in from the Standard profile if this profile doesn't already
// exist. // exist.
$package_directories = $this->featuresManager->listPackageDirectories(array(), $current_bundle); $package_directories = $this->featuresManager->listPackageDirectories([], $current_bundle);
if (!isset($package_directories[$profile_name])) { if (!isset($package_directories[$profile_name])) {
$standard_directory = 'core/profiles/standard'; $standard_directory = 'core/profiles/standard';
// Conditionally add files from the 'standard' install profile. // Conditionally add files from the 'standard' install profile.
@@ -128,7 +128,7 @@ class FeaturesGenerationArchive extends FeaturesGenerationMethodBase implements
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function generate(array $packages = array(), FeaturesBundleInterface $bundle = NULL) { public function generate(array $packages = [], FeaturesBundleInterface $bundle = NULL) {
// If no packages were specified, get all packages. // If no packages were specified, get all packages.
if (empty($packages)) { if (empty($packages)) {
@@ -101,7 +101,7 @@ class FeaturesGenerationWrite extends FeaturesGenerationMethodBase implements Co
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function generate(array $packages = array(), FeaturesBundleInterface $bundle = NULL) { public function generate(array $packages = [], FeaturesBundleInterface $bundle = NULL) {
// If no packages were specified, get all packages. // If no packages were specified, get all packages.
if (empty($packages)) { if (empty($packages)) {
$packages = $this->featuresManager->getPackages(); $packages = $this->featuresManager->getPackages();
@@ -6,8 +6,8 @@ package: Test
dependencies: dependencies:
- features - features
# Information added by Drupal.org packaging script on 2018-02-27 # Information added by Drupal.org packaging script on 2018-09-09
version: '8.x-3.7' version: '8.x-3.8'
core: '8.x' core: '8.x'
project: 'features' project: 'features'
datestamp: 1519763291 datestamp: 1536512288
@@ -6,8 +6,8 @@ package: Test
dependencies: dependencies:
- features - features
# Information added by Drupal.org packaging script on 2018-02-27 # Information added by Drupal.org packaging script on 2018-09-09
version: '8.x-3.7' version: '8.x-3.8'
core: '8.x' core: '8.x'
project: 'features' project: 'features'
datestamp: 1519763291 datestamp: 1536512288
@@ -18,6 +18,15 @@ class FeaturesAssignerTest extends KernelTestBase {
protected $strictConfigSchema = FALSE; protected $strictConfigSchema = FALSE;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// We need system.site in order to run $this->configImporter->import().
$this->installConfig('system');
}
/** /**
* Test bundle auto-creation during config import. * Test bundle auto-creation during config import.
* *
@@ -41,7 +50,7 @@ class FeaturesAssignerTest extends KernelTestBase {
// Uninstall modules. // Uninstall modules.
$installer->uninstall(['features', 'test_feature']); $installer->uninstall(['features', 'test_feature']);
// Restore the config from after install.. // Restore the config from after install.
$this->configImporter()->import(); $this->configImporter()->import();
// Find the auto-created bundle. // Find the auto-created bundle.
@@ -11,3 +11,10 @@ reduce_ascii : FALSE
case : TRUE case : TRUE
ignore_words : 'a, an, as, at, before, but, by, for, from, is, in, into, like, of, off, on, onto, per, since, than, the, this, that, to, up, via, with' ignore_words : 'a, an, as, at, before, but, by, for, from, is, in, into, like, of, off, on, onto, per, since, than, the, this, that, to, up, via, with'
update_action : 2 update_action : 2
safe_tokens:
- alias
- path
- join-path
- login-url
- url
- url-brief
@@ -22,14 +22,17 @@ pathauto.settings:
type: boolean type: boolean
reduce_ascii: reduce_ascii:
type: boolean type: boolean
ignore_words:
type: string
case: case:
type: boolean type: boolean
ignore_words: ignore_words:
type: string type: string
update_action: update_action:
type: integer type: integer
safe_tokens:
label: Tokens that are safe to use and do not need to be cleaned.
type: sequence
sequence:
type: string
action.configuration.pathauto_update_alias: action.configuration.pathauto_update_alias:
type: action_configuration_default type: action_configuration_default
@@ -93,9 +93,8 @@ function hook_pathauto_is_alias_reserved($alias, $source, $langcode) {
* This hook will only be called if a default pattern is configured (on * This hook will only be called if a default pattern is configured (on
* admin/config/search/path/patterns). * admin/config/search/path/patterns).
* *
* @param string $pattern * @param \Drupal\pathauto\PathautoPatternInterface $pattern
* The alias pattern for Pathauto to pass to token_replace() to generate the * The Pathauto pattern to be used.
* URL alias.
* @param array $context * @param array $context
* An associative array of additional options, with the following elements: * An associative array of additional options, with the following elements:
* - 'module': The module or entity type being aliased. * - 'module': The module or entity type being aliased.
@@ -103,14 +102,14 @@ function hook_pathauto_is_alias_reserved($alias, $source, $langcode) {
* aliased. Can be either 'insert', 'update', 'return', or 'bulkupdate'. * aliased. Can be either 'insert', 'update', 'return', or 'bulkupdate'.
* - 'source': A string of the source path for the alias (e.g. 'node/1'). * - 'source': A string of the source path for the alias (e.g. 'node/1').
* - 'data': An array of keyed objects to pass to token_replace(). * - 'data': An array of keyed objects to pass to token_replace().
* - 'type': The sub-type or bundle of the object being aliased. * - 'bundle': The sub-type or bundle of the object being aliased.
* - 'language': A string of the language code for the alias (e.g. 'en'). * - 'language': A string of the language code for the alias (e.g. 'en').
* This can be altered by reference. * This can be altered by reference.
*/ */
function hook_pathauto_pattern_alter(&$pattern, array $context) { function hook_pathauto_pattern_alter(\Drupal\pathauto\PathautoPatternInterface $pattern, array $context) {
// Switch out any [node:created:*] tokens with [node:updated:*] on update. // Switch out any [node:created:*] tokens with [node:updated:*] on update.
if ($context['module'] == 'node' && ($context['op'] == 'update')) { if ($context['module'] == 'node' && ($context['op'] == 'update')) {
$pattern = preg_replace('/\[node:created(\:[^]]*)?\]/', '[node:updated$1]', $pattern); $pattern->setPattern(preg_replace('/\[node:created(\:[^]]*)?\]/', '[node:updated$1]', $pattern->getPattern()));
} }
} }
@@ -133,7 +132,7 @@ function hook_pathauto_pattern_alter(&$pattern, array $context) {
* - 'pattern': A string of the pattern used for aliasing the object. * - 'pattern': A string of the pattern used for aliasing the object.
*/ */
function hook_pathauto_alias_alter(&$alias, array &$context) { function hook_pathauto_alias_alter(&$alias, array &$context) {
// Add a suffix so that all aliases get saved as 'content/my-title.html' // Add a suffix so that all aliases get saved as 'content/my-title.html'.
$alias .= '.html'; $alias .= '.html';
// Force all aliases to be saved as language neutral. // Force all aliases to be saved as language neutral.
@@ -143,7 +142,7 @@ function hook_pathauto_alias_alter(&$alias, array &$context) {
/** /**
* Alter the list of punctuation characters for Pathauto control. * Alter the list of punctuation characters for Pathauto control.
* *
* @param $punctuation * @param array $punctuation
* An array of punctuation to be controlled by Pathauto during replacement * An array of punctuation to be controlled by Pathauto during replacement
* keyed by punctuation name. Each punctuation record should be an array * keyed by punctuation name. Each punctuation record should be an array
* with the following key/value pairs: * with the following key/value pairs:
@@ -6,6 +6,7 @@ type: module
dependencies: dependencies:
- ctools:ctools - ctools:ctools
- drupal:path - drupal:path
- drupal:system (>=8.5)
- token:token - token:token
configure: entity.pathauto_pattern.collection configure: entity.pathauto_pattern.collection
@@ -13,8 +14,8 @@ configure: entity.pathauto_pattern.collection
recommends: recommends:
- redirect:redirect - redirect:redirect
# Information added by Drupal.org packaging script on 2018-03-03 # Information added by Drupal.org packaging script on 2018-09-08
version: '8.x-1.1' version: '8.x-1.3'
core: '8.x' core: '8.x'
project: 'pathauto' project: 'pathauto'
datestamp: 1520092688 datestamp: 1536407890
@@ -8,15 +8,13 @@
*/ */
use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\pathauto\Entity\PathautoPattern; use Drupal\pathauto\Entity\PathautoPattern;
/** /**
* Implements hook_install(). * Implements hook_install().
*/ */
function pathauto_install() { function pathauto_install() {
// Set the weight to 1 // Set the weight to 1.
module_set_weight('pathauto', 1); module_set_weight('pathauto', 1);
// Ensure the url_alias table exists. // Ensure the url_alias table exists.
@@ -170,7 +168,8 @@ function pathauto_update_8100() {
continue; continue;
} }
// This is a pattern for a bundle and a language, such as "node_article_es". // This is a pattern for a bundle and a language, such as
// "node_article_es".
$pattern = PathautoPattern::create([ $pattern = PathautoPattern::create([
'id' => $entity_type . '_' . $extracted_bundle . '_' . str_replace('-', '_', $langcode), 'id' => $entity_type . '_' . $extracted_bundle . '_' . str_replace('-', '_', $langcode),
'label' => $entity_label . ' ' . $bundle_info[$extracted_bundle]['label'] . ' ' . $language->getName(), 'label' => $entity_label . ' ' . $bundle_info[$extracted_bundle]['label'] . ' ' . $language->getName(),
@@ -299,3 +298,23 @@ function pathauto_update_8106() {
$config->set('enabled_entity_types', ['user']); $config->set('enabled_entity_types', ['user']);
$config->save(); $config->save();
} }
/**
* Initialize the new safe tokens setting.
*/
function pathauto_update_8107() {
$safe_tokens = [
'alias',
'alias',
'path',
'join-path',
'login-url',
'url',
'url-brief',
];
\Drupal::configFactory()->getEditable('pathauto.settings')
->set('safe_tokens', $safe_tokens)
->save();
}
@@ -2,9 +2,9 @@
'use strict'; 'use strict';
Drupal.behaviors.pathFieldsetSummaries = { Drupal.behaviors.pathFieldsetSummaries = {
attach: function (context) { attach: function (context) {
$('fieldset.path-form', context).drupalSetSummary(function (context) { $(context).find('.path-form').drupalSetSummary(function (context) {
var path = $('.form-item-path-alias input', context).val(); var path = $('.js-form-item-path-0-alias input', context).val();
var automatic = $('.form-item-path-pathauto input', context).attr('checked'); var automatic = $('.js-form-item-path-0-pathauto input', context).prop('checked');
if (automatic) { if (automatic) {
return Drupal.t('Automatic alias'); return Drupal.t('Automatic alias');
@@ -3,4 +3,3 @@ entity.pathauto_pattern.add_form:
title: 'Add Pathauto pattern' title: 'Add Pathauto pattern'
appears_on: appears_on:
- entity.pathauto_pattern.collection - entity.pathauto_pattern.collection
@@ -18,6 +18,8 @@
* @ingroup pathauto * @ingroup pathauto
*/ */
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
@@ -82,6 +84,30 @@ function pathauto_help($route_name, RouteMatchInterface $route_match) {
} }
} }
/**
* Implements hook_entity_insert().
*/
function pathauto_entity_insert(EntityInterface $entity) {
\Drupal::service('pathauto.generator')->updateEntityAlias($entity, 'insert');
}
/**
* Implements hook_entity_update().
*/
function pathauto_entity_update(EntityInterface $entity) {
\Drupal::service('pathauto.generator')->updateEntityAlias($entity, 'update');
}
/**
* Implements hook_entity_delete().
*/
function pathauto_entity_delete(EntityInterface $entity) {
if ($entity->hasLinkTemplate('canonical') && $entity instanceof ContentEntityInterface && $entity->hasField('path')) {
\Drupal::service('pathauto.alias_storage_helper')->deleteEntityPathAll($entity);
$entity->get('path')->first()->get('pathauto')->purge();
}
}
/** /**
* Implements hook_field_info_alter(). * Implements hook_field_info_alter().
*/ */
@@ -15,7 +15,7 @@ services:
arguments: ['@config.factory', '@pathauto.alias_storage_helper','@module_handler', '@router.route_provider', '@path.alias_manager'] arguments: ['@config.factory', '@pathauto.alias_storage_helper','@module_handler', '@router.route_provider', '@path.alias_manager']
pathauto.verbose_messenger: pathauto.verbose_messenger:
class: Drupal\pathauto\VerboseMessenger class: Drupal\pathauto\VerboseMessenger
arguments: ['@config.factory', '@current_user'] arguments: ['@config.factory', '@current_user', '@messenger']
plugin.manager.alias_type: plugin.manager.alias_type:
class: Drupal\pathauto\AliasTypeManager class: Drupal\pathauto\AliasTypeManager
parent: default_plugin_manager parent: default_plugin_manager
@@ -104,7 +104,7 @@ class AliasCleaner implements AliasCleanerInterface {
// Trim duplicate, leading, and trailing separators. Do this before cleaning // Trim duplicate, leading, and trailing separators. Do this before cleaning
// backslashes since a pattern like "[token1]/[token2]-[token3]/[token4]" // backslashes since a pattern like "[token1]/[token2]-[token3]/[token4]"
// could end up like "value1/-/value2" and if backslashes were cleaned first // could end up like "value1/-/value2" and if backslashes were cleaned first
// this would result in a duplicate blackslash. // this would result in a duplicate backslash.
$output = $this->getCleanSeparators($output); $output = $this->getCleanSeparators($output);
// Trim duplicate, leading, and trailing backslashes. // Trim duplicate, leading, and trailing backslashes.
@@ -247,7 +247,7 @@ class AliasCleaner implements AliasCleanerInterface {
// Get rid of words that are on the ignore list. // Get rid of words that are on the ignore list.
if ($this->cleanStringCache['ignore_words_regex']) { if ($this->cleanStringCache['ignore_words_regex']) {
$words_removed = $this->cleanStringCache['ignore_words_callback']($this->cleanStringCache['ignore_words_regex'], '', $output); $words_removed = $this->cleanStringCache['ignore_words_callback']($this->cleanStringCache['ignore_words_regex'], '', $output);
if (Unicode::strlen(trim($words_removed)) > 0) { if (mb_strlen(trim($words_removed)) > 0) {
$output = $words_removed; $output = $words_removed;
} }
} }
@@ -260,7 +260,7 @@ class AliasCleaner implements AliasCleanerInterface {
// Optionally convert to lower case. // Optionally convert to lower case.
if ($this->cleanStringCache['lowercase']) { if ($this->cleanStringCache['lowercase']) {
$output = Unicode::strtolower($output); $output = mb_strtolower($output);
} }
// Shorten to a logical place based on word boundaries. // Shorten to a logical place based on word boundaries.
@@ -335,7 +335,9 @@ class AliasCleaner implements AliasCleanerInterface {
public function cleanTokenValues(&$replacements, $data = array(), $options = array()) { public function cleanTokenValues(&$replacements, $data = array(), $options = array()) {
foreach ($replacements as $token => $value) { foreach ($replacements as $token => $value) {
// Only clean non-path tokens. // Only clean non-path tokens.
if (!preg_match('/(path|alias|url|url-brief)\]$/', $token)) { $config = $this->configFactory->get('pathauto.settings');
$safe_tokens = implode('|', (array) $config->get('safe_tokens'));
if (!preg_match('/:(' . $safe_tokens . ')(:|\]$)/', $token)) {
$replacements[$token] = $this->cleanString($value, $options); $replacements[$token] = $this->cleanString($value, $options);
} }
} }
@@ -72,8 +72,8 @@ interface AliasCleanerInterface {
/** /**
* Return an array of arrays for punctuation values. * Return an array of arrays for punctuation values.
* *
* Returns an array of arrays for punctuation values keyed by a name, including * Returns an array of arrays for punctuation values keyed by a name,
* the value and a textual description. * including the value and a textual description.
* Can and should be expanded to include "all" non text punctuation values. * Can and should be expanded to include "all" non text punctuation values.
* *
* @return array * @return array
@@ -1,6 +1,7 @@
<?php <?php
namespace Drupal\pathauto; namespace Drupal\pathauto;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Language\LanguageInterface;
@@ -94,7 +95,6 @@ interface AliasStorageHelperInterface {
*/ */
public function loadBySourcePrefix($source); public function loadBySourcePrefix($source);
/** /**
* Returns the count of url aliases for the source. * Returns the count of url aliases for the source.
* *
@@ -13,7 +13,8 @@ interface AliasTypeBatchUpdateInterface extends AliasTypeInterface {
* @param string $action * @param string $action
* One of: * One of:
* - 'create' to generate a URL alias for paths having none. * - 'create' to generate a URL alias for paths having none.
* - 'update' to recreate the URL alias for paths already having one, useful if the pattern changed. * - 'update' to recreate the URL alias for paths already having one, useful
* if the pattern changed.
* - 'all' to do both actions above at the same time. * - 'all' to do both actions above at the same time.
* @param array $context * @param array $context
* Batch context. * Batch context.
@@ -38,7 +38,7 @@ class AliasUniquifier implements AliasUniquifierInterface {
/** /**
* The route provider service. * The route provider service.
* *
* @var \Drupal\Core\Routing\RouteProviderInterface. * @var \Drupal\Core\Routing\RouteProviderInterface
*/ */
protected $routeProvider; protected $routeProvider;
@@ -60,6 +60,8 @@ class AliasUniquifier implements AliasUniquifierInterface {
* The module handler. * The module handler.
* @param \Drupal\Core\Routing\RouteProviderInterface $route_provider * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
* The route provider service. * The route provider service.
* @param \Drupal\Core\Path\AliasManagerInterface $alias_manager
* The alias manager.
*/ */
public function __construct(ConfigFactoryInterface $config_factory, AliasStorageHelperInterface $alias_storage_helper, ModuleHandlerInterface $module_handler, RouteProviderInterface $route_provider, AliasManagerInterface $alias_manager) { public function __construct(ConfigFactoryInterface $config_factory, AliasStorageHelperInterface $alias_storage_helper, ModuleHandlerInterface $module_handler, RouteProviderInterface $route_provider, AliasManagerInterface $alias_manager) {
$this->configFactory = $config_factory; $this->configFactory = $config_factory;
@@ -1,6 +1,7 @@
<?php <?php
namespace Drupal\pathauto; namespace Drupal\pathauto;
use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Language\LanguageInterface;
/** /**
@@ -21,9 +21,9 @@ class AliasType extends Plugin {
/** /**
* The human-readable name of the action plugin. * The human-readable name of the action plugin.
* *
* @ingroup plugin_translatable
*
* @var \Drupal\Core\Annotation\Translation * @var \Drupal\Core\Annotation\Translation
*
* @ingroup plugin_translatable
*/ */
public $label; public $label;
@@ -13,11 +13,25 @@ use Drupal\pathauto\AliasTypeManager;
*/ */
class PathautoSettingsCacheTag implements EventSubscriberInterface { class PathautoSettingsCacheTag implements EventSubscriberInterface {
/**
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $entityFieldManager; protected $entityFieldManager;
/**
* The alias type manager.
*
* @var \Drupal\pathauto\AliasTypeManager
*/
protected $aliasTypeManager; protected $aliasTypeManager;
/** /**
* Constructs a PathautoSettingsCacheTag object. * Constructs a PathautoSettingsCacheTag object.
*
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
* The entity field manager.
* @param \Drupal\pathauto\AliasTypeManager $alias_type_manager
* The alias type manager.
*/ */
public function __construct(EntityFieldManagerInterface $entity_field_manager, AliasTypeManager $alias_type_manager) { public function __construct(EntityFieldManagerInterface $entity_field_manager, AliasTypeManager $alias_type_manager) {
$this->entityFieldManager = $entity_field_manager; $this->entityFieldManager = $entity_field_manager;
@@ -133,14 +133,14 @@ class PathautoAdminDelete extends FormBase {
} }
else if ($delete_all) { else if ($delete_all) {
\Drupal::service('pathauto.alias_storage_helper')->deleteAll(); \Drupal::service('pathauto.alias_storage_helper')->deleteAll();
drupal_set_message($this->t('All of your path aliases have been deleted.')); $this->messenger()->addMessage($this->t('All of your path aliases have been deleted.'));
} }
else { else {
$storage_helper = \Drupal::service('pathauto.alias_storage_helper'); $storage_helper = \Drupal::service('pathauto.alias_storage_helper');
foreach (array_keys(array_filter($form_state->getValue(['delete', 'plugins']))) as $id) { foreach (array_keys(array_filter($form_state->getValue(['delete', 'plugins']))) as $id) {
$alias_type = $this->aliasTypeManager->createInstance($id); $alias_type = $this->aliasTypeManager->createInstance($id);
$storage_helper->deleteBySourcePrefix((string) $alias_type->getSourcePrefix()); $storage_helper->deleteBySourcePrefix((string) $alias_type->getSourcePrefix());
drupal_set_message($this->t('All of your %label path aliases have been deleted.', ['%label' => $alias_type->getLabel()])); $this->messenger()->addMessage($this->t('All of your %label path aliases have been deleted.', ['%label' => $alias_type->getLabel()]));
} }
} }
} }
@@ -168,17 +168,25 @@ class PathautoAdminDelete extends FormBase {
public static function batchFinished($success, $results, $operations) { public static function batchFinished($success, $results, $operations) {
if ($success) { if ($success) {
if ($results['delete_all']) { if ($results['delete_all']) {
drupal_set_message(t('All of your automatically generated path aliases have been deleted.')); \Drupal::service('messenger')
->addMessage(t('All of your automatically generated path aliases have been deleted.'));
} }
else if (isset($results['deletions'])) { else if (isset($results['deletions'])) {
foreach (array_values($results['deletions']) as $label) { foreach (array_values($results['deletions']) as $label) {
drupal_set_message(t('All of your automatically generated %label path aliases have been deleted.', ['%label' => $label])); \Drupal::service('messenger')
->addMessage(t('All of your automatically generated %label path aliases have been deleted.', [
'%label' => $label,
]));
} }
} }
} }
else { else {
$error_operation = reset($operations); $error_operation = reset($operations);
drupal_set_message(t('An error occurred while processing @operation with arguments : @args', array('@operation' => $error_operation[0], '@args' => print_r($error_operation[0], TRUE)))); \Drupal::service('messenger')
->addMessage(t('An error occurred while processing @operation with arguments : @args', [
'@operation' => $error_operation[0],
'@args' => print_r($error_operation[0]),
]));
} }
} }
@@ -149,15 +149,21 @@ class PathautoBulkUpdateForm extends FormBase {
public static function batchFinished($success, $results, $operations) { public static function batchFinished($success, $results, $operations) {
if ($success) { if ($success) {
if ($results['updates']) { if ($results['updates']) {
drupal_set_message(\Drupal::translation()->formatPlural($results['updates'], 'Generated 1 URL alias.', 'Generated @count URL aliases.')); \Drupal::service('messenger')->addMessage(\Drupal::translation()
->formatPlural($results['updates'], 'Generated 1 URL alias.', 'Generated @count URL aliases.'));
} }
else { else {
drupal_set_message(t('No new URL aliases to generate.')); \Drupal::service('messenger')
->addMessage(t('No new URL aliases to generate.'));
} }
} }
else { else {
$error_operation = reset($operations); $error_operation = reset($operations);
drupal_set_message(t('An error occurred while processing @operation with arguments : @args', array('@operation' => $error_operation[0], '@args' => print_r($error_operation[0], TRUE)))); \Drupal::service('messenger')
->addMessage(t('An error occurred while processing @operation with arguments : @args'), [
'@operation' => $error_operation[0],
'@args' => print_r($error_operation[0]),
]);
} }
} }
@@ -35,7 +35,7 @@ class PathautoSettingsForm extends ConfigFormBase {
protected $aliasTypeManager; protected $aliasTypeManager;
/** /**
* {@inheritDoc} * {@inheritdoc}
*/ */
public function __construct(ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, AliasTypeManager $alias_type_manager) { public function __construct(ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, AliasTypeManager $alias_type_manager) {
parent::__construct($config_factory); parent::__construct($config_factory);
@@ -45,7 +45,7 @@ class PathautoSettingsForm extends ConfigFormBase {
} }
/** /**
* {@inheritDoc} * {@inheritdoc}
*/ */
public static function create(ContainerInterface $container) { public static function create(ContainerInterface $container) {
return new static( return new static(
@@ -195,7 +195,13 @@ class PathautoSettingsForm extends ConfigFormBase {
'#title' => $this->t('Strings to Remove'), '#title' => $this->t('Strings to Remove'),
'#default_value' => $config->get('ignore_words'), '#default_value' => $config->get('ignore_words'),
'#description' => $this->t('Words to strip out of the URL alias, separated by commas. Do not use this to remove punctuation.'), '#description' => $this->t('Words to strip out of the URL alias, separated by commas. Do not use this to remove punctuation.'),
'#wysiwyg' => FALSE, );
$form['safe_tokens'] = array(
'#type' => 'textarea',
'#title' => $this->t('Safe tokens'),
'#default_value' => implode(', ', $config->get('safe_tokens')),
'#description' => $this->t('List of tokens that are safe to use in alias patterns and do not need to be cleaned. For example urls, aliases, machine names. Separated with a comma.'),
); );
$form['punctuation'] = array( $form['punctuation'] = array(
@@ -254,6 +260,9 @@ class PathautoSettingsForm extends ConfigFormBase {
} }
$value = $enabled_entity_types; $value = $enabled_entity_types;
} }
elseif ($key == 'safe_tokens') {
$value = array_filter(array_map('trim', explode(',', $value)));
}
$config->set($key, $value); $config->set($key, $value);
} }
$config->save(); $config->save();
@@ -44,7 +44,9 @@ class PatternDisableForm extends EntityConfirmFormBase {
*/ */
public function submitForm(array &$form, FormStateInterface $form_state) { public function submitForm(array &$form, FormStateInterface $form_state) {
$this->entity->disable()->save(); $this->entity->disable()->save();
drupal_set_message($this->t('Disabled pattern %label.', array('%label' => $this->entity->label()))); $this->messenger()->addMessage($this->t('Disabled pattern %label.', [
'%label' => $this->entity->label(),
]));
$form_state->setRedirectUrl($this->getCancelUrl()); $form_state->setRedirectUrl($this->getCancelUrl());
} }
@@ -16,6 +16,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
class PatternEditForm extends EntityForm { class PatternEditForm extends EntityForm {
/** /**
* The alias type manager.
*
* @var \Drupal\pathauto\AliasTypeManager * @var \Drupal\pathauto\AliasTypeManager
*/ */
protected $manager; protected $manager;
@@ -33,11 +35,15 @@ class PatternEditForm extends EntityForm {
protected $entityTypeBundleInfo; protected $entityTypeBundleInfo;
/** /**
* The entity manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface * @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/ */
protected $entityTypeManager; protected $entityTypeManager;
/** /**
* The language manager service.
*
* @var \Drupal\Core\Language\LanguageManagerInterface * @var \Drupal\Core\Language\LanguageManagerInterface
*/ */
protected $languageManager; protected $languageManager;
@@ -58,9 +64,13 @@ class PatternEditForm extends EntityForm {
* PatternEditForm constructor. * PatternEditForm constructor.
* *
* @param \Drupal\pathauto\AliasTypeManager $manager * @param \Drupal\pathauto\AliasTypeManager $manager
* The alias type manager.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
* The entity type bundle info service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity manager service.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager service.
*/ */
function __construct(AliasTypeManager $manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityTypeManagerInterface $entity_type_manager, LanguageManagerInterface $language_manager) { function __construct(AliasTypeManager $manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityTypeManagerInterface $entity_type_manager, LanguageManagerInterface $language_manager) {
$this->manager = $manager; $this->manager = $manager;
@@ -70,7 +80,7 @@ class PatternEditForm extends EntityForm {
} }
/** /**
* {@inheritDoc} * {@inheritdoc}
*/ */
public function buildForm(array $form, FormStateInterface $form_state) { public function buildForm(array $form, FormStateInterface $form_state) {
@@ -199,7 +209,7 @@ class PatternEditForm extends EntityForm {
} }
/** /**
* {@inheritDoc} * {@inheritdoc}
*/ */
public function buildEntity(array $form, FormStateInterface $form_state) { public function buildEntity(array $form, FormStateInterface $form_state) {
/** @var \Drupal\pathauto\PathautoPatternInterface $entity */ /** @var \Drupal\pathauto\PathautoPatternInterface $entity */
@@ -259,11 +269,13 @@ class PatternEditForm extends EntityForm {
} }
/** /**
* {@inheritDoc} * {@inheritdoc}
*/ */
public function save(array $form, FormStateInterface $form_state) { public function save(array $form, FormStateInterface $form_state) {
parent::save($form, $form_state); parent::save($form, $form_state);
drupal_set_message($this->t('Pattern @label saved.', ['@label' => $this->entity->label()])); $this->messenger()->addMessage($this->t('Pattern %label saved.', [
'%label' => $this->entity->label(),
]));
$form_state->setRedirectUrl($this->entity->toUrl('collection')); $form_state->setRedirectUrl($this->entity->toUrl('collection'));
} }
@@ -44,7 +44,9 @@ class PatternEnableForm extends EntityConfirmFormBase {
*/ */
public function submitForm(array &$form, FormStateInterface $form_state) { public function submitForm(array &$form, FormStateInterface $form_state) {
$this->entity->enable()->save(); $this->entity->enable()->save();
drupal_set_message($this->t('Enabled pattern %label.', array('%label' => $this->entity->label()))); $this->messenger()->addMessage($this->t('Enabled pattern %label.', [
'%label' => $this->entity->label(),
]));
$form_state->setRedirectUrl($this->getCancelUrl()); $form_state->setRedirectUrl($this->getCancelUrl());
} }
@@ -7,7 +7,7 @@ use Drupal\path\Plugin\Field\FieldType\PathFieldItemList;
class PathautoFieldItemList extends PathFieldItemList { class PathautoFieldItemList extends PathFieldItemList {
/** /**
* @inheritDoc * @{inheritdoc}
*/ */
protected function delegateMethod($method) { protected function delegateMethod($method) {
// @todo Workaround until this is fixed, see // @todo Workaround until this is fixed, see
@@ -27,7 +27,7 @@ class PathautoFieldItemList extends PathFieldItemList {
} }
/** /**
* @inheritDoc * @{inheritdoc}
*/ */
protected function computeValue() { protected function computeValue() {
parent::computeValue(); parent::computeValue();
@@ -38,12 +38,4 @@ class PathautoFieldItemList extends PathFieldItemList {
} }
} }
/**
* @inheritDoc
*/
public function delete() {
\Drupal::service('pathauto.alias_storage_helper')->deleteEntityPathAll($this->getEntity());
$this->first()->get('pathauto')->purge();
}
} }
@@ -2,7 +2,6 @@
namespace Drupal\pathauto; namespace Drupal\pathauto;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
@@ -87,12 +86,16 @@ class PathautoGenerator implements PathautoGeneratorInterface {
protected $messenger; protected $messenger;
/** /**
* The token entity mapper.
*
* @var \Drupal\token\TokenEntityMapperInterface * @var \Drupal\token\TokenEntityMapperInterface
*/ */
protected $tokenEntityMapper; protected $tokenEntityMapper;
/** /**
* @var Drupal\Core\Entity\EntityTypeManagerInterface * The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/ */
protected $entityTypeManager; protected $entityTypeManager;
@@ -115,10 +118,12 @@ class PathautoGenerator implements PathautoGeneratorInterface {
* The messenger service. * The messenger service.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The string translation service. * The string translation service.
* @param Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * @param \Drupal\token\TokenEntityMapperInterface $token_entity_mapper
* The entity type manager * The token entity mapper.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/ */
public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, Token $token, AliasCleanerInterface $alias_cleaner, AliasStorageHelperInterface $alias_storage_helper, AliasUniquifierInterface $alias_uniquifier, MessengerInterface $messenger, TranslationInterface $string_translation, TokenEntityMapperInterface $token_entity_mappper, EntityTypeManagerInterface $entity_type_manager) { public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, Token $token, AliasCleanerInterface $alias_cleaner, AliasStorageHelperInterface $alias_storage_helper, AliasUniquifierInterface $alias_uniquifier, MessengerInterface $messenger, TranslationInterface $string_translation, TokenEntityMapperInterface $token_entity_mapper, EntityTypeManagerInterface $entity_type_manager) {
$this->configFactory = $config_factory; $this->configFactory = $config_factory;
$this->moduleHandler = $module_handler; $this->moduleHandler = $module_handler;
$this->token = $token; $this->token = $token;
@@ -127,7 +132,7 @@ class PathautoGenerator implements PathautoGeneratorInterface {
$this->aliasUniquifier = $alias_uniquifier; $this->aliasUniquifier = $alias_uniquifier;
$this->messenger = $messenger; $this->messenger = $messenger;
$this->stringTranslation = $string_translation; $this->stringTranslation = $string_translation;
$this->tokenEntityMapper = $token_entity_mappper; $this->tokenEntityMapper = $token_entity_mapper;
$this->entityTypeManager = $entity_type_manager; $this->entityTypeManager = $entity_type_manager;
} }
@@ -165,8 +170,9 @@ class PathautoGenerator implements PathautoGeneratorInterface {
'bundle' => $entity->bundle(), 'bundle' => $entity->bundle(),
'language' => &$langcode, 'language' => &$langcode,
); );
// @todo Is still hook still useful? $pattern_original = $pattern->getPattern();
$this->moduleHandler->alter('pathauto_pattern', $pattern, $context); $this->moduleHandler->alter('pathauto_pattern', $pattern, $context);
$pattern_altered = $pattern->getPattern();
// Special handling when updating an item which is already aliased. // Special handling when updating an item which is already aliased.
$existing_alias = NULL; $existing_alias = NULL;
@@ -209,7 +215,7 @@ class PathautoGenerator implements PathautoGeneratorInterface {
$this->moduleHandler->alter('pathauto_alias', $alias, $context); $this->moduleHandler->alter('pathauto_alias', $alias, $context);
// If we have arrived at an empty string, discontinue. // If we have arrived at an empty string, discontinue.
if (!Unicode::strlen($alias)) { if (!mb_strlen($alias)) {
return NULL; return NULL;
} }
@@ -236,11 +242,19 @@ class PathautoGenerator implements PathautoGeneratorInterface {
'language' => $langcode, 'language' => $langcode,
); );
return $this->aliasStorageHelper->save($path, $existing_alias, $op); $return = $this->aliasStorageHelper->save($path, $existing_alias, $op);
// Because there is no way to set an altered pattern to not be cached,
// change it back to the original value.
if ($pattern_altered !== $pattern_original) {
$pattern->setPattern($pattern_original);
}
return $return;
} }
/** /**
* Loads pathauto patterns for a given entity type ID * Loads pathauto patterns for a given entity type ID.
* *
* @param string $entity_type_id * @param string $entity_type_id
* An entity type ID. * An entity type ID.
@@ -335,7 +349,7 @@ class PathautoGenerator implements PathautoGeneratorInterface {
$result = $this->createEntityAlias($entity, $op); $result = $this->createEntityAlias($entity, $op);
} }
catch (\InvalidArgumentException $e) { catch (\InvalidArgumentException $e) {
drupal_set_message($e->getMessage(), 'error'); $this->messenger->addError($e->getMessage());
return NULL; return NULL;
} }
@@ -49,6 +49,7 @@ interface PathautoGeneratorInterface {
* *
* @param \Drupal\Core\Entity\EntityInterface $entity * @param \Drupal\Core\Entity\EntityInterface $entity
* An entity. * An entity.
*
* @return \Drupal\pathauto\PathautoPatternInterface|null * @return \Drupal\pathauto\PathautoPatternInterface|null
*/ */
public function getPatternByEntity(EntityInterface $entity); public function getPatternByEntity(EntityInterface $entity);
@@ -33,9 +33,6 @@ class PathautoItem extends PathItem {
if ($this->pathauto == PathautoState::SKIP) { if ($this->pathauto == PathautoState::SKIP) {
parent::postSave($update); parent::postSave($update);
} }
else {
\Drupal::service('pathauto.generator')->updateEntityAlias($this->getEntity(), $update ? 'update' : 'insert');
}
$this->get('pathauto')->persist(); $this->get('pathauto')->persist();
} }
@@ -88,6 +88,7 @@ class PathautoState extends TypedData {
/** /**
* Returns the key value collection that should be used for the given entity. * Returns the key value collection that should be used for the given entity.
*
* @return string * @return string
*/ */
protected function getCollection() { protected function getCollection() {
@@ -26,6 +26,8 @@ class EntityAliasTypeDeriver extends DeriverBase implements ContainerDeriverInte
protected $entityTypeManager; protected $entityTypeManager;
/** /**
* The entity field manager.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface * @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/ */
protected $entityFieldManager; protected $entityFieldManager;
@@ -44,7 +46,7 @@ class EntityAliasTypeDeriver extends DeriverBase implements ContainerDeriverInte
* The entity field manager. * The entity field manager.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The string translation service. * The string translation service.
* @apram \Drupal\Token\TokenEntityMapperInterface $token_entity_mapper * @param \Drupal\Token\TokenEntityMapperInterface $token_entity_mapper
* The token entity mapper. * The token entity mapper.
*/ */
public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, TranslationInterface $string_translation, TokenEntityMapperInterface $token_entity_mapper) { public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, TranslationInterface $string_translation, TokenEntityMapperInterface $token_entity_mapper) {
@@ -11,6 +11,7 @@ use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\Context\Context; use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\ContextAwarePluginBase; use Drupal\Core\Plugin\ContextAwarePluginBase;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\pathauto\AliasTypeBatchUpdateInterface; use Drupal\pathauto\AliasTypeBatchUpdateInterface;
use Drupal\pathauto\AliasTypeInterface; use Drupal\pathauto\AliasTypeInterface;
use Drupal\pathauto\PathautoState; use Drupal\pathauto\PathautoState;
@@ -26,6 +27,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*/ */
class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInterface, AliasTypeBatchUpdateInterface, ContainerFactoryPluginInterface { class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInterface, AliasTypeBatchUpdateInterface, ContainerFactoryPluginInterface {
use MessengerTrait;
/** /**
* The module handler service. * The module handler service.
* *
@@ -151,12 +154,15 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
case 'create': case 'create':
$query->isNull('ua.source'); $query->isNull('ua.source');
break; break;
case 'update': case 'update':
$query->isNotNull('ua.source'); $query->isNotNull('ua.source');
break; break;
case 'all': case 'all':
// Nothing to do. We want all paths. // Nothing to do. We want all paths.
break; break;
default: default:
// Unknown action. Abort! // Unknown action. Abort!
return; return;
@@ -182,7 +188,7 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
$updates = $this->bulkUpdate($ids); $updates = $this->bulkUpdate($ids);
$context['sandbox']['count'] += count($ids); $context['sandbox']['count'] += count($ids);
$context['sandbox']['current'] = max($ids); $context['sandbox']['current'] = !empty($ids) ? max($ids) : 0;
$context['results']['updates'] += $updates; $context['results']['updates'] += $updates;
$context['message'] = $this->t('Updated alias for %label @id.', array('%label' => $entity_type->getLabel(), '@id' => end($ids))); $context['message'] = $this->t('Updated alias for %label @id.', array('%label' => $entity_type->getLabel(), '@id' => end($ids)));
@@ -255,7 +261,7 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
* An optional array of additional options. * An optional array of additional options.
* *
* @return int * @return int
* The number of updated URL aliases. * The number of updated URL aliases.
*/ */
protected function bulkUpdate(array $ids, array $options = array()) { protected function bulkUpdate(array $ids, array $options = array()) {
$options += array('message' => FALSE); $options += array('message' => FALSE);
@@ -274,7 +280,10 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
} }
if (!empty($options['message'])) { if (!empty($options['message'])) {
drupal_set_message(\Drupal::translation()->formatPlural(count($ids), 'Updated 1 %label URL alias.', 'Updated @count %label URL aliases.'), array('%label' => $this->getLabel())); $this->messenger->addMessage($this->translationManager
->formatPlural(count($ids), 'Updated 1 %label URL alias.', 'Updated @count %label URL aliases.'), [
'%label' => $this->getLabel(),
]);
} }
return $updates; return $updates;
@@ -330,5 +339,4 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
return $this; return $this;
} }
} }
@@ -44,7 +44,7 @@ class PathautoBulkUpdateTest extends WebTestBase {
protected $patterns; protected $patterns;
/** /**
* {inheritdoc} * {@inheritdoc}
*/ */
function setUp() { function setUp() {
parent::setUp(); parent::setUp();
@@ -103,7 +103,7 @@ class PathautoBulkUpdateTest extends WebTestBase {
$this->assertText('No new URL aliases to generate.'); $this->assertText('No new URL aliases to generate.');
$this->assertNoEntityAliasExists($new_node); $this->assertNoEntityAliasExists($new_node);
// Make sure existing aliases can be overriden. // Make sure existing aliases can be overridden.
$this->drupalPostForm('admin/config/search/path/settings', ['update_action' => PathautoGeneratorInterface::UPDATE_ACTION_DELETE], t('Save configuration')); $this->drupalPostForm('admin/config/search/path/settings', ['update_action' => PathautoGeneratorInterface::UPDATE_ACTION_DELETE], t('Save configuration'));
// Patterns did not change, so no aliases should be regenerated. // Patterns did not change, so no aliases should be regenerated.
@@ -111,16 +111,17 @@ class PathautoBulkUpdateTest extends WebTestBase {
$this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update')); $this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update'));
$this->assertText('No new URL aliases to generate.'); $this->assertText('No new URL aliases to generate.');
// Update the node pattern, and leave other patterns alone. Existing nodes should get a new alias, // Update the node pattern, and leave other patterns alone. Existing nodes
// except the node above whose alias is manually set. Other aliases must be left alone. // should get a new alias, except the node above whose alias is manually
// set. Other aliases must be left alone.
$this->patterns['node']->delete(); $this->patterns['node']->delete();
$this->patterns['node'] = $this->createPattern('node', '/archive/node-[node:nid]'); $this->patterns['node'] = $this->createPattern('node', '/archive/node-[node:nid]');
$this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update')); $this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update'));
$this->assertText('Generated 5 URL aliases.'); $this->assertText('Generated 5 URL aliases.');
// Prevent existing aliases to be overriden. The bulk generate page should only offer // Prevent existing aliases to be overridden. The bulk generate page should
// to create an alias for paths which have none. // only offer to create an alias for paths which have none.
$this->drupalPostForm('admin/config/search/path/settings', ['update_action' => PathautoGeneratorInterface::UPDATE_ACTION_NO_NEW], t('Save configuration')); $this->drupalPostForm('admin/config/search/path/settings', ['update_action' => PathautoGeneratorInterface::UPDATE_ACTION_NO_NEW], t('Save configuration'));
$this->drupalGet('admin/config/search/path/update_bulk'); $this->drupalGet('admin/config/search/path/update_bulk');
@@ -13,6 +13,7 @@ use Drupal\comment\Tests\CommentTestTrait;
class PathautoEnablingEntityTypesTest extends WebTestBase { class PathautoEnablingEntityTypesTest extends WebTestBase {
use PathautoTestHelperTrait; use PathautoTestHelperTrait;
use CommentTestTrait; use CommentTestTrait;
/** /**
@@ -30,7 +31,7 @@ class PathautoEnablingEntityTypesTest extends WebTestBase {
protected $adminUser; protected $adminUser;
/** /**
* {inheritdoc} * {@inheritdoc}
*/ */
function setUp() { function setUp() {
parent::setUp(); parent::setUp();
@@ -49,9 +49,8 @@ class PathautoMassDeleteTest extends WebTestBase {
*/ */
protected $terms; protected $terms;
/** /**
* {inheritdoc} * {@inheritdoc}
*/ */
function setUp() { function setUp() {
parent::setUp(); parent::setUp();
@@ -136,14 +135,16 @@ class PathautoMassDeleteTest extends WebTestBase {
* Helper function to generate aliases. * Helper function to generate aliases.
*/ */
function generateAliases() { function generateAliases() {
// Delete all aliases to avoid duplicated aliases. They will be recreated below. // Delete all aliases to avoid duplicated aliases. They will be recreated
// below.
$this->deleteAllAliases(); $this->deleteAllAliases();
// We generate a bunch of aliases for nodes, users and taxonomy terms. If // We generate a bunch of aliases for nodes, users and taxonomy terms. If
// the entities are already created we just update them, otherwise we create // the entities are already created we just update them, otherwise we create
// them. // them.
if (empty($this->nodes)) { if (empty($this->nodes)) {
// Create a large number of nodes (100+) to make sure that the batch code works. // Create a large number of nodes (100+) to make sure that the batch code
// works.
for ($i = 1; $i <= 105; $i++) { for ($i = 1; $i <= 105; $i++) {
// Set the alias of two nodes manually. // Set the alias of two nodes manually.
$settings = ($i > 103) ? ['path' => ['alias' => "/custom_alias_$i", 'pathauto' => PathautoState::SKIP]] : []; $settings = ($i > 103) ? ['path' => ['alias' => "/custom_alias_$i", 'pathauto' => PathautoState::SKIP]] : [];
@@ -1,6 +1,7 @@
<?php <?php
namespace Drupal\pathauto\Tests; namespace Drupal\pathauto\Tests;
use Drupal\pathauto\Entity\PathautoPattern; use Drupal\pathauto\Entity\PathautoPattern;
use Drupal\node\Entity\Node; use Drupal\node\Entity\Node;
use Drupal\pathauto\PathautoState; use Drupal\pathauto\PathautoState;
@@ -30,7 +31,7 @@ class PathautoNodeWebTest extends WebTestBase {
protected $adminUser; protected $adminUser;
/** /**
* {inheritdoc} * {@inheritdoc}
*/ */
function setUp() { function setUp() {
parent::setUp(); parent::setUp();
@@ -56,7 +57,8 @@ class PathautoNodeWebTest extends WebTestBase {
* Tests editing nodes with different settings. * Tests editing nodes with different settings.
*/ */
function testNodeEditing() { function testNodeEditing() {
// Ensure that the Pathauto checkbox is checked by default on the node add form. // Ensure that the Pathauto checkbox is checked by default on the node add
// form.
$this->drupalGet('node/add/page'); $this->drupalGet('node/add/page');
$this->assertFieldChecked('edit-path-0-pathauto'); $this->assertFieldChecked('edit-path-0-pathauto');
@@ -85,7 +85,7 @@ class PathautoSettingsFormWebTest extends WebTestBase {
); );
/** /**
* {inheritdoc} * {@inheritdoc}
*/ */
function setUp() { function setUp() {
parent::setUp(); parent::setUp();
@@ -27,7 +27,7 @@ class PathautoTaxonomyWebTest extends WebTestBase {
protected $adminUser; protected $adminUser;
/** /**
* {inheritdoc} * {@inheritdoc}
*/ */
function setUp() { function setUp() {
parent::setUp(); parent::setUp();
@@ -45,7 +45,6 @@ class PathautoTaxonomyWebTest extends WebTestBase {
$this->createPattern('taxonomy_term', '/[term:vocabulary]/[term:name]'); $this->createPattern('taxonomy_term', '/[term:vocabulary]/[term:name]');
} }
/** /**
* Basic functional testing of Pathauto with taxonomy terms. * Basic functional testing of Pathauto with taxonomy terms.
*/ */
@@ -2,7 +2,6 @@
namespace Drupal\pathauto\Tests; namespace Drupal\pathauto\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Language\Language; use Drupal\Core\Language\Language;
use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\BubbleableMetadata;
@@ -34,7 +33,7 @@ trait PathautoTestHelperTrait {
$type = ($entity_type_id == 'forum') ? 'forum' : 'canonical_entities:' . $entity_type_id; $type = ($entity_type_id == 'forum') ? 'forum' : 'canonical_entities:' . $entity_type_id;
$pattern = PathautoPattern::create([ $pattern = PathautoPattern::create([
'id' => Unicode::strtolower($this->randomMachineName()), 'id' => mb_strtolower($this->randomMachineName()),
'type' => $type, 'type' => $type,
'pattern' => $pattern, 'pattern' => $pattern,
'weight' => $weight, 'weight' => $weight,
@@ -51,7 +50,7 @@ trait PathautoTestHelperTrait {
* @param string $entity_type * @param string $entity_type
* The entity type ID. * The entity type ID.
* @param string $bundle * @param string $bundle
* The bundle * The bundle.
*/ */
protected function addBundleCondition(PathautoPatternInterface $pattern, $entity_type, $bundle) { protected function addBundleCondition(PathautoPatternInterface $pattern, $entity_type, $bundle) {
$plugin_id = $entity_type == 'node' ? 'node_type' : 'entity_bundle:' . $entity_type; $plugin_id = $entity_type == 'node' ? 'node_type' : 'entity_bundle:' . $entity_type;
@@ -142,10 +141,11 @@ trait PathautoTestHelperTrait {
/** /**
* @param array $values * @param array $values
*
* @return \Drupal\taxonomy\VocabularyInterface * @return \Drupal\taxonomy\VocabularyInterface
*/ */
public function addVocabulary(array $values = array()) { public function addVocabulary(array $values = array()) {
$name = Unicode::strtolower($this->randomMachineName(5)); $name = mb_strtolower($this->randomMachineName(5));
$values += array( $values += array(
'name' => $name, 'name' => $name,
'vid' => $name, 'vid' => $name,
@@ -158,7 +158,7 @@ trait PathautoTestHelperTrait {
public function addTerm(VocabularyInterface $vocabulary, array $values = array()) { public function addTerm(VocabularyInterface $vocabulary, array $values = array()) {
$values += array( $values += array(
'name' => Unicode::strtolower($this->randomMachineName(5)), 'name' => mb_strtolower($this->randomMachineName(5)),
'vid' => $vocabulary->id(), 'vid' => $vocabulary->id(),
); );
@@ -30,7 +30,7 @@ class PathautoUiTest extends WebTestBase {
protected $adminUser; protected $adminUser;
/** /**
* {inheritdoc} * {@inheritdoc}
*/ */
function setUp() { function setUp() {
parent::setUp(); parent::setUp();
@@ -1,7 +1,7 @@
<?php <?php
namespace Drupal\pathauto\Tests; namespace Drupal\pathauto\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\simpletest\WebTestBase; use Drupal\simpletest\WebTestBase;
use Drupal\views\Views; use Drupal\views\Views;
@@ -29,7 +29,7 @@ class PathautoUserWebTest extends WebTestBase {
protected $adminUser; protected $adminUser;
/** /**
* {inheritdoc} * {@inheritdoc}
*/ */
function setUp() { function setUp() {
parent::setUp(); parent::setUp();
@@ -47,7 +47,6 @@ class PathautoUserWebTest extends WebTestBase {
$this->createPattern('user', '/users/[user:name]'); $this->createPattern('user', '/users/[user:name]');
} }
/** /**
* Basic functional testing of Pathauto with users. * Basic functional testing of Pathauto with users.
*/ */
@@ -71,7 +70,6 @@ class PathautoUserWebTest extends WebTestBase {
$view->initDisplay(); $view->initDisplay();
$view->preview('page_1'); $view->preview('page_1');
foreach ($view->result as $key => $row) { foreach ($view->result as $key => $row) {
if ($view->field['name']->getValue($row) == $account->getUsername()) { if ($view->field['name']->getValue($row) == $account->getUsername()) {
break; break;
@@ -85,7 +83,7 @@ class PathautoUserWebTest extends WebTestBase {
$this->drupalPostForm('admin/people', $edit, t('Apply to selected items')); $this->drupalPostForm('admin/people', $edit, t('Apply to selected items'));
$this->assertText('Update URL alias was applied to 1 item.'); $this->assertText('Update URL alias was applied to 1 item.');
$this->assertEntityAlias($account, '/users/' . Unicode::strtolower($account->getUsername())); $this->assertEntityAlias($account, '/users/' . mb_strtolower($account->getUsername()));
$this->assertEntityAlias($this->adminUser, '/user/' . $this->adminUser->id()); $this->assertEntityAlias($this->adminUser, '/user/' . $this->adminUser->id());
} }
@@ -3,6 +3,7 @@
namespace Drupal\pathauto; namespace Drupal\pathauto;
use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface as CoreMessengerInterface;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
/** /**
@@ -32,11 +33,26 @@ class VerboseMessenger implements MessengerInterface {
protected $account; protected $account;
/** /**
* Creates a verbose messenger. * The messenger service.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/ */
public function __construct(ConfigFactoryInterface $config_factory, AccountInterface $account) { protected $messenger;
/**
* Creates a verbose messenger.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user account.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger service.
*/
public function __construct(ConfigFactoryInterface $config_factory, AccountInterface $account, CoreMessengerInterface $messenger) {
$this->configFactory = $config_factory; $this->configFactory = $config_factory;
$this->account = $account; $this->account = $account;
$this->messenger = $messenger;
} }
/** /**
@@ -54,7 +70,7 @@ class VerboseMessenger implements MessengerInterface {
} }
if ($message) { if ($message) {
drupal_set_message($message); $this->messenger->addMessage($message);
} }
return TRUE; return TRUE;
@@ -6,8 +6,8 @@ package: Testing
dependencies: dependencies:
- token - token
# Information added by Drupal.org packaging script on 2018-03-03 # Information added by Drupal.org packaging script on 2018-09-08
version: '8.x-1.1' version: '8.x-1.3'
core: '8.x' core: '8.x'
project: 'pathauto' project: 'pathauto'
datestamp: 1520092688 datestamp: 1536407890
@@ -7,8 +7,8 @@ package: Testing
dependencies: dependencies:
- views - views
# Information added by Drupal.org packaging script on 2018-03-03 # Information added by Drupal.org packaging script on 2018-09-08
version: '8.x-1.1' version: '8.x-1.3'
core: '8.x' core: '8.x'
project: 'pathauto' project: 'pathauto'
datestamp: 1520092688 datestamp: 1536407890
@@ -61,7 +61,7 @@ class PathautoEntityWithStringIdTest extends KernelTestBase {
protected function setUp() { protected function setUp() {
parent::setUp(); parent::setUp();
$this->installSchema('system', ['key_value']); $this->installSchema('system', ['key_value']);
$this->installConfig(['system']); $this->installConfig(['system', 'pathauto']);
$this->installEntitySchema('pathauto_string_id_test'); $this->installEntitySchema('pathauto_string_id_test');
$this->createPattern('pathauto_string_id_test', '/[pathauto_string_id_test:name]'); $this->createPattern('pathauto_string_id_test', '/[pathauto_string_id_test:name]');
/** @var \Drupal\pathauto\AliasTypeManager $alias_type_manager */ /** @var \Drupal\pathauto\AliasTypeManager $alias_type_manager */
@@ -87,7 +87,7 @@ class PathautoEntityWithStringIdTest extends KernelTestBase {
$entity->save(); $entity->save();
// Check that the path was generated. // Check that the path was generated.
$this->assertEntityAlias($entity, "/$name"); $this->assertEntityAlias($entity, mb_strtolower("/$name"));
// Check that the path auto state was saved with the expected key. // Check that the path auto state was saved with the expected key.
$value = \Drupal::keyValue('pathauto_state.pathauto_string_id_test')->get($expected_key); $value = \Drupal::keyValue('pathauto_state.pathauto_string_id_test')->get($expected_key);
$this->assertEquals(PathautoState::CREATE, $value); $this->assertEquals(PathautoState::CREATE, $value);
@@ -3,7 +3,6 @@
namespace Drupal\Tests\pathauto\Kernel; namespace Drupal\Tests\pathauto\Kernel;
use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Language\Language; use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Language\LanguageInterface;
use Drupal\language\Entity\ConfigurableLanguage; use Drupal\language\Entity\ConfigurableLanguage;
@@ -285,7 +284,7 @@ class PathautoKernelTest extends KernelTestBase {
$this->assertEntityAlias($node, '/content/second-title'); $this->assertEntityAlias($node, '/content/second-title');
$this->assertNoAliasExists(array('alias' => '/content/first-title')); $this->assertNoAliasExists(array('alias' => '/content/first-title'));
// Test PATHAUTO_UPDATE_ACTION_LEAVE // Test PATHAUTO_UPDATE_ACTION_LEAVE.
$config->set('update_action', PathautoGeneratorInterface::UPDATE_ACTION_LEAVE); $config->set('update_action', PathautoGeneratorInterface::UPDATE_ACTION_LEAVE);
$config->save(); $config->save();
$node->setTitle('Third title'); $node->setTitle('Third title');
@@ -323,8 +322,8 @@ class PathautoKernelTest extends KernelTestBase {
} }
/** /**
* Test that \Drupal::service('pathauto.generator')->createEntityAlias() will not create an alias for a pattern * Test that \Drupal::service('pathauto.generator')->createEntityAlias() will
* that does not get any tokens replaced. * not create an alias for a pattern that does not get any tokens replaced.
*/ */
public function testNoTokensNoAlias() { public function testNoTokensNoAlias() {
$this->installConfig(['filter']); $this->installConfig(['filter']);
@@ -365,12 +364,11 @@ class PathautoKernelTest extends KernelTestBase {
function testParentChildPathTokens() { function testParentChildPathTokens() {
// First create a field which will be used to create the path. It must // First create a field which will be used to create the path. It must
// begin with a letter. // begin with a letter.
$this->installEntitySchema('taxonomy_term'); $this->installEntitySchema('taxonomy_term');
Vocabulary::create(['vid' => 'tags'])->save(); Vocabulary::create(['vid' => 'tags'])->save();
$fieldname = 'a' . Unicode::strtolower($this->randomMachineName()); $fieldname = 'a' . mb_strtolower($this->randomMachineName());
$field_storage = FieldStorageConfig::create(['entity_type' => 'taxonomy_term', 'field_name' => $fieldname, 'type' => 'string']); $field_storage = FieldStorageConfig::create(['entity_type' => 'taxonomy_term', 'field_name' => $fieldname, 'type' => 'string']);
$field_storage->save(); $field_storage->save();
$field = FieldConfig::create(['field_storage' => $field_storage, 'bundle' => 'tags']); $field = FieldConfig::create(['field_storage' => $field_storage, 'bundle' => 'tags']);
@@ -391,11 +389,11 @@ class PathautoKernelTest extends KernelTestBase {
// Create the child term. // Create the child term.
$child = Term::create(['vid' => 'tags', $fieldname => $this->randomMachineName(), 'parent' => $parent, 'name' => $this->randomMachineName()]); $child = Term::create(['vid' => 'tags', $fieldname => $this->randomMachineName(), 'parent' => $parent, 'name' => $this->randomMachineName()]);
$child->save(); $child->save();
$this->assertEntityAlias($child, '/' . Unicode::strtolower($parent->getName() . '/' . $child->$fieldname->value)); $this->assertEntityAlias($child, '/' . mb_strtolower($parent->getName() . '/' . $child->$fieldname->value));
// Re-saving the parent term should not modify the child term's alias. // Re-saving the parent term should not modify the child term's alias.
$parent->save(); $parent->save();
$this->assertEntityAlias($child, '/' . Unicode::strtolower($parent->getName() . '/' . $child->$fieldname->value)); $this->assertEntityAlias($child, '/' . mb_strtolower($parent->getName() . '/' . $child->$fieldname->value));
} }
/** /**
@@ -506,7 +504,7 @@ class PathautoKernelTest extends KernelTestBase {
} }
/** /**
* Tests that enabled entity types genrates the necessary fields and plugins. * Tests that enabled entity types generates the necessary fields and plugins.
*/ */
public function testSettingChangeInvalidatesCache() { public function testSettingChangeInvalidatesCache() {
@@ -39,6 +39,42 @@ class PathautoTokenTest extends KernelTestBase {
$alias_cleaner = \Drupal::service('pathauto.alias_cleaner'); $alias_cleaner = \Drupal::service('pathauto.alias_cleaner');
$alias_cleaner->cleanTokenValues($replacements, $data, array()); $alias_cleaner->cleanTokenValues($replacements, $data, array());
$this->assertEqual($replacements['[array:join-path]'], 'test-first-arg/array-value'); $this->assertEqual($replacements['[array:join-path]'], 'test-first-arg/array-value');
// Test additional token cleaning and its configuration.
$safe_tokens = $this->config('pathauto.settings')->get('safe_tokens');
$safe_tokens[] = 'safe';
$this->config('pathauto.settings')
->set('safe_tokens', $safe_tokens)
->save();
$safe_tokens = [
'[example:path]',
'[example:url]',
'[example:url-brief]',
'[example:login-url]',
'[example:login-url:relative]',
'[example:url:relative]',
'[example:safe]',
];
$unsafe_tokens = [
'[example:path_part]',
'[example:something_url]',
'[example:unsafe]',
];
foreach ($safe_tokens as $token) {
$replacements = [
$token => 'this/is/a/path',
];
$alias_cleaner->cleanTokenValues($replacements);
$this->assertEquals('this/is/a/path', $replacements[$token], "Token $token cleaned.");
}
foreach ($unsafe_tokens as $token) {
$replacements = [
$token => 'This is not a / path',
];
$alias_cleaner->cleanTokenValues($replacements);
$this->assertEquals('not-path', $replacements[$token], "Token $token not cleaned.");
}
} }
/** /**
@@ -1,59 +1,54 @@
<?php <?php
namespace Drupal\Tests\pathauto\Unit { namespace Drupal\Tests\pathauto\Unit;
use Drupal\pathauto\VerboseMessenger; use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Tests\UnitTestCase; use Drupal\Core\Session\AccountInterface;
use Drupal\pathauto\VerboseMessenger;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\pathauto\VerboseMessenger
* @group pathauto
*/
class VerboseMessengerTest extends UnitTestCase {
/** /**
* @coversDefaultClass \Drupal\pathauto\VerboseMessenger * The messenger under test.
* @group pathauto *
* @var \Drupal\pathauto\VerboseMessenger
*/ */
class VerboseMessengerTest extends UnitTestCase { protected $messenger;
/** /**
* The messenger under test. * {@inheritdoc}
* */
* @var \Drupal\pathauto\VerboseMessenger protected function setUp() {
*/ $config_factory = $this->getConfigFactoryStub(['pathauto.settings' => ['verbose' => TRUE]]);
protected $messenger; $account = $this->createMock(AccountInterface::class);
$account->expects($this->once())
->method('hasPermission')
->withAnyParameters()
->willReturn(TRUE);
$messenger = $this->createMock(MessengerInterface::class);
/** $this->messenger = new VerboseMessenger($config_factory, $account, $messenger);
* {@inheritdoc}
*/
protected function setUp() {
$config_factory = $this->getConfigFactoryStub(array('pathauto.settings' => array('verbose' => TRUE)));
$account = $this->getMock('\Drupal\Core\Session\AccountInterface');
$account->expects($this->once())
->method('hasPermission')
->withAnyParameters()
->willReturn(TRUE);
$this->messenger = new VerboseMessenger($config_factory, $account);
}
/**
* Tests add messages.
* @covers ::addMessage
*/
public function testAddMessage() {
$this->assertTrue($this->messenger->addMessage("Test message"), "The message was added");
}
/**
* @covers ::addMessage
*/
public function testDoNotAddMessageWhileBulkupdate() {
$this->assertFalse($this->messenger->addMessage("Test message", "bulkupdate"), "The message was NOT added");
}
}
}
namespace {
// @todo Delete after https://drupal.org/node/1858196 is in.
if (!function_exists('drupal_set_message')) {
function drupal_set_message() {
}
} }
/**
* Tests add messages.
*
* @covers ::addMessage
*/
public function testAddMessage() {
$this->assertTrue($this->messenger->addMessage("Test message"), "The message was added");
}
/**
* @covers ::addMessage
*/
public function testDoNotAddMessageWhileBulkupdate() {
$this->assertFalse($this->messenger->addMessage("Test message", "bulkupdate"), "The message was NOT added");
}
} }
@@ -4,6 +4,8 @@ dependencies:
enforced: enforced:
module: module:
- redirect - redirect
module:
- redirect
id: redirect_delete_action id: redirect_delete_action
label: 'Delete redirect' label: 'Delete redirect'
type: redirect type: redirect
@@ -575,6 +575,8 @@ display:
- url.query_args - url.query_args
- user.permissions - user.permissions
cacheable: false cacheable: false
max-age: 0
tags: { }
page_1: page_1:
display_plugin: page display_plugin: page
id: page_1 id: page_1
@@ -591,3 +593,5 @@ display:
- url.query_args - url.query_args
- user.permissions - user.permissions
cacheable: false cacheable: false
max-age: 0
tags: { }
@@ -1,5 +1,8 @@
langcode: en
status: true status: true
dependencies: { } dependencies:
module:
- redirect
id: redirect.redirect id: redirect.redirect
target_entity_type_id: redirect target_entity_type_id: redirect
target_bundle: redirect target_bundle: redirect
@@ -7,8 +7,8 @@ dependencies:
- redirect - redirect
- views - views
# Information added by Drupal.org packaging script on 2018-03-12 # Information added by Drupal.org packaging script on 2018-05-04
version: '8.x-1.1' version: '8.x-1.2'
core: '8.x' core: '8.x'
project: 'redirect' project: 'redirect'
datestamp: 1520897884 datestamp: 1525419807
@@ -6,8 +6,8 @@ description: 'Allows users to redirect between domains.'
dependencies: dependencies:
- redirect - redirect
# Information added by Drupal.org packaging script on 2018-03-12 # Information added by Drupal.org packaging script on 2018-05-04
version: '8.x-1.1' version: '8.x-1.2'
core: '8.x' core: '8.x'
project: 'redirect' project: 'redirect'
datestamp: 1520897884 datestamp: 1525419807
@@ -8,8 +8,8 @@ dependencies:
- drupal:link - drupal:link
- drupal:views - drupal:views
# Information added by Drupal.org packaging script on 2018-03-12 # Information added by Drupal.org packaging script on 2018-05-04
version: '8.x-1.1' version: '8.x-1.2'
core: '8.x' core: '8.x'
project: 'redirect' project: 'redirect'
datestamp: 1520897884 datestamp: 1525419807
@@ -22,6 +22,7 @@ use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url; use Drupal\Core\Url;
use Drupal\Core\Site\Settings; use Drupal\Core\Site\Settings;
use Drupal\redirect\Entity\Redirect; use Drupal\redirect\Entity\Redirect;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
/** /**
* Implements hook_hook_info(). * Implements hook_hook_info().
@@ -79,9 +80,15 @@ function redirect_help($route_name, RouteMatchInterface $route_match) {
* Will delete redirects based on the entity URL. * Will delete redirects based on the entity URL.
*/ */
function redirect_entity_delete(EntityInterface $entity) { function redirect_entity_delete(EntityInterface $entity) {
if ($entity->getEntityType()->hasLinkTemplate('canonical')) { try {
redirect_delete_by_path('internal:/' . $entity->toUrl('canonical')->getInternalPath()); if ($entity->getEntityType()->hasLinkTemplate('canonical') && $entity->toUrl('canonical')->isRouted()) {
redirect_delete_by_path('entity:' . $entity->getEntityTypeId() . '/' . $entity->id()); redirect_delete_by_path('internal:/' . $entity->toUrl('canonical')->getInternalPath());
redirect_delete_by_path('entity:' . $entity->getEntityTypeId() . '/' . $entity->id());
}
}
catch (RouteNotFoundException $e) {
// This can happen if a module incorrectly defines a link template, ignore
// such errors.
} }
} }
@@ -128,12 +128,6 @@ class RouteNormalizerRequestSubscriber implements EventSubscriberInterface {
$response = new TrustedRedirectResponse($redirect_uri, $this->config->get('default_status_code')); $response = new TrustedRedirectResponse($redirect_uri, $this->config->get('default_status_code'));
$response->headers->set('X-Drupal-Route-Normalizer', 1); $response->headers->set('X-Drupal-Route-Normalizer', 1);
$event->setResponse($response); $event->setResponse($response);
// Disable page cache for redirects as that results in unpredictable
// behavior, e.g. when a trailing ? without query parameters is
// involved.
// @todo Remove when https://www.drupal.org/node/2761639 is fixed in
// Drupal core.
\Drupal::service('page_cache_kill_switch')->trigger();
} }
} }
} }
@@ -9,7 +9,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
* *
* @MigrateSource( * @MigrateSource(
* id = "d6_path_redirect", * id = "d6_path_redirect",
* source_module = "redirect" * source_module = "path_redirect"
* ) * )
*/ */
class PathRedirect extends DrupalSqlBase { class PathRedirect extends DrupalSqlBase {
@@ -173,15 +173,14 @@ $connection->insert('system')
'info', 'info',
)) ))
->values(array( ->values(array(
'filename' => 'modules/contrib/redirect/redirect.module', 'filename' => 'modules/contrib/path_redirect/path_redirect.module',
'name' => 'redirect', 'name' => 'path_redirect',
'type' => 'module', 'type' => 'module',
'owner' => '', 'owner' => '',
'status' => '1', 'status' => '1',
'bootstrap' => '0', 'bootstrap' => '0',
'schema_version' => '7000', 'schema_version' => '7000',
'weight' => '0', 'weight' => '0',
'info' => 'a:10:{s:4:"name";s:8:"Redirect";s:11:"description";s:51:"Allows users to redirect from old URLs to new URLs.";s:7:"package";s:5:"Other";s:7:"version";s:3:"6.0";s:4:"core";s:3:"6.x";s:7:"project";s:8:"redirect";s:9:"datestamp";s:10:"1347989995";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}', 'info' => 'a:10:{s:4:"name";s:13:"Path Redirect";s:11:"description";s:51:"Allows users to redirect from old URLs to new URLs.";s:7:"package";s:5:"Other";s:7:"version";s:3:"6.0";s:4:"core";s:3:"6.x";s:7:"project";s:13:"path_redirect";s:9:"datestamp";s:10:"1347989995";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
)) ))
->execute(); ->execute();
@@ -5,8 +5,8 @@ type: module
dependencies: dependencies:
- drupal:system (>=8.5.0) - drupal:system (>=8.5.0)
# Information added by Drupal.org packaging script on 2018-03-12 # Information added by Drupal.org packaging script on 2018-06-08
version: '8.x-1.0-beta2' version: '8.x-1.0-beta4'
core: '8.x' core: '8.x'
project: 'entity' project: 'entity'
datestamp: 1520873296 datestamp: 1528452194
@@ -69,6 +69,20 @@ class EntityRevisionRouteAccessChecker implements AccessInterface {
} }
} }
/**
* Performs access checks.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The entity for which to check access.
* @param \Drupal\Core\Session\AccountInterface $account
* The user for which to check access.
* @param string $operation
* The entity operation. Usually one of 'view', 'view label', 'update' or
* 'delete'.
*
* @return bool
* The access result.
*/
protected function checkAccess(ContentEntityInterface $entity, AccountInterface $account, $operation = 'view') { protected function checkAccess(ContentEntityInterface $entity, AccountInterface $account, $operation = 'view') {
$entity_type = $entity->getEntityType(); $entity_type = $entity->getEntityType();
$entity_type_id = $entity->getEntityTypeId(); $entity_type_id = $entity->getEntityTypeId();
@@ -126,7 +140,6 @@ class EntityRevisionRouteAccessChecker implements AccessInterface {
return $this->accessCache[$cid]; return $this->accessCache[$cid];
} }
/** /**
* Counts the number of revisions in the default language. * Counts the number of revisions in the default language.
* *
@@ -0,0 +1,49 @@
<?php
namespace Drupal\entity;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityAccessControlHandler as CoreEntityAccessControlHandler;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Controls access to bundle entities.
*
* Allows the bundle entity label to be viewed if the account has
* access to view entities of that bundle.
*/
class BundleEntityAccessControlHandler extends CoreEntityAccessControlHandler {
/**
* {@inheritdoc}
*/
protected $viewLabelOperation = TRUE;
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
if ($operation === 'view label') {
$bundle = $entity->id();
$entity_type_id = $this->entityType->getBundleOf();
$permissions = [
"administer $entity_type_id",
// View permissions provided by EntityPermissionProvider.
"view $entity_type_id",
"view $bundle $entity_type_id",
// View permissions provided by UncacheableEntityPermissionProvider.
"view own $entity_type_id",
"view any $entity_type_id",
"view own $bundle $entity_type_id",
"view any $bundle $entity_type_id",
];
return AccessResult::allowedIfHasPermissions($account, $permissions, 'OR');
}
else {
return parent::checkAccess($entity, $operation, $account);
}
}
}

Some files were not shown because too many files have changed in this diff Show More