Skip to content
Snippets Groups Projects
Commit c5c1b8b9 authored by megachriz's avatar megachriz Committed by MegaChriz
Browse files

Issue #3046797 by MegaChriz: Switch to item author when the "Authorize" option is checked.

parent c46f7b92
No related branches found
No related tags found
No related merge requests found
......@@ -144,9 +144,7 @@ class FeedsNodeProcessor extends FeedsProcessor {
/**
* Validates a node.
*/
protected function entityValidate($entity) {
parent::entityValidate($entity);
protected function entityValidate($entity, FeedsSource $source = NULL) {
// Set or correct user ID.
if (!isset($entity->uid) || !is_numeric($entity->uid)) {
$entity->uid = $this->config['author'];
......@@ -157,6 +155,28 @@ class FeedsNodeProcessor extends FeedsProcessor {
// not an integer nor a string.
$entity->uid = (int) $entity->uid;
}
// When the import should be authorized, make an extra account switch.
if ($source && $this->config['authorize'] && !empty($entity->uid)) {
$author = user_load($entity->uid);
$switcher = $source->accountSwitcher->switchTo($author);
}
try {
parent::entityValidate($entity, $source);
}
catch (Exception $e) {
// Catch any exceptions, throw these at the end.
}
// When an user switch happened because of an authorized import, be sure to
// switch back to the previous logged in account.
if (!empty($switcher)) {
$switcher->switchBack();
}
if (!empty($e)) {
throw $e;
}
}
/**
......
......@@ -162,11 +162,13 @@ abstract class FeedsProcessor extends FeedsPlugin {
*
* @param object $entity
* The entity to validate.
* @param FeedsSource $source
* (optional) The source to import from.
*
* @throws FeedsValidationException $e
* Thrown if validation fails.
*/
protected function entityValidate($entity) {
protected function entityValidate($entity, FeedsSource $source = NULL) {
$info = $this->entityInfo();
if (!empty($info['entity keys']['language'])) {
......@@ -438,7 +440,7 @@ abstract class FeedsProcessor extends FeedsPlugin {
// Allow modules to alter the entity before validating.
module_invoke_all('feeds_prevalidate', $source, $entity, $item, $entity_id);
$this->entityValidate($entity);
$this->entityValidate($entity, $source);
// Allow modules to alter the entity before saving.
module_invoke_all('feeds_presave', $source, $entity, $item, $entity_id);
......
......@@ -57,7 +57,7 @@ class FeedsTermProcessor extends FeedsProcessor {
/**
* Validates a term.
*/
protected function entityValidate($term) {
protected function entityValidate($term, FeedsSource $source = NULL) {
parent::entityValidate($term);
if (drupal_strlen($term->name) == 0) {
......
......@@ -99,7 +99,7 @@ class FeedsUserProcessor extends FeedsProcessor {
/**
* Validates a user account.
*/
protected function entityValidate($account) {
protected function entityValidate($account, FeedsSource $source = NULL) {
parent::entityValidate($account);
if (empty($account->name) || empty($account->mail) || !valid_email_address($account->mail)) {
......
<?php
/**
* @file
* Contains FeedsAccountSwitcherTest.
*/
/**
* Test case for account switching.
*/
class FeedsAccountSwitcherTest extends FeedsWebTestCase {
class FeedsAccountSwitcherTest extends FeedsMapperTestCase {
/**
* {@inheritdoc}
......@@ -137,6 +142,117 @@ class FeedsAccountSwitcherTest extends FeedsWebTestCase {
)));
}
/**
* Tests if an extra account switch happens on authorized imports.
*/
public function testAuthorizedImport() {
// Enable feeds_test_field module.
module_enable(array('feeds_test_field'));
// Create content type.
$typename = $this->createContentType(array(), array(
'alpha' => array(
'type' => 'feeds_test_field',
'widget' => 'feeds_test_field_textfield',
),
));
// Create a role with permission to create content and permission to edit
// fields of type 'feeds_test_field'.
$rid1 = $this->drupalCreateRole(array(
'access content',
'create ' . $typename . ' content',
'feeds_test_field.edit',
));
// Create also a role that only may create content, but may NOT edit fields
// of type 'feeds_test_field'.
$rid2 = $this->drupalCreateRole(array(
'access content',
'create ' . $typename . ' content',
));
// Create one account that may create content and an other
// who may not.
$morticia = user_save(drupal_anonymous_user(), array(
'name' => 'Morticia',
'mail' => 'morticia@example.com',
'pass' => 'mort',
'status' => 1,
'roles' => array(
$rid1 => $rid1,
),
));
// Fester may not edit feeds_test_field fields.
$fester = user_save(drupal_anonymous_user(), array(
'name' => 'Fester',
'mail' => 'fester@example.com',
'pass' => 'fester',
'status' => 1,
'roles' => array(
$rid2 => $rid2,
),
));
// Assert that the admin user is logged in. After import, we check again
// which user is logged in. It is important to ensure that it's the same
// user who's logged in after import, so we can ensure that account switches
// get reverted properly.
$this->drupalGet('user');
$this->clickLink('Edit');
$this->assertUrl('user/' . $this->admin_user->uid . '/edit');
// Use the CSV parser.
$this->setPlugin('syndication', 'FeedsCSVParser');
// Turn on authorize option and set bundle.
$this->setSettings('syndication', 'FeedsNodeProcessor', array(
'authorize' => TRUE,
'bundle' => $typename,
));
// The column 'author' from the CSV contains the username.
$this->addMappings('syndication',
array(
1 => array(
'source' => 'author',
'target' => 'user_name',
),
2 => array(
'source' => 'alpha',
'target' => 'field_alpha',
),
)
);
// Create a feed node and change the author of the node. During the import,
// Feeds will initially switch to the author's account. This author is
// allowed to create content, but not edit fields of type
// 'feeds_test_field'. Since the import requires that permission, we can
// ensure another account switch happened if the content gets imported
// successfully.
$nid = $this->createFeedNode('syndication', $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/content_author.csv', 'Node 1');
$account = $this->drupalCreateUser(array(
'access content',
'create ' . $typename . ' content',
));
$this->changeNodeAuthor($nid, $account);
// And perform import.
$this->drupalPost('node/' . $nid . '/import', NULL, 'Import');
// Assert that only one node was imported. Only the author of the first item
// is expected to be allowed to edit field_alpha, but the author of the
// second item isn't.
$this->assertText('Created 1 node');
$this->assertText('Failed importing 1 node');
$this->assertText("Field validation errors in item 'Ut wisi enim ad minim veniam'");
$this->assertText('You are not authorized to edit this field');
// Assert that the admin user is still logged in. This ensures that after
// the import the account switch has been reverted.
$this->drupalGet('user');
$this->clickLink('Edit');
$this->assertUrl('user/' . $this->admin_user->uid . '/edit');
}
/**
* Tests if the user is switched back properly when an import fails.
*/
......@@ -167,21 +283,4 @@ class FeedsAccountSwitcherTest extends FeedsWebTestCase {
$this->assertUrl('user/' . $this->admin_user->uid . '/edit');
}
/**
* Changes the author of a node and asserts the change in the UI.
*
* @param int $nid
* The ID of the node to change author.
* @param object $account
* The new author.
*/
protected function changeNodeAuthor($nid, $account) {
$node = node_load($nid);
$node->uid = $account->uid;
node_save($node);
// Assert that author was in fact changed.
$this->drupalGet('node/' . $nid);
$this->assertText($account->name);
}
}
......@@ -665,6 +665,23 @@ class FeedsWebTestCase extends DrupalWebTestCase {
return $nid;
}
/**
* Changes the author of a node and asserts the change in the UI.
*
* @param int $nid
* The ID of the node to change author.
* @param object $account
* The new author.
*/
protected function changeNodeAuthor($nid, $account) {
$node = node_load($nid);
$node->uid = $account->uid;
node_save($node);
// Assert that author was in fact changed.
$this->drupalGet('node/' . $nid);
$this->assertText($account->name);
}
/**
* Copies a directory.
*
......
"guid","title","created","author","alpha"
1,"Lorem ipsum",1251936720,Morticia,"Lorem"
2,"Ut wisi enim ad minim veniam",1251932360,Fester,"Ut wisi"
\ No newline at end of file
<?php
/**
* @file
* Integration with the Feeds module.
*/
/**
* Implements hook_feeds_processor_targets().
*/
function feeds_test_field_feeds_processor_targets($entity_type, $bundle_name) {
$targets = array();
foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name);
if (in_array($info['type'], array('feeds_test_field'))) {
$targets[$name] = array(
'name' => $instance['label'],
'callback' => 'feeds_test_field_feeds_set_target',
'description' => t('The @label field of the node.', array('@label' => $instance['label'])),
);
}
}
return $targets;
}
/**
* Implements callback_my_module_set_target().
*/
function feeds_test_field_feeds_set_target(FeedsSource $source, $entity, $target, array $values, array $mapping) {
$language = $mapping['language'];
// Iterate over all values.
$field = isset($entity->$target) ? $entity->$target : array($language => array());
foreach ($values as $value) {
$field[$language][] = array('value' => $value);
}
$entity->$target = $field;
}
name = "Feeds test field"
description = "Provides a field with special validation."
package = Testing
core = 7.x
hidden = TRUE
dependencies[] = text
\ No newline at end of file
<?php
/**
* @file
* Defines schema for Feeds test field.
*/
/**
* Implements hook_field_schema().
*/
function feeds_test_field_field_schema($field) {
return array(
'columns' => array(
'value' => array(
'type' => 'varchar',
'length' => 255,
'not null' => FALSE,
),
),
);
}
<?php
/**
* @file
* Provides a field with special validation.
*/
/**
* Implements hook_permission().
*/
function feeds_test_field_permission() {
return array(
'feeds_test_field.edit' => array(
'title' => 'Edit Feeds test fields',
),
);
}
/**
* Implements hook_field_info().
*/
function feeds_test_field_field_info() {
return array(
'feeds_test_field' => array(
// Since this module is only used in tests, label and description
// don't have to be translatable.
'label' => 'Feeds test field',
'description' => 'This field stores text and requires special validation.',
'default_widget' => 'feeds_test_field_textfield',
'default_formatter' => 'feeds_test_field_default',
'property_type' => 'text',
),
);
}
/**
* Implements hook_field_validate().
*/
function feeds_test_field_field_validate($obj_type, $object, $field, $instance, $langcode, $items, &$errors) {
foreach ($items as $delta => $item) {
// Verify that the current user has access to this field.
if (!user_access('feeds_test_field.edit') && !user_access('administer feeds')) {
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'access_denied',
// Since this module is only used in tests, the message doesn't have to
// be translatable.
'message' => 'You are not authorized to edit this field.',
);
}
}
}
/**
* Implements hook_field_is_empty().
*/
function feeds_test_field_field_is_empty($item, $field) {
if (empty($item['value'])) {
return TRUE;
}
return FALSE;
}
/**
* Implements hook_field_formatter_info().
*/
function feeds_test_field_field_formatter_info() {
return array(
'feeds_test_field_default' => array(
'label' => t('Default'),
'description' => t('Display the text.'),
'field types' => array('feeds_test_field'),
),
);
}
/**
* Implements hook_field_formatter_view().
*/
function feeds_test_field_field_formatter_view($object_type, $object, $field, $instance, $langcode, $items, $display) {
$element = array();
foreach ($items as $delta => $item) {
$element[$delta] = array('#markup' => check_plain($item['value']));
}
return $element;
}
/**
* Implements hook_field_widget_info().
*/
function feeds_test_field_field_widget_info() {
return array(
'feeds_test_field_textfield' => array(
'label' => t('Text field'),
'field types' => array('feeds_test_field'),
),
);
}
/**
* Implements hook_field_widget_form().
*/
function feeds_test_field_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $base) {
$element = $base;
$element['value'] = $base + array(
'#type' => 'textfield',
'#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
'#prefix' => '<div class="text-full-wrapper">',
'#suffix' => '</div>',
);
return $element;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment