diff --git a/core/modules/forum/forum.admin.inc b/core/modules/forum/forum.admin.inc index 2a8a50d..b3accfb 100644 --- a/core/modules/forum/forum.admin.inc +++ b/core/modules/forum/forum.admin.inc @@ -8,209 +8,6 @@ use Drupal\taxonomy\Plugin\Core\Entity\Term; /** - * Page callback: Returns a form for creating a new forum or container. - * - * @param $type - * What is being added. Possible values are 'forum' and 'container'. - * @param \Drupal\taxonomy\Plugin\Core\Entity\Term $term - * (optional) A forum or container term to be edited. Defaults to NULL. - * - * @return - * A form for creating a new forum or container. - * - * @see forum_menu() - */ -function forum_form_main($type, Term $term = NULL) { - if (!$term) { - $term = entity_create('taxonomy_term', array('vid' => config('forum.settings')->get('vocabulary'))); - } - - switch ($type) { - case 'forum': - return drupal_get_form('forum_form_forum', $term); - break; - case 'container': - return drupal_get_form('forum_form_container', $term); - break; - } -} - -/** - * Form constructor for adding and editing a forum. - * - * @param \Drupal\taxonomy\Plugin\Core\Entity\Term $term - * A forum term to be edited. - * - * @see forum_form_submit() - * @ingroup forms - */ -function forum_form_forum($form, &$form_state, Term $term) { - $form['name'] = array('#type' => 'textfield', - '#title' => t('Forum name'), - '#default_value' => $term->name->value, - '#maxlength' => 255, - '#description' => t('Short but meaningful name for this collection of threaded discussions.'), - '#required' => TRUE, - ); - $form['description'] = array('#type' => 'textarea', - '#title' => t('Description'), - '#default_value' => $term->description->value, - '#description' => t('Description and guidelines for discussions within this forum.'), - ); - $form['parent']['#tree'] = TRUE; - $form['parent'][0] = _forum_parent_select($term->id(), t('Parent'), 'forum'); - $form['weight'] = array('#type' => 'weight', - '#title' => t('Weight'), - '#default_value' => $term->weight->value, - '#description' => t('Forums are displayed in ascending order by weight (forums with equal weights are displayed alphabetically).'), - ); - - $form['vid'] = array('#type' => 'hidden', '#value' => config('forum.settings')->get('vocabulary')); - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Save'), - '#button_type' => 'primary', - '#submit' => array('forum_form_submit') - ); - if (!$term->isNew()) { - $form['actions']['delete'] = array( - '#type' => 'submit', - '#value' => t('Delete'), - '#submit' => array('forum_forum_delete'), - ); - $form['tid'] = array('#type' => 'value', '#value' => $term->id()); - } - $form['#theme'] = 'forum_form'; - - return $form; -} - -/** - * Form submission handler for forum_form_forum() and forum_form_container(). - */ -function forum_form_submit($form, &$form_state) { - $config = config('forum.settings'); - if ($form['form_id']['#value'] == 'forum_form_container') { - $container = TRUE; - $type = t('forum container'); - } - else { - $container = FALSE; - $type = t('forum'); - } - - // @todo Set explicit entity properties instead of arbitrary form values. - form_state_values_clean($form_state); - $term = entity_create('taxonomy_term', $form_state['values']); - $status = $term->save(); - switch ($status) { - case SAVED_NEW: - if ($container) { - $containers = $config->get('containers'); - $containers[] = $term->id(); - $config->set('containers', $containers)->save(); - } - $form_state['values']['tid'] = $term->id(); - drupal_set_message(t('Created new @type %term.', array('%term' => $form_state['values']['name'], '@type' => $type))); - break; - case SAVED_UPDATED: - drupal_set_message(t('The @type %term has been updated.', array('%term' => $form_state['values']['name'], '@type' => $type))); - // Clear the page and block caches to avoid stale data. - cache_invalidate_tags(array('content' => TRUE)); - break; - } - $form_state['redirect'] = 'admin/structure/forum'; -} - -/** - * Returns HTML for a forum form. - * - * By default this does not alter the appearance of a form at all, but is - * provided as a convenience for themers. - * - * @param $variables - * An associative array containing: - * - form: A render element representing the form. - * - * @ingroup themeable - */ -function theme_forum_form($variables) { - return drupal_render_children($variables['form']); -} - -/** - * Form constructor for adding and editing forum containers. - * - * @param \Drupal\taxonomy\Plugin\Core\Entity\Term $term - * A container term to be edited. - * - * @see forum_form_submit() - * @ingroup forms - */ -function forum_form_container($form, &$form_state, Term $term) { - $config = config('forum.settings'); - // Handle a delete operation. - $form['name'] = array( - '#title' => t('Container name'), - '#type' => 'textfield', - '#default_value' => $term->name->value, - '#maxlength' => 255, - '#description' => t('Short but meaningful name for this collection of related forums.'), - '#required' => TRUE - ); - - $form['description'] = array( - '#type' => 'textarea', - '#title' => t('Description'), - '#default_value' => $term->description->value, - '#description' => t('Description and guidelines for forums within this container.') - ); - $form['parent']['#tree'] = TRUE; - $form['parent'][0] = _forum_parent_select($term->id(), t('Parent'), 'container'); - $form['weight'] = array( - '#type' => 'weight', - '#title' => t('Weight'), - '#default_value' => $term->weight->value, - '#description' => t('Containers are displayed in ascending order by weight (containers with equal weights are displayed alphabetically).') - ); - - $form['vid'] = array( - '#type' => 'hidden', - '#value' => $config->get('vocabulary'), - ); - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Save'), - '#button_type' => 'primary', - '#submit' => array('forum_form_submit'), - ); - if (!$term->isNew()) { - $form['actions']['delete'] = array( - '#type' => 'submit', - '#value' => t('Delete'), - '#submit' => array('forum_forum_delete'), - ); - $form['tid'] = array('#type' => 'value', '#value' => $term->id()); - } - $form['#theme'] = 'forum_form'; - - return $form; -} - -/** - * Form submission handler for forum_form_forum() and forum_form_container(). - * - * Handler for when 'delete' is clicked. - * - * @see \Drupal\forum\Form\DeleteForm - */ -function forum_forum_delete($form, &$form_state) { - $form_state['redirect'] = 'admin/structure/forum/delete/forum/' . $form_state['values']['tid']; -} - -/** * Form constructor for the forum overview form. * * Returns a form for controlling the hierarchy of existing forums and @@ -257,55 +54,3 @@ function forum_overview($form, &$form_state) { $form['terms']['#empty'] = t('No containers or forums available. Add container or Add forum.', array('@container' => url('admin/structure/forum/add/container'), '@forum' => url('admin/structure/forum/add/forum'))); return $form; } - -/** - * Returns a select box for available parent terms. - * - * @param $tid - * ID of the term that is being added or edited. - * @param $title - * Title for the select box. - * @param $child_type - * Whether the child is a forum or a container. - * - * @return - * A select form element. - */ -function _forum_parent_select($tid, $title, $child_type) { - - $parents = taxonomy_term_load_parents($tid); - if ($parents) { - $parent = array_shift($parents); - $parent = $parent->id(); - } - else { - $parent = 0; - } - - $vid = config('forum.settings')->get('vocabulary'); - $children = taxonomy_get_tree($vid, $tid, NULL, TRUE); - - // A term can't be the child of itself, nor of its children. - foreach ($children as $child) { - $exclude[] = $child->id(); - } - $exclude[] = $tid; - - $tree = taxonomy_get_tree($vid, 0, NULL, TRUE); - $options[0] = '<' . t('root') . '>'; - if ($tree) { - foreach ($tree as $term) { - if (!in_array($term->id(), $exclude)) { - $options[$term->id()] = str_repeat(' -- ', $term->depth) . $term->label(); - } - } - } - if ($child_type == 'container') { - $description = t('Containers are usually placed at the top (root) level, but may also be placed inside another container or forum.'); - } - elseif ($child_type == 'forum') { - $description = t('Forums may be placed at the top (root) level, or inside another container or forum.'); - } - - return array('#type' => 'select', '#title' => $title, '#default_value' => $parent, '#options' => $options, '#description' => $description, '#required' => TRUE); -} diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module index c06edde..aa93ba6 100644 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@ -120,21 +120,13 @@ function forum_menu() { ); $items['admin/structure/forum/add/container'] = array( 'title' => 'Add container', - 'page callback' => 'forum_form_main', - 'page arguments' => array('container'), - 'access arguments' => array('administer forums'), - 'type' => MENU_LOCAL_ACTION, - 'parent' => 'admin/structure/forum', - 'file' => 'forum.admin.inc', + 'tab_parent' => 'admin/structure/forum', + 'route_name' => 'forum_add_container', ); $items['admin/structure/forum/add/forum'] = array( + 'tab_parent' => 'admin/structure/forum', 'title' => 'Add forum', - 'page callback' => 'forum_form_main', - 'page arguments' => array('forum'), - 'access arguments' => array('administer forums'), - 'type' => MENU_LOCAL_ACTION, - 'parent' => 'admin/structure/forum', - 'file' => 'forum.admin.inc', + 'route_name' => 'forum_add_forum', ); $items['admin/structure/forum/settings'] = array( 'title' => 'Settings', @@ -145,17 +137,11 @@ function forum_menu() { ); $items['admin/structure/forum/edit/container/%taxonomy_term'] = array( 'title' => 'Edit container', - 'page callback' => 'forum_form_main', - 'page arguments' => array('container', 5), - 'access arguments' => array('administer forums'), - 'file' => 'forum.admin.inc', + 'route_name' => 'forum_edit_container', ); $items['admin/structure/forum/edit/forum/%taxonomy_term'] = array( 'title' => 'Edit forum', - 'page callback' => 'forum_form_main', - 'page arguments' => array('forum', 5), - 'access arguments' => array('administer forums'), - 'file' => 'forum.admin.inc', + 'route_name' => 'forum_edit_forum', ); return $items; } @@ -226,6 +212,15 @@ function forum_menu_local_tasks_alter(&$data, $router_item, $root_path) { } /** + * Implements hook_entity_info_alter(). + */ +function forum_entity_info_alter(&$info) { + // Register forum specific form controllers. + $info['taxonomy_term']['controllers']['form']['forum'] = 'Drupal\forum\ForumFormController'; + $info['taxonomy_term']['controllers']['form']['container'] = 'Drupal\forum\ContainerFormController'; +} + +/** * Implements hook_entity_bundle_info_alter(). */ function forum_entity_bundle_info_alter(&$bundles) { @@ -238,7 +233,7 @@ function forum_entity_bundle_info_alter(&$bundles) { } /** - * Entity URI callback used in forum_entity_info_alter(). + * Entity URI callback used in forum_entity_bundle_info_alter(). */ function forum_uri($forum) { return array( @@ -1338,3 +1333,19 @@ function forum_rdf_mapping() { ), ); } + +/** + * Returns HTML for a forum form. + * + * By default this does not alter the appearance of a form at all, but is + * provided as a convenience for themers. + * + * @param $variables + * An associative array containing: + * - form: A render element representing the form. + * + * @ingroup themeable + */ +function theme_forum_form($variables) { + return drupal_render_children($variables['form']); +} diff --git a/core/modules/forum/forum.routing.yml b/core/modules/forum/forum.routing.yml index f7d90f8..a5573d0 100644 --- a/core/modules/forum/forum.routing.yml +++ b/core/modules/forum/forum.routing.yml @@ -10,3 +10,27 @@ forum_settings: _form: '\Drupal\forum\ForumSettingsForm' requirements: _permission: 'administer forums' +forum_add_container: + pattern: 'admin/structure/forum/add/container' + defaults: + _content: 'Drupal\forum\ForumController::addContainer' + requirements: + _permission: 'administer forums' +forum_add_forum: + pattern: 'admin/structure/forum/add/forum' + defaults: + _content: 'Drupal\forum\ForumController::addForum' + requirements: + _permission: 'administer forums' +forum_edit_container: + pattern: 'admin/structure/forum/edit/container/{taxonomy_term}' + defaults: + _entity_form: 'taxonomy_term.container' + requirements: + _permission: 'administer forums' +forum_edit_forum: + pattern: 'admin/structure/forum/edit/forum/{taxonomy_term}' + defaults: + _entity_form: 'taxonomy_term.forum' + requirements: + _permission: 'administer forums' diff --git a/core/modules/forum/lib/Drupal/forum/ContainerFormController.php b/core/modules/forum/lib/Drupal/forum/ContainerFormController.php new file mode 100644 index 0000000..24dbd1d --- /dev/null +++ b/core/modules/forum/lib/Drupal/forum/ContainerFormController.php @@ -0,0 +1,54 @@ +entity; + // Build the bulk of the form from the parent forum form. + $form = parent::form($form, $form_state, $taxonomy_term); + + // Set the title and description of the name field. + $form['name']['#title'] = t('Container name'); + $form['name']['#description'] = t('Short but meaningful name for this collection of related forums.'); + + // Alternate description for the container parent. + $form['parent'][0]['#description'] = t('Containers are usually placed at the top (root) level, but may also be placed inside another container or forum.'); + $this->forumFormType = t('forum container'); + return $form; + } + + /** + * {@inheritdoc} + */ + public function save(array $form, array &$form_state) { + $is_new = $this->entity->isNew(); + $term = parent::save($form, $form_state); + if ($is_new) { + // Update config item to track the container terms. + $containers = $this->config->get('containers'); + $containers[] = $term->id(); + $this->config->set('containers', $containers)->save(); + } + } + +} diff --git a/core/modules/forum/lib/Drupal/forum/ForumController.php b/core/modules/forum/lib/Drupal/forum/ForumController.php new file mode 100644 index 0000000..670cca9 --- /dev/null +++ b/core/modules/forum/lib/Drupal/forum/ForumController.php @@ -0,0 +1,86 @@ +get('plugin.manager.entity'), $container->get('config.factory')); + } + + /** + * Constructs a ForumController object. + * + * @param \Drupal\Core\Entity\EntityManager $entity_manager + * The entity manager service. + * @param \Drupal\Core\Config\ConfigFactory $config_factory + * The factory for configuration objects. + */ + public function __construct(EntityManager $entity_manager, ConfigFactory $config_factory) { + $this->entityManager = $entity_manager; + $this->config = $config_factory->get('forum.settings'); + } + + /** + * Returns add forum entity form. + * + * @return array + * Render array for the add form. + */ + public function addForum() { + $vid = $this->config->get('vocabulary'); + $taxonomy_term = $this->entityManager->getStorageController('taxonomy_term')->create(array( + 'vid' => $vid, + )); + // @todo use $this->entityManager->getform() when + // http://drupal.org/node/1982980 is in. + return entity_get_form($taxonomy_term, 'forum'); + } + + /** + * Returns add container entity form. + * + * @return array + * Render array for the add form. + */ + public function addContainer() { + $vid = $this->config->get('vocabulary'); + $taxonomy_term = $this->entityManager->getStorageController('taxonomy_term')->create(array( + 'vid' => $vid, + )); + // @todo use $this->entityManager->getform() when + // http://drupal.org/node/1982980 is in. + return entity_get_form($taxonomy_term, 'container'); + } + +} diff --git a/core/modules/forum/lib/Drupal/forum/ForumFormController.php b/core/modules/forum/lib/Drupal/forum/ForumFormController.php new file mode 100644 index 0000000..9480f8a --- /dev/null +++ b/core/modules/forum/lib/Drupal/forum/ForumFormController.php @@ -0,0 +1,227 @@ +config = $config_factory->get('forum.settings'); + $this->request = $request; + $this->storageController = $storage_controller; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info, $operation = NULL) { + return new static( + $operation, + $container->get('config.factory'), + $container->get('request'), + $container->get('plugin.manager.entity')->getStorageController('taxonomy_term') + ); + } + + /** + * {@inheritdoc} + */ + public function form(array $form, array &$form_state) { + $taxonomy_term = $this->entity; + // Build the bulk of the form from the parent taxonomy term form. + $form = parent::form($form, $form_state, $taxonomy_term); + + // Set the title and description of the name field. + $form['name']['#title'] = t('Forum name'); + $form['name']['#description'] = t('Short but meaningful name for this collection of threaded discussions.'); + + // Change the description. + $form['description']['#description'] = t('Description and guidelines for discussions within this forum.'); + + // Re-use the weight field. + $form['weight'] = $form['relations']['weight']; + + // Remove the remaining relations fields. + unset($form['relations']); + + // Our parent field is different to the taxonomy term. + $form['parent']['#tree'] = TRUE; + $form['parent'][0] = $this->forumParentSelect($taxonomy_term->id(), t('Parent')); + + $form['#theme'] = 'forum_form'; + $this->forumFormType = t('forum'); + return $form; + } + + /** + * {@inheritdoc} + */ + public function buildEntity(array $form, array &$form_state) { + $term = parent::buildEntity($form, $form_state); + + // Assign parents from forum parent select field. + $term->parent = array($form_state['values']['parent'][0]); + + return $term; + } + + /** + * {@inheritdoc} + */ + public function save(array $form, array &$form_state) { + $term = $this->entity; + + $status = $this->storageController->save($term); + switch ($status) { + case SAVED_NEW: + drupal_set_message(t('Created new @type %term.', array('%term' => $term->label(), '@type' => $this->forumFormType))); + watchdog('forum', 'Created new @type %term.', array('%term' => $term->label(), '@type' => $this->forumFormType), WATCHDOG_NOTICE, l(t('edit'), 'admin/structure/forum/edit/' . $this->urlStub . '/' . $term->id())); + $form_state['values']['tid'] = $term->id(); + break; + + case SAVED_UPDATED: + drupal_set_message(t('The @type %term has been updated.', array('%term' => $term->label(), '@type' => $this->forumFormType))); + watchdog('taxonomy', 'Updated @type %term.', array('%term' => $term->label(), '@type' => $this->forumFormType), WATCHDOG_NOTICE, l(t('edit'), 'admin/structure/forum/edit/' . $this->urlStub . '/' . $term->id())); + // Clear the page and block caches to avoid stale data. + Cache::invalidateTags(array('content' => TRUE)); + break; + } + + $form_state['redirect'] = 'admin/structure/forum'; + return $term; + } + + /** + * {@inheritdoc} + */ + public function delete(array $form, array &$form_state) { + $destination = array(); + if ($this->request->query->get('destination')) { + $destination = drupal_get_destination(); + $this->request->query->remove('destination'); + } + $term = $this->getEntity($form_state); + $form_state['redirect'] = array( + 'admin/structure/forum/delete/forum/' . $term->id(), + array('query' => $destination) + ); + } + + /** + * Returns a select box for available parent terms. + * + * @param int $tid + * ID of the term that is being added or edited. + * @param string $title + * Title for the select box. + * + * @return array + * A select form element. + */ + protected function forumParentSelect($tid, $title) { + // @todo Inject a taxonomy service when one exists. + $parents = taxonomy_term_load_parents($tid); + if ($parents) { + $parent = array_shift($parents); + $parent = $parent->id(); + } + else { + $parent = 0; + } + + $vid = $this->config->get('vocabulary'); + // @todo Inject a taxonomy service when one exists. + $children = taxonomy_get_tree($vid, $tid, NULL, TRUE); + + // A term can't be the child of itself, nor of its children. + foreach ($children as $child) { + $exclude[] = $child->tid; + } + $exclude[] = $tid; + + // @todo Inject a taxonomy service when one exists. + $tree = taxonomy_get_tree($vid, 0, NULL, TRUE); + $options[0] = '<' . t('root') . '>'; + if ($tree) { + foreach ($tree as $term) { + if (!in_array($term->id(), $exclude)) { + $options[$term->id()] = str_repeat(' -- ', $term->depth) . $term->label(); + } + } + } + + $description = t('Forums may be placed at the top (root) level, or inside another container or forum.'); + + return array( + '#type' => 'select', + '#title' => $title, + '#default_value' => $parent, + '#options' => $options, + '#description' => $description, + '#required' => TRUE + ); + } +} diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php index c28b1dc..7acb9d2 100644 --- a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php +++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php @@ -388,7 +388,7 @@ function createForum($type, $parent = 0) { $edit = array( 'name' => $name, - 'description' => $description, + 'description[value]' => $description, 'parent[0]' => $parent, 'weight' => '0', );