Unverified Commit fad126b7 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3047328 by quietone, iyyappan.govind, dinarcon, efpapado, vadim.hirbu,...

Issue #3047328 by quietone, iyyappan.govind, dinarcon, efpapado, vadim.hirbu, esolitos, mikelutz, heddn, alexpott, benjifisher, catch: Allow logging for non-strings values
parent ad1cbe9b
Loading
Loading
Loading
Loading
+31 −2
Original line number Diff line number Diff line
@@ -31,9 +31,38 @@ class Log extends ProcessPluginBase {
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    // Log the value.
    $migrate_executable->saveMessage($value);
    if (is_null($value) || is_bool($value)) {
      $export = var_export($value, TRUE);
    }
    elseif (is_float($value)) {
      $export = sprintf('%f', $value);
    }
    elseif (method_exists($value, 'toString')) {
      $export = print_r($value->toString(), TRUE);
    }
    elseif (method_exists($value, 'toArray')) {
      $export = print_r($value->toArray(), TRUE);
    }
    elseif (is_string($value) || is_numeric($value) || is_array($value)) {
      $export = print_r($value, TRUE);
    }
    elseif (method_exists($value, '__toString')) {
      $export = print_r((string) $value, TRUE);
    }
    else {
      $export = NULL;
    }

    $class_name = $export !== NULL && is_object($value)
      ? $class_name = get_class($value) . ":\n"
      : '';

    $message = $export === NULL
      ? "Unable to log the value for '$destination_property'"
      : "'$destination_property' value is $class_name'$export'";

    // Log the value.
    $migrate_executable->saveMessage($message);
    // Pass through the same value we received.
    return $value;
  }
+183 −10
Original line number Diff line number Diff line
@@ -2,9 +2,11 @@

namespace Drupal\Tests\migrate\Kernel\Plugin;

use Drupal\Core\Url;
use Drupal\KernelTests\KernelTestBase;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\Row;
use Drupal\node\Entity\Node;

/**
 * Tests the Log process plugin.
@@ -16,21 +18,192 @@ class LogTest extends KernelTestBase {
  /**
   * {@inheritdoc}
   */
  protected static $modules = ['migrate'];
  protected static $modules = ['node', 'migrate'];

  /**
   * The Log process plugin.
   *
   * @var \Drupal\migrate\Plugin\migrate\process\Log
   */
  protected $logPlugin;

  /**
   * Migrate executable.
   *
   * @var \Drupal\Tests\migrate\Kernel\Plugin\TestMigrateExecutable
   */
  protected $executable;

  /**
   * {@inheritdoc}
   */
  public function setUp(): void {
    parent::setUp();
    $definition = [
      'source' => [
        'plugin' => 'embedded_data',
        'data_rows' => [
          ['id' => '1'],
        ],
        'ids' => [
          'id' => ['type' => 'integer'],
        ],
      ],
      'destination' => [
        'plugin' => 'null',
      ],
    ];

    /** @var \Drupal\migrate\Plugin\migration $migration */
    $migration = \Drupal::service('plugin.manager.migration')
      ->createStubMigration($definition);
    $this->executable = new TestMigrateExecutable($migration);

    // Plugin being tested.
    $this->logPlugin = \Drupal::service('plugin.manager.migrate.process')
      ->createInstance('log');
  }

  /**
   * Test the Log plugin.
   */
  public function testLog() {
    $plugin = \Drupal::service('plugin.manager.migrate.process')
      ->createInstance('log');
    $executable = $this->prophesize(MigrateExecutableInterface::class)->reveal();
    $row = new Row();
    $log_message = "Testing the log message";
    $values = [
      'nid' => 2,
      'type' => 'page',
      'title' => 'page',
    ];

    $node = new Node($values, 'node', 'test');
    $node_array = <<< NODE
Array
(
    [nid] => Array
        (
        )

    [uuid] => Array
        (
        )

    [vid] => Array
        (
        )

    [langcode] => Array
        (
        )

    [type] => Array
        (
        )

    [revision_timestamp] => Array
        (
        )

    [revision_uid] => Array
        (
        )

    [revision_log] => Array
        (
        )

    [status] => Array
        (
        )

    [uid] => Array
        (
        )

    [title] => Array
        (
        )

    // Ensure the log is getting saved.
    $saved_message = $plugin->transform($log_message, $executable, $row, 'buffalo');
    $this->assertSame($log_message, $saved_message);
    [created] => Array
        (
        )

    [changed] => Array
        (
        )

    [promote] => Array
        (
        )

    [sticky] => Array
        (
        )

    [default_langcode] => Array
        (
        )

    [revision_default] => Array
        (
        )

    [revision_translation_affected] => Array
        (
        )

)

NODE;

    $data = [
      'node' => [
        'value' => $node,
        'expected_message' => "'foo' value is Drupal\\node\Entity\Node:\n'$node_array'",
      ],
      'url' => [
        'value' => Url::fromUri('https://en.wikipedia.org/wiki/Drupal#Community'),
        'expected_message' => "'foo' value is Drupal\Core\Url:\n'https://en.wikipedia.org/wiki/Drupal#Community'",
      ],
    ];

    $i = 1;
    foreach ($data as $datum) {
      $this->executable->sourceIdValues = ['id' => $i++];

      // Test the input value is not altered.
      $new_value = $this->logPlugin->transform($datum['value'], $this->executable, new Row(), 'foo');
      $this->assertSame($datum['value'], $new_value);

      // Test the stored message.
      $message = $this->executable->getIdMap()
        ->getMessages($this->executable->sourceIdValues)
        ->fetchAllAssoc('message');
      $actual_message = key($message);
      $this->assertSame($datum['expected_message'], $actual_message);
    }
  }

}

