Révision 41cc1b08
Ajouté par Assos Assos il y a presque 9 ans
drupal7/sites/all/modules/feeds/plugins/FeedsProcessor.inc | ||
---|---|---|
9 | 9 |
define('FEEDS_SKIP_EXISTING', 0); |
10 | 10 |
define('FEEDS_REPLACE_EXISTING', 1); |
11 | 11 |
define('FEEDS_UPDATE_EXISTING', 2); |
12 |
// Options for handling content in Drupal but not in source data. |
|
13 |
define('FEEDS_SKIP_NON_EXISTENT', 'skip'); |
|
14 |
define('FEEDS_DELETE_NON_EXISTENT', 'delete'); |
|
12 | 15 |
|
13 | 16 |
// Default limit for creating items on a page load, not respected by all |
14 | 17 |
// processors. |
... | ... | |
176 | 179 |
*/ |
177 | 180 |
public function process(FeedsSource $source, FeedsParserResult $parser_result) { |
178 | 181 |
$state = $source->state(FEEDS_PROCESS); |
182 |
if (!isset($state->removeList) && $parser_result->items) { |
|
183 |
$this->initEntitiesToBeRemoved($source, $state); |
|
184 |
} |
|
179 | 185 |
|
180 | 186 |
while ($item = $parser_result->shiftItem()) { |
181 | 187 |
|
182 | 188 |
// Check if this item already exists. |
183 | 189 |
$entity_id = $this->existingEntityId($source, $parser_result); |
190 |
// If it's included in the feed, it must not be removed on clean. |
|
191 |
if ($entity_id) { |
|
192 |
unset($state->removeList[$entity_id]); |
|
193 |
} |
|
184 | 194 |
$skip_existing = $this->config['update_existing'] == FEEDS_SKIP_EXISTING; |
185 | 195 |
|
186 | 196 |
module_invoke_all('feeds_before_update', $source, $item, $entity_id); |
... | ... | |
190 | 200 |
continue; |
191 | 201 |
} |
192 | 202 |
|
193 |
$hash = $this->hash($item); |
|
194 |
$changed = ($hash !== $this->getHash($entity_id)); |
|
195 |
$force_update = $this->config['skip_hash_check']; |
|
203 |
try { |
|
196 | 204 |
|
197 |
// Do not proceed if the item exists, has not changed, and we're not |
|
198 |
// forcing the update. |
|
199 |
if ($entity_id && !$changed && !$force_update) { |
|
200 |
continue; |
|
201 |
} |
|
205 |
$hash = $this->hash($item); |
|
206 |
$changed = ($hash !== $this->getHash($entity_id)); |
|
207 |
$force_update = $this->config['skip_hash_check']; |
|
202 | 208 |
|
203 |
try { |
|
209 |
// Do not proceed if the item exists, has not changed, and we're not |
|
210 |
// forcing the update. |
|
211 |
if ($entity_id && !$changed && !$force_update) { |
|
212 |
continue; |
|
213 |
} |
|
204 | 214 |
|
205 | 215 |
// Load an existing entity. |
206 | 216 |
if ($entity_id) { |
... | ... | |
255 | 265 |
catch (Exception $e) { |
256 | 266 |
$state->failed++; |
257 | 267 |
drupal_set_message($e->getMessage(), 'warning'); |
258 |
$message = $this->createLogMessage($e, $entity, $item);
|
|
259 |
$source->log('import', $message, array(), WATCHDOG_ERROR);
|
|
268 |
list($message, $arguments) = $this->createLogEntry($e, $entity, $item);
|
|
269 |
$source->log('import', $message, $arguments, WATCHDOG_ERROR);
|
|
260 | 270 |
} |
261 | 271 |
} |
262 | 272 |
|
... | ... | |
264 | 274 |
if ($source->progressImporting() != FEEDS_BATCH_COMPLETE) { |
265 | 275 |
return; |
266 | 276 |
} |
277 |
// Remove not included items if needed. |
|
278 |
// It depends on the implementation of the clean() method what will happen |
|
279 |
// to items that were no longer in the source. |
|
280 |
$this->clean($state); |
|
267 | 281 |
$info = $this->entityInfo(); |
268 | 282 |
$tokens = array( |
269 | 283 |
'@entity' => strtolower($info['label']), |
... | ... | |
290 | 304 |
), |
291 | 305 |
); |
292 | 306 |
} |
307 |
if ($state->unpublished) { |
|
308 |
$messages[] = array( |
|
309 |
'message' => format_plural( |
|
310 |
$state->unpublished, |
|
311 |
'Unpublished @number @entity.', |
|
312 |
'Unpublished @number @entities.', |
|
313 |
array('@number' => $state->unpublished) + $tokens |
|
314 |
), |
|
315 |
); |
|
316 |
} |
|
317 |
if ($state->blocked) { |
|
318 |
$messages[] = array( |
|
319 |
'message' => format_plural( |
|
320 |
$state->blocked, |
|
321 |
'Blocked @number @entity.', |
|
322 |
'Blocked @number @entities.', |
|
323 |
array('@number' => $state->blocked) + $tokens |
|
324 |
), |
|
325 |
); |
|
326 |
} |
|
327 |
if ($state->deleted) { |
|
328 |
$messages[] = array( |
|
329 |
'message' => format_plural( |
|
330 |
$state->deleted, |
|
331 |
'Removed @number @entity.', |
|
332 |
'Removed @number @entities.', |
|
333 |
array('@number' => $state->deleted) + $tokens |
|
334 |
), |
|
335 |
); |
|
336 |
} |
|
293 | 337 |
if ($state->failed) { |
294 | 338 |
$messages[] = array( |
295 | 339 |
'message' => format_plural( |
... | ... | |
312 | 356 |
} |
313 | 357 |
} |
314 | 358 |
|
359 |
/** |
|
360 |
* Initialize the array of entities to remove with all existing entities |
|
361 |
* previously imported from the source. |
|
362 |
* |
|
363 |
* @param FeedsSource $source |
|
364 |
* Source information about this import. |
|
365 |
* @param FeedsState $state |
|
366 |
* The FeedsState object for the given stage. |
|
367 |
*/ |
|
368 |
protected function initEntitiesToBeRemoved(FeedsSource $source, FeedsState $state) { |
|
369 |
$state->removeList = array(); |
|
370 |
// We fill it only if needed. |
|
371 |
if (!isset($this->config['update_non_existent']) || $this->config['update_non_existent'] == FEEDS_SKIP_NON_EXISTENT) { |
|
372 |
return; |
|
373 |
} |
|
374 |
// Build base select statement. |
|
375 |
$info = $this->entityInfo(); |
|
376 |
$id_key = db_escape_field($info['entity keys']['id']); |
|
377 |
$select = db_select($info['base table'], 'e'); |
|
378 |
$select->addField('e', $info['entity keys']['id'], 'entity_id'); |
|
379 |
$select->join( |
|
380 |
'feeds_item', |
|
381 |
'fi', |
|
382 |
'e.' . $id_key . ' = fi.entity_id AND fi.entity_type = :entity_type', array( |
|
383 |
':entity_type' => $this->entityType(), |
|
384 |
)); |
|
385 |
|
|
386 |
$select->condition('fi.id', $this->id); |
|
387 |
$select->condition('fi.feed_nid', $source->feed_nid); |
|
388 |
// No need to remove item again if same method of removal was already used. |
|
389 |
$select->condition('fi.hash', $this->config['update_non_existent'], '<>'); |
|
390 |
$entities = $select->execute(); |
|
391 |
// If not found on process, existing entities will be deleted. |
|
392 |
foreach ($entities as $entity) { |
|
393 |
// Obviously, items which are still included in the source feed will be |
|
394 |
// removed from this array when processed. |
|
395 |
$state->removeList[$entity->entity_id] = $entity->entity_id; |
|
396 |
} |
|
397 |
} |
|
398 |
|
|
399 |
/** |
|
400 |
* Deletes entities which were not found during processing. |
|
401 |
* |
|
402 |
* @todo batch delete? |
|
403 |
* |
|
404 |
* @param FeedsState $state |
|
405 |
* The FeedsState object for the given stage. |
|
406 |
*/ |
|
407 |
protected function clean(FeedsState $state) { |
|
408 |
// We clean only if needed. |
|
409 |
if (!isset($this->config['update_non_existent']) || $this->config['update_non_existent'] == FEEDS_SKIP_NON_EXISTENT) { |
|
410 |
return; |
|
411 |
} |
|
412 |
|
|
413 |
$total = count($state->removeList); |
|
414 |
if ($total) { |
|
415 |
$this->entityDeleteMultiple($state->removeList); |
|
416 |
$state->deleted += $total; |
|
417 |
} |
|
418 |
} |
|
419 |
|
|
315 | 420 |
/** |
316 | 421 |
* Remove all stored results or stored results up to a certain time for a |
317 | 422 |
* source. |
... | ... | |
400 | 505 |
} |
401 | 506 |
|
402 | 507 |
/** |
403 |
* Delete feed items younger than now - $time. Do not invoke expire on a |
|
404 |
* processor directly, but use FeedsImporter::expire() instead. |
|
508 |
* Deletes feed items older than REQUEST_TIME - $time. |
|
405 | 509 |
* |
406 |
* @see FeedsImporter::expire(). |
|
407 |
* @see FeedsDataProcessor::expire(). |
|
510 |
* Do not invoke expire on a processor directly, but use |
|
511 |
* FeedsSource::expire() instead. |
|
512 |
* |
|
513 |
* @param FeedsSource $source |
|
514 |
* The source to expire entities for. |
|
408 | 515 |
* |
409 | 516 |
* @param $time |
410 |
* If implemented, all items produced by this configuration that are older
|
|
411 |
* than REQUEST_TIME - $time should be deleted.
|
|
412 |
* If $time === NULL processor should use internal configuration.
|
|
517 |
* (optional) All items produced by this configuration that are older than
|
|
518 |
* REQUEST_TIME - $time should be deleted. If NULL, processor should use
|
|
519 |
* internal configuration. Defaults to NULL.
|
|
413 | 520 |
* |
414 |
* @return |
|
521 |
* @return float
|
|
415 | 522 |
* FEEDS_BATCH_COMPLETE if all items have been processed, a float between 0 |
416 | 523 |
* and 0.99* indicating progress otherwise. |
524 |
* |
|
525 |
* @see FeedsSource::expire() |
|
417 | 526 |
*/ |
418 |
public function expire($time = NULL) { |
|
419 |
return FEEDS_BATCH_COMPLETE; |
|
527 |
public function expire(FeedsSource $source, $time = NULL) { |
|
528 |
$state = $source->state(FEEDS_PROCESS_EXPIRE); |
|
529 |
|
|
530 |
if ($time === NULL) { |
|
531 |
$time = $this->expiryTime(); |
|
532 |
} |
|
533 |
if ($time == FEEDS_EXPIRE_NEVER) { |
|
534 |
return; |
|
535 |
} |
|
536 |
|
|
537 |
$select = $this->expiryQuery($source, $time); |
|
538 |
|
|
539 |
// If there is no total, query it. |
|
540 |
if (!$state->total) { |
|
541 |
$state->total = $select->countQuery()->execute()->fetchField(); |
|
542 |
} |
|
543 |
|
|
544 |
// Delete a batch of entities. |
|
545 |
$entity_ids = $select->range(0, $this->getLimit())->execute()->fetchCol(); |
|
546 |
if ($entity_ids) { |
|
547 |
$this->entityDeleteMultiple($entity_ids); |
|
548 |
$state->deleted += count($entity_ids); |
|
549 |
$state->progress($state->total, $state->deleted); |
|
550 |
} |
|
551 |
else { |
|
552 |
$state->progress($state->total, $state->total); |
|
553 |
} |
|
554 |
} |
|
555 |
|
|
556 |
/** |
|
557 |
* Returns a database query used to select entities to expire. |
|
558 |
* |
|
559 |
* Processor classes should override this method to set the age portion of the |
|
560 |
* query. |
|
561 |
* |
|
562 |
* @param FeedsSource $source |
|
563 |
* The feed source. |
|
564 |
* @param int $time |
|
565 |
* Delete entities older than this. |
|
566 |
* |
|
567 |
* @return SelectQuery |
|
568 |
* A select query to execute. |
|
569 |
* |
|
570 |
* @see FeedsNodeProcessor::expiryQuery() |
|
571 |
*/ |
|
572 |
protected function expiryQuery(FeedsSource $source, $time) { |
|
573 |
// Build base select statement. |
|
574 |
$info = $this->entityInfo(); |
|
575 |
$id_key = db_escape_field($info['entity keys']['id']); |
|
576 |
|
|
577 |
$select = db_select($info['base table'], 'e'); |
|
578 |
$select->addField('e', $info['entity keys']['id'], 'entity_id'); |
|
579 |
$select->join( |
|
580 |
'feeds_item', |
|
581 |
'fi', |
|
582 |
"e.$id_key = fi.entity_id AND fi.entity_type = :entity_type", array( |
|
583 |
':entity_type' => $this->entityType(), |
|
584 |
)); |
|
585 |
$select->condition('fi.id', $this->id); |
|
586 |
$select->condition('fi.feed_nid', $source->feed_nid); |
|
587 |
|
|
588 |
return $select; |
|
420 | 589 |
} |
421 | 590 |
|
422 | 591 |
/** |
... | ... | |
426 | 595 |
return db_query("SELECT count(*) FROM {feeds_item} WHERE id = :id AND entity_type = :entity_type AND feed_nid = :feed_nid", array(':id' => $this->id, ':entity_type' => $this->entityType(), ':feed_nid' => $source->feed_nid))->fetchField(); |
427 | 596 |
} |
428 | 597 |
|
598 |
/** |
|
599 |
* Returns a statically cached version of the target mappings. |
|
600 |
* |
|
601 |
* @return array |
|
602 |
* The targets for this importer. |
|
603 |
*/ |
|
604 |
protected function getCachedTargets() { |
|
605 |
$targets = &drupal_static('FeedsProcessor::getCachedTargets', array()); |
|
606 |
|
|
607 |
if (!isset($targets[$this->id])) { |
|
608 |
$targets[$this->id] = $this->getMappingTargets(); |
|
609 |
} |
|
610 |
|
|
611 |
return $targets[$this->id]; |
|
612 |
} |
|
613 |
|
|
614 |
/** |
|
615 |
* Returns a statically cached version of the source mappings. |
|
616 |
* |
|
617 |
* @return array |
|
618 |
* The sources for this importer. |
|
619 |
*/ |
|
620 |
protected function getCachedSources() { |
|
621 |
$sources = &drupal_static('FeedsProcessor::getCachedSources', array()); |
|
622 |
|
|
623 |
if (!isset($sources[$this->id])) { |
|
624 |
|
|
625 |
$sources[$this->id] = feeds_importer($this->id)->parser->getMappingSources(); |
|
626 |
|
|
627 |
if (is_array($sources[$this->id])) { |
|
628 |
foreach ($sources[$this->id] as $source_key => $source) { |
|
629 |
if (empty($source['callback']) || !is_callable($source['callback'])) { |
|
630 |
unset($sources[$this->id][$source_key]['callback']); |
|
631 |
} |
|
632 |
} |
|
633 |
} |
|
634 |
} |
|
635 |
|
|
636 |
return $sources[$this->id]; |
|
637 |
} |
|
638 |
|
|
429 | 639 |
/** |
430 | 640 |
* Execute mapping on an item. |
431 | 641 |
* |
... | ... | |
444 | 654 |
* @ingroup mappingapi |
445 | 655 |
* |
446 | 656 |
* @see hook_feeds_parser_sources_alter() |
447 |
* @see hook_feeds_data_processor_targets_alter() |
|
448 |
* @see hook_feeds_node_processor_targets_alter() |
|
449 |
* @see hook_feeds_term_processor_targets_alter() |
|
450 |
* @see hook_feeds_user_processor_targets_alter() |
|
657 |
* @see hook_feeds_processor_targets() |
|
658 |
* @see hook_feeds_processor_targets_alter() |
|
451 | 659 |
*/ |
452 | 660 |
protected function map(FeedsSource $source, FeedsParserResult $result, $target_item = NULL) { |
661 |
$targets = $this->getCachedTargets(); |
|
453 | 662 |
|
454 |
// Static cache $targets as getMappingTargets() may be an expensive method. |
|
455 |
static $sources; |
|
456 |
if (!isset($sources[$this->id])) { |
|
457 |
$sources[$this->id] = feeds_importer($this->id)->parser->getMappingSources(); |
|
458 |
} |
|
459 |
static $targets; |
|
460 |
if (!isset($targets[$this->id])) { |
|
461 |
$targets[$this->id] = $this->getMappingTargets(); |
|
462 |
} |
|
463 |
$parser = feeds_importer($this->id)->parser; |
|
464 | 663 |
if (empty($target_item)) { |
465 | 664 |
$target_item = array(); |
466 | 665 |
} |
... | ... | |
469 | 668 |
// need to clear target elements of each item before mapping in case we are |
470 | 669 |
// mapping on a prepopulated item such as an existing node. |
471 | 670 |
foreach ($this->config['mappings'] as $mapping) { |
472 |
if (isset($targets[$this->id][$mapping['target']]['real_target'])) {
|
|
473 |
unset($target_item->{$targets[$this->id][$mapping['target']]['real_target']});
|
|
671 |
if (isset($targets[$mapping['target']]['real_target'])) { |
|
672 |
$target_item->{$targets[$mapping['target']]['real_target']} = NULL;
|
|
474 | 673 |
} |
475 |
elseif (isset($target_item->{$mapping['target']})) {
|
|
476 |
unset($target_item->{$mapping['target']});
|
|
674 |
else { |
|
675 |
$target_item->{$mapping['target']} = NULL;
|
|
477 | 676 |
} |
478 | 677 |
} |
479 | 678 |
|
480 |
/* |
|
481 |
This is where the actual mapping happens: For every mapping we envoke |
|
482 |
the parser's getSourceElement() method to retrieve the value of the source |
|
483 |
element and pass it to the processor's setTargetElement() to stick it |
|
484 |
on the right place of the target item. |
|
485 |
|
|
486 |
If the mapping specifies a callback method, use the callback instead of |
|
487 |
setTargetElement(). |
|
488 |
*/ |
|
489 |
self::loadMappers(); |
|
679 |
// This is where the actual mapping happens: For every mapping we invoke |
|
680 |
// the parser's getSourceElement() method to retrieve the value of the |
|
681 |
// source element and pass it to the processor's setTargetElement() to stick |
|
682 |
// it on the right place of the target item. |
|
490 | 683 |
foreach ($this->config['mappings'] as $mapping) { |
491 |
// Retrieve source element's value from parser. |
|
492 |
if (isset($sources[$this->id][$mapping['source']]) && |
|
493 |
is_array($sources[$this->id][$mapping['source']]) && |
|
494 |
isset($sources[$this->id][$mapping['source']]['callback']) && |
|
495 |
function_exists($sources[$this->id][$mapping['source']]['callback'])) { |
|
496 |
$callback = $sources[$this->id][$mapping['source']]['callback']; |
|
497 |
$value = $callback($source, $result, $mapping['source']); |
|
498 |
} |
|
499 |
else { |
|
500 |
$value = $parser->getSourceElement($source, $result, $mapping['source']); |
|
501 |
} |
|
684 |
$value = $this->getSourceValue($source, $result, $mapping['source']); |
|
685 |
|
|
686 |
$this->mapToTarget($source, $mapping['target'], $target_item, $value, $mapping); |
|
687 |
} |
|
688 |
|
|
689 |
return $target_item; |
|
690 |
} |
|
502 | 691 |
|
503 |
// Map the source element's value to the target. |
|
504 |
if (isset($targets[$this->id][$mapping['target']]) && |
|
505 |
is_array($targets[$this->id][$mapping['target']]) && |
|
506 |
isset($targets[$this->id][$mapping['target']]['callback']) && |
|
507 |
function_exists($targets[$this->id][$mapping['target']]['callback'])) { |
|
508 |
$callback = $targets[$this->id][$mapping['target']]['callback']; |
|
509 |
$callback($source, $target_item, $mapping['target'], $value, $mapping); |
|
692 |
/** |
|
693 |
* Returns the values from the parser, or callback. |
|
694 |
* |
|
695 |
* @param FeedsSource $source |
|
696 |
* The feed source. |
|
697 |
* @param FeedsParserResult $result |
|
698 |
* The parser result. |
|
699 |
* @param string $source_key |
|
700 |
* The current key being processed. |
|
701 |
* |
|
702 |
* @return mixed |
|
703 |
* A value, or a list of values. |
|
704 |
*/ |
|
705 |
protected function getSourceValue(FeedsSource $source, FeedsParserResult $result, $source_key) { |
|
706 |
$sources = $this->getCachedSources(); |
|
707 |
|
|
708 |
if (isset($sources[$source_key]['callback'])) { |
|
709 |
return call_user_func($sources[$source_key]['callback'], $source, $result, $source_key); |
|
710 |
} |
|
711 |
|
|
712 |
return feeds_importer($this->id)->parser->getSourceElement($source, $result, $source_key); |
|
713 |
} |
|
714 |
|
|
715 |
/** |
|
716 |
* Maps values onto the target item. |
|
717 |
* |
|
718 |
* @param FeedsSource $source |
|
719 |
* The feed source. |
|
720 |
* @param mixed &$target_item |
|
721 |
* The target item to apply values into. |
|
722 |
* @param mixed $value |
|
723 |
* A value, or a list of values. |
|
724 |
* @param array $mapping |
|
725 |
* The mapping configuration. |
|
726 |
*/ |
|
727 |
protected function mapToTarget(FeedsSource $source, $target, &$target_item, $value, array $mapping) { |
|
728 |
$targets = $this->getCachedTargets(); |
|
729 |
|
|
730 |
if (isset($targets[$target]['preprocess_callbacks'])) { |
|
731 |
foreach ($targets[$target]['preprocess_callbacks'] as $callback) { |
|
732 |
call_user_func_array($callback, array($source, $target_item, $target, &$mapping)); |
|
510 | 733 |
} |
511 |
else { |
|
512 |
$this->setTargetElement($source, $target_item, $mapping['target'], $value, $mapping); |
|
734 |
} |
|
735 |
|
|
736 |
// Map the source element's value to the target. |
|
737 |
// If the mapping specifies a callback method, use the callback instead of |
|
738 |
// setTargetElement(). |
|
739 |
if (isset($targets[$target]['callback'])) { |
|
740 |
|
|
741 |
// All target callbacks expect an array. |
|
742 |
if (!is_array($value)) { |
|
743 |
$value = array($value); |
|
513 | 744 |
} |
745 |
|
|
746 |
call_user_func($targets[$target]['callback'], $source, $target_item, $target, $value, $mapping); |
|
747 |
} |
|
748 |
|
|
749 |
else { |
|
750 |
$this->setTargetElement($source, $target_item, $target, $value, $mapping); |
|
514 | 751 |
} |
515 |
return $target_item; |
|
516 | 752 |
} |
517 | 753 |
|
518 | 754 |
/** |
... | ... | |
535 | 771 |
return array( |
536 | 772 |
'mappings' => array(), |
537 | 773 |
'update_existing' => FEEDS_SKIP_EXISTING, |
774 |
'update_non_existent' => FEEDS_SKIP_NON_EXISTENT, |
|
538 | 775 |
'input_format' => NULL, |
539 | 776 |
'skip_hash_check' => FALSE, |
540 | 777 |
'bundle' => $bundle, |
... | ... | |
592 | 829 |
$form['input_format'] = array( |
593 | 830 |
'#type' => 'select', |
594 | 831 |
'#title' => t('Text format'), |
595 |
'#description' => t('Select the input format for the body field of the nodes to be created.'),
|
|
832 |
'#description' => t('Select the default input format for the text fields of the nodes to be created.'),
|
|
596 | 833 |
'#options' => $format_options, |
597 | 834 |
'#default_value' => isset($this->config['input_format']) ? $this->config['input_format'] : 'plain_text', |
598 | 835 |
'#required' => TRUE, |
599 | 836 |
); |
600 | 837 |
|
838 |
$form['update_non_existent'] = array( |
|
839 |
'#type' => 'radios', |
|
840 |
'#title' => t('Action to take when previously imported @entities are missing in the feed', $tokens), |
|
841 |
'#description' => t('Select how @entities previously imported and now missing in the feed should be updated.', $tokens), |
|
842 |
'#options' => array( |
|
843 |
FEEDS_SKIP_NON_EXISTENT => t('Skip non-existent @entities', $tokens), |
|
844 |
FEEDS_DELETE_NON_EXISTENT => t('Delete non-existent @entities', $tokens), |
|
845 |
), |
|
846 |
'#default_value' => $this->config['update_non_existent'], |
|
847 |
); |
|
848 |
|
|
601 | 849 |
return $form; |
602 | 850 |
} |
603 | 851 |
|
... | ... | |
643 | 891 |
); |
644 | 892 |
} |
645 | 893 |
|
894 |
/** |
|
895 |
* Allows other modules to expose targets. |
|
896 |
* |
|
897 |
* @param array &$targets |
|
898 |
* The existing target array. |
|
899 |
*/ |
|
900 |
protected function getHookTargets(array &$targets) { |
|
901 |
self::loadMappers(); |
|
902 |
|
|
903 |
$entity_type = $this->entityType(); |
|
904 |
$bundle = $this->bundle(); |
|
905 |
$targets += module_invoke_all('feeds_processor_targets', $entity_type, $bundle); |
|
906 |
|
|
907 |
drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle); |
|
908 |
} |
|
909 |
|
|
646 | 910 |
/** |
647 | 911 |
* Set a concrete target element. Invoked from FeedsProcessor::map(). |
648 | 912 |
* |
... | ... | |
654 | 918 |
case 'guid': |
655 | 919 |
$target_item->feeds_item->$target_element = $value; |
656 | 920 |
break; |
921 |
|
|
657 | 922 |
default: |
658 | 923 |
$target_item->$target_element = $value; |
659 | 924 |
break; |
... | ... | |
667 | 932 |
* |
668 | 933 |
* @param FeedsSource $source |
669 | 934 |
* The source information about this import. |
670 |
* @param $result |
|
935 |
* @param FeedsParserResult $result
|
|
671 | 936 |
* A FeedsParserResult object. |
672 | 937 |
* |
673 |
* @return |
|
938 |
* @return int
|
|
674 | 939 |
* The serial id of an entity if found, 0 otherwise. |
675 | 940 |
*/ |
676 | 941 |
protected function existingEntityId(FeedsSource $source, FeedsParserResult $result) { |
677 |
$query = db_select('feeds_item') |
|
678 |
->fields('feeds_item', array('entity_id')) |
|
679 |
->condition('feed_nid', $source->feed_nid) |
|
680 |
->condition('entity_type', $this->entityType()) |
|
681 |
->condition('id', $source->id); |
|
682 |
|
|
683 |
// Iterate through all unique targets and test whether they do already |
|
684 |
// exist in the database. |
|
942 |
$targets = $this->getCachedTargets(); |
|
943 |
|
|
944 |
$entity_id = 0; |
|
945 |
|
|
946 |
// Iterate through all unique targets and test whether they already exist in |
|
947 |
// the database. |
|
685 | 948 |
foreach ($this->uniqueTargets($source, $result) as $target => $value) { |
686 |
switch ($target) { |
|
687 |
case 'url': |
|
688 |
$entity_id = $query->condition('url', $value)->execute()->fetchField(); |
|
689 |
break; |
|
690 |
case 'guid': |
|
691 |
$entity_id = $query->condition('guid', $value)->execute()->fetchField(); |
|
692 |
break; |
|
949 |
if ($target === 'guid' || $target === 'url') { |
|
950 |
$entity_id = db_select('feeds_item') |
|
951 |
->fields('feeds_item', array('entity_id')) |
|
952 |
->condition('feed_nid', $source->feed_nid) |
|
953 |
->condition('entity_type', $this->entityType()) |
|
954 |
->condition('id', $source->id) |
|
955 |
->condition($target, $value) |
|
956 |
->execute() |
|
957 |
->fetchField(); |
|
693 | 958 |
} |
694 |
if (isset($entity_id)) { |
|
695 |
// Return with the content id found. |
|
959 |
|
|
960 |
if (!$entity_id && !empty($targets[$target]['unique_callbacks'])) { |
|
961 |
if (!is_array($value)) { |
|
962 |
$value = array($value); |
|
963 |
} |
|
964 |
|
|
965 |
foreach ($targets[$target]['unique_callbacks'] as $callback) { |
|
966 |
if ($entity_id = call_user_func($callback, $source, $this->entityType(), $this->bundle(), $target, $value)) { |
|
967 |
// Stop at the first unique ID returned by a callback. |
|
968 |
break; |
|
969 |
} |
|
970 |
} |
|
971 |
} |
|
972 |
|
|
973 |
// Return with the content id found. |
|
974 |
if ($entity_id) { |
|
696 | 975 |
return $entity_id; |
697 | 976 |
} |
698 | 977 |
} |
699 |
return 0; |
|
978 |
|
|
979 |
return $entity_id; |
|
700 | 980 |
} |
701 | 981 |
|
702 | 982 |
|
... | ... | |
796 | 1076 |
} |
797 | 1077 |
|
798 | 1078 |
/** |
799 |
* Creates a log message for when an exception occured during import. |
|
1079 |
* DEPRECATED: Creates a log message for exceptions during import. |
|
1080 |
* |
|
1081 |
* Don't use this method as it concatenates user variables into the log |
|
1082 |
* message, which will pollute the locales_source table when the log message |
|
1083 |
* is translated. Use ::createLogEntry instead. |
|
800 | 1084 |
* |
801 | 1085 |
* @param Exception $e |
802 | 1086 |
* The exception that was throwned during processing the item. |
... | ... | |
807 | 1091 |
* |
808 | 1092 |
* @return string |
809 | 1093 |
* The message to log. |
1094 |
* |
|
1095 |
* @deprecated |
|
1096 |
* Use ::createLogEntry instead. |
|
810 | 1097 |
*/ |
811 | 1098 |
protected function createLogMessage(Exception $e, $entity, $item) { |
812 |
include_once DRUPAL_ROOT . '/includes/utility.inc'; |
|
813 | 1099 |
$message = $e->getMessage(); |
814 | 1100 |
$message .= '<h3>Original item</h3>'; |
815 |
$message .= '<pre>' . check_plain(drupal_var_export($item)) . '</pre>'; |
|
1101 |
// $this->exportObjectVars() already runs check_plain() for us, so we can |
|
1102 |
// concatenate here as is. |
|
1103 |
$message .= '<pre>' . $this->exportObjectVars($item) . '</pre>'; |
|
816 | 1104 |
$message .= '<h3>Entity</h3>'; |
817 |
$message .= '<pre>' . check_plain(drupal_var_export($entity)) . '</pre>'; |
|
1105 |
$message .= '<pre>' . $this->exportObjectVars($entity) . '</pre>'; |
|
1106 |
|
|
818 | 1107 |
return $message; |
819 | 1108 |
} |
820 | 1109 |
|
1110 |
/** |
|
1111 |
* Creates a log entry for when an exception occured during import. |
|
1112 |
* |
|
1113 |
* @param Exception $e |
|
1114 |
* The exception that was throwned during processing the item. |
|
1115 |
* @param object $entity |
|
1116 |
* The entity object. |
|
1117 |
* @param array $item |
|
1118 |
* The parser result for this entity. |
|
1119 |
* |
|
1120 |
* @return array |
|
1121 |
* The message and arguments to log. |
|
1122 |
*/ |
|
1123 |
protected function createLogEntry(Exception $e, $entity, $item) { |
|
1124 |
$message = '@exception'; |
|
1125 |
$message .= '<h3>Original item</h3>'; |
|
1126 |
$message .= '<pre>!item</pre>'; |
|
1127 |
$message .= '<h3>Entity</h3>'; |
|
1128 |
$message .= '<pre>!entity</pre>'; |
|
1129 |
$arguments = array( |
|
1130 |
'@exception' => $e->getMessage(), |
|
1131 |
// $this->exportObjectVars() already runs check_plain() for us, so we can |
|
1132 |
// use the "!" placeholder. |
|
1133 |
'!item' => $this->exportObjectVars($item), |
|
1134 |
'!entity' => $this->exportObjectVars($entity), |
|
1135 |
); |
|
1136 |
|
|
1137 |
return array($message, $arguments); |
|
1138 |
} |
|
1139 |
|
|
1140 |
/** |
|
1141 |
* Returns a string representation of an object or array for log messages. |
|
1142 |
* |
|
1143 |
* @param object|array $object |
|
1144 |
* The object to convert. |
|
1145 |
* |
|
1146 |
* @return string |
|
1147 |
* The sanitized string representation of the object. |
|
1148 |
*/ |
|
1149 |
protected function exportObjectVars($object) { |
|
1150 |
include_once DRUPAL_ROOT . '/includes/utility.inc'; |
|
1151 |
|
|
1152 |
$out = is_array($object) ? $object : get_object_vars($object); |
|
1153 |
$out = array_filter($out, 'is_scalar'); |
|
1154 |
|
|
1155 |
foreach ($out as $key => $value) { |
|
1156 |
if (is_string($value)) { |
|
1157 |
$out[$key] = truncate_utf8($value, 100, FALSE, TRUE); |
|
1158 |
} |
|
1159 |
} |
|
1160 |
|
|
1161 |
if (is_array($object)) { |
|
1162 |
return check_plain(drupal_var_export($out)); |
|
1163 |
} |
|
1164 |
|
|
1165 |
return check_plain(drupal_var_export((object) $out)); |
|
1166 |
} |
|
1167 |
|
|
1168 |
/** |
|
1169 |
* Overrides FeedsPlugin::dependencies(). |
|
1170 |
*/ |
|
1171 |
public function dependencies() { |
|
1172 |
$dependencies = parent::dependencies(); |
|
1173 |
|
|
1174 |
// Find out which module defined the entity type. |
|
1175 |
$info = $this->entityInfo(); |
|
1176 |
if (isset($info['module'])) { |
|
1177 |
$dependencies[$info['module']] = $info['module']; |
|
1178 |
} |
|
1179 |
|
|
1180 |
return $dependencies; |
|
1181 |
} |
|
1182 |
|
|
821 | 1183 |
} |
822 | 1184 |
|
823 | 1185 |
class FeedsProcessorBundleNotDefined extends Exception {} |
Formats disponibles : Unified diff
Update feeds 7.x-2.0-alpha9 -> 7.x-2.0-beta1
Install lib simplepie 1.3.1