From 3c6305c121f26ca103192fd941103dcd5736c050 Mon Sep 17 00:00:00 2001
From: Jeremiah VALERIE <jeremiah@over-blog.com>
Date: Tue, 19 Apr 2016 21:16:09 +0200
Subject: [PATCH] * Optimized implementation to interfaces using lazy loader *
 Union types now accepting callback

---
 src/Schema.php                        |  2 ++
 src/Type/Definition/InterfaceType.php | 25 +++++++++++++++++++++----
 src/Type/Definition/Type.php          |  2 +-
 src/Type/Definition/UnionType.php     |  2 +-
 src/Types.php                         |  9 ---------
 5 files changed, 25 insertions(+), 15 deletions(-)
 delete mode 100644 src/Types.php

diff --git a/src/Schema.php b/src/Schema.php
index a3e9246..134d9f8 100644
--- a/src/Schema.php
+++ b/src/Schema.php
@@ -33,6 +33,8 @@ class Schema
         $this->mutationSchema = $mutationSchema;
         $this->subscriptionSchema = $subscriptionSchema;
 
+        InterfaceType::loadImplementationToInterfaces();
+
         // Build type map now to detect any errors within this schema.
         $map = [];
         foreach ([$this->getQueryType(), $this->getMutationType(), Introspection::_schema()] as $type) {
diff --git a/src/Type/Definition/InterfaceType.php b/src/Type/Definition/InterfaceType.php
index 4ef8b54..8ba859b 100644
--- a/src/Type/Definition/InterfaceType.php
+++ b/src/Type/Definition/InterfaceType.php
@@ -18,6 +18,11 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
      */
     private $_implementations = [];
 
+    /**
+     * @var \Closure[]
+     */
+    private static $_lazyLoadImplementations = [];
+
     /**
      * @var {[typeName: string]: boolean}
      */
@@ -34,18 +39,30 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
     public $config;
 
     /**
-     * Update the interfaces to know about this implementation.
+     * Queue the update of the interfaces to know about this implementation.
      * This is an rare and unfortunate use of mutation in the type definition
      * implementations, but avoids an expensive "getPossibleTypes"
      * implementation for Interface types.
      *
      * @param ObjectType $impl
-     * @param InterfaceType[] $interfaces
      */
     public static function addImplementationToInterfaces(ObjectType $impl)
     {
-        foreach ($impl->getInterfaces() as $interface) {
-            $interface->_implementations[] = $impl;
+        self::$_lazyLoadImplementations[] = function() use ($impl) {
+            foreach ($impl->getInterfaces() as $interface) {
+                $interface->_implementations[] = $impl;
+            }
+        };
+    }
+
+    /**
+     * Process ImplementationToInterfaces Queue
+     */
+    public static function loadImplementationToInterfaces()
+    {
+        foreach (self::$_lazyLoadImplementations as $i => &$lazyLoadImplementation) {
+            call_user_func($lazyLoadImplementation);
+            unset(self::$_lazyLoadImplementations[$i]);
         }
     }
 
diff --git a/src/Type/Definition/Type.php b/src/Type/Definition/Type.php
index 22e90d9..123bb5e 100644
--- a/src/Type/Definition/Type.php
+++ b/src/Type/Definition/Type.php
@@ -98,7 +98,7 @@ GraphQLNonNull;
     }
 
     /**
-     * @return Type
+     * @return Type[]
      */
     public static function getInternalTypes()
     {
diff --git a/src/Type/Definition/UnionType.php b/src/Type/Definition/UnionType.php
index d6151f1..cd6cfcf 100644
--- a/src/Type/Definition/UnionType.php
+++ b/src/Type/Definition/UnionType.php
@@ -29,7 +29,7 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType
     {
         Config::validate($config, [
             'name' => Config::STRING | Config::REQUIRED,
-            'types' => Config::arrayOf(Config::OBJECT_TYPE, Config::REQUIRED),
+            'types' => Config::arrayOf(Config::OBJECT_TYPE, Config::MAYBE_THUNK | Config::REQUIRED),
             'resolveType' => Config::CALLBACK, // function($value, ResolveInfo $info) => ObjectType
             'description' => Config::STRING
         ]);
diff --git a/src/Types.php b/src/Types.php
deleted file mode 100644
index da85983..0000000
--- a/src/Types.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php
-namespace GraphQL;
-
-class Types
-{
-    public static function Int()
-    {
-    }
-}