Commit f63cdc38 authored by webchick's avatar webchick

Issue #1588422 by andypost, disasm, sun, dawehner, vasi1186, alexpott,...

Issue #1588422 by andypost, disasm, sun, dawehner, vasi1186, alexpott, tim.plunkett, larowlan, Gábor Hojtsy: Convert contact categories to configuration system.
parent 3088640c
id: feedback
label: Website feedback
recipients: []
reply: ''
weight: '0'
......@@ -5,220 +5,47 @@
* Admin page callbacks for the Contact module.
*/
use Drupal\contact\Category;
/**
* Page callback: Lists contact categories.
*
* @see contact_menu()
*/
function contact_category_list() {
$header = array(
t('Category'),
t('Recipients'),
t('Selected'),
t('Operations'),
);
$rows = array();
// Get all the contact categories from the database.
$categories = db_select('contact', 'c')
->addTag('translatable')
->fields('c', array('cid', 'category', 'recipients', 'selected'))
->orderBy('weight')
->orderBy('category')
->execute()
->fetchAll();
// Loop through the categories and add them to the table.
foreach ($categories as $category) {
$row = array();
$row[] = check_plain($category->category);
$row[] = check_plain($category->recipients);
$row[] = ($category->selected ? t('Yes') : t('No'));
$links = array();
$links['edit'] = array(
'title' => t('Edit'),
'href' => 'admin/structure/contact/edit/' . $category->cid,
);
$links['delete'] = array(
'title' => t('Delete'),
'href' => 'admin/structure/contact/delete/' . $category->cid,
);
$row[] = array(
'data' => array(
'#type' => 'operations',
'#links' => $links,
),
);
$rows[] = $row;
}
if (!$rows) {
$rows[] = array(array(
'data' => t('No categories available.'),
'colspan' => 5,
));
}
$build['category_table'] = array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
);
return $build;
return entity_list_controller('contact_category')->render();
}
/**
* Form constructor for the category edit form.
*
* @param $category
* An array describing the category to be edited. May be empty for new
* categories. Recognized array keys are:
* - category: The name of the category.
* - recipients: A comma-separated list of recipients.
* - reply: (optional) The body of the auto-reply message.
* - weight: The weight of the category.
* - selected: Boolean indicating whether the category should be selected by
* default.
* - cid: The category ID for which the form is to be displayed.
*
* @see contact_menu()
* @see contact_category_edit_form_validate()
* @see contact_category_edit_form_submit()
* @ingroup forms
* Page callback: provides the category creation form.
*/
function contact_category_edit_form($form, &$form_state, array $category = array()) {
// If this is a new category, add the default values.
$category += array(
'category' => '',
'recipients' => '',
'reply' => '',
'weight' => 0,
'selected' => 0,
'cid' => NULL,
);
$form['category'] = array(
'#type' => 'textfield',
'#title' => t('Category'),
'#maxlength' => 255,
'#default_value' => $category['category'],
'#description' => t("Example: 'website feedback' or 'product information'."),
'#required' => TRUE,
);
$form['recipients'] = array(
'#type' => 'textarea',
'#title' => t('Recipients'),
'#default_value' => $category['recipients'],
'#description' => t("Example: 'webmaster@example.com' or 'sales@example.com,support@example.com' . To specify multiple recipients, separate each e-mail address with a comma."),
'#required' => TRUE,
);
$form['reply'] = array(
'#type' => 'textarea',
'#title' => t('Auto-reply'),
'#default_value' => $category['reply'],
'#description' => t('Optional auto-reply. Leave empty if you do not want to send the user an auto-reply message.'),
);
$form['weight'] = array(
'#type' => 'weight',
'#title' => t('Weight'),
'#default_value' => $category['weight'],
'#description' => t('When listing categories, those with lighter (smaller) weights get listed before categories with heavier (larger) weights. Categories with equal weights are sorted alphabetically.'),
);
$form['selected'] = array(
'#type' => 'checkbox',
'#title' => t('Make this the default category.'),
'#default_value' => $category['selected'],
);
$form['cid'] = array(
'#type' => 'value',
'#value' => $category['cid'],
);
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
/**
* Form validation handler for contact_category_edit_form().
*
* @see contact_category_edit_form_submit()
*/
function contact_category_edit_form_validate($form, &$form_state) {
// Validate and each e-mail recipient.
$recipients = explode(',', $form_state['values']['recipients']);
// When creating a new contact form, or renaming the category on an existing
// contact form, make sure that the given category is unique.
$category = $form_state['values']['category'];
$query = db_select('contact', 'c')->condition('c.category', $category, '=');
if (!empty($form_state['values']['cid'])) {
$query->condition('c.cid', $form_state['values']['cid'], '<>');
}
if ($query->countQuery()->execute()->fetchField()) {
form_set_error('category', t('A contact form with category %category already exists.', array('%category' => $category)));
}
foreach ($recipients as &$recipient) {
$recipient = trim($recipient);
if (!valid_email_address($recipient)) {
form_set_error('recipients', t('%recipient is an invalid e-mail address.', array('%recipient' => $recipient)));
}
}
$form_state['values']['recipients'] = implode(',', $recipients);
}
/**
* Form submission handler for contact_category_edit_form().
*
* @see contact_category_edit_form_validate()
*/
function contact_category_edit_form_submit($form, &$form_state) {
if ($form_state['values']['selected']) {
// Unselect all other contact categories.
db_update('contact')
->fields(array('selected' => '0'))
->execute();
}
if (empty($form_state['values']['cid'])) {
drupal_write_record('contact', $form_state['values']);
}
else {
drupal_write_record('contact', $form_state['values'], array('cid'));
}
drupal_set_message(t('Category %category has been saved.', array('%category' => $form_state['values']['category'])));
watchdog('contact', 'Category %category has been saved.', array('%category' => $form_state['values']['category']), WATCHDOG_NOTICE, l(t('Edit'), 'admin/structure/contact/edit/' . $form_state['values']['cid']));
$form_state['redirect'] = 'admin/structure/contact';
function contact_category_add() {
$category = entity_create('contact_category', array());
return entity_get_form($category);
}
/**
* Form constructor for the contact category deletion form.
*
* @param $contact
* Array describing the contact category to be deleted. See the documentation
* of contact_category_edit_form() for the recognized keys.
* @param Drupal\contact\Category $category
* The contact category to be deleted.
*
* @see contact_menu()
* @see contact_category_delete_form_submit()
*/
function contact_category_delete_form($form, &$form_state, array $contact) {
$form['contact'] = array(
function contact_category_delete_form($form, &$form_state, Category $category) {
$form_state['contact_category'] = $category;
$form['id'] = array(
'#type' => 'value',
'#value' => $contact,
'#value' => $category->id(),
);
return confirm_form(
$form,
t('Are you sure you want to delete %category?', array('%category' => $contact['category'])),
t('Are you sure you want to delete %label?', array('%label' => $category->label())),
'admin/structure/contact',
t('This action cannot be undone.'),
t('Delete'),
t('Cancel')
t('Delete')
);
}
......@@ -226,14 +53,11 @@ function contact_category_delete_form($form, &$form_state, array $contact) {
* Form submission handler for contact_category_delete_form().
*/
function contact_category_delete_form_submit($form, &$form_state) {
$contact = $form['contact']['#value'];
db_delete('contact')
->condition('cid', $contact['cid'])
->execute();
$category = $form_state['contact_category'];
$category->delete();
drupal_set_message(t('Category %category has been deleted.', array('%category' => $contact['category'])));
watchdog('contact', 'Category %category has been deleted.', array('%category' => $contact['category']), WATCHDOG_NOTICE);
drupal_set_message(t('Category %label has been deleted.', array('%label' => $category->label())));
watchdog('contact', 'Category %label has been deleted.', array('%label' => $category->label()), WATCHDOG_NOTICE);
$form_state['redirect'] = 'admin/structure/contact';
}
......@@ -5,65 +5,6 @@
* Install, update and uninstall functions for the contact module.
*/
/**
* Implements hook_schema().
*/
function contact_schema() {
$schema['contact'] = array(
'description' => 'Contact form category settings.',
'fields' => array(
'cid' => array(
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => 'Primary Key: Unique category ID.',
),
'category' => array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'Category name.',
'translatable' => TRUE,
),
'recipients' => array(
'type' => 'text',
'not null' => TRUE,
'size' => 'big',
'description' => 'Comma-separated list of recipient e-mail addresses.',
),
'reply' => array(
'type' => 'text',
'not null' => TRUE,
'size' => 'big',
'description' => 'Text of the auto-reply message.',
),
'weight' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => "The category's weight.",
),
'selected' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
'description' => 'Flag to indicate whether or not category is selected by default. (1 = Yes, 0 = No)',
),
),
'primary key' => array('cid'),
'unique keys' => array(
'category' => array('category'),
),
'indexes' => array(
'list' => array('weight', 'category'),
),
);
return $schema;
}
/**
* Implements hook_install().
*/
......@@ -72,17 +13,14 @@ function contact_install() {
if (empty($site_mail)) {
$site_mail = ini_get('sendmail_from');
}
// Insert a default contact category.
db_insert('contact')
->fields(array(
'category' => 'Website feedback',
'recipients' => $site_mail,
'selected' => 1,
'reply' => '',
))
->execute();
config('contact.category.feedback')->set('recipients', array($site_mail))->save();
}
/**
* @addtogroup updates-7.x-to-8.x
* @{
*/
/**
* Moves contact setting from variable to config.
*
......@@ -95,3 +33,42 @@ function contact_update_8000() {
'contact_threshold_window' => 'flood.interval',
));
}
/**
* Migrate contact categories into configuration.
*
* @ingroup config_upgrade
*/
function contact_update_8001() {
$result = db_query('SELECT * FROM {contact}');
foreach ($result as $category) {
// Take over the category's serial ID as new machine name.
$category->id = $category->cid;
// Save default category setting.
if ($category->selected) {
config('contact.settings')
->set('default_category', $category->id)
->save();
}
// Save the config object.
config('contact.category.' . $category->id)
->set('id', $category->id)
->set('label', $category->category)
->set('recipients', explode(',', $category->recipients))
->set('reply', $category->reply)
->set('weight', $category->weight)
->save();
}
}
/**
* Drop the {contact} table.
*/
function contact_update_8002() {
db_drop_table('contact');
}
/**
* @} End of "defgroup updates-7.x-to-8.x".
* The next series of updates should start at 9000.
*/
......@@ -5,6 +5,8 @@
* Enables the use of personal and site-wide contact forms.
*/
use Drupal\contact\Category;
/**
* Implements hook_help().
*/
......@@ -64,22 +66,20 @@ function contact_menu() {
);
$items['admin/structure/contact/add'] = array(
'title' => 'Add category',
'page callback' => 'drupal_get_form',
'page arguments' => array('contact_category_edit_form'),
'page callback' => 'contact_category_add',
'access arguments' => array('administer contact forms'),
'type' => MENU_LOCAL_ACTION,
'weight' => 1,
'file' => 'contact.admin.inc',
);
$items['admin/structure/contact/edit/%contact'] = array(
$items['admin/structure/contact/manage/%contact_category/edit'] = array(
'title' => 'Edit contact category',
'page callback' => 'drupal_get_form',
'page arguments' => array('contact_category_edit_form', 4),
'page callback' => 'entity_get_form',
'page arguments' => array(4),
'access arguments' => array('administer contact forms'),
'file' => 'contact.admin.inc',
);
$items['admin/structure/contact/delete/%contact'] = array(
'title' => 'Delete contact',
$items['admin/structure/contact/manage/%contact_category/delete'] = array(
'title' => 'Delete contact category',
'page callback' => 'drupal_get_form',
'page arguments' => array('contact_category_delete_form', 4),
'access arguments' => array('administer contact forms'),
......@@ -146,22 +146,105 @@ function _contact_personal_tab_access($account) {
return user_access('access user contact forms');
}
/**
* Implements MODULE_config_import_create().
*/
function contact_config_import_create($name, $new_config, $old_config) {
if (strpos($name, 'contact.category.') !== 0) {
return FALSE;
}
$category = entity_create('contact_category', $new_config->get());
$category->save();
return TRUE;
}
/**
* Implements MODULE_config_import_change().
*/
function contact_config_import_change($name, $new_config, $old_config) {
if (strpos($name, 'contact.category.') !== 0) {
return FALSE;
}
list(, , $id) = explode('.', $name);
$category = entity_load('contact_category', $id);
$category->original = clone $category;
foreach ($old_config->get() as $property => $value) {
$category->original->$property = $value;
}
foreach ($new_config->get() as $property => $value) {
$category->$property = $value;
}
$category->save();
return TRUE;
}
/**
* Implements MODULE_config_import_delete().
*/
function contact_config_import_delete($name, $new_config, $old_config) {
if (strpos($name, 'contact.category.') !== 0) {
return FALSE;
}
list(, , $id) = explode('.', $name);
entity_delete_multiple('contact_category', array($id));
return TRUE;
}
/**
* Implements hook_entity_info().
*/
function contact_entity_info() {
$types['contact_category'] = array(
'label' => 'Category',
'entity class' => 'Drupal\contact\Category',
'controller class' => 'Drupal\Core\Config\Entity\ConfigStorageController',
'list controller class' => 'Drupal\contact\CategoryListController',
'form controller class' => array(
'default' => 'Drupal\contact\CategoryFormController',
),
'uri callback' => 'contact_category_uri',
'config prefix' => 'contact.category',
'entity keys' => array(
'id' => 'id',
'label' => 'label',
'uuid' => 'uuid',
),
);
return $types;
}
/**
* Loads a contact category.
*
* @param $cid
* The contact category ID.
* @param $id
* The ID of the contact category to load.
*
* @return
* An array with the contact category's data.
* @return Drupal\contact\Category|false
* A Category object or FALSE if the requested $id does not exist.
*/
function contact_load($cid) {
return db_select('contact', 'c')
->addTag('translatable')
->fields('c')
->condition('cid', $cid)
->execute()
->fetchAssoc();
function contact_category_load($id) {
return entity_load('contact_category', $id);
}
/**
* Entity URI callback.
*
* @param Drupal\category\Category $category
* A contact category entity.
*
* @return array
* An array with 'path' as the key and the path to the category as the value.
*/
function contact_category_uri(Category $category) {
return array(
'path' => 'admin/structure/contact/manage/' . $category->id(),
);
}
/**
......@@ -172,7 +255,7 @@ function contact_mail($key, &$message, $params) {
$variables = array(
'!site-name' => config('system.site')->get('name'),
'!subject' => $params['subject'],
'!category' => isset($params['category']['category']) ? $params['category']['category'] : '',
'!category' => isset($params['category']) ? $params['category']->label() : '',
'!form-url' => url(current_path(), array('absolute' => TRUE, 'language' => $language)),
'!sender-name' => user_format_name($params['sender']),
'!sender-url' => $params['sender']->uid ? url('user/' . $params['sender']->uid, array('absolute' => TRUE, 'language' => $language)) : $params['sender']->mail,
......@@ -188,7 +271,7 @@ function contact_mail($key, &$message, $params) {
case 'page_autoreply':
$message['subject'] .= t('[!category] !subject', $variables, array('langcode' => $language->langcode));
$message['body'][] = $params['category']['reply'];
$message['body'][] = $params['category']->reply;
break;
case 'user_mail':
......
......@@ -12,7 +12,6 @@
* Form constructor for the site-wide contact form.
*
* @see contact_menu()
* @see contact_site_form_validate()
* @see contact_site_form_submit()
* @ingroup forms
*/
......@@ -29,14 +28,7 @@ function contact_site_form($form, &$form_state) {
}
// Get an array of the categories and the current default category.
$categories = db_select('contact', 'c')
->addTag('translatable')
->fields('c', array('cid', 'category'))
->orderBy('weight')
->orderBy('category')
->execute()
->fetchAllKeyed();
$default_category = db_query("SELECT cid FROM {contact} WHERE selected = 1")->fetchField();
$categories = entity_load_multiple('contact_category');
// If there are no categories, do not display the form.
if (!$categories) {
......@@ -48,15 +40,18 @@ function contact_site_form($form, &$form_state) {
}
}
// Prepare array for select options.
uasort($categories, 'Drupal\Core\Config\Entity\ConfigEntityBase::sort');
$options = array();
foreach ($categories as $category) {
$options[$category->id()] = $category->label();
}
// If there is more than one category available and no default category has
// been selected, prepend a default placeholder value.
$default_category = $config->get('default_category');
if (!$default_category) {
if (count($categories) > 1) {
$categories = array(0 => t('- Please choose -')) + $categories;
}
else {
$default_category = key($categories);
}
$default_category = !empty($categories) ? key($categories) : NULL;
}
if (!$user->uid) {
......@@ -102,11 +97,12 @@ function contact_site_form($form, &$form_state) {
'#maxlength' => 255,
'#required' => TRUE,
);
$form['cid'] = array(
$form['category'] = array(
'#type' => 'select',
'#title' => t('Category'),
'#default_value' => $default_category,
'#options' => $categories,
'#options' => $options,
'#empty_value' => 0,
'#required' => TRUE,
'#access' => count($categories) > 1,
);
......@@ -131,17 +127,6 @@ function contact_site_form($form, &$form_state) {
return $form;
}
/**
* Form validation handler for contact_site_form().
*
* @see contact_site_form_submit()
*/
function contact_site_form_validate($form, &$form_state) {
if (!$form_state[