From 8a296baeb8ca08f81e3785f67cec41dcb3d1cd48 Mon Sep 17 00:00:00 2001
From: SylvainM <SylvainM@2441778.no-reply.drupal.org>
Date: Fri, 25 May 2018 16:26:44 -0600
Subject: [PATCH] Issue #2906264 by SylvainM, Amerie, leewbutler, heddn:
 Undefined index notifications when JSON source missing fields

---
 src/Plugin/migrate_plus/data_parser/Json.php  |   7 +-
 tests/data/missing_properties.json            |  21 ++++
 .../migrate_plus/data_parser/JsonTest.php     | 112 ++++++++++++++++++
 3 files changed, 139 insertions(+), 1 deletion(-)
 create mode 100644 tests/data/missing_properties.json
 create mode 100644 tests/src/Kernel/Plugin/migrate_plus/data_parser/JsonTest.php

diff --git a/src/Plugin/migrate_plus/data_parser/Json.php b/src/Plugin/migrate_plus/data_parser/Json.php
index df9b3fca..07f8b5c3 100755
--- a/src/Plugin/migrate_plus/data_parser/Json.php
+++ b/src/Plugin/migrate_plus/data_parser/Json.php
@@ -119,7 +119,12 @@ class Json extends DataParserPluginBase implements ContainerFactoryPluginInterfa
         $field_data = $current;
         $field_selectors = explode('/', trim($selector, '/'));
         foreach ($field_selectors as $field_selector) {
-          $field_data = $field_data[$field_selector];
+          if (is_array($field_data) && array_key_exists($field_selector, $field_data)) {
+            $field_data = $field_data[$field_selector];
+	        }
+	        else {
+            $field_data = '';
+          }
         }
         $this->currentItem[$field_name] = $field_data;
       }
diff --git a/tests/data/missing_properties.json b/tests/data/missing_properties.json
new file mode 100644
index 00000000..59b7d6a6
--- /dev/null
+++ b/tests/data/missing_properties.json
@@ -0,0 +1,21 @@
+[
+  {
+    "id": "1",
+    "title": "Title",
+    "video": {
+      "title": "Video title",
+      "url": "https://localhost/"
+    }
+  },
+  {
+    "id": "2",
+    "video": {
+      "title": "Video title",
+      "url": "https://localhost/"
+    }
+  },
+  {
+    "id": "3",
+    "title": "Title 3"
+  }
+]
diff --git a/tests/src/Kernel/Plugin/migrate_plus/data_parser/JsonTest.php b/tests/src/Kernel/Plugin/migrate_plus/data_parser/JsonTest.php
new file mode 100644
index 00000000..2fb4f245
--- /dev/null
+++ b/tests/src/Kernel/Plugin/migrate_plus/data_parser/JsonTest.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace Drupal\Tests\migrate_plus\Kernel\Plugin\migrate_plus\data_parser;
+
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Test of the data_parser Json migrate_plus plugin.
+ *
+ * @group migrate_plus
+ */
+class JsonTest extends KernelTestBase {
+
+  public static $modules = ['migrate', 'migrate_plus'];
+
+  /**
+   * Tests missing properties in json file.
+   *
+   * @param string $file
+   *   File name in tests/data/ directory of this module.
+   * @param array $ids
+   *   Array of ids to pass to the plugin.
+   * @param array $fields
+   *   Array of fields to pass to the plugin.
+   * @param array $expected
+   *   Expected array from json decoded file.
+   *
+   * @dataProvider jsonBaseDataProvider
+   *
+   * @throws \Drupal\Component\Plugin\Exception\PluginException
+   * @throws \Exception
+   */
+  public function testMissingProperties($file, array $ids, array $fields, array $expected) {
+    $path = $this->container
+      ->get('module_handler')
+      ->getModule('migrate_plus')
+      ->getPath();
+    $url = $path . '/tests/data/' . $file;
+
+    /** @var \Drupal\migrate_plus\DataParserPluginManager $plugin_manager */
+    $plugin_manager = $this->container
+      ->get('plugin.manager.migrate_plus.data_parser');
+    $conf = [
+      'plugin' => 'url',
+      'data_fetcher_plugin' => 'file',
+      'data_parser_plugin' => 'json',
+      'destination' => 'node',
+      'urls' => [$url],
+      'ids' => $ids,
+      'fields' => $fields,
+      'item_selector' => NULL,
+    ];
+    $json_parser = $plugin_manager->createInstance('json', $conf);
+
+    $data = [];
+    foreach ($json_parser as $item) {
+      $data[] = $item;
+    }
+
+    $this->assertEquals($expected, $data);
+  }
+
+  /**
+   * Provides multiple test cases for the testMissingProperty method.
+   *
+   * @return array
+   *   The test cases.
+   */
+  public function jsonBaseDataProvider() {
+    return [
+      'missing properties' => [
+        'file' => 'missing_properties.json',
+        'ids' => ['id' => ['type' => 'integer']],
+        'fields' => [
+          [
+            'name' => 'id',
+            'label' => 'Id',
+            'selector' => '/id',
+          ],
+          [
+            'name' => 'title',
+            'label' => 'Title',
+            'selector' => '/title',
+          ],
+          [
+            'name' => 'video_url',
+            'label' => 'Video url',
+            'selector' => '/video/url',
+          ],
+        ],
+        'expected' => [
+          [
+            'id' => '1',
+            'title' => 'Title',
+            'video_url' => 'https://localhost/',
+          ],
+          [
+            'id' => '2',
+            'title' => '',
+            'video_url' => 'https://localhost/',
+          ],
+          [
+            'id' => '3',
+            'title' => 'Title 3',
+            'video_url' => '',
+          ],
+        ],
+      ],
+    ];
+  }
+
+}
-- 
GitLab