View source
<?php
namespace Drupal\config_actions;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Component\Utility\SortArray;
use Drupal\Component\Serialization\Yaml;
use Drupal\Core\Config\FileStorage;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Component\Utility\NestedArray;
class ConfigActionsService implements ConfigActionsServiceInterface {
use StringTranslationTrait;
const ACTION_KEY = 'actions';
const CONFIG_ACTIONS_LIST_COMMAND = '_list';
protected $pluginManager;
protected $sourceManager;
protected $moduleHandler;
protected $sourceCache = [];
protected $auto = FALSE;
protected $merge = FALSE;
public function __construct(PluginManagerInterface $plugin_manager, ConfigActionsSourceManager $source_manager, ModuleHandlerInterface $module_handler) {
$this->pluginManager = $plugin_manager;
$this->sourceManager = $source_manager;
$this->moduleHandler = $module_handler;
}
protected function getConfigActionsFiles($module_name = '') {
$result = [];
$modules = empty($module_name) ? $modules = $this->moduleHandler
->getModuleList() : [
$module_name => $this->moduleHandler
->getModule($module_name),
];
foreach ($modules as $module_name => $module) {
$module_path = $module
->getPath();
$path = $module_path . '/' . static::CONFIG_ACTIONS_CONFIG_DIR;
if (is_dir($path)) {
$action_storage = new FileStorage($path, StorageInterface::DEFAULT_COLLECTION);
$files = $action_storage
->listAll();
foreach ($files as $file) {
$result[] = [
'module' => $module_name,
'file' => $file,
'path' => $path . '/' . $file . '.yml',
];
}
}
}
return $result;
}
protected function readActions($filename) {
if (file_exists($filename)) {
return Yaml::decode(file_get_contents($filename));
}
return [];
}
protected function getSourceKey($source, $type = '', $base = '') {
$source = is_string($source) ? $source : md5(serialize($source));
return $base . ':' . $type . ':' . $source;
}
protected function getSourcePlugin($source, $type = '', $base = '') {
if (is_string($source) && strpos($source, '::') > 0) {
list($type, $source) = explode('::', $source);
}
$source_key = $this
->getSourceKey($source, $type, $base);
if (isset($this->sourceCache[$source_key])) {
return $this->sourceCache[$source_key];
}
$source_plugin = NULL;
$options = array(
'source' => $source,
'base' => $base,
);
$definitions = $this->sourceManager
->getDefinitions();
if (!empty($type) && isset($definitions[$type])) {
$source_plugin = $this->sourceManager
->createInstance($type, $options);
}
else {
uasort($definitions, array(
SortArray::class,
'sortByWeightElement',
));
foreach ($definitions as $plugin_id => $definition) {
$plugin = $this->sourceManager
->createInstance($plugin_id, $options);
if ($plugin
->detect($source)) {
$source_plugin = $plugin;
break;
}
}
}
$this->sourceCache[$source_key] = $source_plugin;
return $source_plugin;
}
public function loadSource($source, $type = '', $base = '') {
$plugin = $this
->getSourcePlugin($source, $type, $base);
$data = !empty($plugin) ? $plugin
->load() : [];
$this->merge = !empty($plugin) ? $plugin
->getMerge() : FALSE;
return $data;
}
public function saveSource($data, $dest, $type = '', $base = '', $force = FALSE) {
$result = FALSE;
if (!empty($dest)) {
$plugin = $this
->getSourcePlugin($dest, $type, $base);
if (!empty($plugin)) {
$plugin
->setMerge($plugin
->getMerge() || $this->merge);
if ($force) {
$result = $plugin
->save($data);
}
else {
$plugin
->setData($data);
$result = TRUE;
}
}
}
return $result;
}
public function saveAll() {
foreach ($this->sourceCache as $key => $plugin) {
if (isset($plugin) && $plugin
->isChanged()) {
$plugin
->save($plugin
->getData());
}
}
}
public function clearSourceCache() {
$this
->saveAll();
$this->sourceCache = [];
}
protected function doProcessAction(array $action, array $options = [], $overrides = [], $action_id = '', $action_path = '', &$action_list = NULL) {
$result = NULL;
if ($this->auto && isset($action['auto']) && $action['auto'] === FALSE && (!isset($overrides['auto']) || $overrides['auto'] === FALSE)) {
return $result;
}
$options = NestedArray::mergeDeepArray([
$options,
$action,
$overrides,
], TRUE);
unset($options[static::ACTION_KEY]);
if (empty($action_id) || $action_id == $action_path) {
if (array_key_exists(static::ACTION_KEY, $action)) {
foreach ($action[static::ACTION_KEY] as $key => $action_item) {
$path = empty($action_path) ? $key : $action_path . ':' . $key;
$options['id'] = $key;
$action_item = !empty($action_item) ? $action_item : [];
$result = $this
->doProcessAction($action_item, $options, [], '', $path, $action_list);
}
}
elseif (isset($action_list)) {
$action_list[$action_path] = $action;
}
else {
$plugin_id = !empty($action['plugin']) ? $action['plugin'] : (!empty($options['plugin']) ? $options['plugin'] : 'default');
$plugin = $this->pluginManager
->createInstance($plugin_id, $options);
if (!isset($plugin)) {
throw new \Exception($this
->t('Could not find plugin: @name.', [
'@name' => $plugin_id,
]));
}
$result = $plugin
->execute($action);
}
}
elseif (array_key_exists(static::ACTION_KEY, $action)) {
foreach ($action[static::ACTION_KEY] as $key => $action_item) {
$path = empty($action_path) ? $key : $action_path . ':' . $key;
$options['id'] = $key;
$action_item = !empty($action_item) ? $action_item : [];
if ($result = $this
->doProcessAction($action_item, $options, $overrides, $action_id, $path, $action_list)) {
if (!isset($action_list)) {
break;
}
}
}
}
return $result;
}
public function processAction(array $action, array $options = [], $action_id = '') {
$data = $this
->doProcessAction($action, [], $options, $action_id, '');
$this
->saveAll();
return $data;
}
public function listActions(array $action) {
$action_list = [];
$data = $this
->doProcessAction($action, [], [], '', '', $action_list);
return $action_list;
}
public function importAction($module_name, $action_id = '', $file = '', $variables = []) {
$result = [];
$file = str_replace('.yml', '', $file);
$files = $this
->getConfigActionsFiles($module_name);
foreach ($files as $action_file) {
if (empty($file) || $file === $action_file['file']) {
$actions = $this
->readActions($action_file['path']);
$actions['module'] = !empty($actions['module']) ? $actions['module'] : $action_file['module'];
$actions['base'] = DRUPAL_ROOT . '/' . drupal_get_path('module', $actions['module']);
$actions['source'] = !empty($actions['source']) ? $actions['source'] : $action_file['file'];
$this
->autoExecute(empty($file) && empty($action_id));
$result[$action_file['file']] = $this
->processAction($actions, $variables, $action_id);
}
}
return $result;
}
public function listAll($module_name = '', $file = '') {
$result = [];
$modules = !empty($module_name) ? [
$module_name => [],
] : $this->moduleHandler
->getModuleList();
foreach ($modules as $module_name => $extension) {
$files = $this
->getConfigActionsFiles($module_name);
foreach ($files as $action_file) {
if (empty($file) || $file === $action_file['file']) {
$actions = $this
->readActions($action_file['path']);
$result[$module_name][$action_file['file']] = $this
->listActions($actions);
}
}
}
return $result;
}
public function autoExecute($value = NULL) {
if (isset($value)) {
$this->auto = $value;
}
return $this->auto;
}
}