diff --git a/CHANGELOG.md b/CHANGELOG.md index 66a22843d..6f250c84f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [Announce new releases on farmOS.discourse.group #780](https://github.com/farmOS/farmOS/pull/780) - [Add a Product asset type and Product type taxonomy #787](https://github.com/farmOS/farmOS/pull/787) - [Inventory quick form #766](https://github.com/farmOS/farmOS/pull/766) +- [Add UI for creating instances of quick forms #785](https://github.com/farmOS/farmOS/pull/785) ### Changed diff --git a/modules/core/quick/farm_quick.info.yml b/modules/core/quick/farm_quick.info.yml index 4e31dc220..0348efca5 100644 --- a/modules/core/quick/farm_quick.info.yml +++ b/modules/core/quick/farm_quick.info.yml @@ -8,5 +8,6 @@ dependencies: - drupal:taxonomy - farm:asset - farm:farm_log_quantity + - farm:farm_setup - farm:quantity - log:log diff --git a/modules/core/quick/farm_quick.links.action.yml b/modules/core/quick/farm_quick.links.action.yml new file mode 100644 index 000000000..d4c585b6c --- /dev/null +++ b/modules/core/quick/farm_quick.links.action.yml @@ -0,0 +1,5 @@ +farm_quick.add_page: + title: 'Add quick form' + route_name: farm_quick.add_page + appears_on: + - entity.quick_form.collection diff --git a/modules/core/quick/farm_quick.links.menu.yml b/modules/core/quick/farm_quick.links.menu.yml index 15f13a502..f85e836be 100644 --- a/modules/core/quick/farm_quick.links.menu.yml +++ b/modules/core/quick/farm_quick.links.menu.yml @@ -1,3 +1,8 @@ farm.quick: class: Drupal\Core\Menu\MenuLinkDefault deriver: Drupal\farm_quick\Plugin\Derivative\QuickFormMenuLink +farm.quick_setup: + title: Quick Forms + description: Quick forms make it easy to record common activities. + parent: farm.setup + route_name: entity.quick_form.collection diff --git a/modules/core/quick/farm_quick.managed_role_permissions.yml b/modules/core/quick/farm_quick.managed_role_permissions.yml index f227dc564..ff59b802d 100644 --- a/modules/core/quick/farm_quick.managed_role_permissions.yml +++ b/modules/core/quick/farm_quick.managed_role_permissions.yml @@ -1,5 +1,6 @@ farm_quick: config_permissions: - update quick_form + - administer quick_form default_permissions: - view quick_form diff --git a/modules/core/quick/farm_quick.module b/modules/core/quick/farm_quick.module index 56024e9ab..83365901a 100644 --- a/modules/core/quick/farm_quick.module +++ b/modules/core/quick/farm_quick.module @@ -5,7 +5,9 @@ * The farmOS Quick Form module. */ +use Drupal\Component\Utility\Html; use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; /** @@ -23,11 +25,16 @@ function farm_quick_help($route_name, RouteMatchInterface $route_match) { if (strpos($route_name, 'farm.quick.') === 0) { $quick_form_id = $route_match->getParameter('id'); if ($route_name == 'farm.quick.' . $quick_form_id) { + /** @var \Drupal\farm_quick\Entity\QuickFormInstanceInterface $quick_form */ $quick_form = \Drupal::service('quick_form.instance_manager')->getInstance($quick_form_id); - $help_text = $quick_form->getHelpText(); - if (!empty($help_text)) { - $output .= '

' . $help_text . '

'; - } + $output = [ + '#type' => 'html_tag', + '#tag' => 'p', + '#value' => Html::escape($quick_form->getHelpText()), + '#cache' => [ + 'tags' => $quick_form->getCacheTags(), + ], + ]; } } @@ -57,3 +64,42 @@ function farm_quick_farm_entity_bundle_field_info(EntityTypeInterface $entity_ty return $fields; } + +/** + * Implements hook_form_alter(). + */ +function farm_quick_form_alter(&$form, FormStateInterface $form_state, $form_id) { + + // Only alter views_form_ forms. + if (!str_starts_with($form_id, 'views_form_')) { + return; + } + + $target = NULL; + if (isset($form['header']['asset_bulk_form']['action'])) { + $target = 'asset_bulk_form'; + } + if (isset($form['header']['log_bulk_form']['action'])) { + $target = 'log_bulk_form'; + } + + // Alter action options for the target entity type bulk form. + if ($target) { + + // Check for disabled quick forms. + $disabled_quick_forms = \Drupal::entityTypeManager()->getStorage('quick_form')->getQuery() + ->accessCheck(TRUE) + ->condition('status', FALSE) + ->execute(); + if (empty($disabled_quick_forms)) { + return; + } + + // Remove system actions that end with quick_* for a disabled quick form. + foreach (array_keys($form['header'][$target]['action']['#options']) as $option_id) { + if ((preg_match("/quick_(.*)/", $option_id, $matches)) && in_array($matches[1], $disabled_quick_forms)) { + unset($form['header'][$target]['action']['#options'][$option_id]); + } + } + } +} diff --git a/modules/core/quick/farm_quick.routing.yml b/modules/core/quick/farm_quick.routing.yml index 227697e6f..d0a091dbe 100644 --- a/modules/core/quick/farm_quick.routing.yml +++ b/modules/core/quick/farm_quick.routing.yml @@ -6,16 +6,23 @@ farm.quick: requirements: _permission: 'view quick_form' -farm_quick.configure: - path: /quick/{quick_form}/configure +farm_quick.add_page: + path: 'setup/quick/add' defaults: - _entity_form: quick_form.configure - _title_callback: \Drupal\farm_quick\Form\ConfigureQuickForm::getTitle + _controller: \Drupal\farm_quick\Controller\QuickFormAddPage::addPage + _title: 'Add quick form' requirements: - _custom_access: \Drupal\farm_quick\Form\ConfigureQuickForm::access + _permission: 'create quick_form' + +farm_quick.add_form: + path: '/setup/quick/add/{plugin}' + defaults: + _entity_form: quick_form.add + requirements: + _permission: 'create quick_form' options: parameters: - quick_form: + plugin: type: string route_callbacks: diff --git a/modules/core/quick/src/Controller/QuickFormAddPage.php b/modules/core/quick/src/Controller/QuickFormAddPage.php new file mode 100644 index 000000000..c490af184 --- /dev/null +++ b/modules/core/quick/src/Controller/QuickFormAddPage.php @@ -0,0 +1,79 @@ +quickFormPluginManager = $quick_form_plugin_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.quick_form'), + ); + } + + /** + * Add quick form page callback. + * + * @return array + * Render array. + */ + public function addPage(): array { + + $render = [ + '#theme' => 'entity_add_list', + '#bundles' => [], + '#cache' => [ + 'tags' => $this->quickFormPluginManager->getCacheTags(), + ], + ]; + + // Filter to configurable quick form plugins. + $plugins = array_filter($this->quickFormPluginManager->getDefinitions(), function (array $plugin) { + if (($instance = $this->quickFormPluginManager->createInstance($plugin['id'])) && $instance->isConfigurable()) { + return TRUE; + } + return FALSE; + }); + + if (empty($plugins)) { + $render['#add_bundle_message'] = $this->t('No quick forms are available. Enable a module that provides quick forms.'); + } + + // Add link for each configurable plugin. + foreach ($plugins as $plugin_id => $plugin) { + $render['#bundles'][$plugin_id] = [ + 'label' => Html::escape($plugin['label']), + 'description' => Html::escape($plugin['description']) ?? '', + 'add_link' => Link::createFromRoute($plugin['label'], 'farm_quick.add_form', ['plugin' => $plugin_id]), + ]; + } + + return $render; + } + +} diff --git a/modules/core/quick/src/Controller/QuickFormController.php b/modules/core/quick/src/Controller/QuickFormController.php index 3a2c30e18..b8dbc13c2 100644 --- a/modules/core/quick/src/Controller/QuickFormController.php +++ b/modules/core/quick/src/Controller/QuickFormController.php @@ -2,8 +2,10 @@ namespace Drupal\farm_quick\Controller; +use Drupal\Component\Utility\Html; use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Controller\ControllerBase; +use Drupal\Core\Render\Markup; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Url; use Drupal\farm_quick\QuickFormInstanceManagerInterface; @@ -63,8 +65,15 @@ class QuickFormController extends ControllerBase { $url = Url::fromRoute('farm.quick.' . $id); if ($url->access()) { $items[] = [ - 'title' => $quick_form->getLabel(), - 'description' => $quick_form->getDescription(), + // Wrap the title in Markup::create() because the template preprocess + // function for admin_block_content uses Link::fromTextAndUrl(), which + // sanitizes strings automatically. This avoids double-sanitization, + // but also ensures we are sanitizing consistently in this code, in + // case anything changes later. + // @see template_preprocess_admin_block_content() + // @see \Drupal\Core\Link::fromTextAndUrl() + 'title' => Markup::create(Html::escape($quick_form->getLabel())), + 'description' => Html::escape($quick_form->getDescription()), 'url' => $url, ]; } diff --git a/modules/core/quick/src/Entity/QuickFormInstance.php b/modules/core/quick/src/Entity/QuickFormInstance.php index c289f2719..82e779dc7 100644 --- a/modules/core/quick/src/Entity/QuickFormInstance.php +++ b/modules/core/quick/src/Entity/QuickFormInstance.php @@ -23,13 +23,27 @@ use Drupal\farm_quick\QuickFormPluginCollection; * handlers = { * "access" = "\Drupal\entity\EntityAccessControlHandler", * "permission_provider" = "\Drupal\entity\EntityPermissionProvider", + * "list_builder" = "Drupal\farm_quick\QuickFormListBuilder", * "form" = { + * "add" = "Drupal\farm_quick\Form\QuickFormEntityForm", + * "edit" = "Drupal\farm_quick\Form\QuickFormEntityForm", * "configure" = "Drupal\farm_quick\Form\ConfigureQuickForm", + * "delete" = "\Drupal\Core\Entity\EntityDeleteForm", + * }, + * "route_provider" = { + * "default" = "Drupal\entity\Routing\DefaultHtmlRouteProvider", * }, * }, + * admin_permission = "administer quick_form", * entity_keys = { * "id" = "id", - * "status" = "status" + * "status" = "status", + * "label" = "label", + * }, + * links = { + * "edit-form" = "/setup/quick/{quick_form}/edit", + * "delete-form" = "/setup/quick/{quick_form}/delete", + * "collection" = "/setup/quick" * }, * config_export = { * "id", diff --git a/modules/core/quick/src/Form/ConfigureQuickForm.php b/modules/core/quick/src/Form/ConfigureQuickForm.php deleted file mode 100644 index ea85c88e1..000000000 --- a/modules/core/quick/src/Form/ConfigureQuickForm.php +++ /dev/null @@ -1,159 +0,0 @@ -quickFormInstanceManager = $quick_form_instance_manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('quick_form.instance_manager'), - ); - } - - /** - * Get the title of the quick form. - * - * @param string $quick_form - * The quick form ID. - * - * @return \Drupal\Core\StringTranslation\TranslatableMarkup - * Quick form title. - */ - public function getTitle(string $quick_form) { - $quick_form_title = NULL; - if ($quick_form = $this->getQuickFormInstance($quick_form)) { - $quick_form_title = $quick_form->getLabel(); - } - return $this->t('Configure @quick_form', ['@quick_form' => $quick_form_title]); - } - - /** - * Checks access for configuration of a specific quick form. - * - * @param \Drupal\Core\Session\AccountInterface $account - * Run access checks for this account. - * @param string|null $quick_form - * The quick form ID. - * - * @return \Drupal\Core\Access\AccessResultInterface - * The access result. - */ - public function access(AccountInterface $account, string $quick_form = NULL) { - - // Get a quick form config entity. - if ($quick_form !== NULL) { - $quick_form = $this->getQuickFormInstance($quick_form); - } - - // Raise 404 if no quick form exists. This is the case with a quick form - // ID that is not a valid quick form plugin ID. - if ($quick_form === NULL) { - throw new ResourceNotFoundException(); - } - - // Deny access if the quick form plugin is not configurable. - if (!$quick_form->getPlugin() instanceof ConfigurableQuickFormInterface) { - return AccessResult::forbidden(); - } - - // Check the update quick_form permission. - $configure_form_access = AccessResult::allowedIfHasPermissions($account, ['update quick_form']); - return $quick_form->getPlugin()->access($account)->andIf($configure_form_access); - } - - /** - * {@inheritdoc} - */ - public function form(array $form, FormStateInterface $form_state) { - $form = parent::form($form, $form_state); - $form['settings'] = [ - '#tree' => TRUE, - ]; - $form['settings'] = $this->entity->getPlugin()->buildConfigurationForm($form['settings'], SubformState::createForSubform($form['settings'], $form, $form_state)); - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - parent::validateForm($form, $form_state); - $this->entity->getPlugin()->validateConfigurationForm($form['settings'], SubformState::createForSubform($form['settings'], $form, $form_state)); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - parent::submitForm($form, $form_state); - $this->entity->getPlugin()->submitConfigurationForm($form['settings'], SubformState::createForSubform($form['settings'], $form, $form_state)); - } - - /** - * {@inheritdoc} - */ - public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id) { - $entity = NULL; - if ($route_match->getRawParameter($entity_type_id) !== NULL) { - $entity = $this->getQuickFormInstance($route_match->getParameter($entity_type_id)); - } - return $entity; - } - - /** - * Helper function to get a quick form instance. - * - * @param string $quick_form_id - * The quick form ID. - * - * @return \Drupal\farm_quick\Entity\QuickFormInstanceInterface|null - * The quick form instance or NULL if does not exist. - */ - protected function getQuickFormInstance(string $quick_form_id) { - return $this->quickFormInstanceManager->getInstance($quick_form_id); - } - -} diff --git a/modules/core/quick/src/Form/QuickFormEntityForm.php b/modules/core/quick/src/Form/QuickFormEntityForm.php new file mode 100644 index 000000000..b81720cbf --- /dev/null +++ b/modules/core/quick/src/Form/QuickFormEntityForm.php @@ -0,0 +1,210 @@ +quickFormPluginManager = $quick_form_plugin_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.quick_form'), + ); + } + + /** + * {@inheritdoc} + */ + public function form(array $form, FormStateInterface $form_state, string $plugin = NULL) { + $form = parent::form($form, $form_state); + + // Add tabs if the quick form plugin is configurable. + $tab_group = NULL; + if ($this->entity->getPlugin()->isConfigurable()) { + $form['tabs'] = [ + '#type' => 'vertical_tabs', + ]; + $form['quick_form'] = [ + '#type' => 'details', + '#title' => $this->t('Quick form'), + '#group' => 'tabs', + ]; + $tab_group = 'quick_form'; + + // Render the plugin form in settings tab. + $form['settings_tab'] = [ + '#type' => 'details', + '#title' => Html::escape($this->entity->getPlugin()->getLabel()), + '#group' => 'tabs', + '#weight' => 50, + ]; + $form['settings'] = [ + '#tree' => TRUE, + '#type' => 'container', + '#group' => 'settings_tab', + ]; + $form['settings'] = $this->entity->getPlugin()->buildConfigurationForm($form['settings'], SubformState::createForSubform($form['settings'], $form, $form_state)); + } + + $form['label'] = [ + '#type' => 'textfield', + '#title' => $this->t('Label'), + '#maxlength' => 255, + '#required' => TRUE, + '#group' => $tab_group, + ]; + + $form['id'] = [ + '#type' => 'machine_name', + '#machine_name' => [ + 'exists' => '\Drupal\farm_quick\Entity\QuickFormInstance::load', + ], + '#disabled' => !$this->entity->isNew() || $this->getRequest()->get('override'), + '#group' => $tab_group, + ]; + + // Provide default label and ID for existing config entities + // or if the override parameter is set. + if (!$this->entity->isNew() || $this->getRequest()->get('override')) { + $form['label']['#default_value'] = $this->entity->label(); + $form['id']['#default_value'] = $this->entity->id(); + } + + // Adjust form title. + if ($this->entity->isNew()) { + $form['#title'] = $this->t('Add quick form: @label', ['@label' => $this->entity->getPlugin()->getLabel()]); + if ($this->getRequest()->get('override')) { + $form['#title'] = $this->t('Override quick form: @label', ['@label' => $this->entity->getPlugin()->getLabel()]); + } + } + else { + $form['#title'] = $this->t('Edit quick form: @label', ['@label' => $this->entity->label()]); + } + + $form['description'] = [ + '#type' => 'textfield', + '#title' => $this->t('Description'), + '#description' => $this->t('A brief description of this quick form.'), + '#default_value' => $this->entity->getDescription(), + '#group' => $tab_group, + ]; + + $form['status'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Enabled'), + '#description' => $this->t('Enable the quick form.'), + '#default_value' => $this->entity->status(), + '#group' => $tab_group, + ]; + + $form['helpText'] = [ + '#type' => 'textarea', + '#title' => $this->t('Help Text'), + '#description' => $this->t('Help text to display for the quick form.'), + '#default_value' => $this->entity->getHelpText(), + '#group' => $tab_group, + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + parent::validateForm($form, $form_state); + + // Validate plugin form. + if ($this->entity->getPlugin()->isConfigurable()) { + $this->entity->getPlugin()->validateConfigurationForm($form['settings'], SubformState::createForSubform($form['settings'], $form, $form_state)); + } + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + parent::submitForm($form, $form_state); + + // Submit plugin form. + if ($this->entity->getPlugin()->isConfigurable()) { + $this->entity->getPlugin()->submitConfigurationForm($form['settings'], SubformState::createForSubform($form['settings'], $form, $form_state)); + } + } + + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state) { + $status = parent::save($form, $form_state); + $entity_type_label = $this->entity->getEntityType()->getSingularLabel(); + $this->messenger()->addMessage($this->t('Saved @entity_type_label: %label', ['@entity_type_label' => $entity_type_label, '%label' => $this->entity->label()])); + $form_state->setRedirect('entity.quick_form.collection'); + return $status; + } + + /** + * {@inheritdoc} + */ + public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id) { + + // Get existing quick form entity from route parameter. + if ($route_match->getRawParameter($entity_type_id) !== NULL) { + $entity = $route_match->getParameter($entity_type_id); + } + // Else create a new quick form entity, the plugin must be specified. + else { + if (($plugin = $route_match->getRawParameter('plugin')) && $this->quickFormPluginManager->hasDefinition($plugin)) { + $entity = QuickFormInstance::create(['plugin' => $plugin]); + if ($this->getRequest()->get('override')) { + $entity->set('id', $plugin); + } + } + } + + if (empty($entity)) { + throw new NotFoundHttpException(); + } + + return $entity; + } + +} diff --git a/modules/core/quick/src/Plugin/Derivative/QuickFormMenuLink.php b/modules/core/quick/src/Plugin/Derivative/QuickFormMenuLink.php index 7bfae6c65..c8bec5d9c 100644 --- a/modules/core/quick/src/Plugin/Derivative/QuickFormMenuLink.php +++ b/modules/core/quick/src/Plugin/Derivative/QuickFormMenuLink.php @@ -3,6 +3,7 @@ namespace Drupal\farm_quick\Plugin\Derivative; use Drupal\Component\Plugin\Derivative\DeriverBase; +use Drupal\Component\Utility\Html; use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface; use Drupal\farm_quick\QuickFormInstanceManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -59,9 +60,16 @@ class QuickFormMenuLink extends DeriverBase implements ContainerDeriverInterface // Add a link for each quick form. foreach ($quick_forms as $id => $quick_form) { + + // Skip disabled quick forms. + if (!$quick_form->status()) { + continue; + } + + // Create link. $route_id = 'farm.quick.' . $id; $links[$route_id] = [ - 'title' => $quick_form->getLabel(), + 'title' => Html::escape($quick_form->getLabel()), 'parent' => 'farm.quick:farm.quick', 'route_name' => $route_id, ] + $base_plugin_definition; diff --git a/modules/core/quick/src/Plugin/Derivative/QuickFormTaskLink.php b/modules/core/quick/src/Plugin/Derivative/QuickFormTaskLink.php index 2665f8b09..fd4af7848 100644 --- a/modules/core/quick/src/Plugin/Derivative/QuickFormTaskLink.php +++ b/modules/core/quick/src/Plugin/Derivative/QuickFormTaskLink.php @@ -59,19 +59,6 @@ class QuickFormTaskLink extends DeriverBase implements ContainerDeriverInterface 'base_route' => $route_name, 'weight' => 0, ] + $base_plugin_definition; - - // If the quick form is configurable, add a link to the config form. - if ($quick_form->getPlugin()->isConfigurable()) { - $links["farm.quick.$id.configure"] = [ - 'title' => $this->t('Configure'), - 'route_name' => 'farm_quick.configure', - 'route_parameters' => [ - 'quick_form' => $id, - ], - 'base_route' => $route_name, - 'weight' => 100, - ] + $base_plugin_definition; - } } return $links; diff --git a/modules/core/quick/src/QuickFormInstanceManager.php b/modules/core/quick/src/QuickFormInstanceManager.php index da41a41dc..567111932 100644 --- a/modules/core/quick/src/QuickFormInstanceManager.php +++ b/modules/core/quick/src/QuickFormInstanceManager.php @@ -60,7 +60,7 @@ class QuickFormInstanceManager implements QuickFormInstanceManagerInterface { // Load quick form instance configuration entities for this plugin. // Exclude disabled quick forms. /** @var \Drupal\farm_quick\Entity\QuickFormInstanceInterface[] $entities */ - $entities = $this->entityTypeManager->getStorage('quick_form')->loadByProperties(['plugin' => $plugin['id'], 'status' => TRUE]); + $entities = $this->entityTypeManager->getStorage('quick_form')->loadByProperties(['plugin' => $plugin['id']]); foreach ($entities as $entity) { $entity->getPlugin()->setQuickId($entity->id()); $instances[$entity->id()] = $entity; diff --git a/modules/core/quick/src/QuickFormListBuilder.php b/modules/core/quick/src/QuickFormListBuilder.php new file mode 100644 index 000000000..62c9222af --- /dev/null +++ b/modules/core/quick/src/QuickFormListBuilder.php @@ -0,0 +1,157 @@ +quickFormInstanceManager = $quick_form_instance_manager; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { + return new static( + $entity_type, + $container->get('entity_type.manager')->getStorage($entity_type->id()), + $container->get('quick_form.instance_manager'), + ); + } + + /** + * {@inheritdoc} + */ + public function load() { + return $this->quickFormInstanceManager->getInstances(); + } + + /** + * {@inheritdoc} + */ + public function render() { + + $render['table'] = [ + '#type' => 'table', + '#header' => $this->buildHeader(), + '#caption' => $this->t('Configured quick forms'), + '#rows' => [], + '#empty' => $this->t('There are no configured @label.', ['@label' => $this->entityType->getPluralLabel()]), + '#cache' => [ + 'contexts' => $this->entityType->getListCacheContexts(), + 'tags' => $this->entityType->getListCacheTags(), + ], + ]; + + $render['default'] = [ + '#type' => 'table', + '#header' => $this->buildHeader(), + '#caption' => $this->t('Default quick forms'), + '#rows' => [], + '#empty' => $this->t('There are no default @label.', ['@label' => $this->entityType->getPluralLabel()]), + ]; + + // Load all quick form instances into proper table. + $quick_form_instances = $this->load(); + foreach ($quick_form_instances as $entity) { + $target = $entity->isNew() ? 'default' : 'table'; + if ($row = $this->buildRow($entity)) { + $render[$target][$entity->id()] = $row; + } + } + + return $render; + } + + /** + * {@inheritdoc} + */ + public function buildHeader() { + $header['enabled'] = $this->t('Enabled'); + $header['type'] = $this->t('Plugin'); + $header['label'] = $this->t('Label'); + $header['id'] = $this->t('ID'); + $header['description'] = $this->t('Description'); + return $header + parent::buildHeader(); + } + + /** + * {@inheritdoc} + */ + public function buildRow(EntityInterface $entity) { + /** @var \Drupal\farm_quick\Entity\QuickFormInstanceInterface $quick_form */ + $quick_form = $entity; + $row['enabled'] = [ + '#type' => 'checkbox', + '#checked' => $quick_form->status(), + '#attributes' => [ + 'disabled' => 'disabled', + ], + ]; + $row['type'] = [ + '#plain_text' => $quick_form->getPlugin()->getLabel(), + ]; + $row['label'] = [ + '#plain_text' => $quick_form->getLabel(), + ]; + $row['id'] = [ + '#plain_text' => $quick_form->id(), + ]; + $row['description'] = [ + '#plain_text' => $quick_form->getDescription(), + ]; + return $row + parent::buildRow($entity); + } + + /** + * {@inheritdoc} + */ + public function getDefaultOperations(EntityInterface $entity) { + $operations = parent::getDefaultOperations($entity); + + // Override operations for default quick form instances. + if ($entity->isNew()) { + + // Remove edit operation. + unset($operations['edit']); + + // Add override operation. + $operations['override'] = [ + 'title' => $this->t('Override'), + 'weight' => 0, + 'url' => $this->ensureDestination(Url::fromRoute('farm_quick.add_form', ['plugin' => $entity->getPluginId()], ['query' => ['override' => TRUE]])), + ]; + } + + return $operations; + } + +} diff --git a/modules/core/quick/src/Routing/QuickFormRoutes.php b/modules/core/quick/src/Routing/QuickFormRoutes.php index aba2759e5..3c3277aa2 100644 --- a/modules/core/quick/src/Routing/QuickFormRoutes.php +++ b/modules/core/quick/src/Routing/QuickFormRoutes.php @@ -52,6 +52,11 @@ class QuickFormRoutes implements ContainerInjectionInterface { $quick_forms = $this->quickFormInstanceManager->getInstances(); foreach ($quick_forms as $id => $quick_form) { + // Skip quick forms that are disabled. + if (!$quick_form->status()) { + continue; + } + // Build a route for the quick form. $route = new Route( "/quick/$id", diff --git a/modules/core/quick/tests/src/Functional/QuickFormTest.php b/modules/core/quick/tests/src/Functional/QuickFormTest.php index 3077308d5..c3cbf6f41 100644 --- a/modules/core/quick/tests/src/Functional/QuickFormTest.php +++ b/modules/core/quick/tests/src/Functional/QuickFormTest.php @@ -91,21 +91,10 @@ class QuickFormTest extends FarmBrowserTestBase { $this->assertSession()->statusCodeEquals(200); $this->assertSession()->responseContains('value="100"'); - // Go to the test configuration form and confirm that access is denied. - $this->drupalGet('quick/configurable_test/configure'); - $this->assertSession()->statusCodeEquals(403); - - // Create and login a test user with permission to create test logs and - // permission to update quick forms. - $user = $this->createUser(['view quick_form', 'create test log', 'update quick_form']); - $this->drupalLogin($user); - - // Go to the default configurable_test quick form and confirm that the - // default value field is visible and the default value is 100. - $this->drupalGet('quick/configurable_test/configure'); - $this->assertSession()->statusCodeEquals(200); - $this->assertSession()->pageTextContains($this->t('Default value')); - $this->assertSession()->responseContains('value="100"'); + // Attempt to load the edit form for the unsaved configurable_test quick + // form and confirm 404 not found. + $this->drupalGet('setup/quick/foo/configurable_test'); + $this->assertSession()->statusCodeEquals(404); // Go to the configurable_test2 quick form and confirm access is granted and // the default value is 500. @@ -113,9 +102,19 @@ class QuickFormTest extends FarmBrowserTestBase { $this->assertSession()->statusCodeEquals(200); $this->assertSession()->responseContains('value="500"'); + // Attempt to load the edit form for saved configurable_test2 quick + // form and confirm 403. + $this->drupalGet('setup/quick/configurable_test2/edit'); + $this->assertSession()->statusCodeEquals(403); + + // Create and login a test user with permission to create test logs and + // permission to update quick forms. + $user = $this->createUser(['view quick_form', 'create test log', 'update quick_form']); + $this->drupalLogin($user); + // Go to the configurable_test2 quick form and confirm that the default // value field is visible and the default value is 500. - $this->drupalGet('quick/configurable_test2/configure'); + $this->drupalGet('setup/quick/configurable_test2/edit'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains($this->t('Default value')); $this->assertSession()->responseContains('value="500"'); @@ -127,12 +126,12 @@ class QuickFormTest extends FarmBrowserTestBase { $config_entity->save(); $this->drupalGet('quick/configurable_test2'); $this->assertSession()->responseContains('value="600"'); - $this->drupalGet('quick/configurable_test2/configure'); + $this->drupalGet('setup/quick/configurable_test2/edit'); $this->assertSession()->responseContains('value="600"'); - // Attempt to load a configuration form for a non-existent quick form and + // Attempt to load an edit form for a non-existent quick form and // confirm 404 not found. - $this->drupalGet('quick/foo/configure'); + $this->drupalGet('setup/quick/foo/edit'); $this->assertSession()->statusCodeEquals(404); // Go to the requires_entity_test quick form and confirm 404 not found. diff --git a/modules/core/quick/tests/src/Kernel/QuickFormTest.php b/modules/core/quick/tests/src/Kernel/QuickFormTest.php index 8548166e4..0b777c6f9 100644 --- a/modules/core/quick/tests/src/Kernel/QuickFormTest.php +++ b/modules/core/quick/tests/src/Kernel/QuickFormTest.php @@ -3,7 +3,7 @@ namespace Drupal\Tests\farm_quick\Kernel; use Drupal\Core\Form\FormState; -use Drupal\farm_quick\Form\ConfigureQuickForm; +use Drupal\farm_quick\Form\QuickFormEntityForm; use Drupal\KernelTests\KernelTestBase; /** @@ -152,11 +152,15 @@ class QuickFormTest extends KernelTestBase { // Confirm that the config entity for this quick form has not been saved. $this->assertTrue($quick_form->isNew()); - // Programmatically submit the configurable_test config form. - $form = ConfigureQuickForm::create(\Drupal::getContainer()); + // Programmatically submit the quick form entity form. + $form = QuickFormEntityForm::create(\Drupal::getContainer()); $form->setModuleHandler(\Drupal::moduleHandler()); $form->setEntity($quick_form); $form_state = (new FormState())->setValues([ + // Set the ID and label because no default value is provided for these + // in the form unless the override query param is set. + 'id' => $quick_form->id(), + 'label' => (string) $quick_form->label(), 'settings' => [ 'test_default' => '101', ],