diff --git a/feeds_tamper.routing.yml b/feeds_tamper.routing.yml new file mode 100644 index 0000000..3bfa261 --- /dev/null +++ b/feeds_tamper.routing.yml @@ -0,0 +1,23 @@ +entity.feeds_feed_type.tamper_add: + path: '/admin/structure/feeds/manage/{feeds_feed_type}/tamper/add/{source_field}' + defaults: + _form: '\Drupal\feeds_tamper\Form\TamperAddForm' + _title_callback: '\Drupal\feeds_tamper\Form\TamperAddForm::tamperTitle' + requirements: + _custom_access: '\Drupal\feeds_tamper\Form\TamperAddForm::checkAccess' + options: + parameters: + feeds_feed_type: + type: 'entity:feeds_feed_type' + +entity.feeds_feed_type.tamper_edit: + path: '/admin/structure/feeds/manage/{feeds_feed_type}/tamper/{tamper_uuid}/edit' + defaults: + _form: '\Drupal\feeds_tamper\Form\TamperEditForm' + _title_callback: '\Drupal\feeds_tamper\Form\TamperEditForm::tamperTitle' + requirements: + _custom_access: '\Drupal\feeds_tamper\Form\TamperEditForm::checkAccess' + options: + parameters: + feeds_feed_type: + type: 'entity:feeds_feed_type' diff --git a/feeds_tamper_ui/feeds_tamper_ui.admin.inc b/feeds_tamper_ui/feeds_tamper_ui.admin.inc index 5fdd64e..342c4d2 100755 --- a/feeds_tamper_ui/feeds_tamper_ui.admin.inc +++ b/feeds_tamper_ui/feeds_tamper_ui.admin.inc @@ -289,204 +289,6 @@ function theme_feeds_tamper_ui_list_form($variables) { } /** - * Add plugin form. - */ -function feeds_tamper_ui_add_plugin_form($form, &$form_state, $importer, $source) { - // Set importer and source for use in validate and submit. - $form_state['importer'] = $importer; - $form_state['source'] = $source; - - // Build plugin select list. - $feeds_tamper_plugins = feeds_tamper_get_plugins(); - $plugins = array(); - foreach ($feeds_tamper_plugins as $plugin_id => $plugin) { - $plugins[t($plugin['category'])][$plugin_id] = t($plugin['name']); - } - ksort($plugins); - foreach ($plugins as &$p) { - asort($p); - } - - $machine_name = key(reset($plugins)); - if (!empty($form_state['values']['plugin_id'])) { - $machine_name = $form_state['values']['plugin_id']; - } - // Add css. - $form['#attached']['css'][] = drupal_get_path('module', 'feeds_tamper_ui') . '/feeds_tamper_ui.css'; - - $plugin = feeds_tamper_get_plugin($machine_name); - - $form['plugin_id'] = array( - '#title' => t('The plugin to add'), - '#type' => 'select', - '#options' => $plugins, - '#default_value' => '', - '#tree' => TRUE, - '#ajax' => array( - 'callback' => 'feeds_tamper_ajax_callback', - 'wrapper' => 'feeds-tamper-plugin', - 'progress' => 'none', - ), - ); - $form['update'] = array( - '#type' => 'submit', - '#limit_validation_errors' => array( - array('plugin_id') - ), - '#submit' => array('feeds_tamper_ui_add_plugin_form_submit'), - '#value' => t('Choose'), - '#attributes' => array('class' => array('no-js')), - ); - $form['plugin']['#prefix'] = '
'; - $form['plugin']['#suffix'] = '
'; - - $form['plugin']['description'] = array( - '#title' => t('Description'), - '#type' => 'textfield', - '#default_value' => $plugin['default description'] ? t($plugin['default description']) : t($plugin['name']), - '#required' => TRUE, - '#description' => t('A useful description of what this plugin is doing.'), - ); - $form['plugin']['id'] = array( - '#title' => t('Machine name'), - '#type' => 'machine_name', - '#maxlength' => 32, - '#machine_name' => array( - 'exists' => 'feeds_tamper_machine_name_callback', - 'source' => array('plugin', 'description'), - ), - '#default_value' => $machine_name, - // '#disabled' => FALSE, - // '#size' => 60, - ); - $form['plugin']['settings'] = array( - '#title' => t('Configure @name', array('@name' => $plugin['name'])), - '#type' => 'fieldset', - '#tree' => TRUE, - ); - $form['plugin']['settings'] += $plugin['form']($importer, $source, array(), $form_state); - - $form['add'] = array( - '#type' => 'submit', - '#value' => t('Add'), - ); - - return $form; -} - -/** - * Add plugin form validate handler. - */ -function feeds_tamper_ui_add_plugin_form_validate($form, &$form_state) { - if ($form_state['triggering_element']['#value'] == t('Add')) { - if (feeds_tamper_machine_name_callback($form_state['values']['id'], $form, $form_state)) { - form_set_error('id', t('The machine-readable name is already in use. It must be unique.')); - return; - } - $plugin_id = $form_state['values']['plugin_id']; - $plugin = feeds_tamper_get_plugin($plugin_id); - if ($plugin['validate'] && isset($form_state['values']['settings'])) { - $plugin['validate']($form_state['values']['settings']); - } - $id = $form_state['values']['id']; - $importer_id = $form_state['importer']->id; - $source = feeds_tamper_make_machine($form_state['source']); - $form_state['values']['id'] = "$importer_id-$source-$id"; - return; - } - unset($form_state['input']['id']); - unset($form_state['input']['description']); - unset($form_state['input']['settings']); -} - -/** - * Add plugin form submit handler. - */ -function feeds_tamper_ui_add_plugin_form_submit($form, &$form_state) { - if ($form_state['triggering_element']['#value'] == t('Add')) { - $obj = feeds_tamper_new_instance(); - $obj->plugin_id = $form_state['values']['plugin_id']; - if (isset($form_state['values']['settings'])) { - $obj->settings = $form_state['values']['settings']; - } - $obj->importer = $form_state['importer']->id; - - $obj->source = $form_state['source']; - $obj->description = $form_state['values']['description']; - $obj->id = $form_state['values']['id']; - - feeds_tamper_save_instance($obj); - $form_state['redirect'] = 'admin/structure/feeds/' . $obj->importer . '/tamper'; - $source_name = feeds_tamper_ui_source_name($obj); - drupal_set_message(t('Plugin %description was successfully added to %source.', array('%description' => $obj->description, '%source' => $source_name))); - return; - } - $form_state['rebuild'] = TRUE; -} - -/** - * Edit plugin form. - * - * @todo Combine add and edit forms? - */ -function feeds_tamper_ui_edit_plugin_form($form, &$form_state, $instance) { - // Set breadcrumb. - $importer = feeds_importer($instance->importer); - - $form_state['instance'] = $instance; - $plugin = feeds_tamper_get_plugin($instance->plugin_id); - $form['#tree'] = TRUE; - - $form['description'] = array( - '#title' => t('Description'), - '#type' => 'textfield', - '#description' => t('A useful description of what this plugin is doing.'), - '#default_value' => $instance->description, - ); - $form['settings'] = array( - '#title' => t('Configure @plugin', array('@plugin' => $plugin['name'])), - '#type' => 'fieldset', - '#tree' => TRUE, - ); - $form['settings'] += $plugin['form']($importer, $instance->source, $instance->settings, $form_state); - - $form['save'] = array( - '#type' => 'submit', - '#value' => t('Save'), - ); - - $form['#attached']['css'][] = drupal_get_path('module', 'feeds_tamper_ui') . '/feeds_tamper_ui.css'; - - return $form; -} - -/** - * Edit plugin form validate handler. - */ -function feeds_tamper_ui_edit_plugin_form_validate($form, &$form_state) { - $plugin_id = $form_state['instance']->plugin_id; - $plugin = feeds_tamper_get_plugin($plugin_id); - if ($plugin['validate']) { - $plugin['validate']($form_state['values']['settings']); - } -} - -/** - * Edit plugin form submit handler. - */ -function feeds_tamper_ui_edit_plugin_form_submit($form, &$form_state) { - $instance = $form_state['instance']; - if (isset($form_state['values']['settings'])) { - $instance->settings = $form_state['values']['settings']; - } - $instance->description = $form_state['values']['description']; - - feeds_tamper_save_instance($instance); - drupal_set_message(t('The plugin %plugin has been updated.', array('%plugin' => $instance->description))); - $form_state['redirect'] = 'admin/structure/feeds/' . $instance->importer . '/tamper'; -} - -/** * Delete plugin form. */ function feeds_tamper_ui_delete_form($form, &$form_state, $instance) { diff --git a/feeds_tamper_ui/feeds_tamper_ui.module b/feeds_tamper_ui/feeds_tamper_ui.module index dd98d83..fa79c87 100755 --- a/feeds_tamper_ui/feeds_tamper_ui.module +++ b/feeds_tamper_ui/feeds_tamper_ui.module @@ -42,18 +42,6 @@ function feeds_tamper_ui_menu() { 'weight' => 10, ) + $defaults; - $items['admin/structure/feeds/%feeds_importer/tamper/add/%feeds_tamper_ui_source'] = array( - 'title callback' => 'feeds_tamper_ui_add_title', - 'title arguments' => array(6), - 'page arguments' => array('feeds_tamper_ui_add_plugin_form', 3, 6), - ) + $defaults; - - $items['admin/structure/feeds/%feeds_importer/tamper/%feeds_tamper_plugin_instance/edit'] = array( - 'title callback' => 'feeds_tamper_ui_edit_title', - 'page arguments' => array('feeds_tamper_ui_edit_plugin_form', 5), - 'access arguments' => array(NULL, 5), - ) + $defaults; - $items['admin/structure/feeds/%feeds_importer/tamper/%feeds_tamper_plugin_instance/delete'] = array( 'title callback' => 'feeds_tamper_ui_delete_title', 'page arguments' => array('feeds_tamper_ui_delete_form', 5), @@ -91,24 +79,6 @@ function feeds_tamper_ui_source_load($source) { } /** - * Add plugin title callback. - */ -function feeds_tamper_ui_add_title($source) { - // Title callbacks get check_plain'ed already. - return t('Add plugin to: !source', array('!source' => $source)); -} - -/** - * Edit plugin title callback. - */ -function feeds_tamper_ui_edit_title($instance) { - if ($instance->export_type == EXPORT_IN_DATABASE) { - return t('Edit: @id', array('@id' => $instance->description)); - } - return t('Override: @id', array('@id' => $instance->description)); -} - -/** * Delete plugin title callback. */ function feeds_tamper_ui_delete_title($instance) { diff --git a/src/FeedTypeTamperMeta.php b/src/FeedTypeTamperMeta.php index be09bf0..6c83878 100644 --- a/src/FeedTypeTamperMeta.php +++ b/src/FeedTypeTamperMeta.php @@ -125,6 +125,15 @@ class FeedTypeTamperMeta implements FeedTypeTamperMetaInterface { /** * {@inheritdoc} */ + public function updateTamper(TamperInterface $tamper, array $configuration) { + $this->getTampers()->setInstanceConfiguration($tamper->getSetting('uuid'), $configuration); + $this->updateFeedType(); + return $tamper; + } + + /** + * {@inheritdoc} + */ public function removeTamper(TamperInterface $tamper) { $this->getTampers()->removeInstanceId($tamper->getSetting('uuid')); $this->updateFeedType(); diff --git a/src/FeedTypeTamperMetaInterface.php b/src/FeedTypeTamperMetaInterface.php index 8f3bbc9..4cbacd4 100644 --- a/src/FeedTypeTamperMetaInterface.php +++ b/src/FeedTypeTamperMetaInterface.php @@ -49,6 +49,19 @@ interface FeedTypeTamperMetaInterface extends ObjectWithPluginCollectionInterfac public function addTamper(array $configuration); /** + * Updates the tamper plugin instance. + * + * @param \Drupal\tamper\TamperInterface $tamper + * The tamper plugin instance. + * @param array $configuration + * An array of tamper configuration. + * + * @return \Drupal\tamper\TamperInterface + * The updated tamper plugin instance. + */ + public function updateTamper(TamperInterface $tamper, array $configuration); + + /** * Removes a tamper plugin instance from this feed type. * * @param \Drupal\tamper\TamperInterface $tamper diff --git a/src/Form/TamperAddForm.php b/src/Form/TamperAddForm.php new file mode 100644 index 0000000..27bbb03 --- /dev/null +++ b/src/Form/TamperAddForm.php @@ -0,0 +1,109 @@ +getMappingSources(); + if (!isset($sources[$source_field])) { + throw new NotFoundHttpException(); + } + } + + /** + * Prepares the tamper plugin. + * + * @param string $tamper_id + * The id of the tamper plugin. + * + * @return \Drupal\tamper\TamperInterface + * The tamper plugin instance. + */ + protected function preparePlugin($tamper_id = NULL) { + if (empty($tamper_id)) { + return NULL; + } + + try { + /** @var \Drupal\tamper\TamperInterface $tamper */ + $tamper = $this->tamperManager->createInstance($tamper_id); + return $tamper; + } + catch (PluginException $e) { + drupal_set_message($this->t('The specified plugin is invalid.'), 'error'); + } + } + + /** + * Form constructor. + * + * @param array $form + * An associative array containing the structure of the form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + * @param \Drupal\feeds\FeedTypeInterface $feeds_feed_type + * The feed that we are adding a tamper plugin to. + * @param string $source_field + * The source field we are adding the tamper plugin to. + * + * @return array + * The form structure. + */ + public function buildForm(array $form, FormStateInterface $form_state, FeedTypeInterface $feeds_feed_type = NULL, $source_field = NULL) { + $this->assertSourceField($feeds_feed_type, $source_field); + + $this->feedsFeedType = $feeds_feed_type; + $this->sourceField = $source_field; + $this->plugin = $this->preparePlugin($form_state->getValue(self::VAR_TAMPER_ID)); + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $config = $this->prepareConfig($this->sourceField, $form_state); + $tamper_meta = $this->feedTypeTamperManager->getTamperMeta($this->feedsFeedType); + $tamper_meta->addTamper($config); + $this->feedsFeedType->save(); + + drupal_set_message($this->t('Plugin %plugin_label was successfully added to %source.', [ + '%plugin_label' => $this->plugin->getPluginDefinition()['label'], + '%source' => $this->sourceField, + ])); + // TODO Add a form state redirect back to the overview page. + } + +} diff --git a/src/Form/TamperEditForm.php b/src/Form/TamperEditForm.php new file mode 100644 index 0000000..6adc30b --- /dev/null +++ b/src/Form/TamperEditForm.php @@ -0,0 +1,88 @@ +feedTypeTamperManager->getTamperMeta($feeds_feed_type); + + try { + $tamper_meta->getTamper($tamper_uuid); + } + catch (PluginNotFoundException $e) { + throw new NotFoundHttpException(); + } + } + + /** + * Form constructor. + * + * @param array $form + * An associative array containing the structure of the form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + * @param \Drupal\feeds\FeedTypeInterface $feeds_feed_type + * The feed that we are adding a tamper plugin to. + * @param string $tamper_uuid + * The tamper uuid. + * + * @return array + * The form structure. + */ + public function buildForm(array $form, FormStateInterface $form_state, FeedTypeInterface $feeds_feed_type = NULL, $tamper_uuid = NULL) { + $this->assertTamper($feeds_feed_type, $tamper_uuid); + + $this->feedsFeedType = $feeds_feed_type; + $tamper_meta = $this->feedTypeTamperManager->getTamperMeta($feeds_feed_type); + $this->plugin = $tamper_meta->getTamper($tamper_uuid); + + $form = parent::buildForm($form, $form_state); + $form[self::VAR_TAMPER_ID]['#disabled'] = TRUE; + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $tamper_meta = $this->feedTypeTamperManager->getTamperMeta($this->feedsFeedType); + $uuid = $this->plugin->getSetting('uuid'); + $tempers_config = $tamper_meta->getTampers()->getConfiguration(); + + $config = $this->prepareConfig($tempers_config[$uuid]['source'], $form_state); + $tamper_meta->updateTamper($this->plugin, $config); + $this->feedsFeedType->save(); + + drupal_set_message($this->t('The plugin %plugin_label has been updated.', [ + '%plugin_label' => $this->plugin->getPluginDefinition()['label'], + ])); + // TODO Add a form state redirect back to the overview page. + } + +} diff --git a/src/Form/TamperFormBase.php b/src/Form/TamperFormBase.php new file mode 100644 index 0000000..77c6099 --- /dev/null +++ b/src/Form/TamperFormBase.php @@ -0,0 +1,233 @@ +setTamperManager($container->get('plugin.manager.tamper')); + $form->setTamperMetaManager($container->get('feeds_tamper.feed_type_tamper_manager')); + return $form; + } + + /** + * Set the tamper manager. + * + * @param \Drupal\tamper\TamperManagerInterface $tamper_manager + * Tamper plugin manager. + */ + public function setTamperManager(TamperManagerInterface $tamper_manager) { + $this->tamperManager = $tamper_manager; + } + + /** + * Set the feed type tamper manager. + * + * @param \Drupal\feeds_tamper\FeedTypeTamperManagerInterface $feed_type_tamper_manager + * Feed type tamper manager. + */ + public function setTamperMetaManager(FeedTypeTamperManagerInterface $feed_type_tamper_manager) { + $this->feedTypeTamperManager = $feed_type_tamper_manager; + } + + /** + * Page title callback. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. + * + * @return \Drupal\Core\StringTranslation\TranslatableMarkup|null + * Translated string to use as the title. + */ + public function tamperTitle(RouteMatchInterface $route_match) { + /** @var \Drupal\feeds\Entity\FeedType $feed_type */ + $feed_type = $route_match->getParameter('feeds_feed_type'); + $source_field = $route_match->getParameter('source_field'); + $tamper_uuid = $route_match->getParameter('tamper_uuid'); + + if ($source_field) { + return $this->t('Add a tamper plugin to @label : @source', [ + '@label' => $feed_type->label(), + '@source' => $source_field, + ]); + } + elseif ($tamper_uuid) { + $tamper_meta = $this->feedTypeTamperManager->getTamperMeta($feed_type); + $tamper = $tamper_meta->getTamper($tamper_uuid); + return $this->t('Edit @label', [ + '@label' => $tamper->getPluginDefinition()['label'], + ]); + } + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $form[self::VAR_TAMPER_ID] = [ + '#type' => 'select', + '#title' => $this->t('The plugin to add'), + '#options' => $this->getPluginOptions(), + '#required' => TRUE, + '#default_value' => $this->plugin ? $this->plugin->getPluginDefinition()['id'] : NULL, + '#ajax' => [ + 'callback' => self::class . '::getPluginForm', + 'wrapper' => 'plugin-config', + ], + ]; + $form[self::VAR_PLUGIN_CONFIGURATION] = [ + '#type' => 'container', + '#tree' => TRUE, + '#attributes' => ['id' => ['plugin-config']], + ]; + + if ($this->plugin) { + $form[self::VAR_PLUGIN_CONFIGURATION]['description'] = [ + '#markup' => $this->plugin->getPluginDefinition()['description'], + ]; + } + + if ($this->plugin instanceof ConfigurableTamperInterface) { + $subform_state = SubformState::createForSubform($form[self::VAR_PLUGIN_CONFIGURATION], $form, $form_state); + $form[self::VAR_PLUGIN_CONFIGURATION] = $this->plugin->buildConfigurationForm($form[self::VAR_PLUGIN_CONFIGURATION], $subform_state); + } + + $form['actions'] = ['#type' => 'actions']; + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Submit'), + '#button_type' => 'primary', + ]; + // TODO Add a cancel button back to the overview page. + return $form; + } + + /** + * Ajax callback. + * + * Returns the plugin configuration form from an ajax request. + * + * @param array $form + * Drupal form array. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * Form state interface. + * + * @return array + * Plugin form. + */ + public function getPluginForm(array $form, FormStateInterface $form_state) { + return $form[self::VAR_PLUGIN_CONFIGURATION]; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + if (empty($this->plugin)) { + $form_state->setError($form[self::VAR_TAMPER_ID], $this->t('Plugin not selected')); + } + + if ($this->plugin instanceof ConfigurableTamperInterface) { + $subform_state = SubformState::createForSubform($form[self::VAR_PLUGIN_CONFIGURATION], $form, $form_state); + $this->plugin->validateConfigurationForm($form[self::VAR_PLUGIN_CONFIGURATION], $subform_state); + } + } + + /** + * Get the tamper plugin options. + * + * @return array + * List of tamper plugin groups, keyed by group, where the value is another + * array of plugin labels keyed by plugin id. + */ + protected function getPluginOptions() { + // TODO - Move this logic to the tamper manager interface? + $plugin_options = array_map(function ($grouped_plugins) { + $group_options = []; + foreach ($grouped_plugins as $id => $plugin_definition) { + $group_options[$id] = $plugin_definition['label']; + } + return $group_options; + }, $this->tamperManager->getGroupedDefinitions()); + + return $plugin_options; + } + + /** + * Prepares a configuration array. + * + * @param string $source + * The source. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The form state. + * + * @return array + * The configuration array. + */ + protected function prepareConfig($source, FormStateInterface $form_state) { + $config = [ + 'plugin' => $this->plugin->getPluginId(), + 'source' => $source, + ]; + + if ($this->plugin instanceof ConfigurableTamperInterface) { + $config += $form_state->getValue(self::VAR_PLUGIN_CONFIGURATION); + } + + return $config; + } + +} diff --git a/src/Form/TamperFormTrait.php b/src/Form/TamperFormTrait.php new file mode 100644 index 0000000..92b26af --- /dev/null +++ b/src/Form/TamperFormTrait.php @@ -0,0 +1,40 @@ +hasPermission('administer feeds_tamper')) { + return AccessResult::allowed(); + } + + /** @var \Drupal\feeds\Entity\FeedType $feed_type */ + $feed_type = $route_match->getParameter('feeds_feed_type'); + return AccessResult::allowedIf($account->hasPermission('tamper ' . $feed_type->id())) + ->addCacheableDependency($feed_type); + } + +} diff --git a/tests/src/Kernel/FeedTypeTamperMetaTest.php b/tests/src/Kernel/FeedTypeTamperMetaTest.php index 9078015..38a12f0 100644 --- a/tests/src/Kernel/FeedTypeTamperMetaTest.php +++ b/tests/src/Kernel/FeedTypeTamperMetaTest.php @@ -109,6 +109,24 @@ class FeedTypeTamperMetaTest extends KernelTestBase { } /** + * @covers ::updateTamper + */ + public function testUpdateTamper() { + $separator = ':'; + $description = 'Explode with pipe character updated'; + $tamper = $this->feedTypeTamperMeta->getTamper('uuid1'); + $this->feedTypeTamperMeta->updateTamper($tamper, [ + 'separator' => $separator, + 'description' => $description, + ]); + $tempers_config = $this->feedTypeTamperMeta->getTampers()->getConfiguration(); + $config = $tempers_config['uuid1']; + + $this->assertEquals($separator, $config['separator']); + $this->assertEquals($description, $config['description']); + } + + /** * @covers ::removeTamper */ public function testRemoveTamper() {