commit 45080c338310e2411258151a1c0fbae893eecfe8 Author: fago Date: Wed Jan 19 22:36:56 2011 +0100 entity processor diff --git feeds.plugins.inc feeds.plugins.inc index 00723eb..8efb4a5 100644 --- feeds.plugins.inc +++ feeds.plugins.inc @@ -130,6 +130,29 @@ function _feeds_feeds_plugins() { 'path' => $path, ), ); + if (module_exists('entity')) { + + foreach (entity_get_info() as $type => $entity_info) { + // @todo: test for saving and whatever else necessary? + if (entity_type_supports($type, 'create')) { + $info['FeedsEntityProcessor' . drupal_ucfirst($type)] = array( + 'name' => 'Entity processor ' . $entity_info['label'], + // @todo: Use plural label if there. + 'description' => 'Create and update ' . $entity_info['label'] . 's.', + 'help' => 'Create and update ' . $entity_info['label'] . 's from parsed content.', + 'handler' => array( + 'parent' => 'FeedsProcessor', + 'class' => 'FeedsEntityProcessor', + 'file' => 'FeedsEntityProcessor.inc', + 'path' => $path, + ), + // Add in the entity type used. + // @see FeedsEntityProcessor::entityType() + 'type' => $type, + ); + } + } + } $info['FeedsNodeProcessor'] = array( 'name' => 'Node processor', 'description' => 'Create and update nodes.', diff --git plugins/FeedsEntityProcessor.inc plugins/FeedsEntityProcessor.inc new file mode 100644 index 0000000..6fd3623 --- /dev/null +++ plugins/FeedsEntityProcessor.inc @@ -0,0 +1,156 @@ +id); + $plugin_key = $importer->config['processor']['plugin_key']; + $plugin_info = ctools_get_plugins('feeds', 'plugins', $plugin_key); + return $plugin_info['type']; + } + + /** + * Implements parent::entityInfo(). + */ + protected function entityInfo() { + $info = parent::entityInfo(); + $info += array('label plural' => $info['label']); + return $info; + } + + /** + * Creates a new entity in memory and returns it. + */ + protected function newEntity(FeedsSource $source) { + return entity_property_values_create_entity($this->entityType(), $this->config['values']); + } + + /** + * Loads an existing entity. + * + * If the update existing method is not FEEDS_UPDATE_EXISTING, only the entity + * table will be loaded, foregoing the entity_load API for better performance. + */ + protected function entityLoad(FeedsSource $source, $id) { + $result = entity_load(array($id)); + return reset($result); + } + + /** + * Save a entity. + */ + public function entitysave($entity) { + entity_save($this->entityType(), $entity); + } + + /** + * Delete a series of entities. + */ + protected function entityDeleteMultiple($ids) { + entity_delete_multiple($ids); + } + + /** + * Override parent::configDefaults(). + */ + public function configDefaults() { + return array( + 'values' => array(), + ) + parent::configDefaults(); + } + + /** + * Override parent::configForm(). + */ + public function configForm(&$form_state) { + $form = parent::configForm($form_state); + $form['values']['#tree'] = TRUE; + + $wrapper = entity_metadata_wrapper($this->entityType()); + foreach ($wrapper->getPropertyInfo() as $name => $property) { + if (!empty($property['required'])) { + $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' => TRUE, + ); + if (!empty($property['options list'])) { + $form['values'][$name]['#type'] = 'select'; + $form['values'][$name]['#options'] = $wrapper->$name->optionsList(); + } + // @todo: Maybe implement per data-type forms like Rules does? + $form['values'][$name]['#description'] .= ' ' . t('Expected data type: %type.', array('%type' => $wrapper->$name->type())); + if ($wrapper->$name instanceof EntityDrupalWrapper) { + $info = $wrapper->$name->entityInfo(); + $id_info = $wrapper->$name->get($info['entity keys']['id'])->info(); + $form['values'][$name]['#description'] .= ' ' . t('Just enter the identifier of the entity, i.e. %id', array('%id' => $id_info['label'])); + } + } + } + return $form; + } + + public function configFormSubmit(&$values) { + parent::configFormSubmit($values); + } + + /** + * Override setTargetElement to operate on a target item that is a entity. + */ + public function setTargetElement(FeedsSource $source, $target_item, $target_element, $value) { + $wrapper = entity_metadata_wrapper($this->entityType(), $target_item); + switch ($target_element) { + case 'url': + case 'guid': + $target_item->feeds_item->$target_element = $value; + break; + default: + $wrapper->$target_element->set($value); + break; + } + } + + /** + * Return available mapping targets. + */ + public function getMappingTargets() { + // Get a wrapper with the right bundle info. + $entity_info = $this->entityInfo(); + $info = array('bundle' => NULL); + if (isset($entity_info['entity keys']['bundle']) && isset($this->config['values'][$entity_info['entity keys']['bundle']])) { + $info['bundle'] = $this->config['values'][$entity_info['entity keys']['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['setter callback'])) { + $targets[$name] = array( + 'name' => $property['label'], + 'description' => isset($property['description']) ? $property['description'] : NULL, + ); + } + } + $targets[$entity_info['entity keys']['id']]['optional_unique'] = TRUE; + + // Let other modules expose mapping targets. + self::loadMappers(); + feeds_alter('feeds_processor_targets', $targets, $this->entityType(), $info['bundle']); + + return $targets; + } +} +