diff --git a/plugins/FeedsEntityProcessor.inc b/plugins/FeedsEntityProcessor.inc new file mode 100644 index 0000000..43503e0 --- /dev/null +++ b/plugins/FeedsEntityProcessor.inc @@ -0,0 +1,262 @@ +pluginDefinition(); + return $plugin_info['type']; + } + + /** + * Returns the bundle. + * + * @return string + * The bundle of the entities this processor will create. + */ + public function bundle() { + $bundle = NULL; + $entity_info = $this->entityInfo(); + if(!empty($this->config['bundle']) && isset($entity_info['bundles'][$this->config['bundle']])) { + $bundle = $this->config['bundle']; + } + + return $bundle; + } + + /** + * Overrides parent::entityInfo(). + */ + protected function entityInfo() { + $info = parent::entityInfo(); + if (isset($info['label plural'])) { + $plural = $info['label plural']; + } + else { + $plural = $info['label']; + } + + $info += array('label plural' => $plural); + return $info; + } + + /** + * Creates a new entity in memory and returns it. + */ + protected function newEntity(FeedsSource $source) { + $entity_type = $this->entityType(); + $info = entity_get_info($entity_type); + $config = $this->config; + $values = array(); + if (isset($info['entity keys']['bundle']) && isset($config['bundle'])) { + // we have to set the bundle in values when calling + // entity_property_values_create_entity() if the entity has an bundle + // in entity keys, or the bundle will not be set on creation + $values[$info['entity keys']['bundle']] = $config['bundle']; + } + $values = array_merge($config['values'], $values); + $entity = entity_property_values_create_entity($this->entityType(), $values)->value(); + return $entity; + } + + /** + * Check that the user has permission to save an entity. + * + * @todo Is checking the uid safe? A quick glance through core and some + * contrib seems to say yes. + */ + protected function entitySaveAccess($entity) { + + // The check will be skipped for anonymous users. + if (!empty($this->config['authorize']) && !empty($entity->uid)) { + + $author = user_load($entity->uid); + + // If the uid was mapped directly, rather than by email or username, it + // could be invalid. + if (!$author) { + $message = 'User %uid is not a valid user.'; + throw new FeedsAccessException(t($message, array('%uid' => $entity->uid))); + } + + if (!empty($entity->is_new)) { + $op = 'create'; + $access = entity_access($op, $this->entityType(), $author); + } + else { + $op = 'update'; + $access = entity_access($op, $this->entityType(), $author); + } + + if (!$access) { + $message = 'User %name is not authorized to %op entity %entity.'; + $args = array( + '%name' => $author->name, + '%op' => $op, + '%entity' => $this->entityType(), + ); + throw new FeedsAccessException(t($message, $args)); + } + } + } + + /** + * Save a entity. + */ + public function entitysave($entity) { + entity_save($this->entityType(), $entity); + } + + /** + * Delete a series of entities. + */ + protected function entityDeleteMultiple($ids) { + entity_delete_multiple($this->entityType(), $ids); + } + + /** + * Override parent::configDefaults(). + */ + public function configDefaults() { + return array( + 'mappings' => array(), + 'update_existing' => FEEDS_SKIP_EXISTING, + 'input_format' => NULL, + 'skip_hash_check' => FALSE, + 'bundle' => NULL, + 'values' => array(), + ); + } + + /** + * Override parent::configForm(). + */ + public function configForm(&$form_state) { + $form = parent::configForm($form_state); + + $form['values'] = array( + '#type' => 'fieldset', + '#title' => t('Default values'), + '#tree' => TRUE, + '#description' => t('Most of the values below can be overriden by mapping a value.'), + ); + + $entity_info = $this->entityInfo(); + $label_plural = $entity_info['label plural']; + + $form['input_format']['#description'] = t('Select the default input format for the %entity to be created.', array('%entity' => $label_plural)); + + $wrapper = entity_metadata_wrapper($this->entityType()); + + foreach ($wrapper->getPropertyInfo() as $name => $property) { + if (empty($property['field'])) { + $form['values'][$name] = array( + '#type' => 'textfield', + '#title' => $property['label'], + '#description' => isset($property['description']) ? $property['description'] : '', + '#default_value' => isset($this->config['values'][$name]) ? $this->config['values'][$name] : NULL, + '#required' => !empty($property['required']), + ); + + if (!empty($property['options list'])) { + $form['values'][$name]['#type'] = 'select'; + if (isset($property['type']) && entity_property_list_extract_type($property['type'])) { + $form['values'][$name]['#type'] = 'checkboxes'; + if (!is_array($form['values'][$name]['#default_value'])) { + $form['values'][$name]['#default_value'] = array($form['values'][$name]['#default_value']); + } + } + $form['values'][$name]['#options'] = $wrapper->$name->optionsList(); + } + + elseif (!empty($property['type']) && $property['type'] == 'boolean') { + $form['values'][$name]['#type'] = 'checkbox'; + } + // elseif (!empty($property['type']) && $property['type'] == 'date') { + // $form['values'][$name]['#type'] = 'date'; + // } + } + } + return $form; + } + + /** + * Override parent::configFormValidate(). + */ + public function configFormValidate(&$values) { + $form = parent::configFormValidate($values); + + $wrapper = entity_metadata_wrapper($this->entityType()); + + foreach ($wrapper->getPropertyInfo() as $name => $property) { + if (empty($property['field'])) { + + // Entity api won't accept empty date values. + if (!empty($property['type']) && $property['type'] == 'date') { + if (empty($values['values'][$name])) { + unset($values['values'][$name]); + continue; + } + } + + if (isset($property['type']) && array_key_exists($name, $values['values'])) { + if (entity_property_list_extract_type($property['type']) && !is_array($values['values'][$name])) { + $values['values'][$name] = array($values['values'][$name]); + } + $valid = entity_property_verify_data_type($values['values'][$name], $property['type']); + if (!$valid) { + form_set_error("values][$name", t('Invalid data value given. Be sure it matches the required data type and format.')); + } + } + } + } + } + + /** + * Returns available mapping targets. + */ + public function getMappingTargets() { + // Get a wrapper with the right bundle info. + + $targets = parent::getMappingTargets(); + $info = array('bundle' => $this->bundle()); + + $wrapper = entity_metadata_wrapper($this->entityType(), NULL, $info); + // @todo: maybe restrict to data types feeds can deal with. + foreach ($wrapper->getPropertyInfo() as $name => $property) { + if (empty($property['field'])) { + $targets[$name] = array( + 'name' => $property['label'], + 'description' => isset($property['description']) ? $property['description'] : NULL, + ); + } + } + + $entity_info = $this->entityInfo(); + $targets[$entity_info['entity keys']['id']]['optional_unique'] = TRUE; + + // Remove the bundle target. + if (isset($entity_info['bundle keys']['bundle'])) { + unset($targets[$entity_info['bundle keys']['bundle']]); + } + + // Let other modules expose mapping targets. + self::loadMappers(); + $type = $this->entityType(); + drupal_alter('feeds_processor_targets', $targets, $type, $info['bundle']); + + return $targets; + } +}