From 93d0bb8286bf7c64d42117b728a60d47d1baca9f Mon Sep 17 00:00:00 2001
From: Renaud Lemaire <rlemaire@cblue.be>
Date: Fri, 22 Jan 2021 08:56:06 +0100
Subject: [PATCH] #312543 core edit to fix linkedin oauth2 :ambulance: (upgrade
 needed)

---
 lib/classes/oauth2/client.php | 39 ++++++++++++++++++++++++++++++++---
 lib/db/install.xml            |  2 +-
 lib/db/upgrade.php            | 11 ++++++++++
 version.php                   |  2 +-
 4 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/lib/classes/oauth2/client.php b/lib/classes/oauth2/client.php
index 553e8fe312..1b6f3623b7 100644
--- a/lib/classes/oauth2/client.php
+++ b/lib/classes/oauth2/client.php
@@ -293,7 +293,23 @@ class client extends \oauth2_client {
      * @return array|false Moodle user fields for the logged in user (or false if request failed)
      */
     public function get_userinfo() {
+        $emailinfo = null;
+
+        $email_endpoint_url = $this->get_issuer()->get_endpoint_url('email');
+        if ($email_endpoint_url) {
+            $response = $this->get($email_endpoint_url);
+            if (!$response) {
+                return false;
+            }
+            try {
+                $emailinfo = json_decode($response);
+            } catch (\Exception $e) {
+                return false;
+            }
+        }
+
         $url = $this->get_issuer()->get_endpoint_url('userinfo');
+        $isLinkedIn = stripos($url,'linkedin');
         $response = $this->get($url);
         if (!$response) {
             return false;
@@ -301,6 +317,9 @@ class client extends \oauth2_client {
         $userinfo = new stdClass();
         try {
             $userinfo = json_decode($response);
+            if (!is_null($emailinfo)) {
+                $userinfo = (object) array_merge((array) $emailinfo, (array) $userinfo);
+            }
         } catch (\Exception $e) {
             return false;
         }
@@ -312,10 +331,24 @@ class client extends \oauth2_client {
             // We support nested objects via a-b-c syntax.
             $getfunc = function($obj, $prop) use (&$getfunc) {
                 $proplist = explode('-', $prop, 2);
-                if (empty($proplist[0]) || empty($obj->{$proplist[0]})) {
-                    return false;
+
+                $matches = [];
+                if (preg_match('/^(.*)\[([0-9]*)\]$/', $proplist[0], $matches)) {
+                    $array_property = $matches[1];
+                    $array_index = $matches[2];
+                    $obj = $obj->$array_property[$array_index];
+                    if (count($proplist) > 1) {
+                        return $getfunc($obj, $proplist[1]);
+                    }
+                    return $obj;
                 }
-                $obj = $obj->{$proplist[0]};
+                else {
+                    if (empty($proplist[0]) || empty($obj->{$proplist[0]})) {
+                        return false;
+                    }
+                    $obj = $obj->{$proplist[0]};
+                }
+
 
                 if (count($proplist) > 1) {
                     return $getfunc($obj, $proplist[1]);
diff --git a/lib/db/install.xml b/lib/db/install.xml
index a12fa687fb..5258d94f09 100644
--- a/lib/db/install.xml
+++ b/lib/db/install.xml
@@ -3837,7 +3837,7 @@
         <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The time this record was created."/>
         <FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The user who modified this record."/>
         <FIELD NAME="issuerid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The oauth issuer."/>
-        <FIELD NAME="externalfield" TYPE="char" LENGTH="64" NOTNULL="true" SEQUENCE="false" COMMENT="The fieldname returned by the userinfo endpoint."/>
+        <FIELD NAME="externalfield" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The fieldname returned by the userinfo endpoint."/>
         <FIELD NAME="internalfield" TYPE="char" LENGTH="64" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the Moodle field this user field maps to."/>
       </FIELDS>
       <KEYS>
diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php
index 7677467279..7a7b04d82d 100644
--- a/lib/db/upgrade.php
+++ b/lib/db/upgrade.php
@@ -2588,6 +2588,17 @@ function xmldb_main_upgrade($oldversion) {
         // Main savepoint reached.
         upgrade_main_savepoint(true, 2020061501.11);
     }
+    if ($oldversion < 2020061502.0201) {
+        // Changing type of field externalfield on table oauth2_user_field_mapping to char.
+        $table = new xmldb_table('oauth2_user_field_mapping');
+        $field = new xmldb_field('externalfield', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'issuerid');
 
+        // Launch change of type for field confirmtoken.
+        $dbman->change_field_type($table, $field);
+
+        // Oauth2 savepoint reached.        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2020061502.0201);
+
+    }
     return true;
 }
diff --git a/version.php b/version.php
index bdc5c92a65..52db1e609c 100644
--- a/version.php
+++ b/version.php
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2020061502.02;              // 20200615      = branching date YYYYMMDD - do not modify!
+$version  = 2020061502.0201;              // 20200615      = branching date YYYYMMDD - do not modify!
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.
 $release  = '3.9.2+ (Build: 20200924)'; // Human-friendly version name
-- 
2.25.1

