diff --git a/core/modules/aggregator/aggregator.admin.inc b/core/modules/aggregator/aggregator.admin.inc deleted file mode 100644 index 0800960..0000000 --- a/core/modules/aggregator/aggregator.admin.inc +++ /dev/null @@ -1,114 +0,0 @@ - 'textfield', - '#title' => t('Title'), - '#default_value' => isset($edit->title) ? $edit->title : '', - '#maxlength' => 64, - '#required' => TRUE, - ); - $form['description'] = array('#type' => 'textarea', - '#title' => t('Description'), - '#default_value' => isset($edit->description) ? $edit->description : '', - ); - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save')); - if (!empty($edit->cid)) { - $form['actions']['delete'] = array('#type' => 'submit', '#value' => t('Delete')); - $form['cid'] = array('#type' => 'hidden', '#value' => $edit->cid); - } - - return $form; -} - -/** - * Form validation handler for aggregator_form_category(). - * - * @see aggregator_form_category_submit() - */ -function aggregator_form_category_validate($form, &$form_state) { - if ($form_state['values']['op'] == t('Save')) { - // Check for duplicate titles - if (isset($form_state['values']['cid'])) { - $category = db_query("SELECT cid FROM {aggregator_category} WHERE title = :title AND cid <> :cid", array(':title' => $form_state['values']['title'], ':cid' => $form_state['values']['cid']))->fetchObject(); - } - else { - $category = db_query("SELECT cid FROM {aggregator_category} WHERE title = :title", array(':title' => $form_state['values']['title']))->fetchObject(); - } - if ($category) { - form_set_error('title', t('A category named %category already exists. Enter a unique title.', array('%category' => $form_state['values']['title']))); - } - } -} - -/** - * Form submission handler for aggregator_form_category(). - * - * @see aggregator_form_category_validate() - * - * @todo Add delete confirmation dialog. - */ -function aggregator_form_category_submit($form, &$form_state) { - // @todo Replicate this cache invalidation when these ops are separated. - // Invalidate the block cache to update aggregator category-based derivatives. - if (Drupal::moduleHandler()->moduleExists('block')) { - Drupal::service('plugin.manager.block')->clearCachedDefinitions(); - } - if ($form_state['values']['op'] == t('Delete')) { - $title = $form_state['values']['title']; - // Unset the title. - unset($form_state['values']['title']); - } - aggregator_save_category($form_state['values']); - if (isset($form_state['values']['cid'])) { - if (isset($form_state['values']['title'])) { - drupal_set_message(t('The category %category has been updated.', array('%category' => $form_state['values']['title']))); - if (arg(0) == 'admin') { - $form_state['redirect'] = 'admin/config/services/aggregator/'; - return; - } - else { - $form_state['redirect'] = 'aggregator/categories/' . $form_state['values']['cid']; - return; - } - } - else { - watchdog('aggregator', 'Category %category deleted.', array('%category' => $title)); - drupal_set_message(t('The category %category has been deleted.', array('%category' => $title))); - if (arg(0) == 'admin') { - $form_state['redirect'] = 'admin/config/services/aggregator/'; - return; - } - else { - $form_state['redirect'] = 'aggregator/categories/'; - return; - } - } - } - else { - watchdog('aggregator', 'Category %category added.', array('%category' => $form_state['values']['title']), WATCHDOG_NOTICE, l(t('view'), 'admin/config/services/aggregator')); - drupal_set_message(t('The category %category has been added.', array('%category' => $form_state['values']['title']))); - } -} diff --git a/core/modules/aggregator/aggregator.module b/core/modules/aggregator/aggregator.module index 416571d..bee7504 100644 --- a/core/modules/aggregator/aggregator.module +++ b/core/modules/aggregator/aggregator.module @@ -44,6 +44,8 @@ function aggregator_help($path, $arg) { return '

' . t('Categories allow feed items from different feeds to be grouped together. For example, several sport-related feeds may belong to a category named Sports. Feed items may be grouped automatically (by selecting a category when creating or editing a feed) or manually (via the Categorize page available from feed item listings). Each category provides its own feed page and block.') . '

'; case 'admin/config/services/aggregator/add/opml': return '

' . t('OPML is an XML format used to exchange multiple feeds between aggregators. A single OPML document may contain a collection of many feeds. Drupal can parse such a file and import all feeds at once, saving you the effort of adding them manually. You may either upload a local file from your computer or enter a URL where Drupal can download it.') . '

