Newer
Older
Alex Barth
committed
}
/**
* Allows other modules to expose targets.
*
* @param array &$targets
* The existing target array.
*/
protected function getHookTargets(array &$targets) {
self::loadMappers();
$entity_type = $this->entityType();
$bundle = $this->bundle();
$targets += module_invoke_all('feeds_processor_targets', $entity_type, $bundle);
drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle);
}
Alex Barth
committed
/**
* Set a concrete target element. Invoked from FeedsProcessor::map().
*
* @ingroup mappingapi
Alex Barth
committed
*/
public function setTargetElement(FeedsSource $source, $target_item, $target_element, $value) {
switch ($target_element) {
case 'url':
case 'guid':
$target_item->feeds_item->$target_element = $value;
break;
default:
$target_item->$target_element = $value;
break;
}
Alex Barth
committed
}
/**
* Retrieve the target entity's existing id if available. Otherwise return 0.
Alex Barth
committed
*
* @ingroup mappingapi
*
Alex Barth
committed
* @param FeedsSource $source
* The source information about this import.
Chris Leppanen
committed
* @param FeedsParserResult $result
Chris Leppanen
committed
* @return int
* The serial id of an entity if found, 0 otherwise.
Alex Barth
committed
*/
protected function existingEntityId(FeedsSource $source, FeedsParserResult $result) {
$targets = $this->getCachedTargets();
Chris Leppanen
committed
$entity_id = 0;
// Iterate through all unique targets and test whether they already exist in
// the database.
foreach ($this->uniqueTargets($source, $result) as $target => $value) {
Chris Leppanen
committed
if ($target === 'guid' || $target === 'url') {
ekes
committed
$entity_id = db_select('feeds_item')
->fields('feeds_item', array('entity_id'))
->condition('feed_nid', $source->feed_nid)
->condition('entity_type', $this->entityType())
->condition('id', $source->id)
->condition($target, $value)
->execute()
->fetchField();
Chris Leppanen
committed
if (!$entity_id && !empty($targets[$target]['unique_callbacks'])) {
Chris Leppanen
committed
if (!is_array($value)) {
$value = array($value);
}
foreach ($targets[$target]['unique_callbacks'] as $callback) {
if ($entity_id = call_user_func($callback, $source, $this->entityType(), $this->bundle(), $target, $value)) {
Chris Leppanen
committed
// Stop at the first unique ID returned by a callback.
break;
}
}
}
// Return with the content id found.
if ($entity_id) {
Chris Leppanen
committed
return $entity_id;
Alex Barth
committed
}
Alex Barth
committed
/**
* Utility function that iterates over a target array and retrieves all
* sources that are unique.
*
* @param $batch
* A FeedsImportBatch.
Alex Barth
committed
*
* @return
* An array where the keys are target field names and the values are the
* elements from the source item mapped to these targets.
*/
protected function uniqueTargets(FeedsSource $source, FeedsParserResult $result) {
Alex Barth
committed
$parser = feeds_importer($this->id)->parser;
$targets = array();
foreach ($this->getMappings() as $mapping) {
if (!empty($mapping['unique'])) {
Alex Barth
committed
// Invoke the parser's getSourceElement to retrieve the value for this
// mapping's source.
$targets[$mapping['target']] = $parser->getSourceElement($source, $result, $mapping['source']);
Alex Barth
committed
}
}
return $targets;
}
/**
* Adds Feeds specific information on $entity->feeds_item.
*
* @param $entity
* The entity object to be populated with new item info.
* @param $feed_nid
* The feed nid of the source that produces this entity.
* @param $hash
* The fingerprint of the source item.
*/
protected function newItemInfo($entity, $feed_nid, $hash = '') {
$entity->feeds_item = new stdClass();
$entity->feeds_item->is_new = TRUE;
$entity->feeds_item->entity_type = $this->entityType();
$entity->feeds_item->id = $this->id;
$entity->feeds_item->feed_nid = $feed_nid;
$entity->feeds_item->imported = REQUEST_TIME;
$entity->feeds_item->hash = $hash;
$entity->feeds_item->url = '';
$entity->feeds_item->guid = '';
}
/**
* Loads existing entity information and places it on $entity->feeds_item.
*
* @param $entity
* The entity object to load item info for. Id key must be present.
*
* @return
* TRUE if item info could be loaded, false if not.
*/
protected function loadItemInfo($entity) {
$entity_info = entity_get_info($this->entityType());
$key = $entity_info['entity keys']['id'];
if ($item_info = feeds_item_info_load($this->entityType(), $entity->$key)) {
$entity->feeds_item = $item_info;
return TRUE;
}
return FALSE;
}
/**
* Create MD5 hash of item and mappings array.
*
* Include mappings as a change in mappings may have an affect on the item
* produced.
*
mikran
committed
* @return string
* A hash is always returned, even when the item is empty, NULL or FALSE.
*/
protected function hash($item) {
mikran
committed
$sources = feeds_importer($this->id)->parser->getMappingSourceList();
$mapped_item = array_intersect_key($item, array_flip($sources));
return hash('md5', serialize($mapped_item) . serialize($this->getMappings()));
Chris Leppanen
committed
* Retrieves the MD5 hash of $entity_id from the database.
*
* @return string
* Empty string if no item is found, hash otherwise.
*/
protected function getHash($entity_id) {
Chris Leppanen
committed
if ($hash = db_query("SELECT hash FROM {feeds_item} WHERE entity_type = :type AND entity_id = :id", array(':type' => $this->entityType(), ':id' => $entity_id))->fetchField()) {
// Return with the hash.
return $hash;
}
return '';
}
/**
* DEPRECATED: Creates a log message for exceptions during import.
*
* Don't use this method as it concatenates user variables into the log
* message, which will pollute the locales_source table when the log message
* is translated. Use ::createLogEntry instead.
*
* @param Exception $e
* The exception that was throwned during processing the item.
* @param $entity
* The entity object.
* @param $item
* The parser result for this entity.
*
* @return string
* The message to log.
*
* @deprecated
* Use ::createLogEntry instead.
*/
protected function createLogMessage(Exception $e, $entity, $item) {
$message = $e->getMessage();
$message .= '<h3>Original item</h3>';
// $this->exportObjectVars() already runs check_plain() for us, so we can
// concatenate here as is.
$message .= '<pre>' . $this->exportObjectVars($item) . '</pre>';
$message .= '<h3>Entity</h3>';
$message .= '<pre>' . $this->exportObjectVars($entity) . '</pre>';
return $message;
}
/**
* Creates a log entry for when an exception occurred during import.
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
*
* @param Exception $e
* The exception that was throwned during processing the item.
* @param object $entity
* The entity object.
* @param array $item
* The parser result for this entity.
*
* @return array
* The message and arguments to log.
*/
protected function createLogEntry(Exception $e, $entity, $item) {
$message = '@exception';
$message .= '<h3>Original item</h3>';
$message .= '<pre>!item</pre>';
$message .= '<h3>Entity</h3>';
$message .= '<pre>!entity</pre>';
$arguments = array(
'@exception' => $e->getMessage(),
// $this->exportObjectVars() already runs check_plain() for us, so we can
// use the "!" placeholder.
'!item' => $this->exportObjectVars($item),
'!entity' => $this->exportObjectVars($entity),
);
return array($message, $arguments);
}
/**
* Returns a string representation of an object or array for log messages.
*
* @param object|array $object
* The object to convert.
*
* @return string
* The sanitized string representation of the object.
*/
protected function exportObjectVars($object) {
include_once DRUPAL_ROOT . '/includes/utility.inc';
$out = is_array($object) ? $object : get_object_vars($object);
$out = array_filter($out, 'is_scalar');
foreach ($out as $key => $value) {
if (is_string($value)) {
megachriz
committed
if (function_exists('mb_check_encoding') && !mb_check_encoding($value, 'UTF-8')) {
$value = utf8_encode($value);
}
$out[$key] = truncate_utf8($value, 100, FALSE, TRUE);
}
}
if (is_array($object)) {
return check_plain(drupal_var_export($out));
}
return check_plain(drupal_var_export((object) $out));
}
megachriz
committed
/**
* Overrides FeedsPlugin::dependencies().
*/
public function dependencies() {
$dependencies = parent::dependencies();
// Find out which module defined the entity type.
$info = $this->entityInfo();
if (isset($info['module'])) {
$dependencies[$info['module']] = $info['module'];
}
return $dependencies;
}
class FeedsProcessorBundleNotDefined extends Exception {}
/**
* Form after build callback for the field "update_existing".
*
* Adds descriptions to options of this field.
*/
function feeds_processor_config_form_update_existing_after_build($field) {
$field[FEEDS_REPLACE_EXISTING]['#description'] = t('Loads records directly from the database, bypassing the Entity API. Faster, but use with caution.');
$field[FEEDS_UPDATE_EXISTING]['#description'] = t('Loads complete @entities using the Entity API for full integration with other modules. Slower, but most reliable.', $field['#tokens']);
return $field;
}