protected function FeaturesCommands::componentFilter in Features 8.3
Same name and namespace in other branches
- 8.4 src/Commands/FeaturesCommands.php \Drupal\features\Commands\FeaturesCommands::componentFilter()
Filters components by patterns.
2 calls to FeaturesCommands::componentFilter()
- FeaturesCommands::add in src/
Commands/ FeaturesCommands.php - Add a config item to a feature package.
- FeaturesCommands::components in src/
Commands/ FeaturesCommands.php - List features components.
File
- src/
Commands/ FeaturesCommands.php, line 853
Class
- FeaturesCommands
- Drush commands for Features.
Namespace
Drupal\features\CommandsCode
protected function componentFilter($all_components, $patterns = [], $options = []) {
$options += [
'exported' => TRUE,
'not exported' => TRUE,
'provided by' => FALSE,
];
$pool = [];
// Maps exported components to feature modules.
$components_map = $this
->componentMap();
// First filter on exported state.
foreach ($all_components as $source => $components) {
foreach ($components as $name => $title) {
$exported = count($components_map[$source][$name]) > 0;
if ($exported) {
if ($options['exported']) {
$pool[$source][$name] = $title;
}
}
else {
if ($options['not exported']) {
$pool[$source][$name] = $title;
}
}
}
}
$state_string = '';
if (!$options['exported']) {
$state_string = 'unexported';
}
elseif (!$options['not exported']) {
$state_string = 'exported';
}
$selected = [];
foreach ($patterns as $pattern) {
// Rewrite * to %. Let users use both as wildcard.
$pattern = strtr($pattern, [
'*' => '%',
]);
$sources = [];
list($source_pattern, $component_pattern) = explode(':', $pattern, 2);
// If source is empty, use a pattern.
if ($source_pattern == '') {
$source_pattern = '%';
}
if ($component_pattern == '') {
$component_pattern = '%';
}
$preg_source_pattern = strtr(preg_quote($source_pattern, '/'), [
'%' => '.*',
]);
$preg_component_pattern = strtr(preg_quote($component_pattern, '/'), [
'%' => '.*',
]);
// 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
// more natural for patterns.
if (strpos($source_pattern, '%') !== FALSE) {
$preg_source_pattern = '^' . $preg_source_pattern . '$';
}
if (strpos($component_pattern, '%') !== FALSE) {
$preg_component_pattern = '^' . $preg_component_pattern . '$';
}
$matches = [];
// Find the sources.
$all_sources = array_keys($pool);
$matches = preg_grep('/' . $preg_source_pattern . '/', $all_sources);
if (count($matches) > 0) {
// If we have multiple matches and the source string wasn't a
// pattern, check if one of the matches is equal to the pattern, and
// use that, or error out.
if (count($matches) > 1 and $preg_source_pattern[0] != '^') {
if (in_array($source_pattern, $matches)) {
$matches = [
$source_pattern,
];
}
else {
throw new \Exception(dt('Ambiguous source "@source", matches @matches', [
'@source' => $source_pattern,
'@matches' => implode(', ', $matches),
]));
}
}
// Loose the indexes preg_grep preserved.
$sources = array_values($matches);
}
else {
throw new \Exception(dt('No @state sources match "@source"', [
'@state' => $state_string,
'@source' => $source_pattern,
]));
}
// Now find the components.
foreach ($sources as $source) {
// Find the components.
$all_components = array_keys($pool[$source]);
// See if there's any matches.
$matches = preg_grep('/' . $preg_component_pattern . '/', $all_components);
if (count($matches) > 0) {
// If we have multiple matches and the components string wasn't a
// pattern, check if one of the matches is equal to the pattern, and
// use that, or error out.
if (count($matches) > 1 and $preg_component_pattern[0] != '^') {
if (in_array($component_pattern, $matches)) {
$matches = [
$component_pattern,
];
}
else {
throw new \Exception(dt('Ambiguous component "@component", matches @matches', [
'@component' => $component_pattern,
'@matches' => implode(', ', $matches),
]));
}
}
if (!is_array($selected[$source])) {
$selected[$source] = [];
}
$selected[$source] += array_intersect_key($pool[$source], array_flip($matches));
}
else {
// No matches. If the source was a pattern, just carry on, else
// error out. Allows for patterns like ":*field*".
if ($preg_source_pattern[0] != '^') {
throw new \Exception(dt('No @state @source components match "@component"', [
'@state' => $state_string,
'@component' => $component_pattern,
'@source' => $source,
]));
}
}
}
}
// Lastly, provide feature module information on the selected components, if
// requested.
$provided_by = [];
if ($options['provided by'] && $options['exported']) {
foreach ($selected as $source => $components) {
foreach ($components as $name => $title) {
$exported = count($components_map[$source][$name]) > 0;
if ($exported) {
$provided_by[$source . ':' . $name] = implode(', ', $components_map[$source][$name]);
}
}
}
}
return [
'components' => $selected,
'sources' => $provided_by,
];
}