'; + case 'admin/config/services/aggregator/delete': + return; } } @@ -102,11 +104,8 @@ function aggregator_menu() { ); $items['admin/config/services/aggregator/add/category'] = array( 'title' => 'Add category', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_category'), - 'access arguments' => array('administer news feeds'), 'type' => MENU_LOCAL_ACTION, - 'file' => 'aggregator.admin.inc', + 'route_name' => 'aggregator_category_add', ); $items['admin/config/services/aggregator/add/opml'] = array( 'title' => 'Import OPML', @@ -174,12 +173,9 @@ function aggregator_menu() { ); $items['aggregator/categories/%aggregator_category/configure'] = array( 'title' => 'Configure', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_category', 2), - 'access arguments' => array('administer news feeds'), 'type' => MENU_LOCAL_TASK, 'weight' => 10, - 'file' => 'aggregator.admin.inc', + 'route_name' => 'aggregator_category_edit', ); $items['aggregator/sources/%aggregator_feed'] = array( 'title callback' => 'entity_page_label', @@ -208,14 +204,12 @@ function aggregator_menu() { 'access arguments' => array('administer news feeds'), 'type' => MENU_LOCAL_TASK, 'weight' => 10, - 'file' => 'aggregator.admin.inc', ); $items['admin/config/services/aggregator/edit/feed/%aggregator_feed'] = array( 'title' => 'Edit feed', 'page callback' => 'entity_get_form', 'page arguments' => array(6), 'access arguments' => array('administer news feeds'), - 'file' => 'aggregator.admin.inc', ); $items['admin/config/services/aggregator/delete/feed/%aggregator_feed'] = array( 'title' => 'Delete feed', @@ -223,10 +217,11 @@ function aggregator_menu() { ); $items['admin/config/services/aggregator/edit/category/%aggregator_category'] = array( 'title' => 'Edit category', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_category', 6), - 'access arguments' => array('administer news feeds'), - 'file' => 'aggregator.admin.inc', + 'route_name' => 'aggregator_category_admin_edit', + ); + $items['admin/config/services/aggregator/delete/category/%aggregator_category'] = array( + 'title' => 'Delete category', + 'route_name' => 'aggregator_category_delete', ); return $items; diff --git a/core/modules/aggregator/aggregator.routing.yml b/core/modules/aggregator/aggregator.routing.yml index 2c69045..cadbb14 100644 --- a/core/modules/aggregator/aggregator.routing.yml +++ b/core/modules/aggregator/aggregator.routing.yml @@ -67,3 +67,31 @@ aggregator_categories: _content: '\Drupal\aggregator\Controller\AggregatorController::categories' requirements: _access_aggregator_categories: 'TRUE' + +aggregator_category_edit: + pattern: 'aggregator/categories/{cid}/configure' + defaults: + _form: '\Drupal\aggregator\Form\CategoryAdminForm' + requirements: + _permission: 'administer news feeds' + +aggregator_category_admin_edit: + pattern: 'admin/config/services/aggregator/edit/category/{cid}' + defaults: + _form: '\Drupal\aggregator\Form\CategoryAdminForm' + requirements: + _permission: 'administer news feeds' + +aggregator_category_delete: + pattern: 'admin/config/services/aggregator/delete/category/{cid}' + defaults: + _form: '\Drupal\aggregator\Form\CategoryDeleteForm' + requirements: + _permission: 'administer news feeds' + +aggregator_category_add: + pattern: 'admin/config/services/aggregator/add/category' + defaults: + _form: '\Drupal\aggregator\Form\CategoryAdminForm' + requirements: + _permission: 'administer news feeds' diff --git a/core/modules/aggregator/aggregator.services.yml b/core/modules/aggregator/aggregator.services.yml index cf74241..2296922 100644 --- a/core/modules/aggregator/aggregator.services.yml +++ b/core/modules/aggregator/aggregator.services.yml @@ -13,3 +13,6 @@ services: arguments: ['@database'] tags: - { name: access_check } + aggregator.category.storage: + class: Drupal\aggregator\CategoryStorageController + arguments: ['@database', '@plugin.manager.entity', '@module_handler'] diff --git a/core/modules/aggregator/lib/Drupal/aggregator/CategoryStorageController.php b/core/modules/aggregator/lib/Drupal/aggregator/CategoryStorageController.php new file mode 100644 index 0000000..81e2af3 --- /dev/null +++ b/core/modules/aggregator/lib/Drupal/aggregator/CategoryStorageController.php @@ -0,0 +1,80 @@ +database = $database; + } + + /** + * {@inheritdoc} + */ + public function load($cid) { + return $this->database->query("SELECT cid, title, description, block FROM {aggregator_category} WHERE cid = :cid", array(':cid' => $cid))->fetchAssoc(); + } + + /** + * {@inheritdoc} + */ + public function save(array $category) { + $cid = $this->database->insert('aggregator_category') + ->fields(array( + 'title' => $category['title'], + 'description' => $category['description'], + 'block' => 5, + )) + ->execute(); + return $cid; + } + + /** + * {@inheritdoc} + */ + public function update(array $category) { + $this->database->merge('aggregator_category') + ->key(array('cid' => $category['cid'])) + ->fields(array( + 'title' => $category['title'], + 'description' => $category['description'], + )) + ->execute(); + } + + /** + * {@inheritdoc} + */ + public function delete($cid) { + $this->database->delete('aggregator_category') + ->condition('cid', $cid) + ->execute(); + } + + +} diff --git a/core/modules/aggregator/lib/Drupal/aggregator/CategoryStorageControllerInterface.php b/core/modules/aggregator/lib/Drupal/aggregator/CategoryStorageControllerInterface.php new file mode 100644 index 0000000..b47f9c4 --- /dev/null +++ b/core/modules/aggregator/lib/Drupal/aggregator/CategoryStorageControllerInterface.php @@ -0,0 +1,52 @@ + t('Edit'), 'href' => "admin/config/services/aggregator/edit/category/$category->cid", ); + $links['delete'] = array( + 'title' => t('Delete'), + 'href' => "admin/config/services/aggregator/delete/category/$category->cid", + ); $row[] = array( 'data' => array( '#type' => 'operations', diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Form/CategoryAdminForm.php b/core/modules/aggregator/lib/Drupal/aggregator/Form/CategoryAdminForm.php new file mode 100644 index 0000000..414633a --- /dev/null +++ b/core/modules/aggregator/lib/Drupal/aggregator/Form/CategoryAdminForm.php @@ -0,0 +1,186 @@ +database = $database; + $this->moduleHandler = $module_handler; + $this->categoryStorageController = $category_storage_controller; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('database'), + $container->get('module_handler'), + $container->get('aggregator.category.storage') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'aggregator_form_category'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state, $cid = NULL) { + $category = (object) $this->categoryStorageController->load($cid); + $form['title'] = array( + '#type' => 'textfield', + '#title' => t('Title'), + '#default_value' => isset($category->title) ? $category->title : '', + '#maxlength' => 64, + '#required' => TRUE, + ); + $form['description'] = array( + '#type' => 'textarea', + '#title' => t('Description'), + '#default_value' => isset($category->description) ? $category->description : '', + ); + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save')); + if (!empty($category->cid)) { + $form['actions']['delete'] = array('#type' => 'submit', '#value' => t('Delete')); + $form['cid'] = array('#type' => 'hidden', '#value' => $category->cid); + } + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + if ($form_state['values']['op'] == t('Save')) { + // Check for duplicate titles. + if (isset($form_state['values']['cid'])) { + $category = $this->database->query("SELECT cid FROM {aggregator_category} WHERE title = :title AND cid <> :cid", array(':title' => $form_state['values']['title'], ':cid' => $form_state['values']['cid']))->fetchObject(); + } + else { + $category = $this->database->query("SELECT cid FROM {aggregator_category} WHERE title = :title", array(':title' => $form_state['values']['title']))->fetchObject(); + } + if ($category) { + form_set_error('title', t('A category named %category already exists. Enter a unique title.', array('%category' => $form_state['values']['title']))); + } + } + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + // @todo Replicate this cache invalidation when these ops are separated. + // Invalidate the block cache to update aggregator category-based derivatives. + $this->clearBlockCache(); + + $link_path = 'aggregator/categories/'; + $title = $form_state['values']['title']; + + // Redirect to a confirm delete form. + if ($form_state['values']['op'] == t('Delete')) { + $cid = $form_state['values']['cid']; + $form_state['redirect'] = 'admin/config/services/aggregator/delete/category/' . $cid; + return; + } + + // Update the category. + if (!empty($form_state['values']['cid'])) { + $cid = $form_state['values']['cid']; + $this->categoryStorageController->update($form_state['values']); + drupal_set_message(t('The category %category has been updated.', array('%category' => $title))); + $form_state['redirect'] = arg(0) == 'admin' ? 'admin/config/services/aggregator/' : 'aggregator/categories/' . $cid; + $this->updateMenuLink('update', $link_path . $cid, $title); + return; + } + + // Insert the category. + $cid = $this->categoryStorageController->save($form_state['values']); + watchdog('aggregator', 'Category %category added.', array('%category' => $form_state['values']['title']), WATCHDOG_NOTICE, l(t('view'), 'admin/config/services/aggregator')); + drupal_set_message(t('The category %category has been added.', array('%category' => $title))); + + $this->updateMenuLink('insert', $link_path . $cid, $title); + + } + + /** + * Clear the block cached definitions. + */ + protected function clearBlockCache() { + if ($this->moduleHandler->moduleExists('block')) { + \Drupal::service('plugin.manager.block')->clearCachedDefinitions(); + } + } + + /** + * Updates a category menu link. + * + * @param string $op + * The operation to perform. + * @param string $link_path + * The path of the menu link. + * @param string $title + * The title of the menu link. + * + * @see menu_link_maintain() + */ + protected function updateMenuLink($op, $link_path, $title) { + if (isset($op) && $this->moduleHandler->moduleExists('menu_link')) { + menu_link_maintain('aggregator', $op, $link_path, $title); + } + } + +} diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Form/CategoryDeleteForm.php b/core/modules/aggregator/lib/Drupal/aggregator/Form/CategoryDeleteForm.php new file mode 100644 index 0000000..bb46850 --- /dev/null +++ b/core/modules/aggregator/lib/Drupal/aggregator/Form/CategoryDeleteForm.php @@ -0,0 +1,188 @@ +moduleHandler = $module_handler; + $this->entityManager = $entity_manager; + $this->categoryStorageController = $category_storage_controller; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static ( + $container->get('module_handler'), + $container->get('plugin.manager.entity'), + $container->get('aggregator.category.storage') + ); + } + + /** + * {@inheritdoc} + */ + public function getQuestion() { + return t('Are you sure you want to delete the category %title?', array('%title' => $this->category->title)); + } + + /** + * {@inheritdoc} + */ + public function getCancelPath() { + return 'admin/config/services/aggregator'; + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'aggregator_category_delete'; + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return t('Delete'); + } + + /** + * {@inheritdoc} + */ + public function getDescription() { + return t('This will delete the aggregator category, the menu item for this category, and any related category blocks.'); + } + + /** + * Form constructor. + * + * @param array $form + * An associative array containing the structure of the form. + * @param array $form_state + * An associative array containing the current state of the form. + * @param \Symfony\Component\HttpFoundation\Request $request + * The current request. + * @param int|null $cid + * The category ID. + * + * @return array + * The form structure. + * + * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * If the cid param or category is not found. + */ + public function buildForm(array $form, array &$form_state, Request $request = NULL, $cid = NULL) { + $category = (object) $this->categoryStorageController->load($cid); + if (empty($cid) || empty($category)) { + throw new NotFoundHttpException(); + } + $this->category = $category; + return parent::buildForm($form, $form_state, $request); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + $cid = $this->category->cid; + $title = $this->category->title; + $this->categoryStorageController->delete($cid); + // Make sure there is no active block for this category. + $this->deleteBlocks($cid); + watchdog('aggregator', 'Category %category deleted.', array('%category' => $title)); + drupal_set_message(t('The category %category has been deleted.', array('%category' => $title))); + $form_state['redirect'] = arg(0) == 'admin' ? 'admin/config/services/aggregator' : 'aggregator'; + $this->updateMenuLink('delete', 'aggregator/categories/' . $cid, $title); + } + + /** + * Delete aggregator category blocks. + * + * @param int $cid + * The category ID. + */ + protected function deleteBlocks($cid) { + if ($this->moduleHandler->moduleExists('block')) { + foreach ($this->entityManager->getStorageController('block')->loadByProperties(array('plugin' => 'aggregator_category_block:' . $cid)) as $block) { + $block->delete(); + } + } + } + + /** + * Updates a category menu link. + * + * @param string $op + * The operation to perform. + * @param string $link_path + * The path of the menu link. + * @param string $title + * The title of the menu link. + * + * @see menu_link_maintain() + */ + protected function updateMenuLink($op, $link_path, $title) { + if (isset($op) && $this->moduleHandler->moduleExists('menu_link')) { + menu_link_maintain('aggregator', $op, $link_path, $title); + } + } + +}