Commit 38680332 authored by Dries's avatar Dries

Issue #2046303 by kim.pepper: Convert aggregator_form_category() to FormInterface.

parent dd95e4ba
<?php
/**
* @file
* Administration page callbacks for the Aggregator module.
*/
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Drupal\aggregator\Plugin\Core\Entity\Feed;
/**
* Form constructor to add/edit/delete aggregator categories.
*
* @param $edit
* An object containing:
* - title: A string to use for the category title.
* - description: A string to use for the category description.
* - cid: The category ID.
*
* @ingroup forms
* @see aggregator_menu()
* @see aggregator_form_category_validate()
* @see aggregator_form_category_submit()
*/
function aggregator_form_category($form, &$form_state, $edit = NULL) {
$form['title'] = array('#type' => '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'])));
}
}
......@@ -102,11 +102,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 +171,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 +202,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 +215,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;
......@@ -455,16 +448,14 @@ function aggregator_feed_load($fid) {
* @param $cid
* The category id.
*
* @return
* An associative array describing the category.
* @return stdClass|null
* An object containing all category properties.
*
* @deprecated Use Drupal\aggregator\CategoryStorageControllerInterface::load()
* instead.
*/
function aggregator_category_load($cid) {
$categories = &drupal_static(__FUNCTION__);
if (!isset($categories[$cid])) {
$categories[$cid] = db_query('SELECT * FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $cid))->fetchObject();
}
return $categories[$cid];
return Drupal::service('aggregator.category.storage')->load($cid);
}
/**
......
......@@ -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'
......@@ -13,3 +13,6 @@ services:
arguments: ['@database']
tags:
- { name: access_check }
aggregator.category.storage:
class: Drupal\aggregator\CategoryStorageController
arguments: ['@database']
<?php
/**
* @file
* Contains \Drupal\aggregator\CategoryStorageController.
*/
namespace Drupal\aggregator;
use Drupal\Core\Database\Connection;
/**
* Storage controller for aggregator categories.
*/
class CategoryStorageController implements CategoryStorageControllerInterface {
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* A cache of loaded categories.
*
* @var \stdClass[]
*/
protected $categories;
/**
* Creates a new CategoryStorageController object.
*
* @param \Drupal\Core\Database\Connection $database
* The database connection.
*/
public function __construct(Connection $database) {
$this->database = $database;
}
/**
* {@inheritdoc}
*/
public function load($cid) {
if (!isset($this->categories[$cid])) {
$this->categories[$cid] = $this->database->query("SELECT * FROM {aggregator_category} WHERE cid = :cid", array(':cid' => $cid))->fetchObject();
}
return $this->categories[$cid];
}
/**
* {@inheritdoc}
*/
public function save($category) {
$cid = $this->database->insert('aggregator_category')
->fields(array(
'title' => $category->title,
'description' => $category->description,
'block' => 5,
))
->execute();
return $cid;
}
/**
* {@inheritdoc}
*/
public function update($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();
}
/**
* {@inheritdoc}
*/
public function isUnique($title, $cid = NULL) {
$query = $this->database->select('aggregator_category', 'ac')
->fields('ac', array('title'))
->condition('title', $title);
if (!empty($cid)) {
$query->condition('cid', $cid, '<>');
}
$rows = $query->execute()->fetchCol();
return (empty($rows));
}
}
<?php
/**
* @file
* Contains \Drupal\aggregator\CategoryStorageControllerInterface.
*/
namespace Drupal\aggregator;
/**
* Storage Controller for aggregator categories.
*/
interface CategoryStorageControllerInterface {
/**
* Loads an aggregator category by its unique ID.
*
* @param int $cid
* The unique category ID.
*
* @return stdClass|null
* An object containing all category properties.
*/
public function load($cid);
/**
* Saves an aggregator category.
*
* @param \stdClass $category
* The category to save.
*
* @return int
* The new category ID.
*/
public function save($category);
/**
* Updates and aggregator category.
*
* @param \stdClass $category
* The category.
*/
public function update($category);
/**
* Deletes an aggregator category.
*
* @param int $cid
* The category ID.
*/
public function delete($cid);
/**
* Checks if the category title is unique.
*
* Optionally passes a category ID to exclude, if this check is for an
* existing category.
*
* @param string $title
* The category title.
* @param int $cid
* (optional) The category ID to exclude from the check.
*
* @return bool
* TRUE if the category title is unique, FALSE otherwise.
*/
public function isUnique($title, $cid = NULL);
}
......@@ -202,6 +202,10 @@ public function adminOverview() {
'title' => 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',
......
<?php
/**
* @file
* Contains Drupal\aggregator\Form\CategoryAdminForm.
*/
namespace Drupal\aggregator\Form;
use Drupal\aggregator\CategoryStorageControllerInterface;
use Drupal\block\Plugin\Type\BlockManager;
use Drupal\Core\Controller\ControllerInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityManager;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Provides a form for configuring aggregator categories.
*/
class CategoryAdminForm implements FormInterface, ControllerInterface {
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection.
*/
protected $database;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* The category storage controller.
*
* @var \Drupal\aggregator\CategoryStorageControllerInterface.
*/
protected $categoryStorageController;
/**
* The current request.
*
* @var \Symfony\Component\HttpFoundation\Request
*/
protected $request;
/**
* The block manager.
*
* @var \Drupal\block\Plugin\Type\BlockManager
*/
protected $blockManager;
/**
* Creates a new CategoryForm object.
*
* @param \Drupal\Core\Database\Connection $database
* The database connection.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\aggregator\CategoryStorageControllerInterface $category_storage_controller
* The category storage controller.
* @param \Drupal\block\Plugin\Type\BlockManager $block_manager
* (optional) The block manager. Used if block module is enabled.
*/
public function __construct(Connection $database, ModuleHandlerInterface $module_handler, CategoryStorageControllerInterface $category_storage_controller, BlockManager $block_manager = NULL) {
$this->database = $database;
$this->moduleHandler = $module_handler;
$this->categoryStorageController = $category_storage_controller;
$this->blockManager = $block_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$block_manager = NULL;
if ($container->get('module_handler')->moduleExists('block')) {
$block_manager = $container->get('plugin.manager.block');
}
return new static(
$container->get('database'),
$container->get('module_handler'),
$container->get('aggregator.category.storage'),
$block_manager
);
}
/**
* {@inheritdoc}
*/
public function getFormID() {
return 'aggregator_form_category';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, array &$form_state, $cid = NULL, Request $request = NULL) {
$this->request = $request;
$category = $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.
$title = $form_state['values']['title'];
if (isset($form_state['values']['cid'])) {
// Exclude the current category ID when checking if it's unique.
$unique = $this->categoryStorageController->isUnique($title, $form_state['values']['cid']);
}
else {
$unique = $this->categoryStorageController->isUnique($title);
}
if (!$unique) {
form_set_error('title', t('A category named %category already exists. Enter a unique title.', array('%category' => $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((object) $form_state['values']);
drupal_set_message(t('The category %category has been updated.', array('%category' => $title)));
if (preg_match('/^\/admin/', $this->request->getPathInfo())) {
$form_state['redirect'] = 'admin/config/services/aggregator/';
}
else {
$form_state['redirect'] = 'aggregator/categories/' . $cid;
}
$this->updateMenuLink('update', $link_path . $cid, $title);
return;
}
// Insert the category.
$cid = $this->categoryStorageController->save((object) $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);
}
/**