/**
 * MigrateExecutable test class.
 */
class TestMigrateExecutable extends MigrateExecutable {

  /**
   * The configuration values of the source.
   *
   * @var array
   */
  public $sourceIdValues;

  /**
   * Get the ID map from the current migration.
   *
   * @return \Drupal\migrate\Plugin\MigrateIdMapInterface
   *   The ID map.
   */
  public function getIdMap() {
    return parent::getIdMap();
  }

}
+111 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\migrate\Unit\process;

use Drupal\migrate\Plugin\migrate\process\Log;
use Drupal\migrate\Row;

/**
 * Tests the Log process plugin.
 *
 * @group migrate
 */
class LogTest extends MigrateProcessTestCase {

  /**
   * Tests the Log plugin.
   *
   * @dataProvider providerTestLog()
   */
  public function testLog($value, $expected_message) {
    // Test the expected log message.
    $this->migrateExecutable->expects($this->once())
      ->method('saveMessage')
      ->with($expected_message);
    $plugin = new Log([], 'log', []);

    // Test the input value is not altered.
    $new_value = $plugin->transform($value, $this->migrateExecutable, new Row(), 'foo');
    $this->assertSame($value, $new_value);
  }

  /**
   * Provides data for testLog.
   *
   * @return \string[][]
   *   An array of test data arrays.
   */
  public function providerTestLog() {
    $object = (object) [
      'a' => 'test',
      'b' => 'test2',
      'c' => 'test3',
    ];
    $xml_str = <<<XML
<?xml version='1.0'?>
<mathematician>
 <name>Ada Lovelace</name>
</mathematician>
XML;
    return [
      'int zero' => [
        'value' => 0,
        'expected_message' => "'foo' value is '0'",
      ],
      'string empty' => [
        'value' => '',
        'expected_message' => "'foo' value is ''",
      ],
      'string' => [
        'value' => 'Testing the log message',
        'expected_message' => "'foo' value is 'Testing the log message'",
      ],
      'array' => [
        'value' => ['key' => 'value'],
        'expected_message' => "'foo' value is 'Array\n(\n    [key] => value\n)\n'",
      ],
      'float' => [
        'value' => 1.123,
        'expected_message' => "'foo' value is '1.123000'",
      ],
      'NULL' => [
        'value' => NULL,
        'expected_message' => "'foo' value is 'NULL'",
      ],
      'boolean' => [
        'value' => TRUE,
        'expected_message' => "'foo' value is 'true'",
      ],
      'object_with_to_String' => [
        'value' => new ObjWithString(),
        'expected_message' => "'foo' value is Drupal\Tests\migrate\Unit\process\ObjWithString:\n'a test string'",
      ],
      'object_no_to_string' => [
        'value' => $object,
        'expected_message' => "Unable to log the value for 'foo'",
      ],
      'simple_xml' => [
        'value' => new \SimpleXMLElement($xml_str),
        'expected_message' => "'foo' value is SimpleXMLElement:\n'\n \n'",
      ],
    ];
  }

}

/**
 * Test class with a __toString() method.
 */
class ObjWithString {

  /**
   * Returns a string.
   *
   * @return string
   *   A string.
   */
  public function __toString() {
    return 'a test string';
  }

}