Projet

Général

Profil

Révision 41cc1b08

Ajouté par Assos Assos il y a presque 9 ans

Update feeds 7.x-2.0-alpha9 -> 7.x-2.0-beta1

Install lib simplepie 1.3.1

Voir les différences:

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