WordPress Social Login - Version 3.0.4

Version Description

  • Hotfix an issue with default scopes of a certain identity providers.
Download this release

Release Info

Developer miled
Plugin Icon 128x128 WordPress Social Login
Version 3.0.4
Comparing to
See all releases

Code changes from version 3.0.3 to 3.0.4

Files changed (105) hide show
  1. hybridauth/library/CHANGELOG.md +1 -1
  2. hybridauth/library/COPYING.md +75 -75
  3. hybridauth/library/README.md +66 -66
  4. hybridauth/library/src/Adapter/AbstractAdapter.php +364 -364
  5. hybridauth/library/src/Adapter/AdapterInterface.php +149 -149
  6. hybridauth/library/src/Adapter/DataStoreTrait.php +74 -74
  7. hybridauth/library/src/Adapter/OAuth1.php +613 -613
  8. hybridauth/library/src/Adapter/OAuth2.php +738 -738
  9. hybridauth/library/src/Adapter/OpenID.php +275 -275
  10. hybridauth/library/src/Data/Collection.php +160 -160
  11. hybridauth/library/src/Data/Parser.php +119 -119
  12. hybridauth/library/src/Exception/AuthorizationDeniedException.php +15 -15
  13. hybridauth/library/src/Exception/BadMethodCallException.php +17 -17
  14. hybridauth/library/src/Exception/Exception.php +64 -64
  15. hybridauth/library/src/Exception/ExceptionInterface.php +36 -36
  16. hybridauth/library/src/Exception/HttpClientFailureException.php +15 -15
  17. hybridauth/library/src/Exception/HttpRequestFailedException.php +15 -15
  18. hybridauth/library/src/Exception/InvalidAccessTokenException.php +15 -15
  19. hybridauth/library/src/Exception/InvalidApplicationCredentialsException.php +15 -15
  20. hybridauth/library/src/Exception/InvalidArgumentException.php +17 -17
  21. hybridauth/library/src/Exception/InvalidAuthorizationCodeException.php +15 -15
  22. hybridauth/library/src/Exception/InvalidAuthorizationStateException.php +15 -15
  23. hybridauth/library/src/Exception/InvalidOauthTokenException.php +15 -15
  24. hybridauth/library/src/Exception/InvalidOpenidIdentifierException.php +15 -15
  25. hybridauth/library/src/Exception/NotImplementedException.php +15 -15
  26. hybridauth/library/src/Exception/RuntimeException.php +17 -17
  27. hybridauth/library/src/Exception/UnexpectedApiResponseException.php +15 -15
  28. hybridauth/library/src/Exception/UnexpectedValueException.php +19 -19
  29. hybridauth/library/src/HttpClient/Curl.php +314 -314
  30. hybridauth/library/src/HttpClient/Guzzle.php +273 -273
  31. hybridauth/library/src/HttpClient/HttpClientInterface.php +58 -58
  32. hybridauth/library/src/HttpClient/Util.php +100 -100
  33. hybridauth/library/src/Hybridauth.php +268 -268
  34. hybridauth/library/src/Logger/Logger.php +129 -129
  35. hybridauth/library/src/Logger/LoggerInterface.php +50 -50
  36. hybridauth/library/src/Logger/Psr3LoggerWrapper.php +50 -50
  37. hybridauth/library/src/Provider/AOLOpenID.php +26 -26
  38. hybridauth/library/src/Provider/Amazon.php +66 -66
  39. hybridauth/library/src/Provider/Apple.php +287 -287
  40. hybridauth/library/src/Provider/Authentiq.php +111 -111
  41. hybridauth/library/src/Provider/BitBucket.php +111 -111
  42. hybridauth/library/src/Provider/Blizzard.php +65 -65
  43. hybridauth/library/src/Provider/BlizzardAPAC.php +34 -34
  44. hybridauth/library/src/Provider/BlizzardEU.php +34 -34
  45. hybridauth/library/src/Provider/DeviantArt.php +91 -91
  46. hybridauth/library/src/Provider/Discord.php +96 -96
  47. hybridauth/library/src/Provider/Disqus.php +88 -88
  48. hybridauth/library/src/Provider/Dribbble.php +68 -68
  49. hybridauth/library/src/Provider/Dropbox.php +74 -74
  50. hybridauth/library/src/Provider/Facebook.php +444 -444
  51. hybridauth/library/src/Provider/Foursquare.php +140 -140
  52. hybridauth/library/src/Provider/GitHub.php +110 -110
  53. hybridauth/library/src/Provider/GitLab.php +72 -72
  54. hybridauth/library/src/Provider/Google.php +200 -200
  55. hybridauth/library/src/Provider/Instagram.php +170 -170
  56. hybridauth/library/src/Provider/LinkedIn.php +200 -200
  57. hybridauth/library/src/Provider/Mailru.php +83 -83
  58. hybridauth/library/src/Provider/MicrosoftGraph.php +169 -169
  59. hybridauth/library/src/Provider/ORCID.php +242 -242
  60. hybridauth/library/src/Provider/Odnoklassniki.php +110 -110
  61. hybridauth/library/src/Provider/OpenID.php +45 -45
  62. hybridauth/library/src/Provider/Patreon.php +91 -91
  63. hybridauth/library/src/Provider/Paypal.php +113 -113
  64. hybridauth/library/src/Provider/PaypalOpenID.php +71 -71
  65. hybridauth/library/src/Provider/Pinterest.php +74 -74
  66. hybridauth/library/src/Provider/QQ.php +138 -138
  67. hybridauth/library/src/Provider/Reddit.php +91 -91
  68. hybridauth/library/src/Provider/Slack.php +100 -100
  69. hybridauth/library/src/Provider/Spotify.php +93 -93
  70. hybridauth/library/src/Provider/StackExchange.php +107 -107
  71. hybridauth/library/src/Provider/StackExchangeOpenID.php +42 -42
  72. hybridauth/library/src/Provider/Steam.php +150 -150
  73. hybridauth/library/src/Provider/SteemConnect.php +70 -70
  74. hybridauth/library/src/Provider/Strava.php +72 -72
  75. hybridauth/library/src/Provider/Telegram.php +217 -217
  76. hybridauth/library/src/Provider/Tumblr.php +97 -97
  77. hybridauth/library/src/Provider/TwitchTV.php +82 -82
  78. hybridauth/library/src/Provider/Twitter.php +265 -265
  79. hybridauth/library/src/Provider/Vkontakte.php +217 -217
  80. hybridauth/library/src/Provider/WeChat.php +134 -134
  81. hybridauth/library/src/Provider/WeChatChina.php +34 -34
  82. hybridauth/library/src/Provider/WindowsLive.php +103 -103
  83. hybridauth/library/src/Provider/WordPress.php +68 -68
  84. hybridauth/library/src/Provider/Yahoo.php +104 -104
  85. hybridauth/library/src/Provider/Yandex.php +83 -83
  86. hybridauth/library/src/Storage/Session.php +119 -119
  87. hybridauth/library/src/Storage/StorageInterface.php +50 -50
  88. hybridauth/library/src/Thirdparty/OAuth/OAuthConsumer.php +41 -41
  89. hybridauth/library/src/Thirdparty/OAuth/OAuthRequest.php +331 -331
  90. hybridauth/library/src/Thirdparty/OAuth/OAuthSignatureMethod.php +67 -67
  91. hybridauth/library/src/Thirdparty/OAuth/OAuthSignatureMethodHMACSHA1.php +44 -44
  92. hybridauth/library/src/Thirdparty/OAuth/OAuthUtil.php +199 -199
  93. hybridauth/library/src/Thirdparty/OAuth/README.md +7 -7
  94. hybridauth/library/src/Thirdparty/OpenID/LightOpenID.php +1256 -1256
  95. hybridauth/library/src/Thirdparty/OpenID/README.md +7 -7
  96. hybridauth/library/src/Thirdparty/readme.md +14 -14
  97. hybridauth/library/src/User/Activity.php +73 -73
  98. hybridauth/library/src/User/Contact.php +78 -78
  99. hybridauth/library/src/User/Profile.php +190 -190
  100. hybridauth/library/src/autoload.php +53 -53
  101. includes/admin/wsl.admin.ui.php +533 -533
  102. includes/services/wsl.authentication.php +1195 -1190
  103. readme.md +52 -52
  104. readme.txt +220 -224
  105. wp-social-login.php +267 -267
hybridauth/library/CHANGELOG.md CHANGED
@@ -1 +1 @@
1
- see https://github.com/hybridauth/hybridauth/releases
1
+ see https://github.com/hybridauth/hybridauth/releases
hybridauth/library/COPYING.md CHANGED
@@ -1,75 +1,75 @@
1
- Except where otherwise noted in the source code (i.e., LightOpenID and OAuth
2
- Library, which are covered by similar licences but with different Copyright
3
- notices) all the files are:
4
-
5
- Copyright (C) 2009-2019, Hybridauth authors. All Rights Reserved.
6
-
7
- Permission is hereby granted, free of charge, to any person obtaining a copy
8
- of this software and associated documentation files (the "Software"), to deal
9
- in the Software without restriction, including without limitation the rights
10
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- copies of the Software, and to permit persons to whom the Software is
12
- furnished to do so, subject to the following conditions:
13
-
14
- The above copyright notice and this permission notice shall be included in
15
- all copies or substantial portions of the Software.
16
-
17
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- THE SOFTWARE.
24
-
25
-
26
- -----------------------
27
-
28
-
29
- Hybridauth includes a copy of LightOpenID, licensed as follows:
30
-
31
- Copyright (c) 2013-2016 Mewp (mewp151 at gmail dot com)
32
-
33
- Permission is hereby granted, free of charge, to any person obtaining a copy
34
- of this software and associated documentation files (the "Software"), to deal
35
- in the Software without restriction, including without limitation the rights
36
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37
- copies of the Software, and to permit persons to whom the Software is
38
- furnished to do so, subject to the following conditions:
39
-
40
- The above copyright notice and this permission notice shall be included in
41
- all copies or substantial portions of the Software.
42
-
43
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
49
- THE SOFTWARE.
50
-
51
-
52
- -----------------------
53
-
54
-
55
- Hybridauth includes a modified copy of OAuth PHP Library, licensed as follows:
56
-
57
- Copyright (c) 2007-2011 Andy Smith
58
-
59
- Permission is hereby granted, free of charge, to any person obtaining a copy
60
- of this software and associated documentation files (the "Software"), to deal
61
- in the Software without restriction, including without limitation the rights
62
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
63
- copies of the Software, and to permit persons to whom the Software is
64
- furnished to do so, subject to the following conditions:
65
-
66
- The above copyright notice and this permission notice shall be included in
67
- all copies or substantial portions of the Software.
68
-
69
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
72
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
73
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
74
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75
- THE SOFTWARE.
1
+ Except where otherwise noted in the source code (i.e., LightOpenID and OAuth
2
+ Library, which are covered by similar licences but with different Copyright
3
+ notices) all the files are:
4
+
5
+ Copyright (C) 2009-2019, Hybridauth authors. All Rights Reserved.
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in
15
+ all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ THE SOFTWARE.
24
+
25
+
26
+ -----------------------
27
+
28
+
29
+ Hybridauth includes a copy of LightOpenID, licensed as follows:
30
+
31
+ Copyright (c) 2013-2016 Mewp (mewp151 at gmail dot com)
32
+
33
+ Permission is hereby granted, free of charge, to any person obtaining a copy
34
+ of this software and associated documentation files (the "Software"), to deal
35
+ in the Software without restriction, including without limitation the rights
36
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37
+ copies of the Software, and to permit persons to whom the Software is
38
+ furnished to do so, subject to the following conditions:
39
+
40
+ The above copyright notice and this permission notice shall be included in
41
+ all copies or substantial portions of the Software.
42
+
43
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
49
+ THE SOFTWARE.
50
+
51
+
52
+ -----------------------
53
+
54
+
55
+ Hybridauth includes a modified copy of OAuth PHP Library, licensed as follows:
56
+
57
+ Copyright (c) 2007-2011 Andy Smith
58
+
59
+ Permission is hereby granted, free of charge, to any person obtaining a copy
60
+ of this software and associated documentation files (the "Software"), to deal
61
+ in the Software without restriction, including without limitation the rights
62
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
63
+ copies of the Software, and to permit persons to whom the Software is
64
+ furnished to do so, subject to the following conditions:
65
+
66
+ The above copyright notice and this permission notice shall be included in
67
+ all copies or substantial portions of the Software.
68
+
69
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
72
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
73
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
74
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75
+ THE SOFTWARE.
hybridauth/library/README.md CHANGED
@@ -1,66 +1,66 @@
1
- ## [Hybridauth](https://hybridauth.github.io/) 3.5
2
-
3
- [![Build Status](https://travis-ci.org/hybridauth/hybridauth.svg?branch=master)](https://travis-ci.org/hybridauth/hybridauth) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/hybridauth/hybridauth/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/hybridauth/hybridauth/?branch=master) [![Latest Stable Version](https://poser.pugx.org/hybridauth/hybridauth/v/stable.png)](https://packagist.org/packages/hybridauth/hybridauth) [![Join the chat at https://gitter.im/hybridauth/hybridauth](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hybridauth/hybridauth?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
-
5
- Hybridauth enables developers to easily build social applications and tools to engage websites visitors and customers on a social level that starts off with social sign-in and extends to social sharing, users profiles, friends lists, activities streams, status updates and more.
6
-
7
- The main goal of Hybridauth is to act as an abstract API between your application and the various social networks APIs and identities providers such as Facebook, Twitter and Google.
8
-
9
- #### Usage
10
-
11
- Hybridauth provides a number of basic [examples](https://github.com/hybridauth/hybridauth/tree/master/examples). You can also find complete Hybridauth documentation at https://hybridauth.github.io
12
-
13
- ```php
14
- $config = [
15
- 'callback' => 'https://example.com/path/to/script.php',
16
- 'keys' => [
17
- 'key' => 'your-twitter-consumer-key',
18
- 'secret' => 'your-twitter-consumer-secret',
19
- ],
20
- ];
21
-
22
- try {
23
- $twitter = new Hybridauth\Provider\Twitter($config);
24
-
25
- $twitter->authenticate();
26
-
27
- $accessToken = $twitter->getAccessToken();
28
- $userProfile = $twitter->getUserProfile();
29
- $apiResponse = $twitter->apiRequest('statuses/home_timeline.json');
30
- }
31
- catch (\Exception $e) {
32
- echo 'Oops, we ran into an issue! ' . $e->getMessage();
33
- }
34
- ```
35
-
36
- #### Requirements
37
-
38
- * PHP 5.4+
39
- * PHP Session
40
- * PHP cURL
41
-
42
- #### Installation
43
-
44
- To install Hybridauth we recommend [Composer](https://getcomposer.org/), the now defacto dependency manager for PHP. Alternatively, you can download and use the latest release available at [Github](https://github.com/hybridauth/hybridauth/releases).
45
-
46
- #### Versions Status
47
-
48
- | Version | Status | Repository | Documentation | PHP Version |
49
- |---------|-------------|-------------------------|-------------------------|-------------|
50
- | 2.x | Maintenance | [v2][hybridauth-2-repo] | [v2][hybridauth-2-docs] | >= 5.3 |
51
- | 3.x | Development | [v3][hybridauth-3-repo] | [v3][hybridauth-3-docs] | >= 5.4 |
52
-
53
- [hybridauth-2-repo]: https://github.com/hybridauth/hybridauth/tree/v2
54
- [hybridauth-3-repo]: https://github.com/hybridauth/hybridauth/
55
- [hybridauth-2-docs]: https://hybridauth.github.io/hybridauth/
56
- [hybridauth-3-docs]: https://hybridauth.github.io/
57
-
58
- #### Questions, Help and Support?
59
-
60
- For general questions (i.e, "how-to" questions), please consider using [StackOverflow](https://stackoverflow.com/questions/tagged/hybridauth) instead of the Github issues tracker. For convenience, we also have a [low-activity] [Gitter channel](https://gitter.im/hybridauth/hybridauth) if you want to get help directly from the community.
61
-
62
- #### License
63
-
64
- Hybridauth PHP Library is released under the terms of MIT License.
65
-
66
- For the full Copyright Notice and Disclaimer, see [COPYING.md](https://github.com/hybridauth/hybridauth/blob/master/COPYING.md).
1
+ ## [Hybridauth](https://hybridauth.github.io/) 3.5
2
+
3
+ [![Build Status](https://travis-ci.org/hybridauth/hybridauth.svg?branch=master)](https://travis-ci.org/hybridauth/hybridauth) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/hybridauth/hybridauth/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/hybridauth/hybridauth/?branch=master) [![Latest Stable Version](https://poser.pugx.org/hybridauth/hybridauth/v/stable.png)](https://packagist.org/packages/hybridauth/hybridauth) [![Join the chat at https://gitter.im/hybridauth/hybridauth](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hybridauth/hybridauth?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
+
5
+ Hybridauth enables developers to easily build social applications and tools to engage websites visitors and customers on a social level that starts off with social sign-in and extends to social sharing, users profiles, friends lists, activities streams, status updates and more.
6
+
7
+ The main goal of Hybridauth is to act as an abstract API between your application and the various social networks APIs and identities providers such as Facebook, Twitter and Google.
8
+
9
+ #### Usage
10
+
11
+ Hybridauth provides a number of basic [examples](https://github.com/hybridauth/hybridauth/tree/master/examples). You can also find complete Hybridauth documentation at https://hybridauth.github.io
12
+
13
+ ```php
14
+ $config = [
15
+ 'callback' => 'https://example.com/path/to/script.php',
16
+ 'keys' => [
17
+ 'key' => 'your-twitter-consumer-key',
18
+ 'secret' => 'your-twitter-consumer-secret',
19
+ ],
20
+ ];
21
+
22
+ try {
23
+ $twitter = new Hybridauth\Provider\Twitter($config);
24
+
25
+ $twitter->authenticate();
26
+
27
+ $accessToken = $twitter->getAccessToken();
28
+ $userProfile = $twitter->getUserProfile();
29
+ $apiResponse = $twitter->apiRequest('statuses/home_timeline.json');
30
+ }
31
+ catch (\Exception $e) {
32
+ echo 'Oops, we ran into an issue! ' . $e->getMessage();
33
+ }
34
+ ```
35
+
36
+ #### Requirements
37
+
38
+ * PHP 5.4+
39
+ * PHP Session
40
+ * PHP cURL
41
+
42
+ #### Installation
43
+
44
+ To install Hybridauth we recommend [Composer](https://getcomposer.org/), the now defacto dependency manager for PHP. Alternatively, you can download and use the latest release available at [Github](https://github.com/hybridauth/hybridauth/releases).
45
+
46
+ #### Versions Status
47
+
48
+ | Version | Status | Repository | Documentation | PHP Version |
49
+ |---------|-------------|-------------------------|-------------------------|-------------|
50
+ | 2.x | Maintenance | [v2][hybridauth-2-repo] | [v2][hybridauth-2-docs] | >= 5.3 |
51
+ | 3.x | Development | [v3][hybridauth-3-repo] | [v3][hybridauth-3-docs] | >= 5.4 |
52
+
53
+ [hybridauth-2-repo]: https://github.com/hybridauth/hybridauth/tree/v2
54
+ [hybridauth-3-repo]: https://github.com/hybridauth/hybridauth/
55
+ [hybridauth-2-docs]: https://hybridauth.github.io/hybridauth/
56
+ [hybridauth-3-docs]: https://hybridauth.github.io/
57
+
58
+ #### Questions, Help and Support?
59
+
60
+ For general questions (i.e, "how-to" questions), please consider using [StackOverflow](https://stackoverflow.com/questions/tagged/hybridauth) instead of the Github issues tracker. For convenience, we also have a [low-activity] [Gitter channel](https://gitter.im/hybridauth/hybridauth) if you want to get help directly from the community.
61
+
62
+ #### License
63
+
64
+ Hybridauth PHP Library is released under the terms of MIT License.
65
+
66
+ For the full Copyright Notice and Disclaimer, see [COPYING.md](https://github.com/hybridauth/hybridauth/blob/master/COPYING.md).
hybridauth/library/src/Adapter/AbstractAdapter.php CHANGED
@@ -1,364 +1,364 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Adapter;
9
-
10
- use Hybridauth\Exception\NotImplementedException;
11
- use Hybridauth\Exception\InvalidArgumentException;
12
- use Hybridauth\Exception\HttpClientFailureException;
13
- use Hybridauth\Exception\HttpRequestFailedException;
14
- use Hybridauth\Storage\StorageInterface;
15
- use Hybridauth\Storage\Session;
16
- use Hybridauth\Logger\LoggerInterface;
17
- use Hybridauth\Logger\Logger;
18
- use Hybridauth\HttpClient\HttpClientInterface;
19
- use Hybridauth\HttpClient\Curl as HttpClient;
20
- use Hybridauth\Data;
21
-
22
- /**
23
- * Class AbstractAdapter
24
- */
25
- abstract class AbstractAdapter implements AdapterInterface
26
- {
27
- use DataStoreTrait;
28
-
29
- /**
30
- * Provider ID (unique name).
31
- *
32
- * @var string
33
- */
34
- protected $providerId = '';
35
-
36
- /**
37
- * Specific Provider config.
38
- *
39
- * @var mixed
40
- */
41
- protected $config = [];
42
-
43
- /**
44
- * Extra Provider parameters.
45
- *
46
- * @var array
47
- */
48
- protected $params;
49
-
50
- /**
51
- * Callback url
52
- *
53
- * @var string
54
- */
55
- protected $callback = '';
56
-
57
- /**
58
- * Storage.
59
- *
60
- * @var StorageInterface
61
- */
62
- public $storage;
63
-
64
- /**
65
- * HttpClient.
66
- *
67
- * @var HttpClientInterface
68
- */
69
- public $httpClient;
70
-
71
- /**
72
- * Logger.
73
- *
74
- * @var LoggerInterface
75
- */
76
- public $logger;
77
-
78
- /**
79
- * Whether to validate API status codes of http responses
80
- *
81
- * @var boolean
82
- */
83
- protected $validateApiResponseHttpCode = true;
84
-
85
- /**
86
- * Common adapters constructor.
87
- *
88
- * @param array $config
89
- * @param HttpClientInterface $httpClient
90
- * @param StorageInterface $storage
91
- * @param LoggerInterface $logger
92
- */
93
- public function __construct(
94
- $config = [],
95
- HttpClientInterface $httpClient = null,
96
- StorageInterface $storage = null,
97
- LoggerInterface $logger = null
98
- ) {
99
- $this->providerId = (new \ReflectionClass($this))->getShortName();
100
-
101
- $this->config = new Data\Collection($config);
102
-
103
- $this->setHttpClient($httpClient);
104
-
105
- $this->setStorage($storage);
106
-
107
- $this->setLogger($logger);
108
-
109
- $this->configure();
110
-
111
- $this->logger->debug(sprintf('Initialize %s, config: ', get_class($this)), $config);
112
-
113
- $this->initialize();
114
- }
115
-
116
- /**
117
- * Load adapter's configuration
118
- */
119
- abstract protected function configure();
120
-
121
- /**
122
- * Adapter initializer
123
- */
124
- abstract protected function initialize();
125
-
126
- /**
127
- * {@inheritdoc}
128
- */
129
- abstract public function isConnected();
130
-
131
- /**
132
- * {@inheritdoc}
133
- */
134
- public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
135
- {
136
- throw new NotImplementedException('Provider does not support this feature.');
137
- }
138
-
139
- /**
140
- * {@inheritdoc}
141
- */
142
- public function getUserProfile()
143
- {
144
- throw new NotImplementedException('Provider does not support this feature.');
145
- }
146
-
147
- /**
148
- * {@inheritdoc}
149
- */
150
- public function getUserContacts()
151
- {
152
- throw new NotImplementedException('Provider does not support this feature.');
153
- }
154
-
155
- /**
156
- * {@inheritdoc}
157
- */
158
- public function getUserPages()
159
- {
160
- throw new NotImplementedException('Provider does not support this feature.');
161
- }
162
-
163
- /**
164
- * {@inheritdoc}
165
- */
166
- public function getUserActivity($stream)
167
- {
168
- throw new NotImplementedException('Provider does not support this feature.');
169
- }
170
-
171
- /**
172
- * {@inheritdoc}
173
- */
174
- public function setUserStatus($status)
175
- {
176
- throw new NotImplementedException('Provider does not support this feature.');
177
- }
178
-
179
- /**
180
- * {@inheritdoc}
181
- */
182
- public function setPageStatus($status, $pageId)
183
- {
184
- throw new NotImplementedException('Provider does not support this feature.');
185
- }
186
-
187
- /**
188
- * {@inheritdoc}
189
- */
190
- public function disconnect()
191
- {
192
- $this->clearStoredData();
193
- }
194
-
195
- /**
196
- * {@inheritdoc}
197
- */
198
- public function getAccessToken()
199
- {
200
- $tokenNames = [
201
- 'access_token',
202
- 'access_token_secret',
203
- 'token_type',
204
- 'refresh_token',
205
- 'expires_in',
206
- 'expires_at',
207
- ];
208
-
209
- $tokens = [];
210
-
211
- foreach ($tokenNames as $name) {
212
- if ($this->getStoredData($name)) {
213
- $tokens[ $name ] = $this->getStoredData($name);
214
- }
215
- }
216
-
217
- return $tokens;
218
- }
219
-
220
- /**
221
- * {@inheritdoc}
222
- */
223
- public function setAccessToken($tokens = [])
224
- {
225
- $this->clearStoredData();
226
-
227
- foreach ($tokens as $token => $value) {
228
- $this->storeData($token, $value);
229
- }
230
-
231
- // Re-initialize token parameters.
232
- $this->initialize();
233
- }
234
-
235
- /**
236
- * {@inheritdoc}
237
- */
238
- public function setHttpClient(HttpClientInterface $httpClient = null)
239
- {
240
- $this->httpClient = $httpClient ?: new HttpClient();
241
-
242
- if ($this->config->exists('curl_options') && method_exists($this->httpClient, 'setCurlOptions')) {
243
- $this->httpClient->setCurlOptions($this->config->get('curl_options'));
244
- }
245
- }
246
-
247
- /**
248
- * {@inheritdoc}
249
- */
250
- public function getHttpClient()
251
- {
252
- return $this->httpClient;
253
- }
254
-
255
- /**
256
- * {@inheritdoc}
257
- */
258
- public function setStorage(StorageInterface $storage = null)
259
- {
260
- $this->storage = $storage ?: new Session();
261
- }
262
-
263
- /**
264
- * {@inheritdoc}
265
- */
266
- public function getStorage()
267
- {
268
- return $this->storage;
269
- }
270
-
271
- /**
272
- * {@inheritdoc}
273
- */
274
- public function setLogger(LoggerInterface $logger = null)
275
- {
276
- $this->logger = $logger ?: new Logger(
277
- $this->config->get('debug_mode'),
278
- $this->config->get('debug_file')
279
- );
280
-
281
- if (method_exists($this->httpClient, 'setLogger')) {
282
- $this->httpClient->setLogger($this->logger);
283
- }
284
- }
285
-
286
- /**
287
- * {@inheritdoc}
288
- */
289
- public function getLogger()
290
- {
291
- return $this->logger;
292
- }
293
-
294
- /**
295
- * Set Adapter's API callback url
296
- *
297
- * @param string $callback
298
- *
299
- * @throws InvalidArgumentException
300
- */
301
- protected function setCallback($callback)
302
- {
303
- if (! filter_var($callback, FILTER_VALIDATE_URL)) {
304
- throw new InvalidArgumentException('A valid callback url is required.');
305
- }
306
-
307
- $this->callback = $callback;
308
- }
309
-
310
- /**
311
- * Overwrite Adapter's API endpoints
312
- *
313
- * @param array|Data\Collection $endpoints
314
- */
315
- protected function setApiEndpoints($endpoints = null)
316
- {
317
- if (empty($endpoints)) {
318
- return;
319
- }
320
-
321
- $collection = is_array($endpoints) ? new Data\Collection($endpoints) : $endpoints;
322
-
323
- $this->apiBaseUrl = $collection->get('api_base_url') ?: $this->apiBaseUrl;
324
- $this->authorizeUrl = $collection->get('authorize_url') ?: $this->authorizeUrl;
325
- $this->accessTokenUrl = $collection->get('access_token_url') ?: $this->accessTokenUrl;
326
- }
327
-
328
-
329
- /**
330
- * Validate signed API responses Http status code.
331
- *
332
- * Since the specifics of error responses is beyond the scope of RFC6749 and OAuth Core specifications,
333
- * Hybridauth will consider any HTTP status code that is different than '200 OK' as an ERROR.
334
- *
335
- * @param string $error String to pre append to message thrown in exception
336
- *
337
- * @throws HttpClientFailureException
338
- * @throws HttpRequestFailedException
339
- */
340
- protected function validateApiResponse($error = '')
341
- {
342
- $error .= !empty($error) ? '. ' : '';
343
-
344
- if ($this->httpClient->getResponseClientError()) {
345
- throw new HttpClientFailureException(
346
- $error.'HTTP client error: '.$this->httpClient->getResponseClientError().'.'
347
- );
348
- }
349
-
350
- // if validateApiResponseHttpCode is set to false, we by pass verification of http status code
351
- if (! $this->validateApiResponseHttpCode) {
352
- return;
353
- }
354
-
355
- $status = $this->httpClient->getResponseHttpCode();
356
-
357
- if ($status < 200 || $status > 299) {
358
- throw new HttpRequestFailedException(
359
- $error . 'HTTP error '.$this->httpClient->getResponseHttpCode().
360
- '. Raw Provider API response: '.$this->httpClient->getResponseBody().'.'
361
- );
362
- }
363
- }
364
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Adapter;
9
+
10
+ use Hybridauth\Exception\NotImplementedException;
11
+ use Hybridauth\Exception\InvalidArgumentException;
12
+ use Hybridauth\Exception\HttpClientFailureException;
13
+ use Hybridauth\Exception\HttpRequestFailedException;
14
+ use Hybridauth\Storage\StorageInterface;
15
+ use Hybridauth\Storage\Session;
16
+ use Hybridauth\Logger\LoggerInterface;
17
+ use Hybridauth\Logger\Logger;
18
+ use Hybridauth\HttpClient\HttpClientInterface;
19
+ use Hybridauth\HttpClient\Curl as HttpClient;
20
+ use Hybridauth\Data;
21
+
22
+ /**
23
+ * Class AbstractAdapter
24
+ */
25
+ abstract class AbstractAdapter implements AdapterInterface
26
+ {
27
+ use DataStoreTrait;
28
+
29
+ /**
30
+ * Provider ID (unique name).
31
+ *
32
+ * @var string
33
+ */
34
+ protected $providerId = '';
35
+
36
+ /**
37
+ * Specific Provider config.
38
+ *
39
+ * @var mixed
40
+ */
41
+ protected $config = [];
42
+
43
+ /**
44
+ * Extra Provider parameters.
45
+ *
46
+ * @var array
47
+ */
48
+ protected $params;
49
+
50
+ /**
51
+ * Callback url
52
+ *
53
+ * @var string
54
+ */
55
+ protected $callback = '';
56
+
57
+ /**
58
+ * Storage.
59
+ *
60
+ * @var StorageInterface
61
+ */
62
+ public $storage;
63
+
64
+ /**
65
+ * HttpClient.
66
+ *
67
+ * @var HttpClientInterface
68
+ */
69
+ public $httpClient;
70
+
71
+ /**
72
+ * Logger.
73
+ *
74
+ * @var LoggerInterface
75
+ */
76
+ public $logger;
77
+
78
+ /**
79
+ * Whether to validate API status codes of http responses
80
+ *
81
+ * @var boolean
82
+ */
83
+ protected $validateApiResponseHttpCode = true;
84
+
85
+ /**
86
+ * Common adapters constructor.
87
+ *
88
+ * @param array $config
89
+ * @param HttpClientInterface $httpClient
90
+ * @param StorageInterface $storage
91
+ * @param LoggerInterface $logger
92
+ */
93
+ public function __construct(
94
+ $config = [],
95
+ HttpClientInterface $httpClient = null,
96
+ StorageInterface $storage = null,
97
+ LoggerInterface $logger = null
98
+ ) {
99
+ $this->providerId = (new \ReflectionClass($this))->getShortName();
100
+
101
+ $this->config = new Data\Collection($config);
102
+
103
+ $this->setHttpClient($httpClient);
104
+
105
+ $this->setStorage($storage);
106
+
107
+ $this->setLogger($logger);
108
+
109
+ $this->configure();
110
+
111
+ $this->logger->debug(sprintf('Initialize %s, config: ', get_class($this)), $config);
112
+
113
+ $this->initialize();
114
+ }
115
+
116
+ /**
117
+ * Load adapter's configuration
118
+ */
119
+ abstract protected function configure();
120
+
121
+ /**
122
+ * Adapter initializer
123
+ */
124
+ abstract protected function initialize();
125
+
126
+ /**
127
+ * {@inheritdoc}
128
+ */
129
+ abstract public function isConnected();
130
+
131
+ /**
132
+ * {@inheritdoc}
133
+ */
134
+ public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
135
+ {
136
+ throw new NotImplementedException('Provider does not support this feature.');
137
+ }
138
+
139
+ /**
140
+ * {@inheritdoc}
141
+ */
142
+ public function getUserProfile()
143
+ {
144
+ throw new NotImplementedException('Provider does not support this feature.');
145
+ }
146
+
147
+ /**
148
+ * {@inheritdoc}
149
+ */
150
+ public function getUserContacts()
151
+ {
152
+ throw new NotImplementedException('Provider does not support this feature.');
153
+ }
154
+
155
+ /**
156
+ * {@inheritdoc}
157
+ */
158
+ public function getUserPages()
159
+ {
160
+ throw new NotImplementedException('Provider does not support this feature.');
161
+ }
162
+
163
+ /**
164
+ * {@inheritdoc}
165
+ */
166
+ public function getUserActivity($stream)
167
+ {
168
+ throw new NotImplementedException('Provider does not support this feature.');
169
+ }
170
+
171
+ /**
172
+ * {@inheritdoc}
173
+ */
174
+ public function setUserStatus($status)
175
+ {
176
+ throw new NotImplementedException('Provider does not support this feature.');
177
+ }
178
+
179
+ /**
180
+ * {@inheritdoc}
181
+ */
182
+ public function setPageStatus($status, $pageId)
183
+ {
184
+ throw new NotImplementedException('Provider does not support this feature.');
185
+ }
186
+
187
+ /**
188
+ * {@inheritdoc}
189
+ */
190
+ public function disconnect()
191
+ {
192
+ $this->clearStoredData();
193
+ }
194
+
195
+ /**
196
+ * {@inheritdoc}
197
+ */
198
+ public function getAccessToken()
199
+ {
200
+ $tokenNames = [
201
+ 'access_token',
202
+ 'access_token_secret',
203
+ 'token_type',
204
+ 'refresh_token',
205
+ 'expires_in',
206
+ 'expires_at',
207
+ ];
208
+
209
+ $tokens = [];
210
+
211
+ foreach ($tokenNames as $name) {
212
+ if ($this->getStoredData($name)) {
213
+ $tokens[ $name ] = $this->getStoredData($name);
214
+ }
215
+ }
216
+
217
+ return $tokens;
218
+ }
219
+
220
+ /**
221
+ * {@inheritdoc}
222
+ */
223
+ public function setAccessToken($tokens = [])
224
+ {
225
+ $this->clearStoredData();
226
+
227
+ foreach ($tokens as $token => $value) {
228
+ $this->storeData($token, $value);
229
+ }
230
+
231
+ // Re-initialize token parameters.
232
+ $this->initialize();
233
+ }
234
+
235
+ /**
236
+ * {@inheritdoc}
237
+ */
238
+ public function setHttpClient(HttpClientInterface $httpClient = null)
239
+ {
240
+ $this->httpClient = $httpClient ?: new HttpClient();
241
+
242
+ if ($this->config->exists('curl_options') && method_exists($this->httpClient, 'setCurlOptions')) {
243
+ $this->httpClient->setCurlOptions($this->config->get('curl_options'));
244
+ }
245
+ }
246
+
247
+ /**
248
+ * {@inheritdoc}
249
+ */
250
+ public function getHttpClient()
251
+ {
252
+ return $this->httpClient;
253
+ }
254
+
255
+ /**
256
+ * {@inheritdoc}
257
+ */
258
+ public function setStorage(StorageInterface $storage = null)
259
+ {
260
+ $this->storage = $storage ?: new Session();
261
+ }
262
+
263
+ /**
264
+ * {@inheritdoc}
265
+ */
266
+ public function getStorage()
267
+ {
268
+ return $this->storage;
269
+ }
270
+
271
+ /**
272
+ * {@inheritdoc}
273
+ */
274
+ public function setLogger(LoggerInterface $logger = null)
275
+ {
276
+ $this->logger = $logger ?: new Logger(
277
+ $this->config->get('debug_mode'),
278
+ $this->config->get('debug_file')
279
+ );
280
+
281
+ if (method_exists($this->httpClient, 'setLogger')) {
282
+ $this->httpClient->setLogger($this->logger);
283
+ }
284
+ }
285
+
286
+ /**
287
+ * {@inheritdoc}
288
+ */
289
+ public function getLogger()
290
+ {
291
+ return $this->logger;
292
+ }
293
+
294
+ /**
295
+ * Set Adapter's API callback url
296
+ *
297
+ * @param string $callback
298
+ *
299
+ * @throws InvalidArgumentException
300
+ */
301
+ protected function setCallback($callback)
302
+ {
303
+ if (! filter_var($callback, FILTER_VALIDATE_URL)) {
304
+ throw new InvalidArgumentException('A valid callback url is required.');
305
+ }
306
+
307
+ $this->callback = $callback;
308
+ }
309
+
310
+ /**
311
+ * Overwrite Adapter's API endpoints
312
+ *
313
+ * @param array|Data\Collection $endpoints
314
+ */
315
+ protected function setApiEndpoints($endpoints = null)
316
+ {
317
+ if (empty($endpoints)) {
318
+ return;
319
+ }
320
+
321
+ $collection = is_array($endpoints) ? new Data\Collection($endpoints) : $endpoints;
322
+
323
+ $this->apiBaseUrl = $collection->get('api_base_url') ?: $this->apiBaseUrl;
324
+ $this->authorizeUrl = $collection->get('authorize_url') ?: $this->authorizeUrl;
325
+ $this->accessTokenUrl = $collection->get('access_token_url') ?: $this->accessTokenUrl;
326
+ }
327
+
328
+
329
+ /**
330
+ * Validate signed API responses Http status code.
331
+ *
332
+ * Since the specifics of error responses is beyond the scope of RFC6749 and OAuth Core specifications,
333
+ * Hybridauth will consider any HTTP status code that is different than '200 OK' as an ERROR.
334
+ *
335
+ * @param string $error String to pre append to message thrown in exception
336
+ *
337
+ * @throws HttpClientFailureException
338
+ * @throws HttpRequestFailedException
339
+ */
340
+ protected function validateApiResponse($error = '')
341
+ {
342
+ $error .= !empty($error) ? '. ' : '';
343
+
344
+ if ($this->httpClient->getResponseClientError()) {
345
+ throw new HttpClientFailureException(
346
+ $error.'HTTP client error: '.$this->httpClient->getResponseClientError().'.'
347
+ );
348
+ }
349
+
350
+ // if validateApiResponseHttpCode is set to false, we by pass verification of http status code
351
+ if (! $this->validateApiResponseHttpCode) {
352
+ return;
353
+ }
354
+
355
+ $status = $this->httpClient->getResponseHttpCode();
356
+
357
+ if ($status < 200 || $status > 299) {
358
+ throw new HttpRequestFailedException(
359
+ $error . 'HTTP error '.$this->httpClient->getResponseHttpCode().
360
+ '. Raw Provider API response: '.$this->httpClient->getResponseBody().'.'
361
+ );
362
+ }
363
+ }
364
+ }
hybridauth/library/src/Adapter/AdapterInterface.php CHANGED
@@ -1,149 +1,149 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Adapter;
9
-
10
- use Hybridauth\HttpClient\HttpClientInterface;
11
- use Hybridauth\Storage\StorageInterface;
12
- use Hybridauth\Logger\LoggerInterface;
13
-
14
- /**
15
- * Interface AdapterInterface
16
- */
17
- interface AdapterInterface
18
- {
19
- /**
20
- * Initiate the appropriate protocol and process/automate the authentication or authorization flow.
21
- *
22
- * @return boolean|null
23
- */
24
- public function authenticate();
25
-
26
- /**
27
- * Returns TRUE if the user is connected
28
- *
29
- * @return boolean
30
- */
31
- public function isConnected();
32
-
33
- /**
34
- * Clear all access token in storage
35
- */
36
- public function disconnect();
37
-
38
- /**
39
- * Retrieve the connected user profile
40
- *
41
- * @return \Hybridauth\User\Profile
42
- */
43
- public function getUserProfile();
44
-
45
- /**
46
- * Retrieve the connected user contacts list
47
- *
48
- * @return \Hybridauth\User\Contact[]
49
- */
50
- public function getUserContacts();
51
-
52
- /**
53
- * Retrieve the connected user pages|companies|groups list
54
- *
55
- * @return array
56
- */
57
- public function getUserPages();
58
-
59
- /**
60
- * Retrieve the user activity stream
61
- *
62
- * @param string $stream
63
- *
64
- * @return \Hybridauth\User\Activity[]
65
- */
66
- public function getUserActivity($stream);
67
-
68
- /**
69
- * Post a status on user wall|timeline|blog|website|etc.
70
- *
71
- * @param string|array $status
72
- *
73
- * @return mixed API response
74
- */
75
- public function setUserStatus($status);
76
-
77
- /**
78
- * Post a status on page|company|group wall.
79
- *
80
- * @param string|array $status
81
- * @param string $pageId
82
- *
83
- * @return mixed API response
84
- */
85
- public function setPageStatus($status, $pageId);
86
-
87
- /**
88
- * Send a signed request to provider API
89
- *
90
- * @param string $url
91
- * @param string $method
92
- * @param array $parameters
93
- * @param array $headers
94
- * @param bool $multipart
95
- *
96
- * @return mixed
97
- */
98
- public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [], $multipart = false);
99
-
100
- /**
101
- * Return oauth access tokens.
102
- *
103
- * @return array
104
- */
105
- public function getAccessToken();
106
-
107
- /**
108
- * Set oauth access tokens.
109
- *
110
- * @param array $tokens
111
- */
112
- public function setAccessToken($tokens = []);
113
-
114
- /**
115
- * Set http client instance.
116
- *
117
- * @param HttpClientInterface $httpClient
118
- */
119
- public function setHttpClient(HttpClientInterface $httpClient = null);
120
-
121
- /**
122
- * Return http client instance.
123
- */
124
- public function getHttpClient();
125
-
126
- /**
127
- * Set storage instance.
128
- *
129
- * @param StorageInterface $storage
130
- */
131
- public function setStorage(StorageInterface $storage = null);
132
-
133
- /**
134
- * Return storage instance.
135
- */
136
- public function getStorage();
137
-
138
- /**
139
- * Set Logger instance.
140
- *
141
- * @param LoggerInterface $logger
142
- */
143
- public function setLogger(LoggerInterface $logger = null);
144
-
145
- /**
146
- * Return logger instance.
147
- */
148
- public function getLogger();
149
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Adapter;
9
+
10
+ use Hybridauth\HttpClient\HttpClientInterface;
11
+ use Hybridauth\Storage\StorageInterface;
12
+ use Hybridauth\Logger\LoggerInterface;
13
+
14
+ /**
15
+ * Interface AdapterInterface
16
+ */
17
+ interface AdapterInterface
18
+ {
19
+ /**
20
+ * Initiate the appropriate protocol and process/automate the authentication or authorization flow.
21
+ *
22
+ * @return boolean|null
23
+ */
24
+ public function authenticate();
25
+
26
+ /**
27
+ * Returns TRUE if the user is connected
28
+ *
29
+ * @return boolean
30
+ */
31
+ public function isConnected();
32
+
33
+ /**
34
+ * Clear all access token in storage
35
+ */
36
+ public function disconnect();
37
+
38
+ /**
39
+ * Retrieve the connected user profile
40
+ *
41
+ * @return \Hybridauth\User\Profile
42
+ */
43
+ public function getUserProfile();
44
+
45
+ /**
46
+ * Retrieve the connected user contacts list
47
+ *
48
+ * @return \Hybridauth\User\Contact[]
49
+ */
50
+ public function getUserContacts();
51
+
52
+ /**
53
+ * Retrieve the connected user pages|companies|groups list
54
+ *
55
+ * @return array
56
+ */
57
+ public function getUserPages();
58
+
59
+ /**
60
+ * Retrieve the user activity stream
61
+ *
62
+ * @param string $stream
63
+ *
64
+ * @return \Hybridauth\User\Activity[]
65
+ */
66
+ public function getUserActivity($stream);
67
+
68
+ /**
69
+ * Post a status on user wall|timeline|blog|website|etc.
70
+ *
71
+ * @param string|array $status
72
+ *
73
+ * @return mixed API response
74
+ */
75
+ public function setUserStatus($status);
76
+
77
+ /**
78
+ * Post a status on page|company|group wall.
79
+ *
80
+ * @param string|array $status
81
+ * @param string $pageId
82
+ *
83
+ * @return mixed API response
84
+ */
85
+ public function setPageStatus($status, $pageId);
86
+
87
+ /**
88
+ * Send a signed request to provider API
89
+ *
90
+ * @param string $url
91
+ * @param string $method
92
+ * @param array $parameters
93
+ * @param array $headers
94
+ * @param bool $multipart
95
+ *
96
+ * @return mixed
97
+ */
98
+ public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [], $multipart = false);
99
+
100
+ /**
101
+ * Return oauth access tokens.
102
+ *
103
+ * @return array
104
+ */
105
+ public function getAccessToken();
106
+
107
+ /**
108
+ * Set oauth access tokens.
109
+ *
110
+ * @param array $tokens
111
+ */
112
+ public function setAccessToken($tokens = []);
113
+
114
+ /**
115
+ * Set http client instance.
116
+ *
117
+ * @param HttpClientInterface $httpClient
118
+ */
119
+ public function setHttpClient(HttpClientInterface $httpClient = null);
120
+
121
+ /**
122
+ * Return http client instance.
123
+ */
124
+ public function getHttpClient();
125
+
126
+ /**
127
+ * Set storage instance.
128
+ *
129
+ * @param StorageInterface $storage
130
+ */
131
+ public function setStorage(StorageInterface $storage = null);
132
+
133
+ /**
134
+ * Return storage instance.
135
+ */
136
+ public function getStorage();
137
+
138
+ /**
139
+ * Set Logger instance.
140
+ *
141
+ * @param LoggerInterface $logger
142
+ */
143
+ public function setLogger(LoggerInterface $logger = null);
144
+
145
+ /**
146
+ * Return logger instance.
147
+ */
148
+ public function getLogger();
149
+ }
hybridauth/library/src/Adapter/DataStoreTrait.php CHANGED
@@ -1,74 +1,74 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Adapter;
9
-
10
- /**
11
- * Trait DataStoreTrait
12
- */
13
- trait DataStoreTrait
14
- {
15
- /**
16
- * Returns storage instance
17
- *
18
- * @return \Hybridauth\Storage\StorageInterface
19
- */
20
- abstract public function getStorage();
21
-
22
- /**
23
- * Store a piece of data in storage.
24
- *
25
- * This method is mainly used for OAuth tokens (access, secret, refresh, and whatnot), but it
26
- * can be also used by providers to store any other useful data (i.g., user_id, auth_nonce, etc.)
27
- *
28
- * @param string $name
29
- * @param mixed $value
30
- */
31
- protected function storeData($name, $value = null)
32
- {
33
- // if empty, we simply delete the thing as we'd want to only store necessary data
34
- if (empty($value)) {
35
- $this->deleteStoredData($name);
36
- }
37
-
38
- $this->getStorage()->set($this->providerId.'.'.$name, $value);
39
- }
40
-
41
- /**
42
- * Retrieve a piece of data from storage.
43
- *
44
- * This method is mainly used for OAuth tokens (access, secret, refresh, and whatnot), but it
45
- * can be also used by providers to retrieve from store any other useful data (i.g., user_id,
46
- * auth_nonce, etc.)
47
- *
48
- * @param string $name
49
- *
50
- * @return mixed
51
- */
52
- protected function getStoredData($name)
53
- {
54
- return $this->getStorage()->get($this->providerId.'.'.$name);
55
- }
56
-
57
- /**
58
- * Delete a stored piece of data.
59
- *
60
- * @param string $name
61
- */
62
- protected function deleteStoredData($name)
63
- {
64
- $this->getStorage()->delete($this->providerId.'.'.$name);
65
- }
66
-
67
- /**
68
- * Delete all stored data of the instantiated adapter
69
- */
70
- protected function clearStoredData()
71
- {
72
- $this->getStorage()->deleteMatch($this->providerId.'.');
73
- }
74
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Adapter;
9
+
10
+ /**
11
+ * Trait DataStoreTrait
12
+ */
13
+ trait DataStoreTrait
14
+ {
15
+ /**
16
+ * Returns storage instance
17
+ *
18
+ * @return \Hybridauth\Storage\StorageInterface
19
+ */
20
+ abstract public function getStorage();
21
+
22
+ /**
23
+ * Store a piece of data in storage.
24
+ *
25
+ * This method is mainly used for OAuth tokens (access, secret, refresh, and whatnot), but it
26
+ * can be also used by providers to store any other useful data (i.g., user_id, auth_nonce, etc.)
27
+ *
28
+ * @param string $name
29
+ * @param mixed $value
30
+ */
31
+ protected function storeData($name, $value = null)
32
+ {
33
+ // if empty, we simply delete the thing as we'd want to only store necessary data
34
+ if (empty($value)) {
35
+ $this->deleteStoredData($name);
36
+ }
37
+
38
+ $this->getStorage()->set($this->providerId.'.'.$name, $value);
39
+ }
40
+
41
+ /**
42
+ * Retrieve a piece of data from storage.
43
+ *
44
+ * This method is mainly used for OAuth tokens (access, secret, refresh, and whatnot), but it
45
+ * can be also used by providers to retrieve from store any other useful data (i.g., user_id,
46
+ * auth_nonce, etc.)
47
+ *
48
+ * @param string $name
49
+ *
50
+ * @return mixed
51
+ */
52
+ protected function getStoredData($name)
53
+ {
54
+ return $this->getStorage()->get($this->providerId.'.'.$name);
55
+ }
56
+
57
+ /**
58
+ * Delete a stored piece of data.
59
+ *
60
+ * @param string $name
61
+ */
62
+ protected function deleteStoredData($name)
63
+ {
64
+ $this->getStorage()->delete($this->providerId.'.'.$name);
65
+ }
66
+
67
+ /**
68
+ * Delete all stored data of the instantiated adapter
69
+ */
70
+ protected function clearStoredData()
71
+ {
72
+ $this->getStorage()->deleteMatch($this->providerId.'.');
73
+ }
74
+ }
hybridauth/library/src/Adapter/OAuth1.php CHANGED
@@ -1,613 +1,613 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Adapter;
9
-
10
- use Hybridauth\Exception\Exception;
11
- use Hybridauth\Exception\InvalidApplicationCredentialsException;
12
- use Hybridauth\Exception\AuthorizationDeniedException;
13
- use Hybridauth\Exception\InvalidOauthTokenException;
14
- use Hybridauth\Exception\InvalidAccessTokenException;
15
- use Hybridauth\Data;
16
- use Hybridauth\HttpClient;
17
- use Hybridauth\Thirdparty\OAuth\OAuthConsumer;
18
- use Hybridauth\Thirdparty\OAuth\OAuthRequest;
19
- use Hybridauth\Thirdparty\OAuth\OAuthSignatureMethodHMACSHA1;
20
- use Hybridauth\Thirdparty\OAuth\OAuthUtil;
21
-
22
- /**
23
- * This class can be used to simplify the authorization flow of OAuth 1 based service providers.
24
- *
25
- * Subclasses (i.e., providers adapters) can either use the already provided methods or override
26
- * them when necessary.
27
- */
28
- abstract class OAuth1 extends AbstractAdapter implements AdapterInterface
29
- {
30
- /**
31
- * Base URL to provider API
32
- *
33
- * This var will be used to build urls when sending signed requests
34
- *
35
- * @var string
36
- */
37
- protected $apiBaseUrl = '';
38
-
39
- /**
40
- * @var string
41
- */
42
- protected $authorizeUrl = '';
43
-
44
- /**
45
- * @var string
46
- */
47
- protected $requestTokenUrl = '';
48
-
49
- /**
50
- * @var string
51
- */
52
- protected $accessTokenUrl = '';
53
-
54
- /**
55
- * IPD API Documentation
56
- *
57
- * OPTIONAL.
58
- *
59
- * @var string
60
- */
61
- protected $apiDocumentation = '';
62
-
63
- /**
64
- * OAuth Version
65
- *
66
- * '1.0' OAuth Core 1.0
67
- * '1.0a' OAuth Core 1.0 Revision A
68
- *
69
- * @var string
70
- */
71
- protected $oauth1Version = '1.0a';
72
-
73
- /**
74
- * @var string
75
- */
76
- protected $consumerKey = null;
77
-
78
- /**
79
- * @var string
80
- */
81
- protected $consumerSecret = null;
82
-
83
- /**
84
- * @var object
85
- */
86
- protected $OAuthConsumer = null;
87
-
88
- /**
89
- * @var object
90
- */
91
- protected $sha1Method = null;
92
-
93
- /**
94
- * @var object
95
- */
96
- protected $consumerToken = null;
97
-
98
- /**
99
- * Authorization Url Parameters
100
- *
101
- * @var boolean
102
- */
103
- protected $AuthorizeUrlParameters = [];
104
-
105
- /**
106
- * @var string
107
- */
108
- protected $requestTokenMethod = 'POST';
109
-
110
- /**
111
- * @var array
112
- */
113
- protected $requestTokenParameters = [];
114
-
115
- /**
116
- * @var array
117
- */
118
- protected $requestTokenHeaders = [];
119
-
120
- /**
121
- * @var string
122
- */
123
- protected $tokenExchangeMethod = 'POST';
124
-
125
- /**
126
- * @var array
127
- */
128
- protected $tokenExchangeParameters = [];
129
-
130
- /**
131
- * @var array
132
- */
133
- protected $tokenExchangeHeaders = [];
134
-
135
- /**
136
- * @var array
137
- */
138
- protected $apiRequestParameters = [];
139
-
140
- /**
141
- * @var array
142
- */
143
- protected $apiRequestHeaders = [];
144
-
145
- /**
146
- * {@inheritdoc}
147
- */
148
- protected function configure()
149
- {
150
- $this->consumerKey = $this->config->filter('keys')->get('id') ?: $this->config->filter('keys')->get('key');
151
- $this->consumerSecret = $this->config->filter('keys')->get('secret');
152
-
153
- if (! $this->consumerKey || !$this->consumerSecret) {
154
- throw new InvalidApplicationCredentialsException(
155
- 'Your application id is required in order to connect to ' . $this->providerId
156
- );
157
- }
158
-
159
- if ($this->config->exists('tokens')) {
160
- $this->setAccessToken($this->config->get('tokens'));
161
- }
162
-
163
- $this->setCallback($this->config->get('callback'));
164
- $this->setApiEndpoints($this->config->get('endpoints'));
165
- }
166
-
167
- /**
168
- * {@inheritdoc}
169
- */
170
- protected function initialize()
171
- {
172
- /**
173
- * Set up OAuth Signature and Consumer
174
- *
175
- * OAuth Core: All Token requests and Protected Resources requests MUST be signed
176
- * by the Consumer and verified by the Service Provider.
177
- *
178
- * The protocol defines three signature methods: HMAC-SHA1, RSA-SHA1, and PLAINTEXT..
179
- *
180
- * The Consumer declares a signature method in the oauth_signature_method parameter..
181
- *
182
- * http://oauth.net/core/1.0a/#signing_process
183
- */
184
- $this->sha1Method = new OAuthSignatureMethodHMACSHA1();
185
-
186
- $this->OAuthConsumer = new OAuthConsumer(
187
- $this->consumerKey,
188
- $this->consumerSecret
189
- );
190
-
191
- if ($this->getStoredData('request_token')) {
192
- $this->consumerToken = new OAuthConsumer(
193
- $this->getStoredData('request_token'),
194
- $this->getStoredData('request_token_secret')
195
- );
196
- }
197
-
198
- if ($this->getStoredData('access_token')) {
199
- $this->consumerToken = new OAuthConsumer(
200
- $this->getStoredData('access_token'),
201
- $this->getStoredData('access_token_secret')
202
- );
203
- }
204
- }
205
-
206
- /**
207
- * {@inheritdoc}
208
- */
209
- public function authenticate()
210
- {
211
- $this->logger->info(sprintf('%s::authenticate()', get_class($this)));
212
-
213
- if ($this->isConnected()) {
214
- return true;
215
- }
216
-
217
- try {
218
- if (!$this->getStoredData('request_token')) {
219
- // Start a new flow.
220
- $this->authenticateBegin();
221
- } elseif (empty($_GET['oauth_token']) && empty($_GET['denied'])) {
222
- // A previous authentication was not finished, and this request is not finishing it.
223
- $this->authenticateBegin();
224
- } else {
225
- // Finish a flow.
226
- $this->authenticateFinish();
227
- }
228
- } catch (Exception $exception) {
229
- $this->clearStoredData();
230
-
231
- throw $exception;
232
- }
233
-
234
- return null;
235
- }
236
-
237
- /**
238
- * {@inheritdoc}
239
- */
240
- public function isConnected()
241
- {
242
- return (bool)$this->getStoredData('access_token');
243
- }
244
-
245
- /**
246
- * Initiate the authorization protocol
247
- *
248
- * 1. Obtaining an Unauthorized Request Token
249
- * 2. Build Authorization URL for Authorization Request and redirect the user-agent to the
250
- * Authorization Server.
251
- */
252
- protected function authenticateBegin()
253
- {
254
- $response = $this->requestAuthToken();
255
-
256
- $this->validateAuthTokenRequest($response);
257
-
258
- $authUrl = $this->getAuthorizeUrl();
259
-
260
- $this->logger->debug(sprintf('%s::authenticateBegin(), redirecting user to:', get_class($this)), [$authUrl]);
261
-
262
- HttpClient\Util::redirect($authUrl);
263
- }
264
-
265
- /**
266
- * Finalize the authorization process
267
- *
268
- * @throws AuthorizationDeniedException
269
- * @throws \Hybridauth\Exception\HttpClientFailureException
270
- * @throws \Hybridauth\Exception\HttpRequestFailedException
271
- * @throws InvalidAccessTokenException
272
- * @throws InvalidOauthTokenException
273
- */
274
- protected function authenticateFinish()
275
- {
276
- $this->logger->debug(
277
- sprintf('%s::authenticateFinish(), callback url:', get_class($this)),
278
- [HttpClient\Util::getCurrentUrl(true)]
279
- );
280
-
281
- $denied = filter_input(INPUT_GET, 'denied');
282
- $oauth_problem = filter_input(INPUT_GET, 'oauth_problem');
283
- $oauth_token = filter_input(INPUT_GET, 'oauth_token');
284
- $oauth_verifier = filter_input(INPUT_GET, 'oauth_verifier');
285
-
286
- if ($denied) {
287
- throw new AuthorizationDeniedException(
288
- 'User denied access request. Provider returned a denied token: ' . htmlentities($denied)
289
- );
290
- }
291
-
292
- if ($oauth_problem) {
293
- throw new InvalidOauthTokenException(
294
- 'Provider returned an error. oauth_problem: ' . htmlentities($oauth_problem)
295
- );
296
- }
297
-
298
- if (! $oauth_token) {
299
- throw new InvalidOauthTokenException(
300
- 'Expecting a non-null oauth_token to continue the authorization flow.'
301
- );
302
- }
303
-
304
- $response = $this->exchangeAuthTokenForAccessToken($oauth_token, $oauth_verifier);
305
-
306
- $this->validateAccessTokenExchange($response);
307
-
308
- $this->initialize();
309
- }
310
-
311
- /**
312
- * Build Authorization URL for Authorization Request
313
- *
314
- * @param array $parameters
315
- *
316
- * @return string
317
- */
318
- protected function getAuthorizeUrl($parameters = [])
319
- {
320
- $this->AuthorizeUrlParameters = !empty($parameters)
321
- ? $parameters
322
- : array_replace(
323
- (array) $this->AuthorizeUrlParameters,
324
- (array) $this->config->get('authorize_url_parameters')
325
- );
326
-
327
- $this->AuthorizeUrlParameters['oauth_token'] = $this->getStoredData('request_token');
328
-
329
- return $this->authorizeUrl . '?' . http_build_query($this->AuthorizeUrlParameters, '', '&');
330
- }
331
-
332
- /**
333
- * Unauthorized Request Token
334
- *
335
- * OAuth Core: The Consumer obtains an unauthorized Request Token by asking the Service Provider
336
- * to issue a Token. The Request Token's sole purpose is to receive User approval and can only
337
- * be used to obtain an Access Token.
338
- *
339
- * http://oauth.net/core/1.0/#auth_step1
340
- * 6.1.1. Consumer Obtains a Request Token
341
- *
342
- * @return string Raw Provider API response
343
- * @throws \Hybridauth\Exception\HttpClientFailureException
344
- * @throws \Hybridauth\Exception\HttpRequestFailedException
345
- */
346
- protected function requestAuthToken()
347
- {
348
- /**
349
- * OAuth Core 1.0 Revision A: oauth_callback: An absolute URL to which the Service Provider will redirect
350
- * the User back when the Obtaining User Authorization step is completed.
351
- *
352
- * http://oauth.net/core/1.0a/#auth_step1
353
- */
354
- if ('1.0a' == $this->oauth1Version) {
355
- $this->requestTokenParameters['oauth_callback'] = $this->callback;
356
- }
357
-
358
- $response = $this->oauthRequest(
359
- $this->requestTokenUrl,
360
- $this->requestTokenMethod,
361
- $this->requestTokenParameters,
362
- $this->requestTokenHeaders
363
- );
364
-
365
- return $response;
366
- }
367
-
368
- /**
369
- * Validate Unauthorized Request Token Response
370
- *
371
- * OAuth Core: The Service Provider verifies the signature and Consumer Key. If successful,
372
- * it generates a Request Token and Token Secret and returns them to the Consumer in the HTTP
373
- * response body.
374
- *
375
- * http://oauth.net/core/1.0/#auth_step1
376
- * 6.1.2. Service Provider Issues an Unauthorized Request Token
377
- *
378
- * @param string $response
379
- *
380
- * @return \Hybridauth\Data\Collection
381
- * @throws InvalidOauthTokenException
382
- */
383
- protected function validateAuthTokenRequest($response)
384
- {
385
- /**
386
- * The response contains the following parameters:
387
- *
388
- * - oauth_token The Request Token.
389
- * - oauth_token_secret The Token Secret.
390
- * - oauth_callback_confirmed MUST be present and set to true.
391
- *
392
- * http://oauth.net/core/1.0/#auth_step1
393
- * 6.1.2. Service Provider Issues an Unauthorized Request Token
394
- *
395
- * Example of a successful response:
396
- *
397
- * HTTP/1.1 200 OK
398
- * Content-Type: text/html; charset=utf-8
399
- * Cache-Control: no-store
400
- * Pragma: no-cache
401
- *
402
- * oauth_token=80359084-clg1DEtxQF3wstTcyUdHF3wsdHM&oauth_token_secret=OIF07hPmJB:P
403
- * 6qiHTi1znz6qiH3tTcyUdHnz6qiH3tTcyUdH3xW3wsDvV08e&example_parameter=example_value
404
- *
405
- * OAuthUtil::parse_parameters will attempt to decode the raw response into an array.
406
- */
407
- $tokens = OAuthUtil::parse_parameters($response);
408
-
409
- $collection = new Data\Collection($tokens);
410
-
411
- if (! $collection->exists('oauth_token')) {
412
- throw new InvalidOauthTokenException(
413
- 'Provider returned no oauth_token: ' . htmlentities($response)
414
- );
415
- }
416
-
417
- $this->consumerToken = new OAuthConsumer(
418
- $tokens['oauth_token'],
419
- $tokens['oauth_token_secret']
420
- );
421
-
422
- $this->storeData('request_token', $tokens['oauth_token']);
423
- $this->storeData('request_token_secret', $tokens['oauth_token_secret']);
424
-
425
- return $collection;
426
- }
427
-
428
- /**
429
- * Requests an Access Token
430
- *
431
- * OAuth Core: The Request Token and Token Secret MUST be exchanged for an Access Token and Token Secret.
432
- *
433
- * http://oauth.net/core/1.0a/#auth_step3
434
- * 6.3.1. Consumer Requests an Access Token
435
- *
436
- * @param string $oauth_token
437
- * @param string $oauth_verifier
438
- *
439
- * @return string Raw Provider API response
440
- * @throws \Hybridauth\Exception\HttpClientFailureException
441
- * @throws \Hybridauth\Exception\HttpRequestFailedException
442
- */
443
- protected function exchangeAuthTokenForAccessToken($oauth_token, $oauth_verifier = '')
444
- {
445
- $this->tokenExchangeParameters['oauth_token'] = $oauth_token;
446
-
447
- /**
448
- * OAuth Core 1.0 Revision A: oauth_verifier: The verification code received from the Service Provider
449
- * in the "Service Provider Directs the User Back to the Consumer" step.
450
- *
451
- * http://oauth.net/core/1.0a/#auth_step3
452
- */
453
- if ('1.0a' == $this->oauth1Version) {
454
- $this->tokenExchangeParameters['oauth_verifier'] = $oauth_verifier;
455
- }
456
-
457
- $response = $this->oauthRequest(
458
- $this->accessTokenUrl,
459
- $this->tokenExchangeMethod,
460
- $this->tokenExchangeParameters,
461
- $this->tokenExchangeHeaders
462
- );
463
-
464
- return $response;
465
- }
466
-
467
- /**
468
- * Validate Access Token Response
469
- *
470
- * OAuth Core: If successful, the Service Provider generates an Access Token and Token Secret and returns
471
- * them in the HTTP response body.
472
- *
473
- * The Access Token and Token Secret are stored by the Consumer and used when signing Protected Resources requests.
474
- *
475
- * http://oauth.net/core/1.0a/#auth_step3
476
- * 6.3.2. Service Provider Grants an Access Token
477
- *
478
- * @param string $response
479
- *
480
- * @return \Hybridauth\Data\Collection
481
- * @throws InvalidAccessTokenException
482
- */
483
- protected function validateAccessTokenExchange($response)
484
- {
485
- /**
486
- * The response contains the following parameters:
487
- *
488
- * - oauth_token The Access Token.
489
- * - oauth_token_secret The Token Secret.
490
- *
491
- * http://oauth.net/core/1.0/#auth_step3
492
- * 6.3.2. Service Provider Grants an Access Token
493
- *
494
- * Example of a successful response:
495
- *
496
- * HTTP/1.1 200 OK
497
- * Content-Type: text/html; charset=utf-8
498
- * Cache-Control: no-store
499
- * Pragma: no-cache
500
- *
501
- * oauth_token=sHeLU7Far428zj8PzlWR75&oauth_token_secret=fXb30rzoG&oauth_callback_confirmed=true
502
- *
503
- * OAuthUtil::parse_parameters will attempt to decode the raw response into an array.
504
- */
505
- $tokens = OAuthUtil::parse_parameters($response);
506
-
507
- $collection = new Data\Collection($tokens);
508
-
509
- if (! $collection->exists('oauth_token')) {
510
- throw new InvalidAccessTokenException(
511
- 'Provider returned no access_token: ' . htmlentities($response)
512
- );
513
- }
514
-
515
- $this->consumerToken = new OAuthConsumer(
516
- $collection->get('oauth_token'),
517
- $collection->get('oauth_token_secret')
518
- );
519
-
520
- $this->storeData('access_token', $collection->get('oauth_token'));
521
- $this->storeData('access_token_secret', $collection->get('oauth_token_secret'));
522
-
523
- $this->deleteStoredData('request_token');
524
- $this->deleteStoredData('request_token_secret');
525
-
526
- return $collection;
527
- }
528
-
529
- /**
530
- * Send a signed request to provider API
531
- *
532
- * Note: Since the specifics of error responses is beyond the scope of RFC6749 and OAuth specifications,
533
- * Hybridauth will consider any HTTP status code that is different than '200 OK' as an ERROR.
534
- *
535
- * @param string $url
536
- * @param string $method
537
- * @param array $parameters
538
- * @param array $headers
539
- * @param bool $multipart
540
- *
541
- * @return mixed
542
- * @throws \Hybridauth\Exception\HttpClientFailureException
543
- * @throws \Hybridauth\Exception\HttpRequestFailedException
544
- */
545
- public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
546
- {
547
- if (strrpos($url, 'http://') !== 0 && strrpos($url, 'https://') !== 0) {
548
- $url = rtrim($this->apiBaseUrl, '/') . '/' . ltrim($url, '/');
549
- }
550
-
551
- $parameters = array_replace($this->apiRequestParameters, (array)$parameters);
552
-
553
- $headers = array_replace($this->apiRequestHeaders, (array)$headers);
554
-
555
- $response = $this->oauthRequest($url, $method, $parameters, $headers, $multipart);
556
-
557
- $response = (new Data\Parser())->parse($response);
558
-
559
- return $response;
560
- }
561
-
562
- /**
563
- * Setup and Send a Signed Oauth Request
564
- *
565
- * This method uses OAuth Library.
566
- *
567
- * @param string $uri
568
- * @param string $method
569
- * @param array $parameters
570
- * @param array $headers
571
- * @param bool $multipart
572
- *
573
- * @return string Raw Provider API response
574
- * @throws \Hybridauth\Exception\HttpClientFailureException
575
- * @throws \Hybridauth\Exception\HttpRequestFailedException
576
- */
577
- protected function oauthRequest($uri, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
578
- {
579
- $signing_parameters = $parameters;
580
- if ($multipart) {
581
- $signing_parameters = [];
582
- }
583
-
584
- $request = OAuthRequest::from_consumer_and_token(
585
- $this->OAuthConsumer,
586
- $this->consumerToken,
587
- $method,
588
- $uri,
589
- $signing_parameters
590
- );
591
-
592
- $request->sign_request(
593
- $this->sha1Method,
594
- $this->OAuthConsumer,
595
- $this->consumerToken
596
- );
597
-
598
- $uri = $request->get_normalized_http_url();
599
- $headers = array_replace($request->to_header(), (array) $headers);
600
-
601
- $response = $this->httpClient->request(
602
- $uri,
603
- $method,
604
- $parameters,
605
- $headers,
606
- $multipart
607
- );
608
-
609
- $this->validateApiResponse('Signed API request to ' . $uri . ' has returned an error');
610
-
611
- return $response;
612
- }
613
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Adapter;
9
+
10
+ use Hybridauth\Exception\Exception;
11
+ use Hybridauth\Exception\InvalidApplicationCredentialsException;
12
+ use Hybridauth\Exception\AuthorizationDeniedException;
13
+ use Hybridauth\Exception\InvalidOauthTokenException;
14
+ use Hybridauth\Exception\InvalidAccessTokenException;
15
+ use Hybridauth\Data;
16
+ use Hybridauth\HttpClient;
17
+ use Hybridauth\Thirdparty\OAuth\OAuthConsumer;
18
+ use Hybridauth\Thirdparty\OAuth\OAuthRequest;
19
+ use Hybridauth\Thirdparty\OAuth\OAuthSignatureMethodHMACSHA1;
20
+ use Hybridauth\Thirdparty\OAuth\OAuthUtil;
21
+
22
+ /**
23
+ * This class can be used to simplify the authorization flow of OAuth 1 based service providers.
24
+ *
25
+ * Subclasses (i.e., providers adapters) can either use the already provided methods or override
26
+ * them when necessary.
27
+ */
28
+ abstract class OAuth1 extends AbstractAdapter implements AdapterInterface
29
+ {
30
+ /**
31
+ * Base URL to provider API
32
+ *
33
+ * This var will be used to build urls when sending signed requests
34
+ *
35
+ * @var string
36
+ */
37
+ protected $apiBaseUrl = '';
38
+
39
+ /**
40
+ * @var string
41
+ */
42
+ protected $authorizeUrl = '';
43
+
44
+ /**
45
+ * @var string
46
+ */
47
+ protected $requestTokenUrl = '';
48
+
49
+ /**
50
+ * @var string
51
+ */
52
+ protected $accessTokenUrl = '';
53
+
54
+ /**
55
+ * IPD API Documentation
56
+ *
57
+ * OPTIONAL.
58
+ *
59
+ * @var string
60
+ */
61
+ protected $apiDocumentation = '';
62
+
63
+ /**
64
+ * OAuth Version
65
+ *
66
+ * '1.0' OAuth Core 1.0
67
+ * '1.0a' OAuth Core 1.0 Revision A
68
+ *
69
+ * @var string
70
+ */
71
+ protected $oauth1Version = '1.0a';
72
+
73
+ /**
74
+ * @var string
75
+ */
76
+ protected $consumerKey = null;
77
+
78
+ /**
79
+ * @var string
80
+ */
81
+ protected $consumerSecret = null;
82
+
83
+ /**
84
+ * @var object
85
+ */
86
+ protected $OAuthConsumer = null;
87
+
88
+ /**
89
+ * @var object
90
+ */
91
+ protected $sha1Method = null;
92
+
93
+ /**
94
+ * @var object
95
+ */
96
+ protected $consumerToken = null;
97
+
98
+ /**
99
+ * Authorization Url Parameters
100
+ *
101
+ * @var boolean
102
+ */
103
+ protected $AuthorizeUrlParameters = [];
104
+
105
+ /**
106
+ * @var string
107
+ */
108
+ protected $requestTokenMethod = 'POST';
109
+
110
+ /**
111
+ * @var array
112
+ */
113
+ protected $requestTokenParameters = [];
114
+
115
+ /**
116
+ * @var array
117
+ */
118
+ protected $requestTokenHeaders = [];
119
+
120
+ /**
121
+ * @var string
122
+ */
123
+ protected $tokenExchangeMethod = 'POST';
124
+
125
+ /**
126
+ * @var array
127
+ */
128
+ protected $tokenExchangeParameters = [];
129
+
130
+ /**
131
+ * @var array
132
+ */
133
+ protected $tokenExchangeHeaders = [];
134
+
135
+ /**
136
+ * @var array
137
+ */
138
+ protected $apiRequestParameters = [];
139
+
140
+ /**
141
+ * @var array
142
+ */
143
+ protected $apiRequestHeaders = [];
144
+
145
+ /**
146
+ * {@inheritdoc}
147
+ */
148
+ protected function configure()
149
+ {
150
+ $this->consumerKey = $this->config->filter('keys')->get('id') ?: $this->config->filter('keys')->get('key');
151
+ $this->consumerSecret = $this->config->filter('keys')->get('secret');
152
+
153
+ if (! $this->consumerKey || !$this->consumerSecret) {
154
+ throw new InvalidApplicationCredentialsException(
155
+ 'Your application id is required in order to connect to ' . $this->providerId
156
+ );
157
+ }
158
+
159
+ if ($this->config->exists('tokens')) {
160
+ $this->setAccessToken($this->config->get('tokens'));
161
+ }
162
+
163
+ $this->setCallback($this->config->get('callback'));
164
+ $this->setApiEndpoints($this->config->get('endpoints'));
165
+ }
166
+
167
+ /**
168
+ * {@inheritdoc}
169
+ */
170
+ protected function initialize()
171
+ {
172
+ /**
173
+ * Set up OAuth Signature and Consumer
174
+ *
175
+ * OAuth Core: All Token requests and Protected Resources requests MUST be signed
176
+ * by the Consumer and verified by the Service Provider.
177
+ *
178
+ * The protocol defines three signature methods: HMAC-SHA1, RSA-SHA1, and PLAINTEXT..
179
+ *
180
+ * The Consumer declares a signature method in the oauth_signature_method parameter..
181
+ *
182
+ * http://oauth.net/core/1.0a/#signing_process
183
+ */
184
+ $this->sha1Method = new OAuthSignatureMethodHMACSHA1();
185
+
186
+ $this->OAuthConsumer = new OAuthConsumer(
187
+ $this->consumerKey,
188
+ $this->consumerSecret
189
+ );
190
+
191
+ if ($this->getStoredData('request_token')) {
192
+ $this->consumerToken = new OAuthConsumer(
193
+ $this->getStoredData('request_token'),
194
+ $this->getStoredData('request_token_secret')
195
+ );
196
+ }
197
+
198
+ if ($this->getStoredData('access_token')) {
199
+ $this->consumerToken = new OAuthConsumer(
200
+ $this->getStoredData('access_token'),
201
+ $this->getStoredData('access_token_secret')
202
+ );
203
+ }
204
+ }
205
+
206
+ /**
207
+ * {@inheritdoc}
208
+ */
209
+ public function authenticate()
210
+ {
211
+ $this->logger->info(sprintf('%s::authenticate()', get_class($this)));
212
+
213
+ if ($this->isConnected()) {
214
+ return true;
215
+ }
216
+
217
+ try {
218
+ if (!$this->getStoredData('request_token')) {
219
+ // Start a new flow.
220
+ $this->authenticateBegin();
221
+ } elseif (empty($_GET['oauth_token']) && empty($_GET['denied'])) {
222
+ // A previous authentication was not finished, and this request is not finishing it.
223
+ $this->authenticateBegin();
224
+ } else {
225
+ // Finish a flow.
226
+ $this->authenticateFinish();
227
+ }
228
+ } catch (Exception $exception) {
229
+ $this->clearStoredData();
230
+
231
+ throw $exception;
232
+ }
233
+
234
+ return null;
235
+ }
236
+
237
+ /**
238
+ * {@inheritdoc}
239
+ */
240
+ public function isConnected()
241
+ {
242
+ return (bool)$this->getStoredData('access_token');
243
+ }
244
+
245
+ /**
246
+ * Initiate the authorization protocol
247
+ *
248
+ * 1. Obtaining an Unauthorized Request Token
249
+ * 2. Build Authorization URL for Authorization Request and redirect the user-agent to the
250
+ * Authorization Server.
251
+ */
252
+ protected function authenticateBegin()
253
+ {
254
+ $response = $this->requestAuthToken();
255
+
256
+ $this->validateAuthTokenRequest($response);
257
+
258
+ $authUrl = $this->getAuthorizeUrl();
259
+
260
+ $this->logger->debug(sprintf('%s::authenticateBegin(), redirecting user to:', get_class($this)), [$authUrl]);
261
+
262
+ HttpClient\Util::redirect($authUrl);
263
+ }
264
+
265
+ /**
266
+ * Finalize the authorization process
267
+ *
268
+ * @throws AuthorizationDeniedException
269
+ * @throws \Hybridauth\Exception\HttpClientFailureException
270
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
271
+ * @throws InvalidAccessTokenException
272
+ * @throws InvalidOauthTokenException
273
+ */
274
+ protected function authenticateFinish()
275
+ {
276
+ $this->logger->debug(
277
+ sprintf('%s::authenticateFinish(), callback url:', get_class($this)),
278
+ [HttpClient\Util::getCurrentUrl(true)]
279
+ );
280
+
281
+ $denied = filter_input(INPUT_GET, 'denied');
282
+ $oauth_problem = filter_input(INPUT_GET, 'oauth_problem');
283
+ $oauth_token = filter_input(INPUT_GET, 'oauth_token');
284
+ $oauth_verifier = filter_input(INPUT_GET, 'oauth_verifier');
285
+
286
+ if ($denied) {
287
+ throw new AuthorizationDeniedException(
288
+ 'User denied access request. Provider returned a denied token: ' . htmlentities($denied)
289
+ );
290
+ }
291
+
292
+ if ($oauth_problem) {
293
+ throw new InvalidOauthTokenException(
294
+ 'Provider returned an error. oauth_problem: ' . htmlentities($oauth_problem)
295
+ );
296
+ }
297
+
298
+ if (! $oauth_token) {
299
+ throw new InvalidOauthTokenException(
300
+ 'Expecting a non-null oauth_token to continue the authorization flow.'
301
+ );
302
+ }
303
+
304
+ $response = $this->exchangeAuthTokenForAccessToken($oauth_token, $oauth_verifier);
305
+
306
+ $this->validateAccessTokenExchange($response);
307
+
308
+ $this->initialize();
309
+ }
310
+
311
+ /**
312
+ * Build Authorization URL for Authorization Request
313
+ *
314
+ * @param array $parameters
315
+ *
316
+ * @return string
317
+ */
318
+ protected function getAuthorizeUrl($parameters = [])
319
+ {
320
+ $this->AuthorizeUrlParameters = !empty($parameters)
321
+ ? $parameters
322
+ : array_replace(
323
+ (array) $this->AuthorizeUrlParameters,
324
+ (array) $this->config->get('authorize_url_parameters')
325
+ );
326
+
327
+ $this->AuthorizeUrlParameters['oauth_token'] = $this->getStoredData('request_token');
328
+
329
+ return $this->authorizeUrl . '?' . http_build_query($this->AuthorizeUrlParameters, '', '&');
330
+ }
331
+
332
+ /**
333
+ * Unauthorized Request Token
334
+ *
335
+ * OAuth Core: The Consumer obtains an unauthorized Request Token by asking the Service Provider
336
+ * to issue a Token. The Request Token's sole purpose is to receive User approval and can only
337
+ * be used to obtain an Access Token.
338
+ *
339
+ * http://oauth.net/core/1.0/#auth_step1
340
+ * 6.1.1. Consumer Obtains a Request Token
341
+ *
342
+ * @return string Raw Provider API response
343
+ * @throws \Hybridauth\Exception\HttpClientFailureException
344
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
345
+ */
346
+ protected function requestAuthToken()
347
+ {
348
+ /**
349
+ * OAuth Core 1.0 Revision A: oauth_callback: An absolute URL to which the Service Provider will redirect
350
+ * the User back when the Obtaining User Authorization step is completed.
351
+ *
352
+ * http://oauth.net/core/1.0a/#auth_step1
353
+ */
354
+ if ('1.0a' == $this->oauth1Version) {
355
+ $this->requestTokenParameters['oauth_callback'] = $this->callback;
356
+ }
357
+
358
+ $response = $this->oauthRequest(
359
+ $this->requestTokenUrl,
360
+ $this->requestTokenMethod,
361
+ $this->requestTokenParameters,
362
+ $this->requestTokenHeaders
363
+ );
364
+
365
+ return $response;
366
+ }
367
+
368
+ /**
369
+ * Validate Unauthorized Request Token Response
370
+ *
371
+ * OAuth Core: The Service Provider verifies the signature and Consumer Key. If successful,
372
+ * it generates a Request Token and Token Secret and returns them to the Consumer in the HTTP
373
+ * response body.
374
+ *
375
+ * http://oauth.net/core/1.0/#auth_step1
376
+ * 6.1.2. Service Provider Issues an Unauthorized Request Token
377
+ *
378
+ * @param string $response
379
+ *
380
+ * @return \Hybridauth\Data\Collection
381
+ * @throws InvalidOauthTokenException
382
+ */
383
+ protected function validateAuthTokenRequest($response)
384
+ {
385
+ /**
386
+ * The response contains the following parameters:
387
+ *
388
+ * - oauth_token The Request Token.
389
+ * - oauth_token_secret The Token Secret.
390
+ * - oauth_callback_confirmed MUST be present and set to true.
391
+ *
392
+ * http://oauth.net/core/1.0/#auth_step1
393
+ * 6.1.2. Service Provider Issues an Unauthorized Request Token
394
+ *
395
+ * Example of a successful response:
396
+ *
397
+ * HTTP/1.1 200 OK
398
+ * Content-Type: text/html; charset=utf-8
399
+ * Cache-Control: no-store
400
+ * Pragma: no-cache
401
+ *
402
+ * oauth_token=80359084-clg1DEtxQF3wstTcyUdHF3wsdHM&oauth_token_secret=OIF07hPmJB:P
403
+ * 6qiHTi1znz6qiH3tTcyUdHnz6qiH3tTcyUdH3xW3wsDvV08e&example_parameter=example_value
404
+ *
405
+ * OAuthUtil::parse_parameters will attempt to decode the raw response into an array.
406
+ */
407
+ $tokens = OAuthUtil::parse_parameters($response);
408
+
409
+ $collection = new Data\Collection($tokens);
410
+
411
+ if (! $collection->exists('oauth_token')) {
412
+ throw new InvalidOauthTokenException(
413
+ 'Provider returned no oauth_token: ' . htmlentities($response)
414
+ );
415
+ }
416
+
417
+ $this->consumerToken = new OAuthConsumer(
418
+ $tokens['oauth_token'],
419
+ $tokens['oauth_token_secret']
420
+ );
421
+
422
+ $this->storeData('request_token', $tokens['oauth_token']);
423
+ $this->storeData('request_token_secret', $tokens['oauth_token_secret']);
424
+
425
+ return $collection;
426
+ }
427
+
428
+ /**
429
+ * Requests an Access Token
430
+ *
431
+ * OAuth Core: The Request Token and Token Secret MUST be exchanged for an Access Token and Token Secret.
432
+ *
433
+ * http://oauth.net/core/1.0a/#auth_step3
434
+ * 6.3.1. Consumer Requests an Access Token
435
+ *
436
+ * @param string $oauth_token
437
+ * @param string $oauth_verifier
438
+ *
439
+ * @return string Raw Provider API response
440
+ * @throws \Hybridauth\Exception\HttpClientFailureException
441
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
442
+ */
443
+ protected function exchangeAuthTokenForAccessToken($oauth_token, $oauth_verifier = '')
444
+ {
445
+ $this->tokenExchangeParameters['oauth_token'] = $oauth_token;
446
+
447
+ /**
448
+ * OAuth Core 1.0 Revision A: oauth_verifier: The verification code received from the Service Provider
449
+ * in the "Service Provider Directs the User Back to the Consumer" step.
450
+ *
451
+ * http://oauth.net/core/1.0a/#auth_step3
452
+ */
453
+ if ('1.0a' == $this->oauth1Version) {
454
+ $this->tokenExchangeParameters['oauth_verifier'] = $oauth_verifier;
455
+ }
456
+
457
+ $response = $this->oauthRequest(
458
+ $this->accessTokenUrl,
459
+ $this->tokenExchangeMethod,
460
+ $this->tokenExchangeParameters,
461
+ $this->tokenExchangeHeaders
462
+ );
463
+
464
+ return $response;
465
+ }
466
+
467
+ /**
468
+ * Validate Access Token Response
469
+ *
470
+ * OAuth Core: If successful, the Service Provider generates an Access Token and Token Secret and returns
471
+ * them in the HTTP response body.
472
+ *
473
+ * The Access Token and Token Secret are stored by the Consumer and used when signing Protected Resources requests.
474
+ *
475
+ * http://oauth.net/core/1.0a/#auth_step3
476
+ * 6.3.2. Service Provider Grants an Access Token
477
+ *
478
+ * @param string $response
479
+ *
480
+ * @return \Hybridauth\Data\Collection
481
+ * @throws InvalidAccessTokenException
482
+ */
483
+ protected function validateAccessTokenExchange($response)
484
+ {
485
+ /**
486
+ * The response contains the following parameters:
487
+ *
488
+ * - oauth_token The Access Token.
489
+ * - oauth_token_secret The Token Secret.
490
+ *
491
+ * http://oauth.net/core/1.0/#auth_step3
492
+ * 6.3.2. Service Provider Grants an Access Token
493
+ *
494
+ * Example of a successful response:
495
+ *
496
+ * HTTP/1.1 200 OK
497
+ * Content-Type: text/html; charset=utf-8
498
+ * Cache-Control: no-store
499
+ * Pragma: no-cache
500
+ *
501
+ * oauth_token=sHeLU7Far428zj8PzlWR75&oauth_token_secret=fXb30rzoG&oauth_callback_confirmed=true
502
+ *
503
+ * OAuthUtil::parse_parameters will attempt to decode the raw response into an array.
504
+ */
505
+ $tokens = OAuthUtil::parse_parameters($response);
506
+
507
+ $collection = new Data\Collection($tokens);
508
+
509
+ if (! $collection->exists('oauth_token')) {
510
+ throw new InvalidAccessTokenException(
511
+ 'Provider returned no access_token: ' . htmlentities($response)
512
+ );
513
+ }
514
+
515
+ $this->consumerToken = new OAuthConsumer(
516
+ $collection->get('oauth_token'),
517
+ $collection->get('oauth_token_secret')
518
+ );
519
+
520
+ $this->storeData('access_token', $collection->get('oauth_token'));
521
+ $this->storeData('access_token_secret', $collection->get('oauth_token_secret'));
522
+
523
+ $this->deleteStoredData('request_token');
524
+ $this->deleteStoredData('request_token_secret');
525
+
526
+ return $collection;
527
+ }
528
+
529
+ /**
530
+ * Send a signed request to provider API
531
+ *
532
+ * Note: Since the specifics of error responses is beyond the scope of RFC6749 and OAuth specifications,
533
+ * Hybridauth will consider any HTTP status code that is different than '200 OK' as an ERROR.
534
+ *
535
+ * @param string $url
536
+ * @param string $method
537
+ * @param array $parameters
538
+ * @param array $headers
539
+ * @param bool $multipart
540
+ *
541
+ * @return mixed
542
+ * @throws \Hybridauth\Exception\HttpClientFailureException
543
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
544
+ */
545
+ public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
546
+ {
547
+ if (strrpos($url, 'http://') !== 0 && strrpos($url, 'https://') !== 0) {
548
+ $url = rtrim($this->apiBaseUrl, '/') . '/' . ltrim($url, '/');
549
+ }
550
+
551
+ $parameters = array_replace($this->apiRequestParameters, (array)$parameters);
552
+
553
+ $headers = array_replace($this->apiRequestHeaders, (array)$headers);
554
+
555
+ $response = $this->oauthRequest($url, $method, $parameters, $headers, $multipart);
556
+
557
+ $response = (new Data\Parser())->parse($response);
558
+
559
+ return $response;
560
+ }
561
+
562
+ /**
563
+ * Setup and Send a Signed Oauth Request
564
+ *
565
+ * This method uses OAuth Library.
566
+ *
567
+ * @param string $uri
568
+ * @param string $method
569
+ * @param array $parameters
570
+ * @param array $headers
571
+ * @param bool $multipart
572
+ *
573
+ * @return string Raw Provider API response
574
+ * @throws \Hybridauth\Exception\HttpClientFailureException
575
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
576
+ */
577
+ protected function oauthRequest($uri, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
578
+ {
579
+ $signing_parameters = $parameters;
580
+ if ($multipart) {
581
+ $signing_parameters = [];
582
+ }
583
+
584
+ $request = OAuthRequest::from_consumer_and_token(
585
+ $this->OAuthConsumer,
586
+ $this->consumerToken,
587
+ $method,
588
+ $uri,
589
+ $signing_parameters
590
+ );
591
+
592
+ $request->sign_request(
593
+ $this->sha1Method,
594
+ $this->OAuthConsumer,
595
+ $this->consumerToken
596
+ );
597
+
598
+ $uri = $request->get_normalized_http_url();
599
+ $headers = array_replace($request->to_header(), (array) $headers);
600
+
601
+ $response = $this->httpClient->request(
602
+ $uri,
603
+ $method,
604
+ $parameters,
605
+ $headers,
606
+ $multipart
607
+ );
608
+
609
+ $this->validateApiResponse('Signed API request to ' . $uri . ' has returned an error');
610
+
611
+ return $response;
612
+ }
613
+ }
hybridauth/library/src/Adapter/OAuth2.php CHANGED
@@ -1,738 +1,738 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Adapter;
9
-
10
- use Hybridauth\Exception\Exception;
11
- use Hybridauth\Exception\InvalidApplicationCredentialsException;
12
- use Hybridauth\Exception\InvalidAuthorizationStateException;
13
- use Hybridauth\Exception\InvalidAuthorizationCodeException;
14
- use Hybridauth\Exception\AuthorizationDeniedException;
15
- use Hybridauth\Exception\InvalidAccessTokenException;
16
- use Hybridauth\Data;
17
- use Hybridauth\HttpClient;
18
-
19
- /**
20
- * This class can be used to simplify the authorization flow of OAuth 2 based service providers.
21
- *
22
- * Subclasses (i.e., providers adapters) can either use the already provided methods or override
23
- * them when necessary.
24
- */
25
- abstract class OAuth2 extends AbstractAdapter implements AdapterInterface
26
- {
27
- /**
28
- * Client Identifier
29
- *
30
- * RFC6749: client_id REQUIRED. The client identifier issued to the client during
31
- * the registration process described by Section 2.2.
32
- *
33
- * http://tools.ietf.org/html/rfc6749#section-2.2
34
- *
35
- * @var string
36
- */
37
- protected $clientId = '' ;
38
-
39
- /**
40
- * Client Secret
41
- *
42
- * RFC6749: client_secret REQUIRED. The client secret. The client MAY omit the
43
- * parameter if the client secret is an empty string.
44
- *
45
- * http://tools.ietf.org/html/rfc6749#section-2.2
46
- *
47
- * @var string
48
- */
49
- protected $clientSecret = '' ;
50
-
51
- /**
52
- * Access Token Scope
53
- *
54
- * RFC6749: The authorization and token endpoints allow the client to specify the
55
- * scope of the access request using the "scope" request parameter.
56
- *
57
- * http://tools.ietf.org/html/rfc6749#section-3.3
58
- *
59
- * @var string
60
- */
61
- protected $scope = '';
62
-
63
- /**
64
- * Base URL to provider API
65
- *
66
- * This var will be used to build urls when sending signed requests
67
- *
68
- * @var string
69
- */
70
- protected $apiBaseUrl = '';
71
-
72
- /**
73
- * Authorization Endpoint
74
- *
75
- * RFC6749: The authorization endpoint is used to interact with the resource
76
- * owner and obtain an authorization grant.
77
- *
78
- * http://tools.ietf.org/html/rfc6749#section-3.1
79
- *
80
- * @var string
81
- */
82
- protected $authorizeUrl = '';
83
-
84
- /**
85
- * Access Token Endpoint
86
- *
87
- * RFC6749: The token endpoint is used by the client to obtain an access token by
88
- * presenting its authorization grant or refresh token.
89
- *
90
- * http://tools.ietf.org/html/rfc6749#section-3.2
91
- *
92
- * @var string
93
- */
94
- protected $accessTokenUrl = '';
95
-
96
- /**
97
- * TokenInfo endpoint
98
- *
99
- * Access token validation. OPTIONAL.
100
- *
101
- * @var string
102
- */
103
- protected $accessTokenInfoUrl = '';
104
-
105
- /**
106
- * IPD API Documentation
107
- *
108
- * OPTIONAL.
109
- *
110
- * @var string
111
- */
112
- protected $apiDocumentation = '';
113
-
114
- /**
115
- * Redirection Endpoint or Callback
116
- *
117
- * RFC6749: After completing its interaction with the resource owner, the
118
- * authorization server directs the resource owner's user-agent back to
119
- * the client.
120
- *
121
- * http://tools.ietf.org/html/rfc6749#section-3.1.2
122
- *
123
- * @var string
124
- */
125
- protected $callback = '';
126
-
127
- /**
128
- * Authorization Url Parameters
129
- *
130
- * @var array
131
- */
132
- protected $AuthorizeUrlParameters = [];
133
-
134
-
135
- /**
136
- * Authorization Url Parameter encoding type
137
- * @see https://www.php.net/manual/de/function.http-build-query.php
138
- *
139
- * @var string
140
- */
141
- protected $AuthorizeUrlParametersEncType = PHP_QUERY_RFC1738;
142
-
143
- /**
144
- * Authorization Request State
145
- *
146
- * @var boolean
147
- */
148
- protected $supportRequestState = true;
149
-
150
- /**
151
- * Access Token name
152
- *
153
- * While most providers will use 'access_token' as name for the Access Token attribute, other do not.
154
- * On the latter case, this should be set by sub classes.
155
- *
156
- * @var string
157
- */
158
- protected $accessTokenName = 'access_token';
159
-
160
- /**
161
- * Authorization Request HTTP method.
162
- *
163
- * @see exchangeCodeForAccessToken()
164
- *
165
- * @var string
166
- */
167
- protected $tokenExchangeMethod = 'POST';
168
-
169
- /**
170
- * Authorization Request URL parameters.
171
- *
172
- * Sub classes may change add any additional parameter when necessary.
173
- *
174
- * @see exchangeCodeForAccessToken()
175
- *
176
- * @var array
177
- */
178
- protected $tokenExchangeParameters = [];
179
-
180
- /**
181
- * Authorization Request HTTP headers.
182
- *
183
- * Sub classes may add any additional header when necessary.
184
- *
185
- * @see exchangeCodeForAccessToken()
186
- *
187
- * @var array
188
- */
189
- protected $tokenExchangeHeaders = [];
190
-
191
- /**
192
- * Refresh Token Request HTTP method.
193
- *
194
- * @see refreshAccessToken()
195
- *
196
- * @var string
197
- */
198
- protected $tokenRefreshMethod = 'POST';
199
-
200
- /**
201
- * Refresh Token Request URL parameters.
202
- *
203
- * Sub classes may change add any additional parameter when necessary.
204
- *
205
- * @see refreshAccessToken()
206
- *
207
- * @var array|null
208
- */
209
- protected $tokenRefreshParameters = null;
210
-
211
- /**
212
- * Refresh Token Request HTTP headers.
213
- *
214
- * Sub classes may add any additional header when necessary.
215
- *
216
- * @see refreshAccessToken()
217
- *
218
- * @var array
219
- */
220
- protected $tokenRefreshHeaders = [];
221
-
222
- /**
223
- * Authorization Request URL parameters.
224
- *
225
- * Sub classes may change add any additional parameter when necessary.
226
- *
227
- * @see apiRequest()
228
- *
229
- * @var array
230
- */
231
- protected $apiRequestParameters = [];
232
-
233
- /**
234
- * Authorization Request HTTP headers.
235
- *
236
- * Sub classes may add any additional header when necessary.
237
- *
238
- * @see apiRequest()
239
- *
240
- * @var array
241
- */
242
- protected $apiRequestHeaders = [];
243
-
244
- /**
245
- * {@inheritdoc}
246
- */
247
- protected function configure()
248
- {
249
- $this->clientId = $this->config->filter('keys')->get('id') ?: $this->config->filter('keys')->get('key');
250
- $this->clientSecret = $this->config->filter('keys')->get('secret');
251
-
252
- if (! $this->clientId || !$this->clientSecret) {
253
- throw new InvalidApplicationCredentialsException(
254
- 'Your application id is required in order to connect to ' . $this->providerId
255
- );
256
- }
257
-
258
- $this->scope = $this->config->exists('scope') ? $this->config->get('scope') : $this->scope;
259
-
260
- if ($this->config->exists('tokens')) {
261
- $this->setAccessToken($this->config->get('tokens'));
262
- }
263
-
264
- $this->setCallback($this->config->get('callback'));
265
- $this->setApiEndpoints($this->config->get('endpoints'));
266
- }
267
-
268
- /**
269
- * {@inheritdoc}
270
- */
271
- protected function initialize()
272
- {
273
- $this->AuthorizeUrlParameters = [
274
- 'response_type' => 'code',
275
- 'client_id' => $this->clientId,
276
- 'redirect_uri' => $this->callback,
277
- 'scope' => $this->scope,
278
- ];
279
-
280
- $this->tokenExchangeParameters = [
281
- 'client_id' => $this->clientId,
282
- 'client_secret' => $this->clientSecret,
283
- 'grant_type' => 'authorization_code',
284
- 'redirect_uri' => $this->callback
285
- ];
286
-
287
- $refreshToken = $this->getStoredData('refresh_token');
288
- if (!empty($refreshToken)) {
289
- $this->tokenRefreshParameters = [
290
- 'grant_type' => 'refresh_token',
291
- 'refresh_token' => $refreshToken,
292
- ];
293
- }
294
-
295
- $this->apiRequestHeaders = [
296
- 'Authorization' => 'Bearer ' . $this->getStoredData('access_token')
297
- ];
298
- }
299
-
300
- /**
301
- * {@inheritdoc}
302
- */
303
- public function authenticate()
304
- {
305
- $this->logger->info(sprintf('%s::authenticate()', get_class($this)));
306
-
307
- if ($this->isConnected()) {
308
- return true;
309
- }
310
-
311
- try {
312
- $this->authenticateCheckError();
313
-
314
- $code = filter_input($_SERVER['REQUEST_METHOD'] === 'POST' ? INPUT_POST : INPUT_GET, 'code');
315
-
316
- if (empty($code)) {
317
- $this->authenticateBegin();
318
- } else {
319
- $this->authenticateFinish();
320
- }
321
- } catch (Exception $e) {
322
- $this->clearStoredData();
323
-
324
- throw $e;
325
- }
326
-
327
- return null;
328
- }
329
-
330
- /**
331
- * {@inheritdoc}
332
- */
333
- public function isConnected()
334
- {
335
- if ((bool)$this->getStoredData('access_token')) {
336
- return (!$this->hasAccessTokenExpired() || $this->isRefreshTokenAvailable());
337
- }
338
- return false;
339
- }
340
-
341
- /**
342
- * If we can use a refresh token, then an expired token does not stop us being connected.
343
- *
344
- * @return bool
345
- */
346
- public function isRefreshTokenAvailable()
347
- {
348
- return is_array($this->tokenRefreshParameters);
349
- }
350
-
351
- /**
352
- * Authorization Request Error Response
353
- *
354
- * RFC6749: If the request fails due to a missing, invalid, or mismatching
355
- * redirection URI, or if the client identifier is missing or invalid,
356
- * the authorization server SHOULD inform the resource owner of the error.
357
- *
358
- * http://tools.ietf.org/html/rfc6749#section-4.1.2.1
359
- *
360
- * @throws \Hybridauth\Exception\InvalidAuthorizationCodeException
361
- * @throws \Hybridauth\Exception\AuthorizationDeniedException
362
- */
363
- protected function authenticateCheckError()
364
- {
365
- $error = filter_input(INPUT_GET, 'error', FILTER_SANITIZE_SPECIAL_CHARS);
366
-
367
- if (! empty($error)) {
368
- $error_description = filter_input(INPUT_GET, 'error_description', FILTER_SANITIZE_SPECIAL_CHARS);
369
- $error_uri = filter_input(INPUT_GET, 'error_uri', FILTER_SANITIZE_SPECIAL_CHARS);
370
-
371
- $collated_error = sprintf('Provider returned an error: %s %s %s', $error, $error_description, $error_uri);
372
-
373
- if ($error == 'access_denied') {
374
- throw new AuthorizationDeniedException($collated_error);
375
- }
376
-
377
- throw new InvalidAuthorizationCodeException($collated_error);
378
- }
379
- }
380
-
381
- /**
382
- * Initiate the authorization protocol
383
- *
384
- * Build Authorization URL for Authorization Request and redirect the user-agent to the
385
- * Authorization Server.
386
- */
387
- protected function authenticateBegin()
388
- {
389
- $authUrl = $this->getAuthorizeUrl();
390
-
391
- $this->logger->debug(sprintf('%s::authenticateBegin(), redirecting user to:', get_class($this)), [$authUrl]);
392
-
393
- HttpClient\Util::redirect($authUrl);
394
- }
395
-
396
- /**
397
- * Finalize the authorization process
398
- *
399
- * @throws \Hybridauth\Exception\HttpClientFailureException
400
- * @throws \Hybridauth\Exception\HttpRequestFailedException
401
- * @throws InvalidAccessTokenException
402
- * @throws InvalidAuthorizationStateException
403
- */
404
- protected function authenticateFinish()
405
- {
406
- $this->logger->debug(
407
- sprintf('%s::authenticateFinish(), callback url:', get_class($this)),
408
- [HttpClient\Util::getCurrentUrl(true)]
409
- );
410
-
411
- $state = filter_input($_SERVER['REQUEST_METHOD'] === 'POST' ? INPUT_POST : INPUT_GET, 'state');
412
- $code = filter_input($_SERVER['REQUEST_METHOD'] === 'POST' ? INPUT_POST : INPUT_GET, 'code');
413
-
414
- /**
415
- * Authorization Request State
416
- *
417
- * RFC6749: state : RECOMMENDED. An opaque value used by the client to maintain
418
- * state between the request and callback. The authorization server includes
419
- * this value when redirecting the user-agent back to the client.
420
- *
421
- * http://tools.ietf.org/html/rfc6749#section-4.1.1
422
- */
423
- if ($this->supportRequestState
424
- && $this->getStoredData('authorization_state') != $state
425
- ) {
426
- throw new InvalidAuthorizationStateException(
427
- 'The authorization state [state=' . substr(htmlentities($state), 0, 100). '] '
428
- . 'of this page is either invalid or has already been consumed.'
429
- );
430
- }
431
-
432
- /**
433
- * Authorization Request Code
434
- *
435
- * RFC6749: If the resource owner grants the access request, the authorization
436
- * server issues an authorization code and delivers it to the client:
437
- *
438
- * http://tools.ietf.org/html/rfc6749#section-4.1.2
439
- */
440
- $response = $this->exchangeCodeForAccessToken($code);
441
-
442
- $this->validateAccessTokenExchange($response);
443
-
444
- $this->initialize();
445
- }
446
-
447
- /**
448
- * Build Authorization URL for Authorization Request
449
- *
450
- * RFC6749: The client constructs the request URI by adding the following
451
- * $parameters to the query component of the authorization endpoint URI:
452
- *
453
- * - response_type REQUIRED. Value MUST be set to "code".
454
- * - client_id REQUIRED.
455
- * - redirect_uri OPTIONAL.
456
- * - scope OPTIONAL.
457
- * - state RECOMMENDED.
458
- *
459
- * http://tools.ietf.org/html/rfc6749#section-4.1.1
460
- *
461
- * Sub classes may redefine this method when necessary.
462
- *
463
- * @param array $parameters
464
- *
465
- * @return string Authorization URL
466
- */
467
- protected function getAuthorizeUrl($parameters = [])
468
- {
469
- $this->AuthorizeUrlParameters = !empty($parameters)
470
- ? $parameters
471
- : array_replace(
472
- (array) $this->AuthorizeUrlParameters,
473
- (array) $this->config->get('authorize_url_parameters')
474
- );
475
-
476
- if ($this->supportRequestState) {
477
- if (!isset($this->AuthorizeUrlParameters['state'])) {
478
- $this->AuthorizeUrlParameters['state'] = 'HA-' . str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890');
479
- }
480
-
481
- $this->storeData('authorization_state', $this->AuthorizeUrlParameters['state']);
482
- }
483
-
484
- $queryParams = http_build_query($this->AuthorizeUrlParameters, '', '&', $this->AuthorizeUrlParametersEncType);
485
- return $this->authorizeUrl . '?' . $queryParams;
486
- }
487
-
488
- /**
489
- * Access Token Request
490
- *
491
- * This method will exchange the received $code in loginFinish() with an Access Token.
492
- *
493
- * RFC6749: The client makes a request to the token endpoint by sending the
494
- * following parameters using the "application/x-www-form-urlencoded"
495
- * with a character encoding of UTF-8 in the HTTP request entity-body:
496
- *
497
- * - grant_type REQUIRED. Value MUST be set to "authorization_code".
498
- * - code REQUIRED. The authorization code received from the authorization server.
499
- * - redirect_uri REQUIRED.
500
- * - client_id REQUIRED.
501
- *
502
- * http://tools.ietf.org/html/rfc6749#section-4.1.3
503
- *
504
- * @param string $code
505
- *
506
- * @return string Raw Provider API response
507
- * @throws \Hybridauth\Exception\HttpClientFailureException
508
- * @throws \Hybridauth\Exception\HttpRequestFailedException
509
- */
510
- protected function exchangeCodeForAccessToken($code)
511
- {
512
- $this->tokenExchangeParameters['code'] = $code;
513
-
514
- $response = $this->httpClient->request(
515
- $this->accessTokenUrl,
516
- $this->tokenExchangeMethod,
517
- $this->tokenExchangeParameters,
518
- $this->tokenExchangeHeaders
519
- );
520
-
521
- $this->validateApiResponse('Unable to exchange code for API access token');
522
-
523
- return $response;
524
- }
525
-
526
- /**
527
- * Validate Access Token Response
528
- *
529
- * RFC6749: If the access token request is valid and authorized, the
530
- * authorization server issues an access token and optional refresh token.
531
- * If the request client authentication failed or is invalid, the authorization
532
- * server returns an error response as described in Section 5.2.
533
- *
534
- * Example of a successful response:
535
- *
536
- * HTTP/1.1 200 OK
537
- * Content-Type: application/json;charset=UTF-8
538
- * Cache-Control: no-store
539
- * Pragma: no-cache
540
- *
541
- * {
542
- * "access_token":"2YotnFZFEjr1zCsicMWpAA",
543
- * "token_type":"example",
544
- * "expires_in":3600,
545
- * "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
546
- * "example_parameter":"example_value"
547
- * }
548
- *
549
- * http://tools.ietf.org/html/rfc6749#section-4.1.4
550
- *
551
- * This method uses Data_Parser to attempt to decodes the raw $response (usually JSON)
552
- * into a data collection.
553
- *
554
- * @param string $response
555
- *
556
- * @return \Hybridauth\Data\Collection
557
- * @throws InvalidAccessTokenException
558
- */
559
- protected function validateAccessTokenExchange($response)
560
- {
561
- $data = (new Data\Parser())->parse($response);
562
-
563
- $collection = new Data\Collection($data);
564
-
565
- if (! $collection->exists('access_token')) {
566
- throw new InvalidAccessTokenException(
567
- 'Provider returned no access_token: ' . htmlentities($response)
568
- );
569
- }
570
-
571
- $this->storeData('access_token', $collection->get('access_token'));
572
- $this->storeData('token_type', $collection->get('token_type'));
573
-
574
- if ($collection->get('refresh_token')) {
575
- $this->storeData('refresh_token', $collection->get('refresh_token'));
576
- }
577
-
578
- // calculate when the access token expire
579
- if ($collection->exists('expires_in')) {
580
- $expires_at = time() + (int) $collection->get('expires_in');
581
-
582
- $this->storeData('expires_in', $collection->get('expires_in'));
583
- $this->storeData('expires_at', $expires_at);
584
- }
585
-
586
- $this->deleteStoredData('authorization_state');
587
-
588
- $this->initialize();
589
-
590
- return $collection;
591
- }
592
-
593
- /**
594
- * Refreshing an Access Token
595
- *
596
- * RFC6749: If the authorization server issued a refresh token to the
597
- * client, the client makes a refresh request to the token endpoint by
598
- * adding the following parameters ... in the HTTP request entity-body:
599
- *
600
- * - grant_type REQUIRED. Value MUST be set to "refresh_token".
601
- * - refresh_token REQUIRED. The refresh token issued to the client.
602
- * - scope OPTIONAL.
603
- *
604
- * http://tools.ietf.org/html/rfc6749#section-6
605
- *
606
- * This method is similar to exchangeCodeForAccessToken(). The only
607
- * difference is here we exchange refresh_token for a new access_token.
608
- *
609
- * @param array $parameters
610
- *
611
- * @return string|null Raw Provider API response, or null if we cannot refresh
612
- * @throws \Hybridauth\Exception\HttpClientFailureException
613
- * @throws \Hybridauth\Exception\HttpRequestFailedException
614
- * @throws InvalidAccessTokenException
615
- */
616
- public function refreshAccessToken($parameters = [])
617
- {
618
- $this->tokenRefreshParameters = !empty($parameters)
619
- ? $parameters
620
- : $this->tokenRefreshParameters;
621
-
622
- if (!$this->isRefreshTokenAvailable()) {
623
- return null;
624
- }
625
-
626
- $response = $this->httpClient->request(
627
- $this->accessTokenUrl,
628
- $this->tokenRefreshMethod,
629
- $this->tokenRefreshParameters,
630
- $this->tokenRefreshHeaders
631
- );
632
-
633
- $this->validateApiResponse('Unable to refresh the access token');
634
-
635
- $this->validateRefreshAccessToken($response);
636
-
637
- return $response;
638
- }
639
-
640
- /**
641
- * Check whether access token has expired
642
- *
643
- * @param int|null $time
644
- * @return bool|null
645
- */
646
- public function hasAccessTokenExpired($time = null)
647
- {
648
- if ($time === null) {
649
- $time = time();
650
- }
651
-
652
- $expires_at = $this->getStoredData('expires_at');
653
- if (!$expires_at) {
654
- return null;
655
- }
656
-
657
- return $expires_at <= $time;
658
- }
659
-
660
- /**
661
- * Validate Refresh Access Token Request
662
- *
663
- * RFC6749: If valid and authorized, the authorization server issues an
664
- * access token as described in Section 5.1. If the request failed
665
- * verification or is invalid, the authorization server returns an error
666
- * response as described in Section 5.2.
667
- *
668
- * http://tools.ietf.org/html/rfc6749#section-6
669
- * http://tools.ietf.org/html/rfc6749#section-5.1
670
- * http://tools.ietf.org/html/rfc6749#section-5.2
671
- *
672
- * This method simply use validateAccessTokenExchange(), however sub
673
- * classes may redefine it when necessary.
674
- *
675
- * @param $response
676
- *
677
- * @return \Hybridauth\Data\Collection
678
- * @throws InvalidAccessTokenException
679
- */
680
- protected function validateRefreshAccessToken($response)
681
- {
682
- return $this->validateAccessTokenExchange($response);
683
- }
684
-
685
- /**
686
- * Send a signed request to provider API
687
- *
688
- * RFC6749: Accessing Protected Resources: The client accesses protected
689
- * resources by presenting the access token to the resource server. The
690
- * resource server MUST validate the access token and ensure that it has
691
- * not expired and that its scope covers the requested resource.
692
- *
693
- * Note: Since the specifics of error responses is beyond the scope of
694
- * RFC6749 and OAuth specifications, Hybridauth will consider any HTTP
695
- * status code that is different than '200 OK' as an ERROR.
696
- *
697
- * http://tools.ietf.org/html/rfc6749#section-7
698
- *
699
- * @param string $url
700
- * @param string $method
701
- * @param array $parameters
702
- * @param array $headers
703
- * @param bool $multipart
704
- *
705
- * @return mixed
706
- * @throws \Hybridauth\Exception\HttpClientFailureException
707
- * @throws \Hybridauth\Exception\HttpRequestFailedException
708
- * @throws InvalidAccessTokenException
709
- */
710
- public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
711
- {
712
- // refresh tokens if needed
713
- if ($this->hasAccessTokenExpired() === true) {
714
- $this->refreshAccessToken();
715
- }
716
-
717
- if (strrpos($url, 'http://') !== 0 && strrpos($url, 'https://') !== 0) {
718
- $url = rtrim($this->apiBaseUrl, '/') . '/' . ltrim($url, '/');
719
- }
720
-
721
- $parameters = array_replace($this->apiRequestParameters, (array) $parameters);
722
- $headers = array_replace($this->apiRequestHeaders, (array) $headers);
723
-
724
- $response = $this->httpClient->request(
725
- $url,
726
- $method, // HTTP Request Method. Defaults to GET.
727
- $parameters, // Request Parameters
728
- $headers, // Request Headers
729
- $multipart // Is request multipart
730
- );
731
-
732
- $this->validateApiResponse('Signed API request to ' . $url . ' has returned an error');
733
-
734
- $response = (new Data\Parser())->parse($response);
735
-
736
- return $response;
737
- }
738
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Adapter;
9
+
10
+ use Hybridauth\Exception\Exception;
11
+ use Hybridauth\Exception\InvalidApplicationCredentialsException;
12
+ use Hybridauth\Exception\InvalidAuthorizationStateException;
13
+ use Hybridauth\Exception\InvalidAuthorizationCodeException;
14
+ use Hybridauth\Exception\AuthorizationDeniedException;
15
+ use Hybridauth\Exception\InvalidAccessTokenException;
16
+ use Hybridauth\Data;
17
+ use Hybridauth\HttpClient;
18
+
19
+ /**
20
+ * This class can be used to simplify the authorization flow of OAuth 2 based service providers.
21
+ *
22
+ * Subclasses (i.e., providers adapters) can either use the already provided methods or override
23
+ * them when necessary.
24
+ */
25
+ abstract class OAuth2 extends AbstractAdapter implements AdapterInterface
26
+ {
27
+ /**
28
+ * Client Identifier
29
+ *
30
+ * RFC6749: client_id REQUIRED. The client identifier issued to the client during
31
+ * the registration process described by Section 2.2.
32
+ *
33
+ * http://tools.ietf.org/html/rfc6749#section-2.2
34
+ *
35
+ * @var string
36
+ */
37
+ protected $clientId = '' ;
38
+
39
+ /**
40
+ * Client Secret
41
+ *
42
+ * RFC6749: client_secret REQUIRED. The client secret. The client MAY omit the
43
+ * parameter if the client secret is an empty string.
44
+ *
45
+ * http://tools.ietf.org/html/rfc6749#section-2.2
46
+ *
47
+ * @var string
48
+ */
49
+ protected $clientSecret = '' ;
50
+
51
+ /**
52
+ * Access Token Scope
53
+ *
54
+ * RFC6749: The authorization and token endpoints allow the client to specify the
55
+ * scope of the access request using the "scope" request parameter.
56
+ *
57
+ * http://tools.ietf.org/html/rfc6749#section-3.3
58
+ *
59
+ * @var string
60
+ */
61
+ protected $scope = '';
62
+
63
+ /**
64
+ * Base URL to provider API
65
+ *
66
+ * This var will be used to build urls when sending signed requests
67
+ *
68
+ * @var string
69
+ */
70
+ protected $apiBaseUrl = '';
71
+
72
+ /**
73
+ * Authorization Endpoint
74
+ *
75
+ * RFC6749: The authorization endpoint is used to interact with the resource
76
+ * owner and obtain an authorization grant.
77
+ *
78
+ * http://tools.ietf.org/html/rfc6749#section-3.1
79
+ *
80
+ * @var string
81
+ */
82
+ protected $authorizeUrl = '';
83
+
84
+ /**
85
+ * Access Token Endpoint
86
+ *
87
+ * RFC6749: The token endpoint is used by the client to obtain an access token by
88
+ * presenting its authorization grant or refresh token.
89
+ *
90
+ * http://tools.ietf.org/html/rfc6749#section-3.2
91
+ *
92
+ * @var string
93
+ */
94
+ protected $accessTokenUrl = '';
95
+
96
+ /**
97
+ * TokenInfo endpoint
98
+ *
99
+ * Access token validation. OPTIONAL.
100
+ *
101
+ * @var string
102
+ */
103
+ protected $accessTokenInfoUrl = '';
104
+
105
+ /**
106
+ * IPD API Documentation
107
+ *
108
+ * OPTIONAL.
109
+ *
110
+ * @var string
111
+ */
112
+ protected $apiDocumentation = '';
113
+
114
+ /**
115
+ * Redirection Endpoint or Callback
116
+ *
117
+ * RFC6749: After completing its interaction with the resource owner, the
118
+ * authorization server directs the resource owner's user-agent back to
119
+ * the client.
120
+ *
121
+ * http://tools.ietf.org/html/rfc6749#section-3.1.2
122
+ *
123
+ * @var string
124
+ */
125
+ protected $callback = '';
126
+
127
+ /**
128
+ * Authorization Url Parameters
129
+ *
130
+ * @var array
131
+ */
132
+ protected $AuthorizeUrlParameters = [];
133
+
134
+
135
+ /**
136
+ * Authorization Url Parameter encoding type
137
+ * @see https://www.php.net/manual/de/function.http-build-query.php
138
+ *
139
+ * @var string
140
+ */
141
+ protected $AuthorizeUrlParametersEncType = PHP_QUERY_RFC1738;
142
+
143
+ /**
144
+ * Authorization Request State
145
+ *
146
+ * @var boolean
147
+ */
148
+ protected $supportRequestState = true;
149
+
150
+ /**
151
+ * Access Token name
152
+ *
153
+ * While most providers will use 'access_token' as name for the Access Token attribute, other do not.
154
+ * On the latter case, this should be set by sub classes.
155
+ *
156
+ * @var string
157
+ */
158
+ protected $accessTokenName = 'access_token';
159
+
160
+ /**
161
+ * Authorization Request HTTP method.
162
+ *
163
+ * @see exchangeCodeForAccessToken()
164
+ *
165
+ * @var string
166
+ */
167
+ protected $tokenExchangeMethod = 'POST';
168
+
169
+ /**
170
+ * Authorization Request URL parameters.
171
+ *
172
+ * Sub classes may change add any additional parameter when necessary.
173
+ *
174
+ * @see exchangeCodeForAccessToken()
175
+ *
176
+ * @var array
177
+ */
178
+ protected $tokenExchangeParameters = [];
179
+
180
+ /**
181
+ * Authorization Request HTTP headers.
182
+ *
183
+ * Sub classes may add any additional header when necessary.
184
+ *
185
+ * @see exchangeCodeForAccessToken()
186
+ *
187
+ * @var array
188
+ */
189
+ protected $tokenExchangeHeaders = [];
190
+
191
+ /**
192
+ * Refresh Token Request HTTP method.
193
+ *
194
+ * @see refreshAccessToken()
195
+ *
196
+ * @var string
197
+ */
198
+ protected $tokenRefreshMethod = 'POST';
199
+
200
+ /**
201
+ * Refresh Token Request URL parameters.
202
+ *
203
+ * Sub classes may change add any additional parameter when necessary.
204
+ *
205
+ * @see refreshAccessToken()
206
+ *
207
+ * @var array|null
208
+ */
209
+ protected $tokenRefreshParameters = null;
210
+
211
+ /**
212
+ * Refresh Token Request HTTP headers.
213
+ *
214
+ * Sub classes may add any additional header when necessary.
215
+ *
216
+ * @see refreshAccessToken()
217
+ *
218
+ * @var array
219
+ */
220
+ protected $tokenRefreshHeaders = [];
221
+
222
+ /**
223
+ * Authorization Request URL parameters.
224
+ *
225
+ * Sub classes may change add any additional parameter when necessary.
226
+ *
227
+ * @see apiRequest()
228
+ *
229
+ * @var array
230
+ */
231
+ protected $apiRequestParameters = [];
232
+
233
+ /**
234
+ * Authorization Request HTTP headers.
235
+ *
236
+ * Sub classes may add any additional header when necessary.
237
+ *
238
+ * @see apiRequest()
239
+ *
240
+ * @var array
241
+ */
242
+ protected $apiRequestHeaders = [];
243
+
244
+ /**
245
+ * {@inheritdoc}
246
+ */
247
+ protected function configure()
248
+ {
249
+ $this->clientId = $this->config->filter('keys')->get('id') ?: $this->config->filter('keys')->get('key');
250
+ $this->clientSecret = $this->config->filter('keys')->get('secret');
251
+
252
+ if (! $this->clientId || !$this->clientSecret) {
253
+ throw new InvalidApplicationCredentialsException(
254
+ 'Your application id is required in order to connect to ' . $this->providerId
255
+ );
256
+ }
257
+
258
+ $this->scope = $this->config->exists('scope') ? $this->config->get('scope') : $this->scope;
259
+
260
+ if ($this->config->exists('tokens')) {
261
+ $this->setAccessToken($this->config->get('tokens'));
262
+ }
263
+
264
+ $this->setCallback($this->config->get('callback'));
265
+ $this->setApiEndpoints($this->config->get('endpoints'));
266
+ }
267
+
268
+ /**
269
+ * {@inheritdoc}
270
+ */
271
+ protected function initialize()
272
+ {
273
+ $this->AuthorizeUrlParameters = [
274
+ 'response_type' => 'code',
275
+ 'client_id' => $this->clientId,
276
+ 'redirect_uri' => $this->callback,
277
+ 'scope' => $this->scope,
278
+ ];
279
+
280
+ $this->tokenExchangeParameters = [
281
+ 'client_id' => $this->clientId,
282
+ 'client_secret' => $this->clientSecret,
283
+ 'grant_type' => 'authorization_code',
284
+ 'redirect_uri' => $this->callback
285
+ ];
286
+
287
+ $refreshToken = $this->getStoredData('refresh_token');
288
+ if (!empty($refreshToken)) {
289
+ $this->tokenRefreshParameters = [
290
+ 'grant_type' => 'refresh_token',
291
+ 'refresh_token' => $refreshToken,
292
+ ];
293
+ }
294
+
295
+ $this->apiRequestHeaders = [
296
+ 'Authorization' => 'Bearer ' . $this->getStoredData('access_token')
297
+ ];
298
+ }
299
+
300
+ /**
301
+ * {@inheritdoc}
302
+ */
303
+ public function authenticate()
304
+ {
305
+ $this->logger->info(sprintf('%s::authenticate()', get_class($this)));
306
+
307
+ if ($this->isConnected()) {
308
+ return true;
309
+ }
310
+
311
+ try {
312
+ $this->authenticateCheckError();
313
+
314
+ $code = filter_input($_SERVER['REQUEST_METHOD'] === 'POST' ? INPUT_POST : INPUT_GET, 'code');
315
+
316
+ if (empty($code)) {
317
+ $this->authenticateBegin();
318
+ } else {
319
+ $this->authenticateFinish();
320
+ }
321
+ } catch (Exception $e) {
322
+ $this->clearStoredData();
323
+
324
+ throw $e;
325
+ }
326
+
327
+ return null;
328
+ }
329
+
330
+ /**
331
+ * {@inheritdoc}
332
+ */
333
+ public function isConnected()
334
+ {
335
+ if ((bool)$this->getStoredData('access_token')) {
336
+ return (!$this->hasAccessTokenExpired() || $this->isRefreshTokenAvailable());
337
+ }
338
+ return false;
339
+ }
340
+
341
+ /**
342
+ * If we can use a refresh token, then an expired token does not stop us being connected.
343
+ *
344
+ * @return bool
345
+ */
346
+ public function isRefreshTokenAvailable()
347
+ {
348
+ return is_array($this->tokenRefreshParameters);
349
+ }
350
+
351
+ /**
352
+ * Authorization Request Error Response
353
+ *
354
+ * RFC6749: If the request fails due to a missing, invalid, or mismatching
355
+ * redirection URI, or if the client identifier is missing or invalid,
356
+ * the authorization server SHOULD inform the resource owner of the error.
357
+ *
358
+ * http://tools.ietf.org/html/rfc6749#section-4.1.2.1
359
+ *
360
+ * @throws \Hybridauth\Exception\InvalidAuthorizationCodeException
361
+ * @throws \Hybridauth\Exception\AuthorizationDeniedException
362
+ */
363
+ protected function authenticateCheckError()
364
+ {
365
+ $error = filter_input(INPUT_GET, 'error', FILTER_SANITIZE_SPECIAL_CHARS);
366
+
367
+ if (! empty($error)) {
368
+ $error_description = filter_input(INPUT_GET, 'error_description', FILTER_SANITIZE_SPECIAL_CHARS);
369
+ $error_uri = filter_input(INPUT_GET, 'error_uri', FILTER_SANITIZE_SPECIAL_CHARS);
370
+
371
+ $collated_error = sprintf('Provider returned an error: %s %s %s', $error, $error_description, $error_uri);
372
+
373
+ if ($error == 'access_denied') {
374
+ throw new AuthorizationDeniedException($collated_error);
375
+ }
376
+
377
+ throw new InvalidAuthorizationCodeException($collated_error);
378
+ }
379
+ }
380
+
381
+ /**
382
+ * Initiate the authorization protocol
383
+ *
384
+ * Build Authorization URL for Authorization Request and redirect the user-agent to the
385
+ * Authorization Server.
386
+ */
387
+ protected function authenticateBegin()
388
+ {
389
+ $authUrl = $this->getAuthorizeUrl();
390
+
391
+ $this->logger->debug(sprintf('%s::authenticateBegin(), redirecting user to:', get_class($this)), [$authUrl]);
392
+
393
+ HttpClient\Util::redirect($authUrl);
394
+ }
395
+
396
+ /**
397
+ * Finalize the authorization process
398
+ *
399
+ * @throws \Hybridauth\Exception\HttpClientFailureException
400
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
401
+ * @throws InvalidAccessTokenException
402
+ * @throws InvalidAuthorizationStateException
403
+ */
404
+ protected function authenticateFinish()
405
+ {
406
+ $this->logger->debug(
407
+ sprintf('%s::authenticateFinish(), callback url:', get_class($this)),
408
+ [HttpClient\Util::getCurrentUrl(true)]
409
+ );
410
+
411
+ $state = filter_input($_SERVER['REQUEST_METHOD'] === 'POST' ? INPUT_POST : INPUT_GET, 'state');
412
+ $code = filter_input($_SERVER['REQUEST_METHOD'] === 'POST' ? INPUT_POST : INPUT_GET, 'code');
413
+
414
+ /**
415
+ * Authorization Request State
416
+ *
417
+ * RFC6749: state : RECOMMENDED. An opaque value used by the client to maintain
418
+ * state between the request and callback. The authorization server includes
419
+ * this value when redirecting the user-agent back to the client.
420
+ *
421
+ * http://tools.ietf.org/html/rfc6749#section-4.1.1
422
+ */
423
+ if ($this->supportRequestState
424
+ && $this->getStoredData('authorization_state') != $state
425
+ ) {
426
+ throw new InvalidAuthorizationStateException(
427
+ 'The authorization state [state=' . substr(htmlentities($state), 0, 100). '] '
428
+ . 'of this page is either invalid or has already been consumed.'
429
+ );
430
+ }
431
+
432
+ /**
433
+ * Authorization Request Code
434
+ *
435
+ * RFC6749: If the resource owner grants the access request, the authorization
436
+ * server issues an authorization code and delivers it to the client:
437
+ *
438
+ * http://tools.ietf.org/html/rfc6749#section-4.1.2
439
+ */
440
+ $response = $this->exchangeCodeForAccessToken($code);
441
+
442
+ $this->validateAccessTokenExchange($response);
443
+
444
+ $this->initialize();
445
+ }
446
+
447
+ /**
448
+ * Build Authorization URL for Authorization Request
449
+ *
450
+ * RFC6749: The client constructs the request URI by adding the following
451
+ * $parameters to the query component of the authorization endpoint URI:
452
+ *
453
+ * - response_type REQUIRED. Value MUST be set to "code".
454
+ * - client_id REQUIRED.
455
+ * - redirect_uri OPTIONAL.
456
+ * - scope OPTIONAL.
457
+ * - state RECOMMENDED.
458
+ *
459
+ * http://tools.ietf.org/html/rfc6749#section-4.1.1
460
+ *
461
+ * Sub classes may redefine this method when necessary.
462
+ *
463
+ * @param array $parameters
464
+ *
465
+ * @return string Authorization URL
466
+ */
467
+ protected function getAuthorizeUrl($parameters = [])
468
+ {
469
+ $this->AuthorizeUrlParameters = !empty($parameters)
470
+ ? $parameters
471
+ : array_replace(
472
+ (array) $this->AuthorizeUrlParameters,
473
+ (array) $this->config->get('authorize_url_parameters')
474
+ );
475
+
476
+ if ($this->supportRequestState) {
477
+ if (!isset($this->AuthorizeUrlParameters['state'])) {
478
+ $this->AuthorizeUrlParameters['state'] = 'HA-' . str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890');
479
+ }
480
+
481
+ $this->storeData('authorization_state', $this->AuthorizeUrlParameters['state']);
482
+ }
483
+
484
+ $queryParams = http_build_query($this->AuthorizeUrlParameters, '', '&', $this->AuthorizeUrlParametersEncType);
485
+ return $this->authorizeUrl . '?' . $queryParams;
486
+ }
487
+
488
+ /**
489
+ * Access Token Request
490
+ *
491
+ * This method will exchange the received $code in loginFinish() with an Access Token.
492
+ *
493
+ * RFC6749: The client makes a request to the token endpoint by sending the
494
+ * following parameters using the "application/x-www-form-urlencoded"
495
+ * with a character encoding of UTF-8 in the HTTP request entity-body:
496
+ *
497
+ * - grant_type REQUIRED. Value MUST be set to "authorization_code".
498
+ * - code REQUIRED. The authorization code received from the authorization server.
499
+ * - redirect_uri REQUIRED.
500
+ * - client_id REQUIRED.
501
+ *
502
+ * http://tools.ietf.org/html/rfc6749#section-4.1.3
503
+ *
504
+ * @param string $code
505
+ *
506
+ * @return string Raw Provider API response
507
+ * @throws \Hybridauth\Exception\HttpClientFailureException
508
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
509
+ */
510
+ protected function exchangeCodeForAccessToken($code)
511
+ {
512
+ $this->tokenExchangeParameters['code'] = $code;
513
+
514
+ $response = $this->httpClient->request(
515
+ $this->accessTokenUrl,
516
+ $this->tokenExchangeMethod,
517
+ $this->tokenExchangeParameters,
518
+ $this->tokenExchangeHeaders
519
+ );
520
+
521
+ $this->validateApiResponse('Unable to exchange code for API access token');
522
+
523
+ return $response;
524
+ }
525
+
526
+ /**
527
+ * Validate Access Token Response
528
+ *
529
+ * RFC6749: If the access token request is valid and authorized, the
530
+ * authorization server issues an access token and optional refresh token.
531
+ * If the request client authentication failed or is invalid, the authorization
532
+ * server returns an error response as described in Section 5.2.
533
+ *
534
+ * Example of a successful response:
535
+ *
536
+ * HTTP/1.1 200 OK
537
+ * Content-Type: application/json;charset=UTF-8
538
+ * Cache-Control: no-store
539
+ * Pragma: no-cache
540
+ *
541
+ * {
542
+ * "access_token":"2YotnFZFEjr1zCsicMWpAA",
543
+ * "token_type":"example",
544
+ * "expires_in":3600,
545
+ * "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
546
+ * "example_parameter":"example_value"
547
+ * }
548
+ *
549
+ * http://tools.ietf.org/html/rfc6749#section-4.1.4
550
+ *
551
+ * This method uses Data_Parser to attempt to decodes the raw $response (usually JSON)
552
+ * into a data collection.
553
+ *
554
+ * @param string $response
555
+ *
556
+ * @return \Hybridauth\Data\Collection
557
+ * @throws InvalidAccessTokenException
558
+ */
559
+ protected function validateAccessTokenExchange($response)
560
+ {
561
+ $data = (new Data\Parser())->parse($response);
562
+
563
+ $collection = new Data\Collection($data);
564
+
565
+ if (! $collection->exists('access_token')) {
566
+ throw new InvalidAccessTokenException(
567
+ 'Provider returned no access_token: ' . htmlentities($response)
568
+ );
569
+ }
570
+
571
+ $this->storeData('access_token', $collection->get('access_token'));
572
+ $this->storeData('token_type', $collection->get('token_type'));
573
+
574
+ if ($collection->get('refresh_token')) {
575
+ $this->storeData('refresh_token', $collection->get('refresh_token'));
576
+ }
577
+
578
+ // calculate when the access token expire
579
+ if ($collection->exists('expires_in')) {
580
+ $expires_at = time() + (int) $collection->get('expires_in');
581
+
582
+ $this->storeData('expires_in', $collection->get('expires_in'));
583
+ $this->storeData('expires_at', $expires_at);
584
+ }
585
+
586
+ $this->deleteStoredData('authorization_state');
587
+
588
+ $this->initialize();
589
+
590
+ return $collection;
591
+ }
592
+
593
+ /**
594
+ * Refreshing an Access Token
595
+ *
596
+ * RFC6749: If the authorization server issued a refresh token to the
597
+ * client, the client makes a refresh request to the token endpoint by
598
+ * adding the following parameters ... in the HTTP request entity-body:
599
+ *
600
+ * - grant_type REQUIRED. Value MUST be set to "refresh_token".
601
+ * - refresh_token REQUIRED. The refresh token issued to the client.
602
+ * - scope OPTIONAL.
603
+ *
604
+ * http://tools.ietf.org/html/rfc6749#section-6
605
+ *
606
+ * This method is similar to exchangeCodeForAccessToken(). The only
607
+ * difference is here we exchange refresh_token for a new access_token.
608
+ *
609
+ * @param array $parameters
610
+ *
611
+ * @return string|null Raw Provider API response, or null if we cannot refresh
612
+ * @throws \Hybridauth\Exception\HttpClientFailureException
613
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
614
+ * @throws InvalidAccessTokenException
615
+ */
616
+ public function refreshAccessToken($parameters = [])
617
+ {
618
+ $this->tokenRefreshParameters = !empty($parameters)
619
+ ? $parameters
620
+ : $this->tokenRefreshParameters;
621
+
622
+ if (!$this->isRefreshTokenAvailable()) {
623
+ return null;
624
+ }
625
+
626
+ $response = $this->httpClient->request(
627
+ $this->accessTokenUrl,
628
+ $this->tokenRefreshMethod,
629
+ $this->tokenRefreshParameters,
630
+ $this->tokenRefreshHeaders
631
+ );
632
+
633
+ $this->validateApiResponse('Unable to refresh the access token');
634
+
635
+ $this->validateRefreshAccessToken($response);
636
+
637
+ return $response;
638
+ }
639
+
640
+ /**
641
+ * Check whether access token has expired
642
+ *
643
+ * @param int|null $time
644
+ * @return bool|null
645
+ */
646
+ public function hasAccessTokenExpired($time = null)
647
+ {
648
+ if ($time === null) {
649
+ $time = time();
650
+ }
651
+
652
+ $expires_at = $this->getStoredData('expires_at');
653
+ if (!$expires_at) {
654
+ return null;
655
+ }
656
+
657
+ return $expires_at <= $time;
658
+ }
659
+
660
+ /**
661
+ * Validate Refresh Access Token Request
662
+ *
663
+ * RFC6749: If valid and authorized, the authorization server issues an
664
+ * access token as described in Section 5.1. If the request failed
665
+ * verification or is invalid, the authorization server returns an error
666
+ * response as described in Section 5.2.
667
+ *
668
+ * http://tools.ietf.org/html/rfc6749#section-6
669
+ * http://tools.ietf.org/html/rfc6749#section-5.1
670
+ * http://tools.ietf.org/html/rfc6749#section-5.2
671
+ *
672
+ * This method simply use validateAccessTokenExchange(), however sub
673
+ * classes may redefine it when necessary.
674
+ *
675
+ * @param $response
676
+ *
677
+ * @return \Hybridauth\Data\Collection
678
+ * @throws InvalidAccessTokenException
679
+ */
680
+ protected function validateRefreshAccessToken($response)
681
+ {
682
+ return $this->validateAccessTokenExchange($response);
683
+ }
684
+
685
+ /**
686
+ * Send a signed request to provider API
687
+ *
688
+ * RFC6749: Accessing Protected Resources: The client accesses protected
689
+ * resources by presenting the access token to the resource server. The
690
+ * resource server MUST validate the access token and ensure that it has
691
+ * not expired and that its scope covers the requested resource.
692
+ *
693
+ * Note: Since the specifics of error responses is beyond the scope of
694
+ * RFC6749 and OAuth specifications, Hybridauth will consider any HTTP
695
+ * status code that is different than '200 OK' as an ERROR.
696
+ *
697
+ * http://tools.ietf.org/html/rfc6749#section-7
698
+ *
699
+ * @param string $url
700
+ * @param string $method
701
+ * @param array $parameters
702
+ * @param array $headers
703
+ * @param bool $multipart
704
+ *
705
+ * @return mixed
706
+ * @throws \Hybridauth\Exception\HttpClientFailureException
707
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
708
+ * @throws InvalidAccessTokenException
709
+ */
710
+ public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
711
+ {
712
+ // refresh tokens if needed
713
+ if ($this->hasAccessTokenExpired() === true) {
714
+ $this->refreshAccessToken();
715
+ }
716
+
717
+ if (strrpos($url, 'http://') !== 0 && strrpos($url, 'https://') !== 0) {
718
+ $url = rtrim($this->apiBaseUrl, '/') . '/' . ltrim($url, '/');
719
+ }
720
+
721
+ $parameters = array_replace($this->apiRequestParameters, (array) $parameters);
722
+ $headers = array_replace($this->apiRequestHeaders, (array) $headers);
723
+
724
+ $response = $this->httpClient->request(
725
+ $url,
726
+ $method, // HTTP Request Method. Defaults to GET.
727
+ $parameters, // Request Parameters
728
+ $headers, // Request Headers
729
+ $multipart // Is request multipart
730
+ );
731
+
732
+ $this->validateApiResponse('Signed API request to ' . $url . ' has returned an error');
733
+
734
+ $response = (new Data\Parser())->parse($response);
735
+
736
+ return $response;
737
+ }
738
+ }
hybridauth/library/src/Adapter/OpenID.php CHANGED
@@ -1,275 +1,275 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Adapter;
9
-
10
- use Hybridauth\Exception\InvalidOpenidIdentifierException;
11
- use Hybridauth\Exception\AuthorizationDeniedException;
12
- use Hybridauth\Exception\InvalidOpenidResponseException;
13
- use Hybridauth\Exception\UnexpectedApiResponseException;
14
- use Hybridauth\Data;
15
- use Hybridauth\HttpClient;
16
- use Hybridauth\User;
17
- use Hybridauth\Thirdparty\OpenID\LightOpenID;
18
-
19
- /**
20
- * This class can be used to simplify the authentication flow of OpenID based service providers.
21
- *
22
- * Subclasses (i.e., providers adapters) can either use the already provided methods or override
23
- * them when necessary.
24
- */
25
- abstract class OpenID extends AbstractAdapter implements AdapterInterface
26
- {
27
- /**
28
- * LightOpenID instance
29
- *
30
- * @var object
31
- */
32
- protected $openIdClient = null;
33
-
34
- /**
35
- * Openid provider identifier
36
- *
37
- * @var string
38
- */
39
- protected $openidIdentifier = '';
40
-
41
- /**
42
- * {@inheritdoc}
43
- */
44
- protected function configure()
45
- {
46
- if ($this->config->exists('openid_identifier')) {
47
- $this->openidIdentifier = $this->config->get('openid_identifier');
48
- }
49
-
50
- if (empty($this->openidIdentifier)) {
51
- throw new InvalidOpenidIdentifierException('OpenID adapter requires an openid_identifier.', 4);
52
- }
53
-
54
- $this->setCallback($this->config->get('callback'));
55
- $this->setApiEndpoints($this->config->get('endpoints'));
56
- }
57
-
58
- /**
59
- * {@inheritdoc}
60
- */
61
- protected function initialize()
62
- {
63
- $hostPort = parse_url($this->callback, PHP_URL_PORT);
64
- $hostUrl = parse_url($this->callback, PHP_URL_HOST);
65
-
66
- if ($hostPort) {
67
- $hostUrl .= ':' . $hostPort;
68
- }
69
-
70
- // @fixme: add proxy
71
- $this->openIdClient = new LightOpenID($hostUrl, null);
72
- }
73
-
74
- /**
75
- * {@inheritdoc}
76
- */
77
- public function authenticate()
78
- {
79
- $this->logger->info(sprintf('%s::authenticate()', get_class($this)));
80
-
81
- if ($this->isConnected()) {
82
- return true;
83
- }
84
-
85
- if (empty($_REQUEST['openid_mode'])) {
86
- $this->authenticateBegin();
87
- } else {
88
- return $this->authenticateFinish();
89
- }
90
-
91
- return null;
92
- }
93
-
94
- /**
95
- * {@inheritdoc}
96
- */
97
- public function isConnected()
98
- {
99
- return (bool) $this->storage->get($this->providerId . '.user');
100
- }
101
-
102
- /**
103
- * {@inheritdoc}
104
- */
105
- public function disconnect()
106
- {
107
- $this->storage->delete($this->providerId . '.user');
108
-
109
- return true;
110
- }
111
-
112
- /**
113
- * Initiate the authorization protocol
114
- *
115
- * Include and instantiate LightOpenID
116
- */
117
- protected function authenticateBegin()
118
- {
119
- $this->openIdClient->identity = $this->openidIdentifier;
120
- $this->openIdClient->returnUrl = $this->callback;
121
- $this->openIdClient->required = [
122
- 'namePerson/first' ,
123
- 'namePerson/last' ,
124
- 'namePerson/friendly' ,
125
- 'namePerson' ,
126
- 'contact/email' ,
127
- 'birthDate' ,
128
- 'birthDate/birthDay' ,
129
- 'birthDate/birthMonth' ,
130
- 'birthDate/birthYear' ,
131
- 'person/gender' ,
132
- 'pref/language' ,
133
- 'contact/postalCode/home',
134
- 'contact/city/home' ,
135
- 'contact/country/home' ,
136
-
137
- 'media/image/default' ,
138
- ];
139
-
140
- $authUrl = $this->openIdClient->authUrl();
141
-
142
- $this->logger->debug(sprintf('%s::authenticateBegin(), redirecting user to:', get_class($this)), [$authUrl]);
143
-
144
- HttpClient\Util::redirect($authUrl);
145
- }
146
-
147
- /**
148
- * Finalize the authorization process.
149
- *
150
- * @throws AuthorizationDeniedException
151
- * @throws UnexpectedApiResponseException
152
- */
153
- protected function authenticateFinish()
154
- {
155
- $this->logger->debug(
156
- sprintf('%s::authenticateFinish(), callback url:', get_class($this)),
157
- [HttpClient\Util::getCurrentUrl(true)]
158
- );
159
-
160
- if ($this->openIdClient->mode == 'cancel') {
161
- throw new AuthorizationDeniedException('User has cancelled the authentication.');
162
- }
163
-
164
- if (! $this->openIdClient->validate()) {
165
- throw new UnexpectedApiResponseException('Invalid response received.');
166
- }
167
-
168
- $openidAttributes = $this->openIdClient->getAttributes();
169
-
170
- if (! $this->openIdClient->identity) {
171
- throw new UnexpectedApiResponseException('Provider returned an unexpected response.');
172
- }
173
-
174
- $userProfile = $this->fetchUserProfile($openidAttributes);
175
-
176
- /* with openid providers we only get user profiles once, so we store it */
177
- $this->storage->set($this->providerId . '.user', $userProfile);
178
- }
179
-
180
- /**
181
- * Fetch user profile from received openid attributes
182
- *
183
- * @param array $openidAttributes
184
- *
185
- * @return User\Profile
186
- */
187
- protected function fetchUserProfile($openidAttributes)
188
- {
189
- $data = new Data\Collection($openidAttributes);
190
-
191
- $userProfile = new User\Profile();
192
-
193
- $userProfile->identifier = $this->openIdClient->identity;
194
-
195
- $userProfile->firstName = $data->get('namePerson/first');
196
- $userProfile->lastName = $data->get('namePerson/last');
197
- $userProfile->email = $data->get('contact/email');
198
- $userProfile->language = $data->get('pref/language');
199
- $userProfile->country = $data->get('contact/country/home');
200
- $userProfile->zip = $data->get('contact/postalCode/home');
201
- $userProfile->gender = $data->get('person/gender');
202
- $userProfile->photoURL = $data->get('media/image/default');
203
- $userProfile->birthDay = $data->get('birthDate/birthDay');
204
- $userProfile->birthMonth = $data->get('birthDate/birthMonth');
205
- $userProfile->birthYear = $data->get('birthDate/birthDate');
206
-
207
- $userProfile = $this->fetchUserGender($userProfile, $data->get('person/gender'));
208
-
209
- $userProfile = $this->fetchUserDisplayName($userProfile, $data);
210
-
211
- return $userProfile;
212
- }
213
-
214
- /**
215
- * Extract users display names
216
- *
217
- * @param User\Profile $userProfile
218
- * @param Data\Collection $data
219
- *
220
- * @return User\Profile
221
- */
222
- protected function fetchUserDisplayName(User\Profile $userProfile, Data\Collection $data)
223
- {
224
- $userProfile->displayName = $data->get('namePerson');
225
-
226
- $userProfile->displayName = $userProfile->displayName
227
- ? $userProfile->displayName
228
- : $data->get('namePerson/friendly');
229
-
230
- $userProfile->displayName = $userProfile->displayName
231
- ? $userProfile->displayName
232
- : trim($userProfile->firstName . ' ' . $userProfile->lastName);
233
-
234
- return $userProfile;
235
- }
236
-
237
- /**
238
- * Extract users gender
239
- *
240
- * @param User\Profile $userProfile
241
- * @param string $gender
242
- *
243
- * @return User\Profile
244
- */
245
- protected function fetchUserGender(User\Profile $userProfile, $gender)
246
- {
247
- $gender = strtolower($gender);
248
-
249
- if ('f' == $gender) {
250
- $gender = 'female';
251
- }
252
-
253
- if ('m' == $gender) {
254
- $gender = 'male';
255
- }
256
-
257
- $userProfile->gender = $gender;
258
-
259
- return $userProfile;
260
- }
261
-
262
- /**
263
- * OpenID only provide the user profile one. This method will attempt to retrieve the profile from storage.
264
- */
265
- public function getUserProfile()
266
- {
267
- $userProfile = $this->storage->get($this->providerId . '.user');
268
-
269
- if (! is_object($userProfile)) {
270
- throw new UnexpectedApiResponseException('Provider returned an unexpected response.');
271
- }
272
-
273
- return $userProfile;
274
- }
275
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Adapter;
9
+
10
+ use Hybridauth\Exception\InvalidOpenidIdentifierException;
11
+ use Hybridauth\Exception\AuthorizationDeniedException;
12
+ use Hybridauth\Exception\InvalidOpenidResponseException;
13
+ use Hybridauth\Exception\UnexpectedApiResponseException;
14
+ use Hybridauth\Data;
15
+ use Hybridauth\HttpClient;
16
+ use Hybridauth\User;
17
+ use Hybridauth\Thirdparty\OpenID\LightOpenID;
18
+
19
+ /**
20
+ * This class can be used to simplify the authentication flow of OpenID based service providers.
21
+ *
22
+ * Subclasses (i.e., providers adapters) can either use the already provided methods or override
23
+ * them when necessary.
24
+ */
25
+ abstract class OpenID extends AbstractAdapter implements AdapterInterface
26
+ {
27
+ /**
28
+ * LightOpenID instance
29
+ *
30
+ * @var object
31
+ */
32
+ protected $openIdClient = null;
33
+
34
+ /**
35
+ * Openid provider identifier
36
+ *
37
+ * @var string
38
+ */
39
+ protected $openidIdentifier = '';
40
+
41
+ /**
42
+ * {@inheritdoc}
43
+ */
44
+ protected function configure()
45
+ {
46
+ if ($this->config->exists('openid_identifier')) {
47
+ $this->openidIdentifier = $this->config->get('openid_identifier');
48
+ }
49
+
50
+ if (empty($this->openidIdentifier)) {
51
+ throw new InvalidOpenidIdentifierException('OpenID adapter requires an openid_identifier.', 4);
52
+ }
53
+
54
+ $this->setCallback($this->config->get('callback'));
55
+ $this->setApiEndpoints($this->config->get('endpoints'));
56
+ }
57
+
58
+ /**
59
+ * {@inheritdoc}
60
+ */
61
+ protected function initialize()
62
+ {
63
+ $hostPort = parse_url($this->callback, PHP_URL_PORT);
64
+ $hostUrl = parse_url($this->callback, PHP_URL_HOST);
65
+
66
+ if ($hostPort) {
67
+ $hostUrl .= ':' . $hostPort;
68
+ }
69
+
70
+ // @fixme: add proxy
71
+ $this->openIdClient = new LightOpenID($hostUrl, null);
72
+ }
73
+
74
+ /**
75
+ * {@inheritdoc}
76
+ */
77
+ public function authenticate()
78
+ {
79
+ $this->logger->info(sprintf('%s::authenticate()', get_class($this)));
80
+
81
+ if ($this->isConnected()) {
82
+ return true;
83
+ }
84
+
85
+ if (empty($_REQUEST['openid_mode'])) {
86
+ $this->authenticateBegin();
87
+ } else {
88
+ return $this->authenticateFinish();
89
+ }
90
+
91
+ return null;
92
+ }
93
+
94
+ /**
95
+ * {@inheritdoc}
96
+ */
97
+ public function isConnected()
98
+ {
99
+ return (bool) $this->storage->get($this->providerId . '.user');
100
+ }
101
+
102
+ /**
103
+ * {@inheritdoc}
104
+ */
105
+ public function disconnect()
106
+ {
107
+ $this->storage->delete($this->providerId . '.user');
108
+
109
+ return true;
110
+ }
111
+
112
+ /**
113
+ * Initiate the authorization protocol
114
+ *
115
+ * Include and instantiate LightOpenID
116
+ */
117
+ protected function authenticateBegin()
118
+ {
119
+ $this->openIdClient->identity = $this->openidIdentifier;
120
+ $this->openIdClient->returnUrl = $this->callback;
121
+ $this->openIdClient->required = [
122
+ 'namePerson/first' ,
123
+ 'namePerson/last' ,
124
+ 'namePerson/friendly' ,
125
+ 'namePerson' ,
126
+ 'contact/email' ,
127
+ 'birthDate' ,
128
+ 'birthDate/birthDay' ,
129
+ 'birthDate/birthMonth' ,
130
+ 'birthDate/birthYear' ,
131
+ 'person/gender' ,
132
+ 'pref/language' ,
133
+ 'contact/postalCode/home',
134
+ 'contact/city/home' ,
135
+ 'contact/country/home' ,
136
+
137
+ 'media/image/default' ,
138
+ ];
139
+
140
+ $authUrl = $this->openIdClient->authUrl();
141
+
142
+ $this->logger->debug(sprintf('%s::authenticateBegin(), redirecting user to:', get_class($this)), [$authUrl]);
143
+
144
+ HttpClient\Util::redirect($authUrl);
145
+ }
146
+
147
+ /**
148
+ * Finalize the authorization process.
149
+ *
150
+ * @throws AuthorizationDeniedException
151
+ * @throws UnexpectedApiResponseException
152
+ */
153
+ protected function authenticateFinish()
154
+ {
155
+ $this->logger->debug(
156
+ sprintf('%s::authenticateFinish(), callback url:', get_class($this)),
157
+ [HttpClient\Util::getCurrentUrl(true)]
158
+ );
159
+
160
+ if ($this->openIdClient->mode == 'cancel') {
161
+ throw new AuthorizationDeniedException('User has cancelled the authentication.');
162
+ }
163
+
164
+ if (! $this->openIdClient->validate()) {
165
+ throw new UnexpectedApiResponseException('Invalid response received.');
166
+ }
167
+
168
+ $openidAttributes = $this->openIdClient->getAttributes();
169
+
170
+ if (! $this->openIdClient->identity) {
171
+ throw new UnexpectedApiResponseException('Provider returned an unexpected response.');
172
+ }
173
+
174
+ $userProfile = $this->fetchUserProfile($openidAttributes);
175
+
176
+ /* with openid providers we only get user profiles once, so we store it */
177
+ $this->storage->set($this->providerId . '.user', $userProfile);
178
+ }
179
+
180
+ /**
181
+ * Fetch user profile from received openid attributes
182
+ *
183
+ * @param array $openidAttributes
184
+ *
185
+ * @return User\Profile
186
+ */
187
+ protected function fetchUserProfile($openidAttributes)
188
+ {
189
+ $data = new Data\Collection($openidAttributes);
190
+
191
+ $userProfile = new User\Profile();
192
+
193
+ $userProfile->identifier = $this->openIdClient->identity;
194
+
195
+ $userProfile->firstName = $data->get('namePerson/first');
196
+ $userProfile->lastName = $data->get('namePerson/last');
197
+ $userProfile->email = $data->get('contact/email');
198
+ $userProfile->language = $data->get('pref/language');
199
+ $userProfile->country = $data->get('contact/country/home');
200
+ $userProfile->zip = $data->get('contact/postalCode/home');
201
+ $userProfile->gender = $data->get('person/gender');
202
+ $userProfile->photoURL = $data->get('media/image/default');
203
+ $userProfile->birthDay = $data->get('birthDate/birthDay');
204
+ $userProfile->birthMonth = $data->get('birthDate/birthMonth');
205
+ $userProfile->birthYear = $data->get('birthDate/birthDate');
206
+
207
+ $userProfile = $this->fetchUserGender($userProfile, $data->get('person/gender'));
208
+
209
+ $userProfile = $this->fetchUserDisplayName($userProfile, $data);
210
+
211
+ return $userProfile;
212
+ }
213
+
214
+ /**
215
+ * Extract users display names
216
+ *
217
+ * @param User\Profile $userProfile
218
+ * @param Data\Collection $data
219
+ *
220
+ * @return User\Profile
221
+ */
222
+ protected function fetchUserDisplayName(User\Profile $userProfile, Data\Collection $data)
223
+ {
224
+ $userProfile->displayName = $data->get('namePerson');
225
+
226
+ $userProfile->displayName = $userProfile->displayName
227
+ ? $userProfile->displayName
228
+ : $data->get('namePerson/friendly');
229
+
230
+ $userProfile->displayName = $userProfile->displayName
231
+ ? $userProfile->displayName
232
+ : trim($userProfile->firstName . ' ' . $userProfile->lastName);
233
+
234
+ return $userProfile;
235
+ }
236
+
237
+ /**
238
+ * Extract users gender
239
+ *
240
+ * @param User\Profile $userProfile
241
+ * @param string $gender
242
+ *
243
+ * @return User\Profile
244
+ */
245
+ protected function fetchUserGender(User\Profile $userProfile, $gender)
246
+ {
247
+ $gender = strtolower($gender);
248
+
249
+ if ('f' == $gender) {
250
+ $gender = 'female';
251
+ }
252
+
253
+ if ('m' == $gender) {
254
+ $gender = 'male';
255
+ }
256
+
257
+ $userProfile->gender = $gender;
258
+
259
+ return $userProfile;
260
+ }
261
+
262
+ /**
263
+ * OpenID only provide the user profile one. This method will attempt to retrieve the profile from storage.
264
+ */
265
+ public function getUserProfile()
266
+ {
267
+ $userProfile = $this->storage->get($this->providerId . '.user');
268
+
269
+ if (! is_object($userProfile)) {
270
+ throw new UnexpectedApiResponseException('Provider returned an unexpected response.');
271
+ }
272
+
273
+ return $userProfile;
274
+ }
275
+ }
hybridauth/library/src/Data/Collection.php CHANGED
@@ -1,160 +1,160 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Data;
9
-
10
- /**
11
- * A very basic Data collection.
12
- */
13
- final class Collection
14
- {
15
- /**
16
- * Data collection
17
- *
18
- * @var mixed
19
- */
20
- protected $collection = null;
21
-
22
- /**
23
- * @param mixed $data
24
- */
25
- public function __construct($data = null)
26
- {
27
- $this->collection = new \stdClass();
28
-
29
- if (is_object($data)) {
30
- $this->collection = $data;
31
- }
32
-
33
- $this->collection = (object) $data;
34
- }
35
-
36
- /**
37
- * Retrieves the whole collection as array
38
- *
39
- * @return mixed
40
- */
41
- public function toArray()
42
- {
43
- return (array) $this->collection;
44
- }
45
-
46
- /**
47
- * Retrieves an item
48
- *
49
- * @param $property
50
- *
51
- * @return mixed
52
- */
53
- public function get($property)
54
- {
55
- if ($this->exists($property)) {
56
- return $this->collection->$property;
57
- }
58
-
59
- return null;
60
- }
61
-
62
- /**
63
- * Add or update an item
64
- *
65
- * @param $property
66
- * @param mixed $value
67
- */
68
- public function set($property, $value)
69
- {
70
- if ($property) {
71
- $this->collection->$property = $value;
72
- }
73
- }
74
-
75
- /**
76
- * .. until I come with a better name..
77
- *
78
- * @param $property
79
- *
80
- * @return Collection
81
- */
82
- public function filter($property)
83
- {
84
- if ($this->exists($property)) {
85
- $data = $this->get($property);
86
-
87
- if (! is_a($data, 'Collection')) {
88
- $data = new Collection($data);
89
- }
90
-
91
- return $data;
92
- }
93
-
94
- return new Collection([]);
95
- }
96
-
97
- /**
98
- * Checks whether an item within the collection
99
- *
100
- * @param $property
101
- *
102
- * @return bool
103
- */
104
- public function exists($property)
105
- {
106
- return property_exists($this->collection, $property);
107
- }
108
-
109
- /**
110
- * Finds whether the collection is empty
111
- *
112
- * @return bool
113
- */
114
- public function isEmpty()
115
- {
116
- return ! (bool) $this->count();
117
- }
118
-
119
- /**
120
- * Count all items in collection
121
- *
122
- * @return int
123
- */
124
- public function count()
125
- {
126
- return count($this->properties());
127
- }
128
-
129
- /**
130
- * Returns all items properties names
131
- *
132
- * @return array
133
- */
134
- public function properties()
135
- {
136
- $properties = [];
137
-
138
- foreach ($this->collection as $key => $value) {
139
- $properties[] = $key;
140
- }
141
-
142
- return $properties;
143
- }
144
-
145
- /**
146
- * Returns all items values
147
- *
148
- * @return array
149
- */
150
- public function values()
151
- {
152
- $values = [];
153
-
154
- foreach ($this->collection as $value) {
155
- $values[] = $value;
156
- }
157
-
158
- return $values;
159
- }
160
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Data;
9
+
10
+ /**
11
+ * A very basic Data collection.
12
+ */
13
+ final class Collection
14
+ {
15
+ /**
16
+ * Data collection
17
+ *
18
+ * @var mixed
19
+ */
20
+ protected $collection = null;
21
+
22
+ /**
23
+ * @param mixed $data
24
+ */
25
+ public function __construct($data = null)
26
+ {
27
+ $this->collection = new \stdClass();
28
+
29
+ if (is_object($data)) {
30
+ $this->collection = $data;
31
+ }
32
+
33
+ $this->collection = (object) $data;
34
+ }
35
+
36
+ /**
37
+ * Retrieves the whole collection as array
38
+ *
39
+ * @return mixed
40
+ */
41
+ public function toArray()
42
+ {
43
+ return (array) $this->collection;
44
+ }
45
+
46
+ /**
47
+ * Retrieves an item
48
+ *
49
+ * @param $property
50
+ *
51
+ * @return mixed
52
+ */
53
+ public function get($property)
54
+ {
55
+ if ($this->exists($property)) {
56
+ return $this->collection->$property;
57
+ }
58
+
59
+ return null;
60
+ }
61
+
62
+ /**
63
+ * Add or update an item
64
+ *
65
+ * @param $property
66
+ * @param mixed $value
67
+ */
68
+ public function set($property, $value)
69
+ {
70
+ if ($property) {
71
+ $this->collection->$property = $value;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * .. until I come with a better name..
77
+ *
78
+ * @param $property
79
+ *
80
+ * @return Collection
81
+ */
82
+ public function filter($property)
83
+ {
84
+ if ($this->exists($property)) {
85
+ $data = $this->get($property);
86
+
87
+ if (! is_a($data, 'Collection')) {
88
+ $data = new Collection($data);
89
+ }
90
+
91
+ return $data;
92
+ }
93
+
94
+ return new Collection([]);
95
+ }
96
+
97
+ /**
98
+ * Checks whether an item within the collection
99
+ *
100
+ * @param $property
101
+ *
102
+ * @return bool
103
+ */
104
+ public function exists($property)
105
+ {
106
+ return property_exists($this->collection, $property);
107
+ }
108
+
109
+ /**
110
+ * Finds whether the collection is empty
111
+ *
112
+ * @return bool
113
+ */
114
+ public function isEmpty()
115
+ {
116
+ return ! (bool) $this->count();
117
+ }
118
+
119
+ /**
120
+ * Count all items in collection
121
+ *
122
+ * @return int
123
+ */
124
+ public function count()
125
+ {
126
+ return count($this->properties());
127
+ }
128
+
129
+ /**
130
+ * Returns all items properties names
131
+ *
132
+ * @return array
133
+ */
134
+ public function properties()
135
+ {
136
+ $properties = [];
137
+
138
+ foreach ($this->collection as $key => $value) {
139
+ $properties[] = $key;
140
+ }
141
+
142
+ return $properties;
143
+ }
144
+
145
+ /**
146
+ * Returns all items values
147
+ *
148
+ * @return array
149
+ */
150
+ public function values()
151
+ {
152
+ $values = [];
153
+
154
+ foreach ($this->collection as $value) {
155
+ $values[] = $value;
156
+ }
157
+
158
+ return $values;
159
+ }
160
+ }
hybridauth/library/src/Data/Parser.php CHANGED
@@ -1,119 +1,119 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Data;
9
-
10
- /**
11
- * Parser
12
- *
13
- * This class is used to parse plain text into objects. It's used by hybriauth adapters to converts
14
- * providers api responses to a more 'manageable' format.
15
- */
16
- final class Parser
17
- {
18
- /**
19
- * Decodes a string into an object.
20
- *
21
- * This method will first attempt to parse data as a JSON string (since most providers use this format)
22
- * then XML and parse_str.
23
- *
24
- * @param string $raw
25
- *
26
- * @return mixed
27
- */
28
- public function parse($raw = null)
29
- {
30
- $data = $this->parseJson($raw);
31
-
32
- if (! $data) {
33
- $data = $this->parseXml($raw);
34
-
35
- if (! $data) {
36
- $data = $this->parseQueryString($raw);
37
- }
38
- }
39
-
40
- return $data;
41
- }
42
-
43
- /**
44
- * Decodes a JSON string
45
- *
46
- * @param $result
47
- *
48
- * @return mixed
49
- */
50
- public function parseJson($result)
51
- {
52
- return json_decode($result);
53
- }
54
-
55
- /**
56
- * Decodes a XML string
57
- *
58
- * @param $result
59
- *
60
- * @return mixed
61
- */
62
- public function parseXml($result)
63
- {
64
- libxml_use_internal_errors(true);
65
-
66
- $result = preg_replace('/([<<\/])([a-z0-9-]+):/i', '$1', $result);
67
- $xml = simplexml_load_string($result);
68
-
69
- libxml_use_internal_errors(false);
70
-
71
- if (! $xml) {
72
- return [];
73
- }
74
-
75
- $arr = json_decode(json_encode((array) $xml), true);
76
- $arr = array($xml->getName() => $arr);
77
-
78
- return $arr;
79
- }
80
-
81
- /**
82
- * Parses a string into variables
83
- *
84
- * @param $result
85
- *
86
- * @return \StdClass
87
- */
88
- public function parseQueryString($result)
89
- {
90
- parse_str($result, $output);
91
-
92
- if (! is_array($output)) {
93
- return $result;
94
- }
95
-
96
- $result = new \StdClass();
97
-
98
- foreach ($output as $k => $v) {
99
- $result->$k = $v;
100
- }
101
-
102
- return $result;
103
- }
104
-
105
- /**
106
- * needs to be improved
107
- *
108
- * @param $birthday
109
- * @param $seperator
110
- *
111
- * @return array
112
- */
113
- public function parseBirthday($birthday, $seperator)
114
- {
115
- $birthday = date_parse($birthday);
116
-
117
- return [ $birthday['year'], $birthday['month'], $birthday['day'] ];
118
- }
119
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Data;
9
+
10
+ /**
11
+ * Parser
12
+ *
13
+ * This class is used to parse plain text into objects. It's used by hybriauth adapters to converts
14
+ * providers api responses to a more 'manageable' format.
15
+ */
16
+ final class Parser
17
+ {
18
+ /**
19
+ * Decodes a string into an object.
20
+ *
21
+ * This method will first attempt to parse data as a JSON string (since most providers use this format)
22
+ * then XML and parse_str.
23
+ *
24
+ * @param string $raw
25
+ *
26
+ * @return mixed
27
+ */
28
+ public function parse($raw = null)
29
+ {
30
+ $data = $this->parseJson($raw);
31
+
32
+ if (! $data) {
33
+ $data = $this->parseXml($raw);
34
+
35
+ if (! $data) {
36
+ $data = $this->parseQueryString($raw);
37
+ }
38
+ }
39
+
40
+ return $data;
41
+ }
42
+
43
+ /**
44
+ * Decodes a JSON string
45
+ *
46
+ * @param $result
47
+ *
48
+ * @return mixed
49
+ */
50
+ public function parseJson($result)
51
+ {
52
+ return json_decode($result);
53
+ }
54
+
55
+ /**
56
+ * Decodes a XML string
57
+ *
58
+ * @param $result
59
+ *
60
+ * @return mixed
61
+ */
62
+ public function parseXml($result)
63
+ {
64
+ libxml_use_internal_errors(true);
65
+
66
+ $result = preg_replace('/([<<\/])([a-z0-9-]+):/i', '$1', $result);
67
+ $xml = simplexml_load_string($result);
68
+
69
+ libxml_use_internal_errors(false);
70
+
71
+ if (! $xml) {
72
+ return [];
73
+ }
74
+
75
+ $arr = json_decode(json_encode((array) $xml), true);
76
+ $arr = array($xml->getName() => $arr);
77
+
78
+ return $arr;
79
+ }
80
+
81
+ /**
82
+ * Parses a string into variables
83
+ *
84
+ * @param $result
85
+ *
86
+ * @return \StdClass
87
+ */
88
+ public function parseQueryString($result)
89
+ {
90
+ parse_str($result, $output);
91
+
92
+ if (! is_array($output)) {
93
+ return $result;
94
+ }
95
+
96
+ $result = new \StdClass();
97
+
98
+ foreach ($output as $k => $v) {
99
+ $result->$k = $v;
100
+ }
101
+
102
+ return $result;
103
+ }
104
+
105
+ /**
106
+ * needs to be improved
107
+ *
108
+ * @param $birthday
109
+ * @param $seperator
110
+ *
111
+ * @return array
112
+ */
113
+ public function parseBirthday($birthday, $seperator)
114
+ {
115
+ $birthday = date_parse($birthday);
116
+
117
+ return [ $birthday['year'], $birthday['month'], $birthday['day'] ];
118
+ }
119
+ }
hybridauth/library/src/Exception/AuthorizationDeniedException.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- *
12
- */
13
- class AuthorizationDeniedException extends UnexpectedValueException implements ExceptionInterface
14
- {
15
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ *
12
+ */
13
+ class AuthorizationDeniedException extends UnexpectedValueException implements ExceptionInterface
14
+ {
15
+ }
hybridauth/library/src/Exception/BadMethodCallException.php CHANGED
@@ -1,17 +1,17 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- * BadMethodCallException
12
- *
13
- * Exception thrown if a callback refers to an undefined method or if some arguments are missing.
14
- */
15
- class BadMethodCallException extends RuntimeException implements ExceptionInterface
16
- {
17
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ * BadMethodCallException
12
+ *
13
+ * Exception thrown if a callback refers to an undefined method or if some arguments are missing.
14
+ */
15
+ class BadMethodCallException extends RuntimeException implements ExceptionInterface
16
+ {
17
+ }
hybridauth/library/src/Exception/Exception.php CHANGED
@@ -1,64 +1,64 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- * Hybridauth Base Exception
12
- */
13
- class Exception extends \Exception implements ExceptionInterface
14
- {
15
- /**
16
- * Shamelessly Borrowed from Slimframework
17
- *
18
- * @param $object
19
- */
20
- public function debug($object)
21
- {
22
- $title = 'Hybridauth Exception';
23
- $code = $this->getCode();
24
- $message = $this->getMessage();
25
- $file = $this->getFile();
26
- $line = $this->getLine();
27
- $trace = $this->getTraceAsString();
28
-
29
- $html = sprintf('<h1>%s</h1>', $title);
30
- $html .= '<p>Hybridauth has encountered the following error:</p>';
31
- $html .= '<h2>Details</h2>';
32
-
33
- $html .= sprintf('<div><strong>Exception:</strong> %s</div>', get_class($this));
34
-
35
- $html .= sprintf('<div><strong>Message:</strong> <font color="#cc0000">%s</font></div>', $message);
36
-
37
- $html .= sprintf('<div><strong>File:</strong> %s</div>', $file);
38
-
39
- $html .= sprintf('<div><strong>Line:</strong> %s</div>', $line);
40
-
41
- $html .= sprintf('<div><strong>Code:</strong> %s</div>', $code);
42
-
43
- $html .= '<h2>Trace</h2>';
44
- $html .= sprintf('<pre>%s</pre>', $trace);
45
-
46
- if ($object) {
47
- $html .= '<h2>Debug</h2>';
48
-
49
- $obj_dump = print_r($object, true);
50
-
51
- // phpcs:ignore
52
- $html .= sprintf('<b>' . get_class($object) . '</b> extends <b>' . get_parent_class($object) . '</b><pre>%s</pre>', $obj_dump);
53
- }
54
-
55
- $html .= '<h2>Session</h2>';
56
-
57
- $session_dump = print_r($_SESSION, true);
58
-
59
- $html .= sprintf('<pre>%s</pre>', $session_dump);
60
-
61
- // phpcs:ignore
62
- echo sprintf("<html><head><title>%s</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana,sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}strong{display:inline-block;width:75px;}</style></head><body>%s</body></html>", $title, $html);
63
- }
64
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ * Hybridauth Base Exception
12
+ */
13
+ class Exception extends \Exception implements ExceptionInterface
14
+ {
15
+ /**
16
+ * Shamelessly Borrowed from Slimframework
17
+ *
18
+ * @param $object
19
+ */
20
+ public function debug($object)
21
+ {
22
+ $title = 'Hybridauth Exception';
23
+ $code = $this->getCode();
24
+ $message = $this->getMessage();
25
+ $file = $this->getFile();
26
+ $line = $this->getLine();
27
+ $trace = $this->getTraceAsString();
28
+
29
+ $html = sprintf('<h1>%s</h1>', $title);
30
+ $html .= '<p>Hybridauth has encountered the following error:</p>';
31
+ $html .= '<h2>Details</h2>';
32
+
33
+ $html .= sprintf('<div><strong>Exception:</strong> %s</div>', get_class($this));
34
+
35
+ $html .= sprintf('<div><strong>Message:</strong> <font color="#cc0000">%s</font></div>', $message);
36
+
37
+ $html .= sprintf('<div><strong>File:</strong> %s</div>', $file);
38
+
39
+ $html .= sprintf('<div><strong>Line:</strong> %s</div>', $line);
40
+
41
+ $html .= sprintf('<div><strong>Code:</strong> %s</div>', $code);
42
+
43
+ $html .= '<h2>Trace</h2>';
44
+ $html .= sprintf('<pre>%s</pre>', $trace);
45
+
46
+ if ($object) {
47
+ $html .= '<h2>Debug</h2>';
48
+
49
+ $obj_dump = print_r($object, true);
50
+
51
+ // phpcs:ignore
52
+ $html .= sprintf('<b>' . get_class($object) . '</b> extends <b>' . get_parent_class($object) . '</b><pre>%s</pre>', $obj_dump);
53
+ }
54
+
55
+ $html .= '<h2>Session</h2>';
56
+
57
+ $session_dump = print_r($_SESSION, true);
58
+
59
+ $html .= sprintf('<pre>%s</pre>', $session_dump);
60
+
61
+ // phpcs:ignore
62
+ echo sprintf("<html><head><title>%s</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana,sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}strong{display:inline-block;width:75px;}</style></head><body>%s</body></html>", $title, $html);
63
+ }
64
+ }
hybridauth/library/src/Exception/ExceptionInterface.php CHANGED
@@ -1,36 +1,36 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- * Hybridauth Exceptions Interface
12
- */
13
- interface ExceptionInterface
14
- {
15
- /*
16
- ExceptionInterface
17
- Exception extends \Exception implements ExceptionInterface
18
- | RuntimeException extends Exception
19
- | | UnexpectedValueException extends RuntimeException
20
- | | | AuthorizationDeniedException extends UnexpectedValueException
21
- | | | HttpClientFailureException extends UnexpectedValueException
22
- | | | HttpRequestFailedException extends UnexpectedValueException
23
- | | | InvalidAuthorizationCodeException extends UnexpectedValueException
24
- | | | InvalidAuthorizationStateException extends UnexpectedValueException
25
- | | | InvalidOauthTokenException extends UnexpectedValueException
26
- | | | InvalidAccessTokenException extends UnexpectedValueException
27
- | | | UnexpectedApiResponseException extends UnexpectedValueException
28
- | |
29
- | | BadMethodCallException extends RuntimeException
30
- | | | NotImplementedException extends BadMethodCallException
31
- | |
32
- | | InvalidArgumentException extends RuntimeException
33
- | | | InvalidApplicationCredentialsException extends InvalidArgumentException
34
- | | | InvalidOpenidIdentifierException extends InvalidArgumentException
35
- */
36
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ * Hybridauth Exceptions Interface
12
+ */
13
+ interface ExceptionInterface
14
+ {
15
+ /*
16
+ ExceptionInterface
17
+ Exception extends \Exception implements ExceptionInterface
18
+ | RuntimeException extends Exception
19
+ | | UnexpectedValueException extends RuntimeException
20
+ | | | AuthorizationDeniedException extends UnexpectedValueException
21
+ | | | HttpClientFailureException extends UnexpectedValueException
22
+ | | | HttpRequestFailedException extends UnexpectedValueException
23
+ | | | InvalidAuthorizationCodeException extends UnexpectedValueException
24
+ | | | InvalidAuthorizationStateException extends UnexpectedValueException
25
+ | | | InvalidOauthTokenException extends UnexpectedValueException
26
+ | | | InvalidAccessTokenException extends UnexpectedValueException
27
+ | | | UnexpectedApiResponseException extends UnexpectedValueException
28
+ | |
29
+ | | BadMethodCallException extends RuntimeException
30
+ | | | NotImplementedException extends BadMethodCallException
31
+ | |
32
+ | | InvalidArgumentException extends RuntimeException
33
+ | | | InvalidApplicationCredentialsException extends InvalidArgumentException
34
+ | | | InvalidOpenidIdentifierException extends InvalidArgumentException
35
+ */
36
+ }
hybridauth/library/src/Exception/HttpClientFailureException.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- *
12
- */
13
- class HttpClientFailureException extends UnexpectedValueException implements ExceptionInterface
14
- {
15
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ *
12
+ */
13
+ class HttpClientFailureException extends UnexpectedValueException implements ExceptionInterface
14
+ {
15
+ }
hybridauth/library/src/Exception/HttpRequestFailedException.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- *
12
- */
13
- class HttpRequestFailedException extends UnexpectedValueException implements ExceptionInterface
14
- {
15
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ *
12
+ */
13
+ class HttpRequestFailedException extends UnexpectedValueException implements ExceptionInterface
14
+ {
15
+ }
hybridauth/library/src/Exception/InvalidAccessTokenException.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- *
12
- */
13
- class InvalidAccessTokenException extends InvalidArgumentException implements ExceptionInterface
14
- {
15
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ *
12
+ */
13
+ class InvalidAccessTokenException extends InvalidArgumentException implements ExceptionInterface
14
+ {
15
+ }
hybridauth/library/src/Exception/InvalidApplicationCredentialsException.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- *
12
- */
13
- class InvalidApplicationCredentialsException extends InvalidArgumentException implements ExceptionInterface
14
- {
15
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ *
12
+ */
13
+ class InvalidApplicationCredentialsException extends InvalidArgumentException implements ExceptionInterface
14
+ {
15
+ }
hybridauth/library/src/Exception/InvalidArgumentException.php CHANGED
@@ -1,17 +1,17 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- * InvalidArgumentException
12
- *
13
- * Exception thrown if an argument is not of the expected type.
14
- */
15
- class InvalidArgumentException extends RuntimeException implements ExceptionInterface
16
- {
17
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ * InvalidArgumentException
12
+ *
13
+ * Exception thrown if an argument is not of the expected type.
14
+ */
15
+ class InvalidArgumentException extends RuntimeException implements ExceptionInterface
16
+ {
17
+ }
hybridauth/library/src/Exception/InvalidAuthorizationCodeException.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- *
12
- */
13
- class InvalidAuthorizationCodeException extends InvalidArgumentException implements ExceptionInterface
14
- {
15
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ *
12
+ */
13
+ class InvalidAuthorizationCodeException extends InvalidArgumentException implements ExceptionInterface
14
+ {
15
+ }
hybridauth/library/src/Exception/InvalidAuthorizationStateException.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- *
12
- */
13
- class InvalidAuthorizationStateException extends InvalidArgumentException implements ExceptionInterface
14
- {
15
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ *
12
+ */
13
+ class InvalidAuthorizationStateException extends InvalidArgumentException implements ExceptionInterface
14
+ {
15
+ }
hybridauth/library/src/Exception/InvalidOauthTokenException.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- *
12
- */
13
- class InvalidOauthTokenException extends InvalidArgumentException implements ExceptionInterface
14
- {
15
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ *
12
+ */
13
+ class InvalidOauthTokenException extends InvalidArgumentException implements ExceptionInterface
14
+ {
15
+ }
hybridauth/library/src/Exception/InvalidOpenidIdentifierException.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- *
12
- */
13
- class InvalidOpenidIdentifierException extends InvalidArgumentException implements ExceptionInterface
14
- {
15
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ *
12
+ */
13
+ class InvalidOpenidIdentifierException extends InvalidArgumentException implements ExceptionInterface
14
+ {
15
+ }
hybridauth/library/src/Exception/NotImplementedException.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- *
12
- */
13
- class NotImplementedException extends BadMethodCallException implements ExceptionInterface
14
- {
15
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ *
12
+ */
13
+ class NotImplementedException extends BadMethodCallException implements ExceptionInterface
14
+ {
15
+ }
hybridauth/library/src/Exception/RuntimeException.php CHANGED
@@ -1,17 +1,17 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- * RuntimeException
12
- *
13
- * Exception thrown if an error which can only be found on runtime occurs.
14
- */
15
- class RuntimeException extends Exception implements ExceptionInterface
16
- {
17
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ * RuntimeException
12
+ *
13
+ * Exception thrown if an error which can only be found on runtime occurs.
14
+ */
15
+ class RuntimeException extends Exception implements ExceptionInterface
16
+ {
17
+ }
hybridauth/library/src/Exception/UnexpectedApiResponseException.php CHANGED
@@ -1,15 +1,15 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- *
12
- */
13
- class UnexpectedApiResponseException extends UnexpectedValueException implements ExceptionInterface
14
- {
15
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ *
12
+ */
13
+ class UnexpectedApiResponseException extends UnexpectedValueException implements ExceptionInterface
14
+ {
15
+ }
hybridauth/library/src/Exception/UnexpectedValueException.php CHANGED
@@ -1,19 +1,19 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Exception;
9
-
10
- /**
11
- * UnexpectedValueException
12
- *
13
- * Exception thrown if a value does not match with a set of values. Typically this happens when a function calls
14
- * another function and expects the return value to be of a certain type or value not including arithmetic or
15
- * buffer related errors.
16
- */
17
- class UnexpectedValueException extends RuntimeException implements ExceptionInterface
18
- {
19
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Exception;
9
+
10
+ /**
11
+ * UnexpectedValueException
12
+ *
13
+ * Exception thrown if a value does not match with a set of values. Typically this happens when a function calls
14
+ * another function and expects the return value to be of a certain type or value not including arithmetic or
15
+ * buffer related errors.
16
+ */
17
+ class UnexpectedValueException extends RuntimeException implements ExceptionInterface
18
+ {
19
+ }
hybridauth/library/src/HttpClient/Curl.php CHANGED
@@ -1,314 +1,314 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\HttpClient;
9
-
10
- /**
11
- * Hybridauth default Http client
12
- */
13
- class Curl implements HttpClientInterface
14
- {
15
- /**
16
- * Default curl options
17
- *
18
- * These defaults options can be overwritten when sending requests.
19
- *
20
- * See setCurlOptions()
21
- *
22
- * @var array
23
- */
24
- protected $curlOptions = [
25
- CURLOPT_TIMEOUT => 30,
26
- CURLOPT_CONNECTTIMEOUT => 30,
27
- CURLOPT_SSL_VERIFYPEER => false,
28
- CURLOPT_SSL_VERIFYHOST => false,
29
- CURLOPT_RETURNTRANSFER => true,
30
- CURLOPT_FOLLOWLOCATION => true,
31
- CURLOPT_MAXREDIRS => 5,
32
- CURLINFO_HEADER_OUT => true,
33
- CURLOPT_ENCODING => 'identity',
34
- // phpcs:ignore
35
- CURLOPT_USERAGENT => 'Hybridauth, PHP Social Authentication Library (https://github.com/hybridauth/hybridauth)',
36
- ];
37
-
38
- /**
39
- * Method request() arguments
40
- *
41
- * This is used for debugging.
42
- *
43
- * @var array
44
- */
45
- protected $requestArguments = [];
46
-
47
- /**
48
- * Default request headers
49
- *
50
- * @var array
51
- */
52
- protected $requestHeader = [
53
- 'Accept' => '*/*',
54
- 'Cache-Control' => 'max-age=0',
55
- 'Connection' => 'keep-alive',
56
- 'Expect' => '',
57
- 'Pragma' => '',
58
- ];
59
-
60
- /**
61
- * Raw response returned by server
62
- *
63
- * @var string
64
- */
65
- protected $responseBody = '';
66
-
67
- /**
68
- * Headers returned in the response
69
- *
70
- * @var array
71
- */
72
- protected $responseHeader = [];
73
-
74
- /**
75
- * Response HTTP status code
76
- *
77
- * @var integer
78
- */
79
- protected $responseHttpCode = 0;
80
-
81
- /**
82
- * Last curl error number
83
- *
84
- * @var mixed
85
- */
86
- protected $responseClientError = null;
87
-
88
- /**
89
- * Information about the last transfer
90
- *
91
- * @var mixed
92
- */
93
- protected $responseClientInfo = [];
94
-
95
- /**
96
- * Hybridauth logger instance
97
- *
98
- * @var object
99
- */
100
- protected $logger = null;
101
-
102
- /**
103
- * {@inheritdoc}
104
- */
105
- public function request($uri, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
106
- {
107
- $this->requestHeader = array_replace($this->requestHeader, (array) $headers);
108
-
109
- $this->requestArguments = [
110
- 'uri' => $uri,
111
- 'method' => $method,
112
- 'parameters' => $parameters,
113
- 'headers' => $this->requestHeader,
114
- ];
115
-
116
- $curl = curl_init();
117
-
118
- switch ($method) {
119
- case 'GET':
120
- case 'DELETE':
121
- unset($this->curlOptions[CURLOPT_POST]);
122
- unset($this->curlOptions[CURLOPT_POSTFIELDS]);
123
-
124
- $uri = $uri . (strpos($uri, '?') ? '&' : '?') . http_build_query($parameters);
125
- if ($method === 'DELETE') {
126
- $this->curlOptions[CURLOPT_CUSTOMREQUEST] = 'DELETE';
127
- }
128
- break;
129
- case 'PUT':
130
- case 'POST':
131
- case 'PATCH':
132
- $body_content = $multipart ? $parameters : http_build_query($parameters);
133
- if (isset($this->requestHeader['Content-Type'])
134
- && $this->requestHeader['Content-Type'] == 'application/json'
135
- ) {
136
- $body_content = json_encode($parameters);
137
- }
138
-
139
- if ($method === 'POST') {
140
- $this->curlOptions[CURLOPT_POST] = true;
141
- } else {
142
- $this->curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
143
- }
144
- $this->curlOptions[CURLOPT_POSTFIELDS] = $body_content;
145
- break;
146
- }
147
-
148
- $this->curlOptions[CURLOPT_URL] = $uri;
149
- $this->curlOptions[CURLOPT_HTTPHEADER] = $this->prepareRequestHeaders();
150
- $this->curlOptions[CURLOPT_HEADERFUNCTION] = [ $this, 'fetchResponseHeader' ];
151
-
152
- foreach ($this->curlOptions as $opt => $value) {
153
- curl_setopt($curl, $opt, $value);
154
- }
155
-
156
- $response = curl_exec($curl);
157
-
158
- $this->responseBody = $response;
159
- $this->responseHttpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
160
- $this->responseClientError = curl_error($curl);
161
- $this->responseClientInfo = curl_getinfo($curl);
162
-
163
- if ($this->logger) {
164
- // phpcs:ignore
165
- $this->logger->debug(sprintf('%s::request( %s, %s ), response:', get_class($this), $uri, $method), $this->getResponse());
166
-
167
- if (false === $response) {
168
- // phpcs:ignore
169
- $this->logger->error(sprintf('%s::request( %s, %s ), error:', get_class($this), $uri, $method), [$this->responseClientError]);
170
- }
171
- }
172
-
173
- curl_close($curl);
174
-
175
- return $this->responseBody;
176
- }
177
-
178
- /**
179
- * {@inheritdoc}
180
- */
181
- public function getResponse()
182
- {
183
- $curlOptions = $this->curlOptions;
184
-
185
- $curlOptions[CURLOPT_HEADERFUNCTION] = '*omitted';
186
-
187
- return [
188
- 'request' => $this->getRequestArguments(),
189
- 'response' => [
190
- 'code' => $this->getResponseHttpCode(),
191
- 'headers' => $this->getResponseHeader(),
192
- 'body' => $this->getResponseBody(),
193
- ],
194
- 'client' => [
195
- 'error' => $this->getResponseClientError(),
196
- 'info' => $this->getResponseClientInfo(),
197
- 'opts' => $curlOptions,
198
- ],
199
- ];
200
- }
201
-
202
- /**
203
- * Reset curl options
204
- *
205
- * @param array $curlOptions
206
- */
207
- public function setCurlOptions($curlOptions)
208
- {
209
- foreach ($curlOptions as $opt => $value) {
210
- $this->curlOptions[ $opt ] = $value;
211
- }
212
- }
213
-
214
- /**
215
- * Set logger instance
216
- *
217
- * @param object $logger
218
- */
219
- public function setLogger($logger)
220
- {
221
- $this->logger = $logger;
222
- }
223
-
224
- /**
225
- * {@inheritdoc}
226
- */
227
- public function getResponseBody()
228
- {
229
- return $this->responseBody;
230
- }
231
-
232
- /**
233
- * {@inheritdoc}
234
- */
235
- public function getResponseHeader()
236
- {
237
- return $this->responseHeader;
238
- }
239
-
240
- /**
241
- * {@inheritdoc}
242
- */
243
- public function getResponseHttpCode()
244
- {
245
- return $this->responseHttpCode;
246
- }
247
-
248
- /**
249
- * {@inheritdoc}
250
- */
251
- public function getResponseClientError()
252
- {
253
- return $this->responseClientError;
254
- }
255
-
256
- /**
257
- * @return array
258
- */
259
- protected function getResponseClientInfo()
260
- {
261
- return $this->responseClientInfo;
262
- }
263
-
264
- /**
265
- * Returns method request() arguments
266
- *
267
- * This is used for debugging.
268
- *
269
- * @return array
270
- */
271
- protected function getRequestArguments()
272
- {
273
- return $this->requestArguments;
274
- }
275
-
276
- /**
277
- * Fetch server response headers
278
- *
279
- * @param mixed $curl
280
- * @param string $header
281
- *
282
- * @return integer
283
- */
284
- protected function fetchResponseHeader($curl, $header)
285
- {
286
- $pos = strpos($header, ':');
287
-
288
- if (! empty($pos)) {
289
- $key = str_replace('-', '_', strtolower(substr($header, 0, $pos)));
290
-
291
- $value = trim(substr($header, $pos + 2));
292
-
293
- $this->responseHeader[ $key ] = $value;
294
- }
295
-
296
- return strlen($header);
297
- }
298
-
299
- /**
300
- * Convert request headers to the expect curl format
301
- *
302
- * @return array
303
- */
304
- protected function prepareRequestHeaders()
305
- {
306
- $headers = [];
307
-
308
- foreach ($this->requestHeader as $header => $value) {
309
- $headers[] = trim($header) .': '. trim($value);
310
- }
311
-
312
- return $headers;
313
- }
314
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\HttpClient;
9
+
10
+ /**
11
+ * Hybridauth default Http client
12
+ */
13
+ class Curl implements HttpClientInterface
14
+ {
15
+ /**
16
+ * Default curl options
17
+ *
18
+ * These defaults options can be overwritten when sending requests.
19
+ *
20
+ * See setCurlOptions()
21
+ *
22
+ * @var array
23
+ */
24
+ protected $curlOptions = [
25
+ CURLOPT_TIMEOUT => 30,
26
+ CURLOPT_CONNECTTIMEOUT => 30,
27
+ CURLOPT_SSL_VERIFYPEER => false,
28
+ CURLOPT_SSL_VERIFYHOST => false,
29
+ CURLOPT_RETURNTRANSFER => true,
30
+ CURLOPT_FOLLOWLOCATION => true,
31
+ CURLOPT_MAXREDIRS => 5,
32
+ CURLINFO_HEADER_OUT => true,
33
+ CURLOPT_ENCODING => 'identity',
34
+ // phpcs:ignore
35
+ CURLOPT_USERAGENT => 'Hybridauth, PHP Social Authentication Library (https://github.com/hybridauth/hybridauth)',
36
+ ];
37
+
38
+ /**
39
+ * Method request() arguments
40
+ *
41
+ * This is used for debugging.
42
+ *
43
+ * @var array
44
+ */
45
+ protected $requestArguments = [];
46
+
47
+ /**
48
+ * Default request headers
49
+ *
50
+ * @var array
51
+ */
52
+ protected $requestHeader = [
53
+ 'Accept' => '*/*',
54
+ 'Cache-Control' => 'max-age=0',
55
+ 'Connection' => 'keep-alive',
56
+ 'Expect' => '',
57
+ 'Pragma' => '',
58
+ ];
59
+
60
+ /**
61
+ * Raw response returned by server
62
+ *
63
+ * @var string
64
+ */
65
+ protected $responseBody = '';
66
+
67
+ /**
68
+ * Headers returned in the response
69
+ *
70
+ * @var array
71
+ */
72
+ protected $responseHeader = [];
73
+
74
+ /**
75
+ * Response HTTP status code
76
+ *
77
+ * @var integer
78
+ */
79
+ protected $responseHttpCode = 0;
80
+
81
+ /**
82
+ * Last curl error number
83
+ *
84
+ * @var mixed
85
+ */
86
+ protected $responseClientError = null;
87
+
88
+ /**
89
+ * Information about the last transfer
90
+ *
91
+ * @var mixed
92
+ */
93
+ protected $responseClientInfo = [];
94
+
95
+ /**
96
+ * Hybridauth logger instance
97
+ *
98
+ * @var object
99
+ */
100
+ protected $logger = null;
101
+
102
+ /**
103
+ * {@inheritdoc}
104
+ */
105
+ public function request($uri, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
106
+ {
107
+ $this->requestHeader = array_replace($this->requestHeader, (array) $headers);
108
+
109
+ $this->requestArguments = [
110
+ 'uri' => $uri,
111
+ 'method' => $method,
112
+ 'parameters' => $parameters,
113
+ 'headers' => $this->requestHeader,
114
+ ];
115
+
116
+ $curl = curl_init();
117
+
118
+ switch ($method) {
119
+ case 'GET':
120
+ case 'DELETE':
121
+ unset($this->curlOptions[CURLOPT_POST]);
122
+ unset($this->curlOptions[CURLOPT_POSTFIELDS]);
123
+
124
+ $uri = $uri . (strpos($uri, '?') ? '&' : '?') . http_build_query($parameters);
125
+ if ($method === 'DELETE') {
126
+ $this->curlOptions[CURLOPT_CUSTOMREQUEST] = 'DELETE';
127
+ }
128
+ break;
129
+ case 'PUT':
130
+ case 'POST':
131
+ case 'PATCH':
132
+ $body_content = $multipart ? $parameters : http_build_query($parameters);
133
+ if (isset($this->requestHeader['Content-Type'])
134
+ && $this->requestHeader['Content-Type'] == 'application/json'
135
+ ) {
136
+ $body_content = json_encode($parameters);
137
+ }
138
+
139
+ if ($method === 'POST') {
140
+ $this->curlOptions[CURLOPT_POST] = true;
141
+ } else {
142
+ $this->curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
143
+ }
144
+ $this->curlOptions[CURLOPT_POSTFIELDS] = $body_content;
145
+ break;
146
+ }
147
+
148
+ $this->curlOptions[CURLOPT_URL] = $uri;
149
+ $this->curlOptions[CURLOPT_HTTPHEADER] = $this->prepareRequestHeaders();
150
+ $this->curlOptions[CURLOPT_HEADERFUNCTION] = [ $this, 'fetchResponseHeader' ];
151
+
152
+ foreach ($this->curlOptions as $opt => $value) {
153
+ curl_setopt($curl, $opt, $value);
154
+ }
155
+
156
+ $response = curl_exec($curl);
157
+
158
+ $this->responseBody = $response;
159
+ $this->responseHttpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
160
+ $this->responseClientError = curl_error($curl);
161
+ $this->responseClientInfo = curl_getinfo($curl);
162
+
163
+ if ($this->logger) {
164
+ // phpcs:ignore
165
+ $this->logger->debug(sprintf('%s::request( %s, %s ), response:', get_class($this), $uri, $method), $this->getResponse());
166
+
167
+ if (false === $response) {
168
+ // phpcs:ignore
169
+ $this->logger->error(sprintf('%s::request( %s, %s ), error:', get_class($this), $uri, $method), [$this->responseClientError]);
170
+ }
171
+ }
172
+
173
+ curl_close($curl);
174
+
175
+ return $this->responseBody;
176
+ }
177
+
178
+ /**
179
+ * {@inheritdoc}
180
+ */
181
+ public function getResponse()
182
+ {
183
+ $curlOptions = $this->curlOptions;
184
+
185
+ $curlOptions[CURLOPT_HEADERFUNCTION] = '*omitted';
186
+
187
+ return [
188
+ 'request' => $this->getRequestArguments(),
189
+ 'response' => [
190
+ 'code' => $this->getResponseHttpCode(),
191
+ 'headers' => $this->getResponseHeader(),
192
+ 'body' => $this->getResponseBody(),
193
+ ],
194
+ 'client' => [
195
+ 'error' => $this->getResponseClientError(),
196
+ 'info' => $this->getResponseClientInfo(),
197
+ 'opts' => $curlOptions,
198
+ ],
199
+ ];
200
+ }
201
+
202
+ /**
203
+ * Reset curl options
204
+ *
205
+ * @param array $curlOptions
206
+ */
207
+ public function setCurlOptions($curlOptions)
208
+ {
209
+ foreach ($curlOptions as $opt => $value) {
210
+ $this->curlOptions[ $opt ] = $value;
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Set logger instance
216
+ *
217
+ * @param object $logger
218
+ */
219
+ public function setLogger($logger)
220
+ {
221
+ $this->logger = $logger;
222
+ }
223
+
224
+ /**
225
+ * {@inheritdoc}
226
+ */
227
+ public function getResponseBody()
228
+ {
229
+ return $this->responseBody;
230
+ }
231
+
232
+ /**
233
+ * {@inheritdoc}
234
+ */
235
+ public function getResponseHeader()
236
+ {
237
+ return $this->responseHeader;
238
+ }
239
+
240
+ /**
241
+ * {@inheritdoc}
242
+ */
243
+ public function getResponseHttpCode()
244
+ {
245
+ return $this->responseHttpCode;
246
+ }
247
+
248
+ /**
249
+ * {@inheritdoc}
250
+ */
251
+ public function getResponseClientError()
252
+ {
253
+ return $this->responseClientError;
254
+ }
255
+
256
+ /**
257
+ * @return array
258
+ */
259
+ protected function getResponseClientInfo()
260
+ {
261
+ return $this->responseClientInfo;
262
+ }
263
+
264
+ /**
265
+ * Returns method request() arguments
266
+ *
267
+ * This is used for debugging.
268
+ *
269
+ * @return array
270
+ */
271
+ protected function getRequestArguments()
272
+ {
273
+ return $this->requestArguments;
274
+ }
275
+
276
+ /**
277
+ * Fetch server response headers
278
+ *
279
+ * @param mixed $curl
280
+ * @param string $header
281
+ *
282
+ * @return integer
283
+ */
284
+ protected function fetchResponseHeader($curl, $header)
285
+ {
286
+ $pos = strpos($header, ':');
287
+
288
+ if (! empty($pos)) {
289
+ $key = str_replace('-', '_', strtolower(substr($header, 0, $pos)));
290
+
291
+ $value = trim(substr($header, $pos + 2));
292
+
293
+ $this->responseHeader[ $key ] = $value;
294
+ }
295
+
296
+ return strlen($header);
297
+ }
298
+
299
+ /**
300
+ * Convert request headers to the expect curl format
301
+ *
302
+ * @return array
303
+ */
304
+ protected function prepareRequestHeaders()
305
+ {
306
+ $headers = [];
307
+
308
+ foreach ($this->requestHeader as $header => $value) {
309
+ $headers[] = trim($header) .': '. trim($value);
310
+ }
311
+
312
+ return $headers;
313
+ }
314
+ }
hybridauth/library/src/HttpClient/Guzzle.php CHANGED
@@ -1,273 +1,273 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\HttpClient;
9
-
10
- use GuzzleHttp\Client;
11
- use GuzzleHttp\Exception\RequestException;
12
- use GuzzleHttp\Exception\ServerException;
13
- use GuzzleHttp\Exception\TransferException;
14
-
15
- /**
16
- * Hybridauth Guzzle Http client
17
- *
18
- * Note: This is just a proof of concept. Feel free to improve it.
19
- *
20
- * Example:
21
- *
22
- * <code>
23
- * $guzzle = new Hybridauth\HttpClient\Guzzle( new GuzzleHttp\Client(), [
24
- * 'verify' => '/path/to/your/certificate.crt',
25
- * 'headers' => [ 'User-Agent' => '..' ]
26
- * // 'proxy' => ...
27
- * ]);
28
- *
29
- * $adapter = new Hybridauth\Provider\Github( $config, $guzzle );
30
- *
31
- * $adapter->authenticate();
32
- * </code>
33
- */
34
- class Guzzle implements HttpClientInterface
35
- {
36
- /**
37
- * Method request() arguments
38
- *
39
- * This is used for debugging.
40
- *
41
- * @var array
42
- */
43
- protected $requestArguments = [];
44
-
45
- /**
46
- * Default request headers
47
- *
48
- * @var array
49
- */
50
- protected $requestHeader = [];
51
-
52
- /**
53
- * Raw response returned by server
54
- *
55
- * @var string
56
- */
57
- protected $responseBody = '';
58
-
59
- /**
60
- * Headers returned in the response
61
- *
62
- * @var array
63
- */
64
- protected $responseHeader = [];
65
-
66
- /**
67
- * Response HTTP status code
68
- *
69
- * @var integer
70
- */
71
- protected $responseHttpCode = 0;
72
-
73
- /**
74
- * Last curl error number
75
- *
76
- * @var mixed
77
- */
78
- protected $responseClientError = null;
79
-
80
- /**
81
- * Information about the last transfer
82
- *
83
- * @var mixed
84
- */
85
- protected $responseClientInfo = [];
86
-
87
- /**
88
- * Hybridauth logger instance
89
- *
90
- * @var object
91
- */
92
- protected $logger = null;
93
-
94
- /**
95
- * GuzzleHttp client
96
- *
97
- * @var \GuzzleHttp\Client
98
- */
99
- protected $client = null;
100
-
101
- /**
102
- * ..
103
- * @param null $client
104
- * @param array $config
105
- */
106
- public function __construct($client = null, $config = [])
107
- {
108
- $this->client = $client ? $client : new Client($config);
109
- }
110
-
111
- /**
112
- * {@inheritdoc}
113
- */
114
- public function request($uri, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
115
- {
116
- $this->requestHeader = array_replace($this->requestHeader, (array) $headers);
117
-
118
- $this->requestArguments = [
119
- 'uri' => $uri,
120
- 'method' => $method,
121
- 'parameters' => $parameters,
122
- 'headers' => $this->requestHeader,
123
- ];
124
-
125
- $response = null;
126
-
127
- try {
128
- switch ($method) {
129
- case 'GET':
130
- case 'DELETE':
131
- $response = $this->client->request($method, $uri, [
132
- 'query' => $parameters,
133
- 'headers' => $this->requestHeader,
134
- ]);
135
- break;
136
- case 'PUT':
137
- case 'POST':
138
- $body_type = $multipart ? 'multipart' : 'form_params';
139
-
140
- if (isset($this->requestHeader['Content-Type'])
141
- && $this->requestHeader['Content-Type'] === 'application/json'
142
- ) {
143
- $body_type = 'json';
144
- }
145
-
146
- $body_content = $parameters;
147
- if ($multipart) {
148
- $body_content = [];
149
- foreach ($parameters as $key => $val) {
150
- if ($val instanceof \CURLFile) {
151
- $val = fopen($val->getFilename(), 'r');
152
- }
153
-
154
- $body_content[] = [
155
- 'name' => $key,
156
- 'contents' => $val,
157
- ];
158
- }
159
- }
160
-
161
- $response = $this->client->request($method, $uri, [
162
- $body_type => $body_content,
163
- 'headers' => $this->requestHeader,
164
- ]);
165
- break;
166
- }
167
- } catch (\Exception $e) {
168
- $response = $e->getResponse();
169
-
170
- $this->responseClientError = $e->getMessage();
171
- }
172
-
173
- if (!$this->responseClientError) {
174
- $this->responseBody = $response->getBody();
175
- $this->responseHttpCode = $response->getStatusCode();
176
- $this->responseHeader = $response->getHeaders();
177
- }
178
-
179
- if ($this->logger) {
180
- // phpcs:ignore
181
- $this->logger->debug(sprintf('%s::request( %s, %s ), response:', get_class($this), $uri, $method), $this->getResponse());
182
-
183
- if ($this->responseClientError) {
184
- // phpcs:ignore
185
- $this->logger->error(sprintf('%s::request( %s, %s ), error:', get_class($this), $uri, $method), [$this->responseClientError]);
186
- }
187
- }
188
-
189
- return $this->responseBody;
190
- }
191
-
192
- /**
193
- * {@inheritdoc}
194
- */
195
- public function getResponse()
196
- {
197
- return [
198
- 'request' => $this->getRequestArguments(),
199
- 'response' => [
200
- 'code' => $this->getResponseHttpCode(),
201
- 'headers' => $this->getResponseHeader(),
202
- 'body' => $this->getResponseBody(),
203
- ],
204
- 'client' => [
205
- 'error' => $this->getResponseClientError(),
206
- 'info' => $this->getResponseClientInfo(),
207
- 'opts' => null,
208
- ],
209
- ];
210
- }
211
-
212
- /**
213
- * Set logger instance
214
- *
215
- * @param object $logger
216
- */
217
- public function setLogger($logger)
218
- {
219
- $this->logger = $logger;
220
- }
221
-
222
- /**
223
- * {@inheritdoc}
224
- */
225
- public function getResponseBody()
226
- {
227
- return $this->responseBody;
228
- }
229
-
230
- /**
231
- * {@inheritdoc}
232
- */
233
- public function getResponseHeader()
234
- {
235
- return $this->responseHeader;
236
- }
237
-
238
- /**
239
- * {@inheritdoc}
240
- */
241
- public function getResponseHttpCode()
242
- {
243
- return $this->responseHttpCode;
244
- }
245
-
246
- /**
247
- * {@inheritdoc}
248
- */
249
- public function getResponseClientError()
250
- {
251
- return $this->responseClientError;
252
- }
253
-
254
- /**
255
- * @return array
256
- */
257
- protected function getResponseClientInfo()
258
- {
259
- return $this->responseClientInfo;
260
- }
261
-
262
- /**
263
- * Returns method request() arguments
264
- *
265
- * This is used for debugging.
266
- *
267
- * @return array
268
- */
269
- protected function getRequestArguments()
270
- {
271
- return $this->requestArguments;
272
- }
273
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\HttpClient;
9
+
10
+ use GuzzleHttp\Client;
11
+ use GuzzleHttp\Exception\RequestException;
12
+ use GuzzleHttp\Exception\ServerException;
13
+ use GuzzleHttp\Exception\TransferException;
14
+
15
+ /**
16
+ * Hybridauth Guzzle Http client
17
+ *
18
+ * Note: This is just a proof of concept. Feel free to improve it.
19
+ *
20
+ * Example:
21
+ *
22
+ * <code>
23
+ * $guzzle = new Hybridauth\HttpClient\Guzzle( new GuzzleHttp\Client(), [
24
+ * 'verify' => '/path/to/your/certificate.crt',
25
+ * 'headers' => [ 'User-Agent' => '..' ]
26
+ * // 'proxy' => ...
27
+ * ]);
28
+ *
29
+ * $adapter = new Hybridauth\Provider\Github( $config, $guzzle );
30
+ *
31
+ * $adapter->authenticate();
32
+ * </code>
33
+ */
34
+ class Guzzle implements HttpClientInterface
35
+ {
36
+ /**
37
+ * Method request() arguments
38
+ *
39
+ * This is used for debugging.
40
+ *
41
+ * @var array
42
+ */
43
+ protected $requestArguments = [];
44
+
45
+ /**
46
+ * Default request headers
47
+ *
48
+ * @var array
49
+ */
50
+ protected $requestHeader = [];
51
+
52
+ /**
53
+ * Raw response returned by server
54
+ *
55
+ * @var string
56
+ */
57
+ protected $responseBody = '';
58
+
59
+ /**
60
+ * Headers returned in the response
61
+ *
62
+ * @var array
63
+ */
64
+ protected $responseHeader = [];
65
+
66
+ /**
67
+ * Response HTTP status code
68
+ *
69
+ * @var integer
70
+ */
71
+ protected $responseHttpCode = 0;
72
+
73
+ /**
74
+ * Last curl error number
75
+ *
76
+ * @var mixed
77
+ */
78
+ protected $responseClientError = null;
79
+
80
+ /**
81
+ * Information about the last transfer
82
+ *
83
+ * @var mixed
84
+ */
85
+ protected $responseClientInfo = [];
86
+
87
+ /**
88
+ * Hybridauth logger instance
89
+ *
90
+ * @var object
91
+ */
92
+ protected $logger = null;
93
+
94
+ /**
95
+ * GuzzleHttp client
96
+ *
97
+ * @var \GuzzleHttp\Client
98
+ */
99
+ protected $client = null;
100
+
101
+ /**
102
+ * ..
103
+ * @param null $client
104
+ * @param array $config
105
+ */
106
+ public function __construct($client = null, $config = [])
107
+ {
108
+ $this->client = $client ? $client : new Client($config);
109
+ }
110
+
111
+ /**
112
+ * {@inheritdoc}
113
+ */
114
+ public function request($uri, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
115
+ {
116
+ $this->requestHeader = array_replace($this->requestHeader, (array) $headers);
117
+
118
+ $this->requestArguments = [
119
+ 'uri' => $uri,
120
+ 'method' => $method,
121
+ 'parameters' => $parameters,
122
+ 'headers' => $this->requestHeader,
123
+ ];
124
+
125
+ $response = null;
126
+
127
+ try {
128
+ switch ($method) {
129
+ case 'GET':
130
+ case 'DELETE':
131
+ $response = $this->client->request($method, $uri, [
132
+ 'query' => $parameters,
133
+ 'headers' => $this->requestHeader,
134
+ ]);
135
+ break;
136
+ case 'PUT':
137
+ case 'POST':
138
+ $body_type = $multipart ? 'multipart' : 'form_params';
139
+
140
+ if (isset($this->requestHeader['Content-Type'])
141
+ && $this->requestHeader['Content-Type'] === 'application/json'
142
+ ) {
143
+ $body_type = 'json';
144
+ }
145
+
146
+ $body_content = $parameters;
147
+ if ($multipart) {
148
+ $body_content = [];
149
+ foreach ($parameters as $key => $val) {
150
+ if ($val instanceof \CURLFile) {
151
+ $val = fopen($val->getFilename(), 'r');
152
+ }
153
+
154
+ $body_content[] = [
155
+ 'name' => $key,
156
+ 'contents' => $val,
157
+ ];
158
+ }
159
+ }
160
+
161
+ $response = $this->client->request($method, $uri, [
162
+ $body_type => $body_content,
163
+ 'headers' => $this->requestHeader,
164
+ ]);
165
+ break;
166
+ }
167
+ } catch (\Exception $e) {
168
+ $response = $e->getResponse();
169
+
170
+ $this->responseClientError = $e->getMessage();
171
+ }
172
+
173
+ if (!$this->responseClientError) {
174
+ $this->responseBody = $response->getBody();
175
+ $this->responseHttpCode = $response->getStatusCode();
176
+ $this->responseHeader = $response->getHeaders();
177
+ }
178
+
179
+ if ($this->logger) {
180
+ // phpcs:ignore
181
+ $this->logger->debug(sprintf('%s::request( %s, %s ), response:', get_class($this), $uri, $method), $this->getResponse());
182
+
183
+ if ($this->responseClientError) {
184
+ // phpcs:ignore
185
+ $this->logger->error(sprintf('%s::request( %s, %s ), error:', get_class($this), $uri, $method), [$this->responseClientError]);
186
+ }
187
+ }
188
+
189
+ return $this->responseBody;
190
+ }
191
+
192
+ /**
193
+ * {@inheritdoc}
194
+ */
195
+ public function getResponse()
196
+ {
197
+ return [
198
+ 'request' => $this->getRequestArguments(),
199
+ 'response' => [
200
+ 'code' => $this->getResponseHttpCode(),
201
+ 'headers' => $this->getResponseHeader(),
202
+ 'body' => $this->getResponseBody(),
203
+ ],
204
+ 'client' => [
205
+ 'error' => $this->getResponseClientError(),
206
+ 'info' => $this->getResponseClientInfo(),
207
+ 'opts' => null,
208
+ ],
209
+ ];
210
+ }
211
+
212
+ /**
213
+ * Set logger instance
214
+ *
215
+ * @param object $logger
216
+ */
217
+ public function setLogger($logger)
218
+ {
219
+ $this->logger = $logger;
220
+ }
221
+
222
+ /**
223
+ * {@inheritdoc}
224
+ */
225
+ public function getResponseBody()
226
+ {
227
+ return $this->responseBody;
228
+ }
229
+
230
+ /**
231
+ * {@inheritdoc}
232
+ */
233
+ public function getResponseHeader()
234
+ {
235
+ return $this->responseHeader;
236
+ }
237
+
238
+ /**
239
+ * {@inheritdoc}
240
+ */
241
+ public function getResponseHttpCode()
242
+ {
243
+ return $this->responseHttpCode;
244
+ }
245
+
246
+ /**
247
+ * {@inheritdoc}
248
+ */
249
+ public function getResponseClientError()
250
+ {
251
+ return $this->responseClientError;
252
+ }
253
+
254
+ /**
255
+ * @return array
256
+ */
257
+ protected function getResponseClientInfo()
258
+ {
259
+ return $this->responseClientInfo;
260
+ }
261
+
262
+ /**
263
+ * Returns method request() arguments
264
+ *
265
+ * This is used for debugging.
266
+ *
267
+ * @return array
268
+ */
269
+ protected function getRequestArguments()
270
+ {
271
+ return $this->requestArguments;
272
+ }
273
+ }
hybridauth/library/src/HttpClient/HttpClientInterface.php CHANGED
@@ -1,58 +1,58 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\HttpClient;
9
-
10
- /**
11
- * Hybridauth Http clients interface
12
- */
13
- interface HttpClientInterface
14
- {
15
- /**
16
- * Send request to the remote server
17
- *
18
- * Returns the result (Raw response from the server) on success, FALSE on failure
19
- *
20
- * @param string $uri
21
- * @param string $method
22
- * @param array $parameters
23
- * @param array $headers
24
- * @param bool $multipart
25
- *
26
- * @return mixed
27
- */
28
- public function request($uri, $method = 'GET', $parameters = [], $headers = [], $multipart = false);
29
-
30
- /**
31
- * Returns raw response from the server on success, FALSE on failure
32
- *
33
- * @return mixed
34
- */
35
- public function getResponseBody();
36
-
37
- /**
38
- * Retriever the headers returned in the response
39
- *
40
- * @return array
41
- */
42
- public function getResponseHeader();
43
-
44
- /**
45
- * Returns latest request HTTP status code
46
- *
47
- * @return integer
48
- */
49
- public function getResponseHttpCode();
50
-
51
- /**
52
- * Returns latest error encountered by the client
53
- * This can be either a code or error message
54
- *
55
- * @return mixed
56
- */
57
- public function getResponseClientError();
58
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\HttpClient;
9
+
10
+ /**
11
+ * Hybridauth Http clients interface
12
+ */
13
+ interface HttpClientInterface
14
+ {
15
+ /**
16
+ * Send request to the remote server
17
+ *
18
+ * Returns the result (Raw response from the server) on success, FALSE on failure
19
+ *
20
+ * @param string $uri
21
+ * @param string $method
22
+ * @param array $parameters
23
+ * @param array $headers
24
+ * @param bool $multipart
25
+ *
26
+ * @return mixed
27
+ */
28
+ public function request($uri, $method = 'GET', $parameters = [], $headers = [], $multipart = false);
29
+
30
+ /**
31
+ * Returns raw response from the server on success, FALSE on failure
32
+ *
33
+ * @return mixed
34
+ */
35
+ public function getResponseBody();
36
+
37
+ /**
38
+ * Retriever the headers returned in the response
39
+ *
40
+ * @return array
41
+ */
42
+ public function getResponseHeader();
43
+
44
+ /**
45
+ * Returns latest request HTTP status code
46
+ *
47
+ * @return integer
48
+ */
49
+ public function getResponseHttpCode();
50
+
51
+ /**
52
+ * Returns latest error encountered by the client
53
+ * This can be either a code or error message
54
+ *
55
+ * @return mixed
56
+ */
57
+ public function getResponseClientError();
58
+ }
hybridauth/library/src/HttpClient/Util.php CHANGED
@@ -1,100 +1,100 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\HttpClient;
9
-
10
- use Hybridauth\Data;
11
-
12
- /**
13
- * HttpClient\Util home to a number of utility functions.
14
- */
15
- class Util
16
- {
17
- /**
18
- * Redirect handler.
19
- *
20
- * @var callable|null
21
- */
22
- protected static $redirectHandler;
23
-
24
- /**
25
- * Exit handler.
26
- *
27
- * @var callable|null
28
- */
29
- protected static $exitHandler;
30
-
31
- /**
32
- * Redirect to a given URL.
33
- *
34
- * In case your application need to perform certain required actions before Hybridauth redirect users
35
- * to IDPs websites, the default behaviour can be altered in one of two ways:
36
- * If callable $redirectHandler is defined, it will be called instead.
37
- * If callable $exitHandler is defined, it will be called instead of exit().
38
- *
39
- * @param string $url
40
- *
41
- * @return mixed
42
- */
43
- public static function redirect($url)
44
- {
45
- if (static::$redirectHandler) {
46
- return call_user_func(static::$redirectHandler, $url);
47
- }
48
-
49
- header(sprintf('Location: %s', $url));
50
-
51
- if (static::$exitHandler) {
52
- return call_user_func(static::$exitHandler);
53
- }
54
-
55
- exit(1);
56
- }
57
-
58
- /**
59
- * Redirect handler to which the regular redirect() will yield the action of redirecting users.
60
- *
61
- * @param callable $callback
62
- */
63
- public static function setRedirectHandler($callback)
64
- {
65
- self::$redirectHandler = $callback;
66
- }
67
-
68
- /**
69
- * Exit handler will be called instead of regular exit() when calling Util::redirect() method.
70
- *
71
- * @param callable $callback
72
- */
73
- public static function setExitHandler($callback)
74
- {
75
- self::$exitHandler = $callback;
76
- }
77
-
78
- /**
79
- * Returns the Current URL.
80
- *
81
- * @param bool $requestUri TRUE to use $_SERVER['REQUEST_URI'], FALSE for $_SERVER['PHP_SELF']
82
- *
83
- * @return string
84
- */
85
- public static function getCurrentUrl($requestUri = false)
86
- {
87
- $collection = new Data\Collection($_SERVER);
88
-
89
- $protocol = 'http://';
90
-
91
- if (($collection->get('HTTPS') && $collection->get('HTTPS') !== 'off') ||
92
- $collection->get('HTTP_X_FORWARDED_PROTO') === 'https') {
93
- $protocol = 'https://';
94
- }
95
-
96
- return $protocol.
97
- $collection->get('HTTP_HOST').
98
- $collection->get($requestUri ? 'REQUEST_URI' : 'PHP_SELF');
99
- }
100
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\HttpClient;
9
+
10
+ use Hybridauth\Data;
11
+
12
+ /**
13
+ * HttpClient\Util home to a number of utility functions.
14
+ */
15
+ class Util
16
+ {
17
+ /**
18
+ * Redirect handler.
19
+ *
20
+ * @var callable|null
21
+ */
22
+ protected static $redirectHandler;
23
+
24
+ /**
25
+ * Exit handler.
26
+ *
27
+ * @var callable|null
28
+ */
29
+ protected static $exitHandler;
30
+
31
+ /**
32
+ * Redirect to a given URL.
33
+ *
34
+ * In case your application need to perform certain required actions before Hybridauth redirect users
35
+ * to IDPs websites, the default behaviour can be altered in one of two ways:
36
+ * If callable $redirectHandler is defined, it will be called instead.
37
+ * If callable $exitHandler is defined, it will be called instead of exit().
38
+ *
39
+ * @param string $url
40
+ *
41
+ * @return mixed
42
+ */
43
+ public static function redirect($url)
44
+ {
45
+ if (static::$redirectHandler) {
46
+ return call_user_func(static::$redirectHandler, $url);
47
+ }
48
+
49
+ header(sprintf('Location: %s', $url));
50
+
51
+ if (static::$exitHandler) {
52
+ return call_user_func(static::$exitHandler);
53
+ }
54
+
55
+ exit(1);
56
+ }
57
+
58
+ /**
59
+ * Redirect handler to which the regular redirect() will yield the action of redirecting users.
60
+ *
61
+ * @param callable $callback
62
+ */
63
+ public static function setRedirectHandler($callback)
64
+ {
65
+ self::$redirectHandler = $callback;
66
+ }
67
+
68
+ /**
69
+ * Exit handler will be called instead of regular exit() when calling Util::redirect() method.
70
+ *
71
+ * @param callable $callback
72
+ */
73
+ public static function setExitHandler($callback)
74
+ {
75
+ self::$exitHandler = $callback;
76
+ }
77
+
78
+ /**
79
+ * Returns the Current URL.
80
+ *
81
+ * @param bool $requestUri TRUE to use $_SERVER['REQUEST_URI'], FALSE for $_SERVER['PHP_SELF']
82
+ *
83
+ * @return string
84
+ */
85
+ public static function getCurrentUrl($requestUri = false)
86
+ {
87
+ $collection = new Data\Collection($_SERVER);
88
+
89
+ $protocol = 'http://';
90
+
91
+ if (($collection->get('HTTPS') && $collection->get('HTTPS') !== 'off') ||
92
+ $collection->get('HTTP_X_FORWARDED_PROTO') === 'https') {
93
+ $protocol = 'https://';
94
+ }
95
+
96
+ return $protocol.
97
+ $collection->get('HTTP_HOST').
98
+ $collection->get($requestUri ? 'REQUEST_URI' : 'PHP_SELF');
99
+ }
100
+ }
hybridauth/library/src/Hybridauth.php CHANGED
@@ -1,268 +1,268 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth;
9
-
10
- use Hybridauth\Exception\InvalidArgumentException;
11
- use Hybridauth\Exception\UnexpectedValueException;
12
- use Hybridauth\Storage\StorageInterface;
13
- use Hybridauth\Logger\LoggerInterface;
14
- use Hybridauth\Logger\Logger;
15
- use Hybridauth\HttpClient\HttpClientInterface;
16
-
17
- /**
18
- * Hybridauth\Hybridauth
19
- *
20
- * For ease of use of multiple providers, Hybridauth implements the class Hybridauth\Hybridauth,
21
- * a sort of factory/façade which acts as an unified interface or entry point, and it expects a
22
- * configuration array containing the list of providers you want to use, their respective credentials
23
- * and authorized callback.
24
- */
25
- class Hybridauth
26
- {
27
- /**
28
- * Hybridauth config.
29
- *
30
- * @var array
31
- */
32
- protected $config;
33
-
34
- /**
35
- * Storage.
36
- *
37
- * @var StorageInterface
38
- */
39
- protected $storage;
40
-
41
- /**
42
- * HttpClient.
43
- *
44
- * @var HttpClientInterface
45
- */
46
- protected $httpClient;
47
-
48
- /**
49
- * Logger.
50
- *
51
- * @var LoggerInterface
52
- */
53
- protected $logger;
54
-
55
- /**
56
- * @param array|string $config Array with configuration or Path to PHP file that will return array
57
- * @param HttpClientInterface $httpClient
58
- * @param StorageInterface $storage
59
- * @param LoggerInterface $logger
60
- *
61
- * @throws InvalidArgumentException
62
- */
63
- public function __construct(
64
- $config,
65
- HttpClientInterface $httpClient = null,
66
- StorageInterface $storage = null,
67
- LoggerInterface $logger = null
68
- ) {
69
- if (is_string($config) && file_exists($config)) {
70
- $config = include $config;
71
- } elseif (! is_array($config)) {
72
- throw new InvalidArgumentException('Hybridauth config does not exist on the given path.');
73
- }
74
-
75
- $this->config = $config + [
76
- 'debug_mode' => Logger::NONE,
77
- 'debug_file' => '',
78
- 'curl_options' => null,
79
- 'providers' => []
80
- ];
81
- $this->storage = $storage;
82
- $this->logger = $logger;
83
- $this->httpClient = $httpClient;
84
- }
85
-
86
- /**
87
- * Instantiate the given provider and authentication or authorization protocol.
88
- *
89
- * If not authenticated yet, the user will be redirected to the provider's site for
90
- * authentication/authorisation, otherwise it will simply return an instance of
91
- * provider's adapter.
92
- *
93
- * @param string $name adapter's name (case insensitive)
94
- *
95
- * @return \Hybridauth\Adapter\AdapterInterface
96
- * @throws InvalidArgumentException
97
- * @throws UnexpectedValueException
98
- */
99
- public function authenticate($name)
100
- {
101
- $adapter = $this->getAdapter($name);
102
-
103
- $adapter->authenticate();
104
-
105
- return $adapter;
106
- }
107
-
108
- /**
109
- * Returns a new instance of a provider's adapter by name
110
- *
111
- * @param string $name adapter's name (case insensitive)
112
- *
113
- * @return \Hybridauth\Adapter\AdapterInterface
114
- * @throws InvalidArgumentException
115
- * @throws UnexpectedValueException
116
- */
117
- public function getAdapter($name)
118
- {
119
- $config = $this->getProviderConfig($name);
120
-
121
- $adapter = isset($config['adapter']) ? $config['adapter'] : sprintf('Hybridauth\\Provider\\%s', $name);
122
-
123
- if (!class_exists($adapter)) {
124
- $adapter = null;
125
- $fs = new \FilesystemIterator(__DIR__ . '/Provider/');
126
- /** @var \SplFileInfo $file */
127
- foreach ($fs as $file) {
128
- if (!$file->isDir()) {
129
- $provider = strtok($file->getFilename(), '.');
130
- if ($name === mb_strtolower($provider)) {
131
- $adapter = sprintf('Hybridauth\\Provider\\%s', $provider);
132
- break;
133
- }
134
- }
135
- }
136
- if ($adapter === null) {
137
- throw new InvalidArgumentException('Unknown Provider.');
138
- }
139
- }
140
-
141
- return new $adapter($config, $this->httpClient, $this->storage, $this->logger);
142
- }
143
-
144
- /**
145
- * Get provider config by name.
146
- *
147
- * @param string $name adapter's name (case insensitive)
148
- *
149
- * @throws UnexpectedValueException
150
- * @throws InvalidArgumentException
151
- *
152
- * @return array
153
- */
154
- public function getProviderConfig($name)
155
- {
156
- $name = strtolower($name);
157
-
158
- $providersConfig = array_change_key_case($this->config['providers'], CASE_LOWER);
159
-
160
- if (! isset($providersConfig[$name])) {
161
- throw new InvalidArgumentException('Unknown Provider.');
162
- }
163
-
164
- if (! $providersConfig[$name]['enabled']) {
165
- throw new UnexpectedValueException('Disabled Provider.');
166
- }
167
-
168
- $config = $providersConfig[$name];
169
- $config += [
170
- 'debug_mode' => $this->config['debug_mode'],
171
- 'debug_file' => $this->config['debug_file'],
172
- ];
173
-
174
- if (! isset($config['callback']) && isset($this->config['callback'])) {
175
- $config['callback'] = $this->config['callback'];
176
- }
177
-
178
- return $config;
179
- }
180
-
181
- /**
182
- * Returns a boolean of whether the user is connected with a provider
183
- *
184
- * @param string $name adapter's name (case insensitive)
185
- *
186
- * @return boolean
187
- * @throws InvalidArgumentException
188
- * @throws UnexpectedValueException
189
- */
190
- public function isConnectedWith($name)
191
- {
192
- return $this->getAdapter($name)->isConnected();
193
- }
194
-
195
- /**
196
- * Returns a list of enabled adapters names
197
- *
198
- * @return array
199
- */
200
- public function getProviders()
201
- {
202
- $providers = [];
203
-
204
- foreach ($this->config['providers'] as $name => $config) {
205
- if ($config['enabled']) {
206
- $providers[] = $name;
207
- }
208
- }
209
-
210
- return $providers;
211
- }
212
-
213
- /**
214
- * Returns a list of currently connected adapters names
215
- *
216
- * @return array
217
- * @throws InvalidArgumentException
218
- * @throws UnexpectedValueException
219
- */
220
- public function getConnectedProviders()
221
- {
222
- $providers = [];
223
-
224
- foreach ($this->getProviders() as $name) {
225
- if ($this->isConnectedWith($name)) {
226
- $providers[] = $name;
227
- }
228
- }
229
-
230
- return $providers;
231
- }
232
-
233
- /**
234
- * Returns a list of new instances of currently connected adapters
235
- *
236
- * @return \Hybridauth\Adapter\AdapterInterface[]
237
- * @throws InvalidArgumentException
238
- * @throws UnexpectedValueException
239
- */
240
- public function getConnectedAdapters()
241
- {
242
- $adapters = [];
243
-
244
- foreach ($this->getProviders() as $name) {
245
- $adapter = $this->getAdapter($name);
246
-
247
- if ($adapter->isConnected()) {
248
- $adapters[$name] = $adapter;
249
- }
250
- }
251
-
252
- return $adapters;
253
- }
254
-
255
- /**
256
- * Disconnect all currently connected adapters at once
257
- */
258
- public function disconnectAllAdapters()
259
- {
260
- foreach ($this->getProviders() as $name) {
261
- $adapter = $this->getAdapter($name);
262
-
263
- if ($adapter->isConnected()) {
264
- $adapter->disconnect();
265
- }
266
- }
267
- }
268
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth;
9
+
10
+ use Hybridauth\Exception\InvalidArgumentException;
11
+ use Hybridauth\Exception\UnexpectedValueException;
12
+ use Hybridauth\Storage\StorageInterface;
13
+ use Hybridauth\Logger\LoggerInterface;
14
+ use Hybridauth\Logger\Logger;
15
+ use Hybridauth\HttpClient\HttpClientInterface;
16
+
17
+ /**
18
+ * Hybridauth\Hybridauth
19
+ *
20
+ * For ease of use of multiple providers, Hybridauth implements the class Hybridauth\Hybridauth,
21
+ * a sort of factory/façade which acts as an unified interface or entry point, and it expects a
22
+ * configuration array containing the list of providers you want to use, their respective credentials
23
+ * and authorized callback.
24
+ */
25
+ class Hybridauth
26
+ {
27
+ /**
28
+ * Hybridauth config.
29
+ *
30
+ * @var array
31
+ */
32
+ protected $config;
33
+
34
+ /**
35
+ * Storage.
36
+ *
37
+ * @var StorageInterface
38
+ */
39
+ protected $storage;
40
+
41
+ /**
42
+ * HttpClient.
43
+ *
44
+ * @var HttpClientInterface
45
+ */
46
+ protected $httpClient;
47
+
48
+ /**
49
+ * Logger.
50
+ *
51
+ * @var LoggerInterface
52
+ */
53
+ protected $logger;
54
+
55
+ /**
56
+ * @param array|string $config Array with configuration or Path to PHP file that will return array
57
+ * @param HttpClientInterface $httpClient
58
+ * @param StorageInterface $storage
59
+ * @param LoggerInterface $logger
60
+ *
61
+ * @throws InvalidArgumentException
62
+ */
63
+ public function __construct(
64
+ $config,
65
+ HttpClientInterface $httpClient = null,
66
+ StorageInterface $storage = null,
67
+ LoggerInterface $logger = null
68
+ ) {
69
+ if (is_string($config) && file_exists($config)) {
70
+ $config = include $config;
71
+ } elseif (! is_array($config)) {
72
+ throw new InvalidArgumentException('Hybridauth config does not exist on the given path.');
73
+ }
74
+
75
+ $this->config = $config + [
76
+ 'debug_mode' => Logger::NONE,
77
+ 'debug_file' => '',
78
+ 'curl_options' => null,
79
+ 'providers' => []
80
+ ];
81
+ $this->storage = $storage;
82
+ $this->logger = $logger;
83
+ $this->httpClient = $httpClient;
84
+ }
85
+
86
+ /**
87
+ * Instantiate the given provider and authentication or authorization protocol.
88
+ *
89
+ * If not authenticated yet, the user will be redirected to the provider's site for
90
+ * authentication/authorisation, otherwise it will simply return an instance of
91
+ * provider's adapter.
92
+ *
93
+ * @param string $name adapter's name (case insensitive)
94
+ *
95
+ * @return \Hybridauth\Adapter\AdapterInterface
96
+ * @throws InvalidArgumentException
97
+ * @throws UnexpectedValueException
98
+ */
99
+ public function authenticate($name)
100
+ {
101
+ $adapter = $this->getAdapter($name);
102
+
103
+ $adapter->authenticate();
104
+
105
+ return $adapter;
106
+ }
107
+
108
+ /**
109
+ * Returns a new instance of a provider's adapter by name
110
+ *
111
+ * @param string $name adapter's name (case insensitive)
112
+ *
113
+ * @return \Hybridauth\Adapter\AdapterInterface
114
+ * @throws InvalidArgumentException
115
+ * @throws UnexpectedValueException
116
+ */
117
+ public function getAdapter($name)
118
+ {
119
+ $config = $this->getProviderConfig($name);
120
+
121
+ $adapter = isset($config['adapter']) ? $config['adapter'] : sprintf('Hybridauth\\Provider\\%s', $name);
122
+
123
+ if (!class_exists($adapter)) {
124
+ $adapter = null;
125
+ $fs = new \FilesystemIterator(__DIR__ . '/Provider/');
126
+ /** @var \SplFileInfo $file */
127
+ foreach ($fs as $file) {
128
+ if (!$file->isDir()) {
129
+ $provider = strtok($file->getFilename(), '.');
130
+ if ($name === mb_strtolower($provider)) {
131
+ $adapter = sprintf('Hybridauth\\Provider\\%s', $provider);
132
+ break;
133
+ }
134
+ }
135
+ }
136
+ if ($adapter === null) {
137
+ throw new InvalidArgumentException('Unknown Provider.');
138
+ }
139
+ }
140
+
141
+ return new $adapter($config, $this->httpClient, $this->storage, $this->logger);
142
+ }
143
+
144
+ /**
145
+ * Get provider config by name.
146
+ *
147
+ * @param string $name adapter's name (case insensitive)
148
+ *
149
+ * @throws UnexpectedValueException
150
+ * @throws InvalidArgumentException
151
+ *
152
+ * @return array
153
+ */
154
+ public function getProviderConfig($name)
155
+ {
156
+ $name = strtolower($name);
157
+
158
+ $providersConfig = array_change_key_case($this->config['providers'], CASE_LOWER);
159
+
160
+ if (! isset($providersConfig[$name])) {
161
+ throw new InvalidArgumentException('Unknown Provider.');
162
+ }
163
+
164
+ if (! $providersConfig[$name]['enabled']) {
165
+ throw new UnexpectedValueException('Disabled Provider.');
166
+ }
167
+
168
+ $config = $providersConfig[$name];
169
+ $config += [
170
+ 'debug_mode' => $this->config['debug_mode'],
171
+ 'debug_file' => $this->config['debug_file'],
172
+ ];
173
+
174
+ if (! isset($config['callback']) && isset($this->config['callback'])) {
175
+ $config['callback'] = $this->config['callback'];
176
+ }
177
+
178
+ return $config;
179
+ }
180
+
181
+ /**
182
+ * Returns a boolean of whether the user is connected with a provider
183
+ *
184
+ * @param string $name adapter's name (case insensitive)
185
+ *
186
+ * @return boolean
187
+ * @throws InvalidArgumentException
188
+ * @throws UnexpectedValueException
189
+ */
190
+ public function isConnectedWith($name)
191
+ {
192
+ return $this->getAdapter($name)->isConnected();
193
+ }
194
+
195
+ /**
196
+ * Returns a list of enabled adapters names
197
+ *
198
+ * @return array
199
+ */
200
+ public function getProviders()
201
+ {
202
+ $providers = [];
203
+
204
+ foreach ($this->config['providers'] as $name => $config) {
205
+ if ($config['enabled']) {
206
+ $providers[] = $name;
207
+ }
208
+ }
209
+
210
+ return $providers;
211
+ }
212
+
213
+ /**
214
+ * Returns a list of currently connected adapters names
215
+ *
216
+ * @return array
217
+ * @throws InvalidArgumentException
218
+ * @throws UnexpectedValueException
219
+ */
220
+ public function getConnectedProviders()
221
+ {
222
+ $providers = [];
223
+
224
+ foreach ($this->getProviders() as $name) {
225
+ if ($this->isConnectedWith($name)) {
226
+ $providers[] = $name;
227
+ }
228
+ }
229
+
230
+ return $providers;
231
+ }
232
+
233
+ /**
234
+ * Returns a list of new instances of currently connected adapters
235
+ *
236
+ * @return \Hybridauth\Adapter\AdapterInterface[]
237
+ * @throws InvalidArgumentException
238
+ * @throws UnexpectedValueException
239
+ */
240
+ public function getConnectedAdapters()
241
+ {
242
+ $adapters = [];
243
+
244
+ foreach ($this->getProviders() as $name) {
245
+ $adapter = $this->getAdapter($name);
246
+
247
+ if ($adapter->isConnected()) {
248
+ $adapters[$name] = $adapter;
249
+ }
250
+ }
251
+
252
+ return $adapters;
253
+ }
254
+
255
+ /**
256
+ * Disconnect all currently connected adapters at once
257
+ */
258
+ public function disconnectAllAdapters()
259
+ {
260
+ foreach ($this->getProviders() as $name) {
261
+ $adapter = $this->getAdapter($name);
262
+
263
+ if ($adapter->isConnected()) {
264
+ $adapter->disconnect();
265
+ }
266
+ }
267
+ }
268
+ }
hybridauth/library/src/Logger/Logger.php CHANGED
@@ -1,129 +1,129 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Logger;
9
-
10
- use Hybridauth\Exception\RuntimeException;
11
- use Hybridauth\Exception\InvalidArgumentException;
12
-
13
- /**
14
- * Debugging and Logging utility.
15
- */
16
- class Logger implements LoggerInterface
17
- {
18
- const NONE = 'none'; // turn logging off
19
- const DEBUG = 'debug'; // debug, info and error messages
20
- const INFO = 'info'; // info and error messages
21
- const ERROR = 'error'; // only error messages
22
-
23
- /**
24
- * Debug level.
25
- *
26
- * One of Logger::NONE, Logger::DEBUG, Logger::INFO, Logger::ERROR
27
- *
28
- * @var string
29
- */
30
- protected $level;
31
-
32
- /**
33
- * Path to file writeable by the web server. Required if $this->level !== Logger::NONE.
34
- *
35
- * @var string
36
- */
37
- protected $file;
38
-
39
- /**
40
- * @param bool|string $level One of Logger::NONE, Logger::DEBUG, Logger::INFO, Logger::ERROR
41
- * @param string $file File where to write messages
42
- *
43
- * @throws InvalidArgumentException
44
- * @throws RuntimeException
45
- */
46
- public function __construct($level, $file)
47
- {
48
- $this->level = self::NONE;
49
-
50
- if ($level && $level !== self::NONE) {
51
- $this->initialize($file);
52
-
53
- $this->level = $level === true ? Logger::DEBUG : $level;
54
- $this->file = $file;
55
- }
56
- }
57
-
58
- /**
59
- * @param string $file
60
- *
61
- * @throws InvalidArgumentException
62
- * @throws RuntimeException
63
- */
64
- protected function initialize($file)
65
- {
66
- if (!$file) {
67
- throw new InvalidArgumentException('Log file is not specified.');
68
- }
69
-
70
- if (!file_exists($file) && !touch($file)) {
71
- throw new RuntimeException(sprintf('Log file %s can not be created.', $file));
72
- }
73
-
74
- if (!is_writable($file)) {
75
- throw new RuntimeException(sprintf('Log file %s is not writeable.', $file));
76
- }
77
- }
78
-
79
- /**
80
- * @inheritdoc
81
- */
82
- public function info($message, array $context = [])
83
- {
84
- if (!in_array($this->level, [self::DEBUG, self::INFO])) {
85
- return;
86
- }
87
-
88
- $this->log(self::INFO, $message, $context);
89
- }
90
-
91
- /**
92
- * @inheritdoc
93
- */
94
- public function debug($message, array $context = [])
95
- {
96
- if (!in_array($this->level, [self::DEBUG])) {
97
- return;
98
- }
99
-
100
- $this->log(self::DEBUG, $message, $context);
101
- }
102
-
103
- /**
104
- * @inheritdoc
105
- */
106
- public function error($message, array $context = [])
107
- {
108
- if (!in_array($this->level, [self::DEBUG, self::INFO, self::ERROR])) {
109
- return;
110
- }
111
-
112
- $this->log(self::ERROR, $message, $context);
113
- }
114
-
115
- /**
116
- * @inheritdoc
117
- */
118
- public function log($level, $message, array $context = [])
119
- {
120
- $datetime = new \DateTime();
121
- $datetime = $datetime->format(DATE_ATOM);
122
-
123
- $content = sprintf('%s -- %s -- %s -- %s', $level, $_SERVER['REMOTE_ADDR'], $datetime, $message);
124
- $content .= ($context ? "\n".print_r($context, true) : '');
125
- $content .= "\n";
126
-
127
- file_put_contents($this->file, $content, FILE_APPEND);
128
- }
129
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Logger;
9
+
10
+ use Hybridauth\Exception\RuntimeException;
11
+ use Hybridauth\Exception\InvalidArgumentException;
12
+
13
+ /**
14
+ * Debugging and Logging utility.
15
+ */
16
+ class Logger implements LoggerInterface
17
+ {
18
+ const NONE = 'none'; // turn logging off
19
+ const DEBUG = 'debug'; // debug, info and error messages
20
+ const INFO = 'info'; // info and error messages
21
+ const ERROR = 'error'; // only error messages
22
+
23
+ /**
24
+ * Debug level.
25
+ *
26
+ * One of Logger::NONE, Logger::DEBUG, Logger::INFO, Logger::ERROR
27
+ *
28
+ * @var string
29
+ */
30
+ protected $level;
31
+
32
+ /**
33
+ * Path to file writeable by the web server. Required if $this->level !== Logger::NONE.
34
+ *
35
+ * @var string
36
+ */
37
+ protected $file;
38
+
39
+ /**
40
+ * @param bool|string $level One of Logger::NONE, Logger::DEBUG, Logger::INFO, Logger::ERROR
41
+ * @param string $file File where to write messages
42
+ *
43
+ * @throws InvalidArgumentException
44
+ * @throws RuntimeException
45
+ */
46
+ public function __construct($level, $file)
47
+ {
48
+ $this->level = self::NONE;
49
+
50
+ if ($level && $level !== self::NONE) {
51
+ $this->initialize($file);
52
+
53
+ $this->level = $level === true ? Logger::DEBUG : $level;
54
+ $this->file = $file;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * @param string $file
60
+ *
61
+ * @throws InvalidArgumentException
62
+ * @throws RuntimeException
63
+ */
64
+ protected function initialize($file)
65
+ {
66
+ if (!$file) {
67
+ throw new InvalidArgumentException('Log file is not specified.');
68
+ }
69
+
70
+ if (!file_exists($file) && !touch($file)) {
71
+ throw new RuntimeException(sprintf('Log file %s can not be created.', $file));
72
+ }
73
+
74
+ if (!is_writable($file)) {
75
+ throw new RuntimeException(sprintf('Log file %s is not writeable.', $file));
76
+ }
77
+ }
78
+
79
+ /**
80
+ * @inheritdoc
81
+ */
82
+ public function info($message, array $context = [])
83
+ {
84
+ if (!in_array($this->level, [self::DEBUG, self::INFO])) {
85
+ return;
86
+ }
87
+
88
+ $this->log(self::INFO, $message, $context);
89
+ }
90
+
91
+ /**
92
+ * @inheritdoc
93
+ */
94
+ public function debug($message, array $context = [])
95
+ {
96
+ if (!in_array($this->level, [self::DEBUG])) {
97
+ return;
98
+ }
99
+
100
+ $this->log(self::DEBUG, $message, $context);
101
+ }
102
+
103
+ /**
104
+ * @inheritdoc
105
+ */
106
+ public function error($message, array $context = [])
107
+ {
108
+ if (!in_array($this->level, [self::DEBUG, self::INFO, self::ERROR])) {
109
+ return;
110
+ }
111
+
112
+ $this->log(self::ERROR, $message, $context);
113
+ }
114
+
115
+ /**
116
+ * @inheritdoc
117
+ */
118
+ public function log($level, $message, array $context = [])
119
+ {
120
+ $datetime = new \DateTime();
121
+ $datetime = $datetime->format(DATE_ATOM);
122
+
123
+ $content = sprintf('%s -- %s -- %s -- %s', $level, $_SERVER['REMOTE_ADDR'], $datetime, $message);
124
+ $content .= ($context ? "\n".print_r($context, true) : '');
125
+ $content .= "\n";
126
+
127
+ file_put_contents($this->file, $content, FILE_APPEND);
128
+ }
129
+ }
hybridauth/library/src/Logger/LoggerInterface.php CHANGED
@@ -1,50 +1,50 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Logger;
9
-
10
- /**
11
- * Logger interface, forward-compatible with PSR-3.
12
- */
13
- interface LoggerInterface
14
- {
15
- /**
16
- * Interesting events.
17
- *
18
- * Example: User logs in, SQL logs.
19
- *
20
- * @param string $message
21
- * @param array $context
22
- */
23
- public function info($message, array $context = array());
24
-
25
- /**
26
- * Detailed debug information.
27
- *
28
- * @param string $message
29
- * @param array $context
30
- */
31
- public function debug($message, array $context = array());
32
-
33
- /**
34
- * Runtime errors that do not require immediate action but should typically
35
- * be logged and monitored.
36
- *
37
- * @param string $message
38
- * @param array $context
39
- */
40
- public function error($message, array $context = array());
41
-
42
- /**
43
- * Logs with an arbitrary level.
44
- *
45
- * @param mixed $level
46
- * @param string $message
47
- * @param array $context
48
- */
49
- public function log($level, $message, array $context = array());
50
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Logger;
9
+
10
+ /**
11
+ * Logger interface, forward-compatible with PSR-3.
12
+ */
13
+ interface LoggerInterface
14
+ {
15
+ /**
16
+ * Interesting events.
17
+ *
18
+ * Example: User logs in, SQL logs.
19
+ *
20
+ * @param string $message
21
+ * @param array $context
22
+ */
23
+ public function info($message, array $context = array());
24
+
25
+ /**
26
+ * Detailed debug information.
27
+ *
28
+ * @param string $message
29
+ * @param array $context
30
+ */
31
+ public function debug($message, array $context = array());
32
+
33
+ /**
34
+ * Runtime errors that do not require immediate action but should typically
35
+ * be logged and monitored.
36
+ *
37
+ * @param string $message
38
+ * @param array $context
39
+ */
40
+ public function error($message, array $context = array());
41
+
42
+ /**
43
+ * Logs with an arbitrary level.
44
+ *
45
+ * @param mixed $level
46
+ * @param string $message
47
+ * @param array $context
48
+ */
49
+ public function log($level, $message, array $context = array());
50
+ }
hybridauth/library/src/Logger/Psr3LoggerWrapper.php CHANGED
@@ -1,50 +1,50 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Logger;
9
-
10
- use Psr\Log\LoggerAwareTrait;
11
-
12
- /**
13
- * Wrapper for PSR3 logger.
14
- */
15
- class Psr3LoggerWrapper implements LoggerInterface
16
- {
17
- use LoggerAwareTrait;
18
-
19
- /**
20
- * @inheritdoc
21
- */
22
- public function info($message, array $context = [])
23
- {
24
- $this->logger->info($message, $context);
25
- }
26
-
27
- /**
28
- * @inheritdoc
29
- */
30
- public function debug($message, array $context = [])
31
- {
32
- $this->logger->debug($message, $context);
33
- }
34
-
35
- /**
36
- * @inheritdoc
37
- */
38
- public function error($message, array $context = [])
39
- {
40
- $this->logger->error($message, $context);
41
- }
42
-
43
- /**
44
- * @inheritdoc
45
- */
46
- public function log($level, $message, array $context = [])
47
- {
48
- $this->logger->log($level, $message, $context);
49
- }
50
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Logger;
9
+
10
+ use Psr\Log\LoggerAwareTrait;
11
+
12
+ /**
13
+ * Wrapper for PSR3 logger.
14
+ */
15
+ class Psr3LoggerWrapper implements LoggerInterface
16
+ {
17
+ use LoggerAwareTrait;
18
+
19
+ /**
20
+ * @inheritdoc
21
+ */
22
+ public function info($message, array $context = [])
23
+ {
24
+ $this->logger->info($message, $context);
25
+ }
26
+
27
+ /**
28
+ * @inheritdoc
29
+ */
30
+ public function debug($message, array $context = [])
31
+ {
32
+ $this->logger->debug($message, $context);
33
+ }
34
+
35
+ /**
36
+ * @inheritdoc
37
+ */
38
+ public function error($message, array $context = [])
39
+ {
40
+ $this->logger->error($message, $context);
41
+ }
42
+
43
+ /**
44
+ * @inheritdoc
45
+ */
46
+ public function log($level, $message, array $context = [])
47
+ {
48
+ $this->logger->log($level, $message, $context);
49
+ }
50
+ }
hybridauth/library/src/Provider/AOLOpenID.php CHANGED
@@ -1,26 +1,26 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OpenID;
11
-
12
- /**
13
- * AOL OpenID provider adapter.
14
- */
15
- class AOLOpenID extends OpenID
16
- {
17
- /**
18
- * {@inheritdoc}
19
- */
20
- protected $openidIdentifier = 'http://openid.aol.com/';
21
-
22
- /**
23
- * {@inheritdoc}
24
- */
25
- protected $apiDocumentation = ''; // Not available
26
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OpenID;
11
+
12
+ /**
13
+ * AOL OpenID provider adapter.
14
+ */
15
+ class AOLOpenID extends OpenID
16
+ {
17
+ /**
18
+ * {@inheritdoc}
19
+ */
20
+ protected $openidIdentifier = 'http://openid.aol.com/';
21
+
22
+ /**
23
+ * {@inheritdoc}
24
+ */
25
+ protected $apiDocumentation = ''; // Not available
26
+ }
hybridauth/library/src/Provider/Amazon.php CHANGED
@@ -1,66 +1,66 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2019 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Amazon OAuth2 provider adapter.
17
- */
18
- class Amazon extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'profile';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://api.amazon.com/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://www.amazon.com/ap/oa';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://api.amazon.com/auth/o2/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://developer.amazon.com/docs/login-with-amazon/documentation-overview.html';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('user/profile');
51
-
52
- $data = new Data\Collection($response);
53
-
54
- if (!$data->exists('user_id')) {
55
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
- }
57
-
58
- $userProfile = new User\Profile();
59
-
60
- $userProfile->identifier = $data->get('user_id');
61
- $userProfile->displayName = $data->get('name');
62
- $userProfile->email = $data->get('email');
63
-
64
- return $userProfile;
65
- }
66
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2019 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Amazon OAuth2 provider adapter.
17
+ */
18
+ class Amazon extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'profile';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://api.amazon.com/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://www.amazon.com/ap/oa';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://api.amazon.com/auth/o2/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://developer.amazon.com/docs/login-with-amazon/documentation-overview.html';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('user/profile');
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ if (!$data->exists('user_id')) {
55
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
+ }
57
+
58
+ $userProfile = new User\Profile();
59
+
60
+ $userProfile->identifier = $data->get('user_id');
61
+ $userProfile->displayName = $data->get('name');
62
+ $userProfile->email = $data->get('email');
63
+
64
+ return $userProfile;
65
+ }
66
+ }
hybridauth/library/src/Provider/Apple.php CHANGED
@@ -1,287 +1,287 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2020 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Exception\InvalidArgumentException;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Exception\InvalidApplicationCredentialsException;
13
- use Hybridauth\Exception\UnexpectedValueException;
14
-
15
- use Hybridauth\Adapter\OAuth2;
16
- use Hybridauth\Data;
17
- use Hybridauth\User;
18
-
19
- use phpseclib\Crypt\RSA;
20
- use phpseclib\Math\BigInteger;
21
-
22
- use \Firebase\JWT\JWT;
23
- use \Firebase\JWT\JWK;
24
-
25
- /**
26
- * Apple OAuth2 provider adapter.
27
- *
28
- * Example:
29
- *
30
- * $config = [
31
- * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
32
- * 'keys' => [ 'id' => '', 'team_id' => '', 'key_id' => '', 'key_file' => '', 'key_content' => '' ],
33
- * 'scope' => 'name email',
34
- *
35
- * // Apple's custom auth url params
36
- * 'authorize_url_parameters' => [
37
- * 'response_mode' => 'form_post'
38
- * ]
39
- * ];
40
- *
41
- * $adapter = new Hybridauth\Provider\Apple( $config );
42
- *
43
- * try {
44
- * $adapter->authenticate();
45
- *
46
- * $userProfile = $adapter->getUserProfile();
47
- * $tokens = $adapter->getAccessToken();
48
- * $response = $adapter->setUserStatus("Hybridauth test message..");
49
- * }
50
- * catch( Exception $e ){
51
- * echo $e->getMessage() ;
52
- * }
53
- *
54
- * Requires:
55
- *
56
- * composer require codercat/jwk-to-pem
57
- * composer require firebase/php-jwt
58
- *
59
- * @see https://github.com/sputnik73/hybridauth-sign-in-with-apple
60
- * @see https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api
61
- */
62
- class Apple extends OAuth2
63
- {
64
- /**
65
- * {@inheritdoc}
66
- */
67
- protected $scope = 'name email';
68
-
69
- /**
70
- * {@inheritdoc}
71
- */
72
- protected $apiBaseUrl = 'https://appleid.apple.com/auth/';
73
-
74
- /**
75
- * {@inheritdoc}
76
- */
77
- protected $authorizeUrl = 'https://appleid.apple.com/auth/authorize';
78
-
79
- /**
80
- * {@inheritdoc}
81
- */
82
- protected $accessTokenUrl = 'https://appleid.apple.com/auth/token';
83
-
84
- /**
85
- * {@inheritdoc}
86
- */
87
- protected $apiDocumentation = 'https://developer.apple.com/documentation/sign_in_with_apple';
88
-
89
- /**
90
- * {@inheritdoc}
91
- * The Sign in with Apple servers require percent encoding (or URL encoding)
92
- * for its query parameters. If you are using the Sign in with Apple REST API,
93
- * you must provide values with encoded spaces (`%20`) instead of plus (`+`) signs.
94
- */
95
- protected $AuthorizeUrlParametersEncType = PHP_QUERY_RFC3986;
96
-
97
- /**
98
- * {@inheritdoc}
99
- */
100
- protected function initialize()
101
- {
102
- parent::initialize();
103
- $this->AuthorizeUrlParameters['response_mode'] = 'form_post';
104
- }
105
-
106
- /**
107
- * {@inheritdoc}
108
- */
109
- protected function configure()
110
- {
111
- $keys = $this->config->get('keys');
112
- $keys['secret'] = $this->getSecret();
113
- $this->config->set('keys', $keys);
114
- return parent::configure();
115
- }
116
-
117
- /**
118
- * {@inheritdoc}
119
- *
120
- * include id_token $tokenNames
121
- */
122
- public function getAccessToken()
123
- {
124
- $tokenNames = [
125
- 'access_token',
126
- 'id_token',
127
- 'access_token_secret',
128
- 'token_type',
129
- 'refresh_token',
130
- 'expires_in',
131
- 'expires_at',
132
- ];
133
-
134
- $tokens = [];
135
-
136
- foreach ($tokenNames as $name) {
137
- if ($this->getStoredData($name)) {
138
- $tokens[$name] = $this->getStoredData($name);
139
- }
140
- }
141
-
142
- return $tokens;
143
- }
144
-
145
- /**
146
- * {@inheritdoc}
147
- */
148
- protected function validateAccessTokenExchange($response)
149
- {
150
- $collection = parent::validateAccessTokenExchange($response);
151
-
152
- $this->storeData('id_token', $collection->get('id_token'));
153
-
154
- return $collection;
155
- }
156
-
157
- public function getUserProfile()
158
- {
159
- $id_token = $this->getStoredData('id_token');
160
-
161
- $verifyTokenSignature =
162
- ($this->config->exists('verifyTokenSignature')) ? $this->config->get('verifyTokenSignature') : true;
163
-
164
- if (!$verifyTokenSignature) {
165
- // payload extraction by https://github.com/omidborjian
166
- // https://github.com/hybridauth/hybridauth/issues/1095#issuecomment-626479263
167
- // JWT splits the string to 3 components 1) first is header 2) is payload 3) is signature
168
- $payload = explode('.', $id_token)[1];
169
- $payload = json_decode(base64_decode($payload));
170
- } else {
171
- // validate the token signature and get the payload
172
- $publicKeys = $this->apiRequest('keys');
173
-
174
- \Firebase\JWT\JWT::$leeway = 120;
175
-
176
- foreach ($publicKeys->keys as $publicKey) {
177
- try {
178
- $rsa = new RSA();
179
- $jwk = (array) $publicKey;
180
-
181
- $rsa->loadKey(
182
- [
183
- 'e' => new BigInteger(base64_decode($jwk['e']), 256),
184
- 'n' => new BigInteger(base64_decode(strtr($jwk['n'], '-_', '+/'), true), 256)
185
- ]
186
- );
187
- $pem = $rsa->getPublicKey();
188
-
189
- $payload = JWT::decode($id_token, $pem, ['RS256']);
190
- $error = false;
191
- break;
192
- } catch (\Exception $e) {
193
- $error = $e->getMessage();
194
- if ($e instanceof \Firebase\JWT\ExpiredException) {
195
- break;
196
- }
197
- }
198
- }
199
- if ($error) {
200
- throw new \Exception($error);
201
- }
202
- }
203
-
204
- $data = new Data\Collection($payload);
205
-
206
- if (!$data->exists('sub')) {
207
- throw new UnexpectedValueException('Missing token payload.');
208
- }
209
-
210
- $userProfile = new User\Profile();
211
- $userProfile->identifier = $data->get('sub');
212
- $userProfile->email = $data->get('email');
213
- $this->storeData('expires_at', $data->get('exp'));
214
-
215
- if (!empty($_REQUEST['user'])) {
216
- $objUser = json_decode($_REQUEST['user']);
217
- $user = new Data\Collection($objUser);
218
- if (!$user->isEmpty()) {
219
- $name = $user->get('name');
220
- $userProfile->firstName = $name->firstName;
221
- $userProfile->lastName = $name->lastName;
222
- $userProfile->displayName = join(' ', [ $userProfile->firstName, $userProfile->lastName ]);
223
- }
224
- }
225
-
226
- return $userProfile;
227
- }
228
-
229
- /**
230
- * @return string secret token
231
- */
232
- private function getSecret()
233
- {
234
- // Your 10-character Team ID
235
- if (!$team_id = $this->config->filter('keys')->get('team_id')) {
236
- throw new InvalidApplicationCredentialsException(
237
- 'Missing parameter team_id: your team id is required to generate the JWS token.'
238
- );
239
- }
240
-
241
- // Your Services ID, e.g. com.aaronparecki.services
242
- if (!$client_id = $this->config->filter('keys')->get('id') ?: $this->config->filter('keys')->get('key')) {
243
- throw new InvalidApplicationCredentialsException(
244
- 'Missing parameter id: your client id is required to generate the JWS token.'
245
- );
246
- }
247
-
248
- // Find the 10-char Key ID value from the portal
249
- if (!$key_id = $this->config->filter('keys')->get('key_id')) {
250
- throw new InvalidApplicationCredentialsException(
251
- 'Missing parameter key_id: your key id is required to generate the JWS token.'
252
- );
253
- }
254
-
255
- // Find the 10-char Key ID value from the portal
256
- $key_content = $this->config->filter('keys')->get('key_content');
257
-
258
- // Save your private key from Apple in a file called `key.txt`
259
- if (!$key_content) {
260
- if (!$key_file = $this->config->filter('keys')->get('key_file')) {
261
- throw new InvalidApplicationCredentialsException(
262
- 'Missing parameter key_content or key_file: your key is required to generate the JWS token.'
263
- );
264
- }
265
-
266
- if (!file_exists($key_file)) {
267
- throw new InvalidApplicationCredentialsException(
268
- "Your key file $key_file does not exist."
269
- );
270
- }
271
-
272
- $key_content = file_get_contents($key_file);
273
- }
274
-
275
- $data = [
276
- 'iat' => time(),
277
- 'exp' => time() + 86400 * 180,
278
- 'iss' => $team_id,
279
- 'aud' => 'https://appleid.apple.com',
280
- 'sub' => $client_id
281
- ];
282
-
283
- $secret = JWT::encode($data, $key_content, 'ES256', $key_id);
284
-
285
- return $secret;
286
- }
287
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2020 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Exception\InvalidArgumentException;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Exception\InvalidApplicationCredentialsException;
13
+ use Hybridauth\Exception\UnexpectedValueException;
14
+
15
+ use Hybridauth\Adapter\OAuth2;
16
+ use Hybridauth\Data;
17
+ use Hybridauth\User;
18
+
19
+ use phpseclib\Crypt\RSA;
20
+ use phpseclib\Math\BigInteger;
21
+
22
+ use \Firebase\JWT\JWT;
23
+ use \Firebase\JWT\JWK;
24
+
25
+ /**
26
+ * Apple OAuth2 provider adapter.
27
+ *
28
+ * Example:
29
+ *
30
+ * $config = [
31
+ * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
32
+ * 'keys' => [ 'id' => '', 'team_id' => '', 'key_id' => '', 'key_file' => '', 'key_content' => '' ],
33
+ * 'scope' => 'name email',
34
+ *
35
+ * // Apple's custom auth url params
36
+ * 'authorize_url_parameters' => [
37
+ * 'response_mode' => 'form_post'
38
+ * ]
39
+ * ];
40
+ *
41
+ * $adapter = new Hybridauth\Provider\Apple( $config );
42
+ *
43
+ * try {
44
+ * $adapter->authenticate();
45
+ *
46
+ * $userProfile = $adapter->getUserProfile();
47
+ * $tokens = $adapter->getAccessToken();
48
+ * $response = $adapter->setUserStatus("Hybridauth test message..");
49
+ * }
50
+ * catch( Exception $e ){
51
+ * echo $e->getMessage() ;
52
+ * }
53
+ *
54
+ * Requires:
55
+ *
56
+ * composer require codercat/jwk-to-pem
57
+ * composer require firebase/php-jwt
58
+ *
59
+ * @see https://github.com/sputnik73/hybridauth-sign-in-with-apple
60
+ * @see https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api
61
+ */
62
+ class Apple extends OAuth2
63
+ {
64
+ /**
65
+ * {@inheritdoc}
66
+ */
67
+ protected $scope = 'name email';
68
+
69
+ /**
70
+ * {@inheritdoc}
71
+ */
72
+ protected $apiBaseUrl = 'https://appleid.apple.com/auth/';
73
+
74
+ /**
75
+ * {@inheritdoc}
76
+ */
77
+ protected $authorizeUrl = 'https://appleid.apple.com/auth/authorize';
78
+
79
+ /**
80
+ * {@inheritdoc}
81
+ */
82
+ protected $accessTokenUrl = 'https://appleid.apple.com/auth/token';
83
+
84
+ /**
85
+ * {@inheritdoc}
86
+ */
87
+ protected $apiDocumentation = 'https://developer.apple.com/documentation/sign_in_with_apple';
88
+
89
+ /**
90
+ * {@inheritdoc}
91
+ * The Sign in with Apple servers require percent encoding (or URL encoding)
92
+ * for its query parameters. If you are using the Sign in with Apple REST API,
93
+ * you must provide values with encoded spaces (`%20`) instead of plus (`+`) signs.
94
+ */
95
+ protected $AuthorizeUrlParametersEncType = PHP_QUERY_RFC3986;
96
+
97
+ /**
98
+ * {@inheritdoc}
99
+ */
100
+ protected function initialize()
101
+ {
102
+ parent::initialize();
103
+ $this->AuthorizeUrlParameters['response_mode'] = 'form_post';
104
+ }
105
+
106
+ /**
107
+ * {@inheritdoc}
108
+ */
109
+ protected function configure()
110
+ {
111
+ $keys = $this->config->get('keys');
112
+ $keys['secret'] = $this->getSecret();
113
+ $this->config->set('keys', $keys);
114
+ return parent::configure();
115
+ }
116
+
117
+ /**
118
+ * {@inheritdoc}
119
+ *
120
+ * include id_token $tokenNames
121
+ */
122
+ public function getAccessToken()
123
+ {
124
+ $tokenNames = [
125
+ 'access_token',
126
+ 'id_token',
127
+ 'access_token_secret',
128
+ 'token_type',
129
+ 'refresh_token',
130
+ 'expires_in',
131
+ 'expires_at',
132
+ ];
133
+
134
+ $tokens = [];
135
+
136
+ foreach ($tokenNames as $name) {
137
+ if ($this->getStoredData($name)) {
138
+ $tokens[$name] = $this->getStoredData($name);
139
+ }
140
+ }
141
+
142
+ return $tokens;
143
+ }
144
+
145
+ /**
146
+ * {@inheritdoc}
147
+ */
148
+ protected function validateAccessTokenExchange($response)
149
+ {
150
+ $collection = parent::validateAccessTokenExchange($response);
151
+
152
+ $this->storeData('id_token', $collection->get('id_token'));
153
+
154
+ return $collection;
155
+ }
156
+
157
+ public function getUserProfile()
158
+ {
159
+ $id_token = $this->getStoredData('id_token');
160
+
161
+ $verifyTokenSignature =
162
+ ($this->config->exists('verifyTokenSignature')) ? $this->config->get('verifyTokenSignature') : true;
163
+
164
+ if (!$verifyTokenSignature) {
165
+ // payload extraction by https://github.com/omidborjian
166
+ // https://github.com/hybridauth/hybridauth/issues/1095#issuecomment-626479263
167
+ // JWT splits the string to 3 components 1) first is header 2) is payload 3) is signature
168
+ $payload = explode('.', $id_token)[1];
169
+ $payload = json_decode(base64_decode($payload));
170
+ } else {
171
+ // validate the token signature and get the payload
172
+ $publicKeys = $this->apiRequest('keys');
173
+
174
+ \Firebase\JWT\JWT::$leeway = 120;
175
+
176
+ foreach ($publicKeys->keys as $publicKey) {
177
+ try {
178
+ $rsa = new RSA();
179
+ $jwk = (array) $publicKey;
180
+
181
+ $rsa->loadKey(
182
+ [
183
+ 'e' => new BigInteger(base64_decode($jwk['e']), 256),
184
+ 'n' => new BigInteger(base64_decode(strtr($jwk['n'], '-_', '+/'), true), 256)
185
+ ]
186
+ );
187
+ $pem = $rsa->getPublicKey();
188
+
189
+ $payload = JWT::decode($id_token, $pem, ['RS256']);
190
+ $error = false;
191
+ break;
192
+ } catch (\Exception $e) {
193
+ $error = $e->getMessage();
194
+ if ($e instanceof \Firebase\JWT\ExpiredException) {
195
+ break;
196
+ }
197
+ }
198
+ }
199
+ if ($error) {
200
+ throw new \Exception($error);
201
+ }
202
+ }
203
+
204
+ $data = new Data\Collection($payload);
205
+
206
+ if (!$data->exists('sub')) {
207
+ throw new UnexpectedValueException('Missing token payload.');
208
+ }
209
+
210
+ $userProfile = new User\Profile();
211
+ $userProfile->identifier = $data->get('sub');
212
+ $userProfile->email = $data->get('email');
213
+ $this->storeData('expires_at', $data->get('exp'));
214
+
215
+ if (!empty($_REQUEST['user'])) {
216
+ $objUser = json_decode($_REQUEST['user']);
217
+ $user = new Data\Collection($objUser);
218
+ if (!$user->isEmpty()) {
219
+ $name = $user->get('name');
220
+ $userProfile->firstName = $name->firstName;
221
+ $userProfile->lastName = $name->lastName;
222
+ $userProfile->displayName = join(' ', [ $userProfile->firstName, $userProfile->lastName ]);
223
+ }
224
+ }
225
+
226
+ return $userProfile;
227
+ }
228
+
229
+ /**
230
+ * @return string secret token
231
+ */
232
+ private function getSecret()
233
+ {
234
+ // Your 10-character Team ID
235
+ if (!$team_id = $this->config->filter('keys')->get('team_id')) {
236
+ throw new InvalidApplicationCredentialsException(
237
+ 'Missing parameter team_id: your team id is required to generate the JWS token.'
238
+ );
239
+ }
240
+
241
+ // Your Services ID, e.g. com.aaronparecki.services
242
+ if (!$client_id = $this->config->filter('keys')->get('id') ?: $this->config->filter('keys')->get('key')) {
243
+ throw new InvalidApplicationCredentialsException(
244
+ 'Missing parameter id: your client id is required to generate the JWS token.'
245
+ );
246
+ }
247
+
248
+ // Find the 10-char Key ID value from the portal
249
+ if (!$key_id = $this->config->filter('keys')->get('key_id')) {
250
+ throw new InvalidApplicationCredentialsException(
251
+ 'Missing parameter key_id: your key id is required to generate the JWS token.'
252
+ );
253
+ }
254
+
255
+ // Find the 10-char Key ID value from the portal
256
+ $key_content = $this->config->filter('keys')->get('key_content');
257
+
258
+ // Save your private key from Apple in a file called `key.txt`
259
+ if (!$key_content) {
260
+ if (!$key_file = $this->config->filter('keys')->get('key_file')) {
261
+ throw new InvalidApplicationCredentialsException(
262
+ 'Missing parameter key_content or key_file: your key is required to generate the JWS token.'
263
+ );
264
+ }
265
+
266
+ if (!file_exists($key_file)) {
267
+ throw new InvalidApplicationCredentialsException(
268
+ "Your key file $key_file does not exist."
269
+ );
270
+ }
271
+
272
+ $key_content = file_get_contents($key_file);
273
+ }
274
+
275
+ $data = [
276
+ 'iat' => time(),
277
+ 'exp' => time() + 86400 * 180,
278
+ 'iss' => $team_id,
279
+ 'aud' => 'https://appleid.apple.com',
280
+ 'sub' => $client_id
281
+ ];
282
+
283
+ $secret = JWT::encode($data, $key_content, 'ES256', $key_id);
284
+
285
+ return $secret;
286
+ }
287
+ }
hybridauth/library/src/Provider/Authentiq.php CHANGED
@@ -1,111 +1,111 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedValueException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Authentiq OAuth2 provider adapter.
17
- */
18
- class Authentiq extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'aq:name email~rs aq:push openid';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://connect.authentiq.io/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://connect.authentiq.io/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://connect.authentiq.io/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'http://developers.authentiq.io/';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected function initialize()
49
- {
50
- parent::initialize();
51
-
52
- $this->AuthorizeUrlParameters += [
53
- 'prompt' => 'consent'
54
- ];
55
-
56
- $this->tokenExchangeHeaders = [
57
- 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
58
- ];
59
-
60
- $this->tokenRefreshHeaders = [
61
- 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
62
- ];
63
- }
64
-
65
- /**
66
- * {@inheritdoc}
67
- */
68
- public function getUserProfile()
69
- {
70
- $response = $this->apiRequest('userinfo');
71
-
72
- $data = new Data\Collection($response);
73
-
74
- if (!$data->exists('sub')) {
75
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
76
- }
77
-
78
- $userProfile = new User\Profile();
79
-
80
- $userProfile->identifier = $data->get('sub');
81
-
82
- $userProfile->displayName = $data->get('name');
83
- $userProfile->firstName = $data->get('given_name');
84
- // $userProfile->middleName = $data->get('middle_name'); // not supported
85
- $userProfile->lastName = $data->get('family_name');
86
-
87
- if (!empty($userProfile->displayName)) {
88
- $userProfile->displayName = join(' ', array($userProfile->firstName,
89
- // $userProfile->middleName,
90
- $userProfile->lastName));
91
- }
92
-
93
- $userProfile->email = $data->get('email');
94
- $userProfile->emailVerified = $data->get('email_verified') ? $userProfile->email : '';
95
-
96
- $userProfile->phone = $data->get('phone');
97
- // $userProfile->phoneVerified = $data->get('phone_verified') ? $userProfile->phone : ''; // not supported
98
-
99
- $userProfile->profileURL = $data->get('profile');
100
- $userProfile->webSiteURL = $data->get('website');
101
- $userProfile->photoURL = $data->get('picture');
102
- $userProfile->gender = $data->get('gender');
103
- $userProfile->address = $data->filter('address')->get('street_address');
104
- $userProfile->city = $data->filter('address')->get('locality');
105
- $userProfile->country = $data->filter('address')->get('country');
106
- $userProfile->region = $data->filter('address')->get('region');
107
- $userProfile->zip = $data->filter('address')->get('postal_code');
108
-
109
- return $userProfile;
110
- }
111
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedValueException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Authentiq OAuth2 provider adapter.
17
+ */
18
+ class Authentiq extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'aq:name email~rs aq:push openid';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://connect.authentiq.io/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://connect.authentiq.io/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://connect.authentiq.io/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'http://developers.authentiq.io/';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function initialize()
49
+ {
50
+ parent::initialize();
51
+
52
+ $this->AuthorizeUrlParameters += [
53
+ 'prompt' => 'consent'
54
+ ];
55
+
56
+ $this->tokenExchangeHeaders = [
57
+ 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
58
+ ];
59
+
60
+ $this->tokenRefreshHeaders = [
61
+ 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
62
+ ];
63
+ }
64
+
65
+ /**
66
+ * {@inheritdoc}
67
+ */
68
+ public function getUserProfile()
69
+ {
70
+ $response = $this->apiRequest('userinfo');
71
+
72
+ $data = new Data\Collection($response);
73
+
74
+ if (!$data->exists('sub')) {
75
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
76
+ }
77
+
78
+ $userProfile = new User\Profile();
79
+
80
+ $userProfile->identifier = $data->get('sub');
81
+
82
+ $userProfile->displayName = $data->get('name');
83
+ $userProfile->firstName = $data->get('given_name');
84
+ // $userProfile->middleName = $data->get('middle_name'); // not supported
85
+ $userProfile->lastName = $data->get('family_name');
86
+
87
+ if (!empty($userProfile->displayName)) {
88
+ $userProfile->displayName = join(' ', array($userProfile->firstName,
89
+ // $userProfile->middleName,
90
+ $userProfile->lastName));
91
+ }
92
+
93
+ $userProfile->email = $data->get('email');
94
+ $userProfile->emailVerified = $data->get('email_verified') ? $userProfile->email : '';
95
+
96
+ $userProfile->phone = $data->get('phone');
97
+ // $userProfile->phoneVerified = $data->get('phone_verified') ? $userProfile->phone : ''; // not supported
98
+
99
+ $userProfile->profileURL = $data->get('profile');
100
+ $userProfile->webSiteURL = $data->get('website');
101
+ $userProfile->photoURL = $data->get('picture');
102
+ $userProfile->gender = $data->get('gender');
103
+ $userProfile->address = $data->filter('address')->get('street_address');
104
+ $userProfile->city = $data->filter('address')->get('locality');
105
+ $userProfile->country = $data->filter('address')->get('country');
106
+ $userProfile->region = $data->filter('address')->get('region');
107
+ $userProfile->zip = $data->filter('address')->get('postal_code');
108
+
109
+ return $userProfile;
110
+ }
111
+ }
hybridauth/library/src/Provider/BitBucket.php CHANGED
@@ -1,111 +1,111 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Set up your OAuth2 at https://bitbucket.org/<yourusername>/workspace/settings/api
17
- */
18
-
19
- /**
20
- * BitBucket OAuth2 provider adapter.
21
- */
22
- class BitBucket extends OAuth2
23
- {
24
- /**
25
- * {@inheritdoc}
26
- */
27
- protected $scope = 'email';
28
-
29
- /**
30
- * {@inheritdoc}
31
- */
32
- protected $apiBaseUrl = 'https://api.bitbucket.org/2.0/';
33
-
34
- /**
35
- * {@inheritdoc}
36
- */
37
- protected $authorizeUrl = 'https://bitbucket.org/site/oauth2/authorize';
38
-
39
- /**
40
- * {@inheritdoc}
41
- */
42
- protected $accessTokenUrl = 'https://bitbucket.org/site/oauth2/access_token';
43
-
44
- /**
45
- * {@inheritdoc}
46
- */
47
- protected $apiDocumentation = 'https://developer.atlassian.com/bitbucket/concepts/oauth2.html';
48
-
49
- /**
50
- * {@inheritdoc}
51
- */
52
- public function getUserProfile()
53
- {
54
- $response = $this->apiRequest('user');
55
-
56
- $data = new Data\Collection($response);
57
-
58
- if (! $data->exists('uuid')) {
59
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
60
- }
61
-
62
- $userProfile = new User\Profile();
63
-
64
- $userProfile->identifier = $data->get('uuid');
65
- $userProfile->profileURL = 'https://bitbucket.org/' . $data->get('username') . '/';
66
- $userProfile->displayName = $data->get('display_name');
67
- $userProfile->email = $data->get('email');
68
- $userProfile->webSiteURL = $data->get('website');
69
- $userProfile->region = $data->get('location');
70
-
71
- $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
72
-
73
- if (empty($userProfile->email) && strpos($this->scope, 'email') !== false) {
74
- try {
75
- // user email is not mandatory so keep it quiet
76
- $userProfile = $this->requestUserEmail($userProfile);
77
- } catch (\Exception $e) {
78
- }
79
- }
80
-
81
- return $userProfile;
82
- }
83
-
84
- /**
85
- * Request user email
86
- *
87
- * @param $userProfile
88
- *
89
- * @return User\Profile
90
- *
91
- * @throws \Exception
92
- */
93
- protected function requestUserEmail($userProfile)
94
- {
95
- $response = $this->apiRequest('user/emails');
96
-
97
- foreach ($response->values as $idx => $item) {
98
- if (! empty($item->is_primary) && $item->is_primary == true) {
99
- $userProfile->email = $item->email;
100
-
101
- if (! empty($item->is_confirmed) && $item->is_confirmed == true) {
102
- $userProfile->emailVerified = $userProfile->email;
103
- }
104
-
105
- break;
106
- }
107
- }
108
-
109
- return $userProfile;
110
- }
111
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Set up your OAuth2 at https://bitbucket.org/<yourusername>/workspace/settings/api
17
+ */
18
+
19
+ /**
20
+ * BitBucket OAuth2 provider adapter.
21
+ */
22
+ class BitBucket extends OAuth2
23
+ {
24
+ /**
25
+ * {@inheritdoc}
26
+ */
27
+ protected $scope = 'email';
28
+
29
+ /**
30
+ * {@inheritdoc}
31
+ */
32
+ protected $apiBaseUrl = 'https://api.bitbucket.org/2.0/';
33
+
34
+ /**
35
+ * {@inheritdoc}
36
+ */
37
+ protected $authorizeUrl = 'https://bitbucket.org/site/oauth2/authorize';
38
+
39
+ /**
40
+ * {@inheritdoc}
41
+ */
42
+ protected $accessTokenUrl = 'https://bitbucket.org/site/oauth2/access_token';
43
+
44
+ /**
45
+ * {@inheritdoc}
46
+ */
47
+ protected $apiDocumentation = 'https://developer.atlassian.com/bitbucket/concepts/oauth2.html';
48
+
49
+ /**
50
+ * {@inheritdoc}
51
+ */
52
+ public function getUserProfile()
53
+ {
54
+ $response = $this->apiRequest('user');
55
+
56
+ $data = new Data\Collection($response);
57
+
58
+ if (! $data->exists('uuid')) {
59
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
60
+ }
61
+
62
+ $userProfile = new User\Profile();
63
+
64
+ $userProfile->identifier = $data->get('uuid');
65
+ $userProfile->profileURL = 'https://bitbucket.org/' . $data->get('username') . '/';
66
+ $userProfile->displayName = $data->get('display_name');
67
+ $userProfile->email = $data->get('email');
68
+ $userProfile->webSiteURL = $data->get('website');
69
+ $userProfile->region = $data->get('location');
70
+
71
+ $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
72
+
73
+ if (empty($userProfile->email) && strpos($this->scope, 'email') !== false) {
74
+ try {
75
+ // user email is not mandatory so keep it quiet
76
+ $userProfile = $this->requestUserEmail($userProfile);
77
+ } catch (\Exception $e) {
78
+ }
79
+ }
80
+
81
+ return $userProfile;
82
+ }
83
+
84
+ /**
85
+ * Request user email
86
+ *
87
+ * @param $userProfile
88
+ *
89
+ * @return User\Profile
90
+ *
91
+ * @throws \Exception
92
+ */
93
+ protected function requestUserEmail($userProfile)
94
+ {
95
+ $response = $this->apiRequest('user/emails');
96
+
97
+ foreach ($response->values as $idx => $item) {
98
+ if (! empty($item->is_primary) && $item->is_primary == true) {
99
+ $userProfile->email = $item->email;
100
+
101
+ if (! empty($item->is_confirmed) && $item->is_confirmed == true) {
102
+ $userProfile->emailVerified = $userProfile->email;
103
+ }
104
+
105
+ break;
106
+ }
107
+ }
108
+
109
+ return $userProfile;
110
+ }
111
+ }
hybridauth/library/src/Provider/Blizzard.php CHANGED
@@ -1,65 +1,65 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Blizzard Battle.net OAuth2 provider adapter.
17
- */
18
- class Blizzard extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = '';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://us.battle.net/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://us.battle.net/oauth/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://us.battle.net/oauth/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://develop.battle.net/documentation';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('oauth/userinfo');
51
-
52
- $data = new Data\Collection($response);
53
-
54
- if (!$data->exists('id')) {
55
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
- }
57
-
58
- $userProfile = new User\Profile();
59
-
60
- $userProfile->identifier = $data->get('id');
61
- $userProfile->displayName = $data->get('battletag') ?: $data->get('login');
62
-
63
- return $userProfile;
64
- }
65
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Blizzard Battle.net OAuth2 provider adapter.
17
+ */
18
+ class Blizzard extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = '';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://us.battle.net/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://us.battle.net/oauth/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://us.battle.net/oauth/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://develop.battle.net/documentation';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('oauth/userinfo');
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ if (!$data->exists('id')) {
55
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
+ }
57
+
58
+ $userProfile = new User\Profile();
59
+
60
+ $userProfile->identifier = $data->get('id');
61
+ $userProfile->displayName = $data->get('battletag') ?: $data->get('login');
62
+
63
+ return $userProfile;
64
+ }
65
+ }
hybridauth/library/src/Provider/BlizzardAPAC.php CHANGED
@@ -1,34 +1,34 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Blizzard US/SEA Battle.net OAuth2 provider adapter.
17
- */
18
- class BlizzardAPAC extends Blizzard
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $apiBaseUrl = 'https://apac.battle.net/';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $authorizeUrl = 'https://apac.battle.net/oauth/authorize';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $accessTokenUrl = 'https://apac.battle.net/oauth/token';
34
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Blizzard US/SEA Battle.net OAuth2 provider adapter.
17
+ */
18
+ class BlizzardAPAC extends Blizzard
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $apiBaseUrl = 'https://apac.battle.net/';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $authorizeUrl = 'https://apac.battle.net/oauth/authorize';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $accessTokenUrl = 'https://apac.battle.net/oauth/token';
34
+ }
hybridauth/library/src/Provider/BlizzardEU.php CHANGED
@@ -1,34 +1,34 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Blizzard EU Battle.net OAuth2 provider adapter.
17
- */
18
- class BlizzardEU extends Blizzard
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $apiBaseUrl = 'https://eu.battle.net/';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $authorizeUrl = 'https://eu.battle.net/oauth/authorize';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $accessTokenUrl = 'https://eu.battle.net/oauth/token';
34
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Blizzard EU Battle.net OAuth2 provider adapter.
17
+ */
18
+ class BlizzardEU extends Blizzard
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $apiBaseUrl = 'https://eu.battle.net/';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $authorizeUrl = 'https://eu.battle.net/oauth/authorize';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $accessTokenUrl = 'https://eu.battle.net/oauth/token';
34
+ }
hybridauth/library/src/Provider/DeviantArt.php CHANGED
@@ -1,91 +1,91 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * DeviantArt OAuth2 provider adapter.
17
- */
18
- class DeviantArt extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'user';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://www.deviantart.com/api/v1/oauth2/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://www.deviantart.com/oauth2/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://www.deviantart.com/oauth2/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://www.deviantart.com/developers/http/v1/20200519';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected function initialize()
49
- {
50
- parent::initialize();
51
-
52
- if ($this->isRefreshTokenAvailable()) {
53
- $this->tokenRefreshParameters += [
54
- 'client_id' => $this->clientId,
55
- 'client_secret' => $this->clientSecret,
56
- ];
57
- }
58
- }
59
-
60
- /**
61
- * {@inheritdoc}
62
- *
63
- * See: https://www.deviantart.com/developers/http/v1/20200519/user_whoami/2413749853e66c5812c9beccc0ab3495
64
- */
65
- public function getUserProfile()
66
- {
67
- $response = $this->apiRequest('user/whoami');
68
-
69
- $data = new Data\Collection($response);
70
-
71
- $userProfile = new User\Profile();
72
-
73
- $full_name = explode(' ', $data->filter('profile')->get('real_name'));
74
- if (count($full_name) < 2) {
75
- $full_name[1] = '';
76
- }
77
-
78
- $userProfile->identifier = $data->get('userid');
79
- $userProfile->displayName = $data->get('username');
80
- $userProfile->profileURL = $data->get('usericon');
81
- $userProfile->webSiteURL = $data->filter('profile')->get('website');
82
- $userProfile->firstName = $full_name[0];
83
- $userProfile->lastName = $full_name[1];
84
- $userProfile->profileURL = $data->filter('profile')->filter('profile_pic')->get('url');
85
- $userProfile->gender = $data->filter('details')->get('sex');
86
- $userProfile->age = $data->filter('details')->get('age');
87
- $userProfile->country = $data->filter('geo')->get('country');
88
-
89
- return $userProfile;
90
- }
91
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * DeviantArt OAuth2 provider adapter.
17
+ */
18
+ class DeviantArt extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'user';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://www.deviantart.com/api/v1/oauth2/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://www.deviantart.com/oauth2/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://www.deviantart.com/oauth2/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://www.deviantart.com/developers/http/v1/20200519';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function initialize()
49
+ {
50
+ parent::initialize();
51
+
52
+ if ($this->isRefreshTokenAvailable()) {
53
+ $this->tokenRefreshParameters += [
54
+ 'client_id' => $this->clientId,
55
+ 'client_secret' => $this->clientSecret,
56
+ ];
57
+ }
58
+ }
59
+
60
+ /**
61
+ * {@inheritdoc}
62
+ *
63
+ * See: https://www.deviantart.com/developers/http/v1/20200519/user_whoami/2413749853e66c5812c9beccc0ab3495
64
+ */
65
+ public function getUserProfile()
66
+ {
67
+ $response = $this->apiRequest('user/whoami');
68
+
69
+ $data = new Data\Collection($response);
70
+
71
+ $userProfile = new User\Profile();
72
+
73
+ $full_name = explode(' ', $data->filter('profile')->get('real_name'));
74
+ if (count($full_name) < 2) {
75
+ $full_name[1] = '';
76
+ }
77
+
78
+ $userProfile->identifier = $data->get('userid');
79
+ $userProfile->displayName = $data->get('username');
80
+ $userProfile->profileURL = $data->get('usericon');
81
+ $userProfile->webSiteURL = $data->filter('profile')->get('website');
82
+ $userProfile->firstName = $full_name[0];
83
+ $userProfile->lastName = $full_name[1];
84
+ $userProfile->profileURL = $data->filter('profile')->filter('profile_pic')->get('url');
85
+ $userProfile->gender = $data->filter('details')->get('sex');
86
+ $userProfile->age = $data->filter('details')->get('age');
87
+ $userProfile->country = $data->filter('geo')->get('country');
88
+
89
+ return $userProfile;
90
+ }
91
+ }
hybridauth/library/src/Provider/Discord.php CHANGED
@@ -1,96 +1,96 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Discord OAuth2 provider adapter.
17
- */
18
- class Discord extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'identify email';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://discordapp.com/api/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://discordapp.com/api/oauth2/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://discordapp.com/api/oauth2/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://discordapp.com/developers/docs/topics/oauth2';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected function initialize()
49
- {
50
- parent::initialize();
51
-
52
- if ($this->isRefreshTokenAvailable()) {
53
- $this->tokenRefreshParameters += [
54
- 'client_id' => $this->clientId,
55
- 'client_secret' => $this->clientSecret,
56
- ];
57
- }
58
- }
59
-
60
- /**
61
- * {@inheritdoc}
62
- */
63
- public function getUserProfile()
64
- {
65
- $response = $this->apiRequest('users/@me');
66
-
67
- $data = new Data\Collection($response);
68
-
69
- if (!$data->exists('id')) {
70
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
71
- }
72
-
73
- // Makes display name more unique.
74
- $displayName = $data->get('username') ?: $data->get('login');
75
- if ($discriminator = $data->get('discriminator')) {
76
- $displayName .= "#{$discriminator}";
77
- }
78
-
79
- $userProfile = new User\Profile();
80
-
81
- $userProfile->identifier = $data->get('id');
82
- $userProfile->displayName = $displayName;
83
- $userProfile->email = $data->get('email');
84
-
85
- if ($data->get('verified')) {
86
- $userProfile->emailVerified = $data->get('email');
87
- }
88
-
89
- if ($data->get('avatar')) {
90
- $userProfile->photoURL = 'https://cdn.discordapp.com/avatars/';
91
- $userProfile->photoURL .= $data->get('id') . '/' . $data->get('avatar') . '.png';
92
- }
93
-
94
- return $userProfile;
95
- }
96
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Discord OAuth2 provider adapter.
17
+ */
18
+ class Discord extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'identify email';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://discordapp.com/api/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://discordapp.com/api/oauth2/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://discordapp.com/api/oauth2/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://discordapp.com/developers/docs/topics/oauth2';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function initialize()
49
+ {
50
+ parent::initialize();
51
+
52
+ if ($this->isRefreshTokenAvailable()) {
53
+ $this->tokenRefreshParameters += [
54
+ 'client_id' => $this->clientId,
55
+ 'client_secret' => $this->clientSecret,
56
+ ];
57
+ }
58
+ }
59
+
60
+ /**
61
+ * {@inheritdoc}
62
+ */
63
+ public function getUserProfile()
64
+ {
65
+ $response = $this->apiRequest('users/@me');
66
+
67
+ $data = new Data\Collection($response);
68
+
69
+ if (!$data->exists('id')) {
70
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
71
+ }
72
+
73
+ // Makes display name more unique.
74
+ $displayName = $data->get('username') ?: $data->get('login');
75
+ if ($discriminator = $data->get('discriminator')) {
76
+ $displayName .= "#{$discriminator}";
77
+ }
78
+
79
+ $userProfile = new User\Profile();
80
+
81
+ $userProfile->identifier = $data->get('id');
82
+ $userProfile->displayName = $displayName;
83
+ $userProfile->email = $data->get('email');
84
+
85
+ if ($data->get('verified')) {
86
+ $userProfile->emailVerified = $data->get('email');
87
+ }
88
+
89
+ if ($data->get('avatar')) {
90
+ $userProfile->photoURL = 'https://cdn.discordapp.com/avatars/';
91
+ $userProfile->photoURL .= $data->get('id') . '/' . $data->get('avatar') . '.png';
92
+ }
93
+
94
+ return $userProfile;
95
+ }
96
+ }
hybridauth/library/src/Provider/Disqus.php CHANGED
@@ -1,88 +1,88 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Disqus OAuth2 provider adapter.
17
- */
18
- class Disqus extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'read,email';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://disqus.com/api/3.0/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://disqus.com/api/oauth/2.0/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://disqus.com/api/oauth/2.0/access_token/';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://disqus.com/api/docs/auth/';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected function initialize()
49
- {
50
- parent::initialize();
51
-
52
- $this->apiRequestParameters = [
53
- 'api_key' => $this->clientId, 'api_secret' => $this->clientSecret
54
- ];
55
- }
56
-
57
- /**
58
- * {@inheritdoc}
59
- */
60
- public function getUserProfile()
61
- {
62
- $response = $this->apiRequest('users/details');
63
-
64
- $data = new Data\Collection($response);
65
-
66
- if (! $data->filter('response')->exists('id')) {
67
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
68
- }
69
-
70
- $userProfile = new User\Profile();
71
-
72
- $data = $data->filter('response');
73
-
74
- $userProfile->identifier = $data->get('id');
75
- $userProfile->displayName = $data->get('name');
76
- $userProfile->description = $data->get('bio');
77
- $userProfile->profileURL = $data->get('profileUrl');
78
- $userProfile->email = $data->get('email');
79
- $userProfile->region = $data->get('location');
80
- $userProfile->description = $data->get('about');
81
-
82
- $userProfile->photoURL = $data->filter('avatar')->get('permalink');
83
-
84
- $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
85
-
86
- return $userProfile;
87
- }
88
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Disqus OAuth2 provider adapter.
17
+ */
18
+ class Disqus extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'read,email';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://disqus.com/api/3.0/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://disqus.com/api/oauth/2.0/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://disqus.com/api/oauth/2.0/access_token/';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://disqus.com/api/docs/auth/';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function initialize()
49
+ {
50
+ parent::initialize();
51
+
52
+ $this->apiRequestParameters = [
53
+ 'api_key' => $this->clientId, 'api_secret' => $this->clientSecret
54
+ ];
55
+ }
56
+
57
+ /**
58
+ * {@inheritdoc}
59
+ */
60
+ public function getUserProfile()
61
+ {
62
+ $response = $this->apiRequest('users/details');
63
+
64
+ $data = new Data\Collection($response);
65
+
66
+ if (! $data->filter('response')->exists('id')) {
67
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
68
+ }
69
+
70
+ $userProfile = new User\Profile();
71
+
72
+ $data = $data->filter('response');
73
+
74
+ $userProfile->identifier = $data->get('id');
75
+ $userProfile->displayName = $data->get('name');
76
+ $userProfile->description = $data->get('bio');
77
+ $userProfile->profileURL = $data->get('profileUrl');
78
+ $userProfile->email = $data->get('email');
79
+ $userProfile->region = $data->get('location');
80
+ $userProfile->description = $data->get('about');
81
+
82
+ $userProfile->photoURL = $data->filter('avatar')->get('permalink');
83
+
84
+ $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
85
+
86
+ return $userProfile;
87
+ }
88
+ }
hybridauth/library/src/Provider/Dribbble.php CHANGED
@@ -1,68 +1,68 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Dribbble OAuth2 provider adapter.
17
- */
18
- class Dribbble extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $apiBaseUrl = 'https://api.dribbble.com/v2/';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $authorizeUrl = 'https://dribbble.com/oauth/authorize';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $accessTokenUrl = 'https://dribbble.com/oauth/token';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $apiDocumentation = 'http://developer.dribbble.com/v2/oauth/';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- public function getUserProfile()
44
- {
45
- $response = $this->apiRequest('user');
46
-
47
- $data = new Data\Collection($response);
48
-
49
- if (! $data->exists('id')) {
50
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
51
- }
52
-
53
- $userProfile = new User\Profile();
54
-
55
- $userProfile->identifier = $data->get('id');
56
- $userProfile->profileURL = $data->get('html_url');
57
- $userProfile->photoURL = $data->get('avatar_url');
58
- $userProfile->description = $data->get('bio');
59
- $userProfile->region = $data->get('location');
60
- $userProfile->displayName = $data->get('name');
61
-
62
- $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
63
-
64
- $userProfile->webSiteURL = $data->filter('links')->get('web');
65
-
66
- return $userProfile;
67
- }
68
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Dribbble OAuth2 provider adapter.
17
+ */
18
+ class Dribbble extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $apiBaseUrl = 'https://api.dribbble.com/v2/';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $authorizeUrl = 'https://dribbble.com/oauth/authorize';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $accessTokenUrl = 'https://dribbble.com/oauth/token';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $apiDocumentation = 'http://developer.dribbble.com/v2/oauth/';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ public function getUserProfile()
44
+ {
45
+ $response = $this->apiRequest('user');
46
+
47
+ $data = new Data\Collection($response);
48
+
49
+ if (! $data->exists('id')) {
50
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
51
+ }
52
+
53
+ $userProfile = new User\Profile();
54
+
55
+ $userProfile->identifier = $data->get('id');
56
+ $userProfile->profileURL = $data->get('html_url');
57
+ $userProfile->photoURL = $data->get('avatar_url');
58
+ $userProfile->description = $data->get('bio');
59
+ $userProfile->region = $data->get('location');
60
+ $userProfile->displayName = $data->get('name');
61
+
62
+ $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
63
+
64
+ $userProfile->webSiteURL = $data->filter('links')->get('web');
65
+
66
+ return $userProfile;
67
+ }
68
+ }
hybridauth/library/src/Provider/Dropbox.php CHANGED
@@ -1,74 +1,74 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2020 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Dropbox OAuth2 provider adapter.
17
- */
18
- class Dropbox extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'account_info.read';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://api.dropbox.com/2/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://www.dropbox.com/1/oauth2/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://api.dropbox.com/1/oauth2/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://www.dropbox.com/developers/documentation/http/documentation';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('users/get_current_account', 'POST', [], [], true);
51
-
52
- $data = new Data\Collection($response);
53
-
54
- if (!$data->exists('account_id') || !$data->get('account_id')) {
55
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
- }
57
-
58
- $userProfile = new User\Profile();
59
-
60
- $userProfile->identifier = $data->get('account_id');
61
- $userProfile->displayName = $data->filter('name')->get('display_name');
62
- $userProfile->firstName = $data->filter('name')->get('given_name');
63
- $userProfile->lastName = $data->filter('name')->get('surname');
64
- $userProfile->email = $data->get('email');
65
- $userProfile->photoURL = $data->get('profile_photo_url');
66
- $userProfile->language = $data->get('locale');
67
- $userProfile->country = $data->get('country');
68
- if ($data->get('email_verified')) {
69
- $userProfile->emailVerified = $data->get('email');
70
- }
71
-
72
- return $userProfile;
73
- }
74
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2020 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Dropbox OAuth2 provider adapter.
17
+ */
18
+ class Dropbox extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'account_info.read';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://api.dropbox.com/2/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://www.dropbox.com/1/oauth2/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://api.dropbox.com/1/oauth2/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://www.dropbox.com/developers/documentation/http/documentation';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('users/get_current_account', 'POST', [], [], true);
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ if (!$data->exists('account_id') || !$data->get('account_id')) {
55
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
+ }
57
+
58
+ $userProfile = new User\Profile();
59
+
60
+ $userProfile->identifier = $data->get('account_id');
61
+ $userProfile->displayName = $data->filter('name')->get('display_name');
62
+ $userProfile->firstName = $data->filter('name')->get('given_name');
63
+ $userProfile->lastName = $data->filter('name')->get('surname');
64
+ $userProfile->email = $data->get('email');
65
+ $userProfile->photoURL = $data->get('profile_photo_url');
66
+ $userProfile->language = $data->get('locale');
67
+ $userProfile->country = $data->get('country');
68
+ if ($data->get('email_verified')) {
69
+ $userProfile->emailVerified = $data->get('email');
70
+ }
71
+
72
+ return $userProfile;
73
+ }
74
+ }
hybridauth/library/src/Provider/Facebook.php CHANGED
@@ -1,444 +1,444 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Exception\InvalidArgumentException;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Adapter\OAuth2;
13
- use Hybridauth\Data;
14
- use Hybridauth\User;
15
-
16
- /**
17
- * Facebook OAuth2 provider adapter.
18
- *
19
- * Facebook doesn't use standard OAuth refresh tokens.
20
- * Instead it has a "token exchange" system. You exchange the token prior to
21
- * expiry, to push back expiry. You start with a short-lived token and each
22
- * exchange gives you a long-lived one (90 days).
23
- * We control this with the 'exchange_by_expiry_days' option.
24
- *
25
- * Example:
26
- *
27
- * $config = [
28
- * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
29
- * 'keys' => [ 'id' => '', 'secret' => '' ],
30
- * 'scope' => 'email, user_status, user_posts',
31
- * 'exchange_by_expiry_days' => 45, // null for no token exchange
32
- * ];
33
- *
34
- * $adapter = new Hybridauth\Provider\Facebook( $config );
35
- *
36
- * try {
37
- * $adapter->authenticate();
38
- *
39
- * $userProfile = $adapter->getUserProfile();
40
- * $tokens = $adapter->getAccessToken();
41
- * $response = $adapter->setUserStatus("Hybridauth test message..");
42
- * }
43
- * catch( Exception $e ){
44
- * echo $e->getMessage() ;
45
- * }
46
- */
47
- class Facebook extends OAuth2
48
- {
49
- /**
50
- * {@inheritdoc}
51
- */
52
- protected $scope = 'email, public_profile';
53
-
54
- /**
55
- * {@inheritdoc}
56
- */
57
- protected $apiBaseUrl = 'https://graph.facebook.com/v6.0/';
58
-
59
- /**
60
- * {@inheritdoc}
61
- */
62
- protected $authorizeUrl = 'https://www.facebook.com/dialog/oauth';
63
-
64
- /**
65
- * {@inheritdoc}
66
- */
67
- protected $accessTokenUrl = 'https://graph.facebook.com/oauth/access_token';
68
-
69
- /**
70
- * {@inheritdoc}
71
- */
72
- protected $apiDocumentation = 'https://developers.facebook.com/docs/facebook-login/overview';
73
-
74
- /**
75
- * @var string Profile URL template as the fallback when no `link` returned from the API.
76
- */
77
- protected $profileUrlTemplate = 'https://www.facebook.com/%s';
78
-
79
- /**
80
- * {@inheritdoc}
81
- */
82
- protected function initialize()
83
- {
84
- parent::initialize();
85
-
86
- // Require proof on all Facebook api calls
87
- // https://developers.facebook.com/docs/graph-api/securing-requests#appsecret_proof
88
- if ($accessToken = $this->getStoredData('access_token')) {
89
- $this->apiRequestParameters['appsecret_proof'] = hash_hmac('sha256', $accessToken, $this->clientSecret);
90
- }
91
- }
92
-
93
- /**
94
- * {@inheritdoc}
95
- */
96
- public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
97
- {
98
- // Handle token exchange prior to the standard handler for an API request
99
- $exchange_by_expiry_days = $this->config->get('exchange_by_expiry_days') ?: 45;
100
- if ($exchange_by_expiry_days !== null) {
101
- $projected_timestamp = time() + 60 * 60 * 24 * $exchange_by_expiry_days;
102
- if (!$this->hasAccessTokenExpired() && $this->hasAccessTokenExpired($projected_timestamp)) {
103
- $this->exchangeAccessToken();
104
- }
105
- }
106
-
107
- return parent::apiRequest($url, $method, $parameters, $headers, $multipart);
108
- }
109
-
110
- /**
111
- * Exchange the Access Token with one that expires further in the future.
112
- *
113
- * @return string Raw Provider API response
114
- * @throws \Hybridauth\Exception\HttpClientFailureException
115
- * @throws \Hybridauth\Exception\HttpRequestFailedException
116
- * @throws InvalidAccessTokenException
117
- */
118
- public function exchangeAccessToken()
119
- {
120
- $exchangeTokenParameters = [
121
- 'grant_type' => 'fb_exchange_token',
122
- 'client_id' => $this->clientId,
123
- 'client_secret' => $this->clientSecret,
124
- 'fb_exchange_token' => $this->getStoredData('access_token'),
125
- ];
126
-
127
- $response = $this->httpClient->request(
128
- $this->accessTokenUrl,
129
- 'GET',
130
- $exchangeTokenParameters
131
- );
132
-
133
- $this->validateApiResponse('Unable to exchange the access token');
134
-
135
- $this->validateAccessTokenExchange($response);
136
-
137
- return $response;
138
- }
139
-
140
- /**
141
- * {@inheritdoc}
142
- */
143
- public function getUserProfile()
144
- {
145
- $fields = [
146
- 'id',
147
- 'name',
148
- 'first_name',
149
- 'last_name',
150
- 'link',
151
- 'website',
152
- 'gender',
153
- 'locale',
154
- 'about',
155
- 'email',
156
- 'hometown',
157
- 'birthday',
158
- ];
159
-
160
- // Note that en_US is needed for gender fields to match convention.
161
- $locale = $this->config->get('locale') ?: 'en_US';
162
- $response = $this->apiRequest('me', 'GET', [
163
- 'fields' => implode(',', $fields),
164
- 'locale' => $locale,
165
- ]);
166
-
167
- $data = new Data\Collection($response);
168
-
169
- if (!$data->exists('id')) {
170
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
171
- }
172
-
173
- $userProfile = new User\Profile();
174
-
175
- $userProfile->identifier = $data->get('id');
176
- $userProfile->displayName = $data->get('name');
177
- $userProfile->firstName = $data->get('first_name');
178
- $userProfile->lastName = $data->get('last_name');
179
- $userProfile->profileURL = $data->get('link');
180
- $userProfile->webSiteURL = $data->get('website');
181
- $userProfile->gender = $data->get('gender');
182
- $userProfile->language = $data->get('locale');
183
- $userProfile->description = $data->get('about');
184
- $userProfile->email = $data->get('email');
185
-
186
- // Fallback for profile URL in case Facebook does not provide "pretty" link with username (if user set it).
187
- if (empty($userProfile->profileURL)) {
188
- $userProfile->profileURL = $this->getProfileUrl($userProfile->identifier);
189
- }
190
-
191
- $userProfile->region = $data->filter('hometown')->get('name');
192
-
193
- $photoSize = $this->config->get('photo_size') ?: '150';
194
-
195
- $userProfile->photoURL = $this->apiBaseUrl . $userProfile->identifier;
196
- $userProfile->photoURL .= '/picture?width=' . $photoSize . '&height=' . $photoSize;
197
-
198
- $userProfile->emailVerified = $userProfile->email;
199
-
200
- $userProfile = $this->fetchUserRegion($userProfile);
201
-
202
- $userProfile = $this->fetchBirthday($userProfile, $data->get('birthday'));
203
-
204
- return $userProfile;
205
- }
206
-
207
- /**
208
- * Retrieve the user region.
209
- *
210
- * @param User\Profile $userProfile
211
- *
212
- * @return \Hybridauth\User\Profile
213
- */
214
- protected function fetchUserRegion(User\Profile $userProfile)
215
- {
216
- if (!empty($userProfile->region)) {
217
- $regionArr = explode(',', $userProfile->region);
218
-
219
- if (count($regionArr) > 1) {
220
- $userProfile->city = trim($regionArr[0]);
221
- $userProfile->country = trim($regionArr[1]);
222
- }
223
- }
224
-
225
- return $userProfile;
226
- }
227
-
228
- /**
229
- * Retrieve the user birthday.
230
- *
231
- * @param User\Profile $userProfile
232
- * @param string $birthday
233
- *
234
- * @return \Hybridauth\User\Profile
235
- */
236
- protected function fetchBirthday(User\Profile $userProfile, $birthday)
237
- {
238
- $result = (new Data\Parser())->parseBirthday($birthday, '/');
239
-
240
- $userProfile->birthYear = (int)$result[0];
241
- $userProfile->birthMonth = (int)$result[1];
242
- $userProfile->birthDay = (int)$result[2];
243
-
244
- return $userProfile;
245
- }
246
-
247
- /**
248
- * /v2.0/me/friends only returns the user's friends who also use the app.
249
- * In the cases where you want to let people tag their friends in stories published by your app,
250
- * you can use the Taggable Friends API.
251
- *
252
- * https://developers.facebook.com/docs/apps/faq#unable_full_friend_list
253
- */
254
- public function getUserContacts()
255
- {
256
- $contacts = [];
257
-
258
- $apiUrl = 'me/friends?fields=link,name';
259
-
260
- do {
261
- $response = $this->apiRequest($apiUrl);
262
-
263
- $data = new Data\Collection($response);
264
-
265
- if (!$data->exists('data')) {
266
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
267
- }
268
-
269
- if (!$data->filter('data')->isEmpty()) {
270
- foreach ($data->filter('data')->toArray() as $item) {
271
- $contacts[] = $this->fetchUserContact($item);
272
- }
273
- }
274
-
275
- if ($data->filter('paging')->exists('next')) {
276
- $apiUrl = $data->filter('paging')->get('next');
277
-
278
- $pagedList = true;
279
- } else {
280
- $pagedList = false;
281
- }
282
- } while ($pagedList);
283
-
284
- return $contacts;
285
- }
286
-
287
- /**
288
- * Parse the user contact.
289
- *
290
- * @param array $item
291
- *
292
- * @return \Hybridauth\User\Contact
293
- */
294
- protected function fetchUserContact($item)
295
- {
296
- $userContact = new User\Contact();
297
-
298
- $item = new Data\Collection($item);
299
-
300
- $userContact->identifier = $item->get('id');
301
- $userContact->displayName = $item->get('name');
302
-
303
- $userContact->profileURL = $item->exists('link')
304
- ?: $this->getProfileUrl($userContact->identifier);
305
-
306
- $userContact->photoURL = $this->apiBaseUrl . $userContact->identifier . '/picture?width=150&height=150';
307
-
308
- return $userContact;
309
- }
310
-
311
- /**
312
- * {@inheritdoc}
313
- */
314
- public function setPageStatus($status, $pageId)
315
- {
316
- $status = is_string($status) ? ['message' => $status] : $status;
317
-
318
- // Post on user wall.
319
- if ($pageId === 'me') {
320
- return $this->setUserStatus($status);
321
- }
322
-
323
- // Retrieve writable user pages and filter by given one.
324
- $pages = $this->getUserPages(true);
325
- $pages = array_filter($pages, function ($page) use ($pageId) {
326
- return $page->id == $pageId;
327
- });
328
-
329
- if (!$pages) {
330
- throw new InvalidArgumentException('Could not find a page with given id.');
331
- }
332
-
333
- $page = reset($pages);
334
-
335
- // Use page access token instead of user access token.
336
- $headers = [
337
- 'Authorization' => 'Bearer ' . $page->access_token,
338
- ];
339
-
340
- // Refresh proof for API call.
341
- $parameters = $status + [
342
- 'appsecret_proof' => hash_hmac('sha256', $page->access_token, $this->clientSecret),
343
- ];
344
-
345
- $response = $this->apiRequest("{$pageId}/feed", 'POST', $parameters, $headers);
346
-
347
- return $response;
348
- }
349
-
350
- /**
351
- * {@inheritdoc}
352
- */
353
- public function getUserPages($writable = false)
354
- {
355
- $pages = $this->apiRequest('me/accounts');
356
-
357
- if (!$writable) {
358
- return $pages->data;
359
- }
360
-
361
- // Filter user pages by CREATE_CONTENT permission.
362
- return array_filter($pages->data, function ($page) {
363
- return in_array('CREATE_CONTENT', $page->tasks);
364
- });
365
- }
366
-
367
- /**
368
- * {@inheritdoc}
369
- */
370
- public function getUserActivity($stream = 'me')
371
- {
372
- $apiUrl = $stream == 'me' ? 'me/feed' : 'me/home';
373
-
374
- $response = $this->apiRequest($apiUrl);
375
-
376
- $data = new Data\Collection($response);
377
-
378
- if (!$data->exists('data')) {
379
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
380
- }
381
-
382
- $activities = [];
383
-
384
- foreach ($data->filter('data')->toArray() as $item) {
385
- $activities[] = $this->fetchUserActivity($item);
386
- }
387
-
388
- return $activities;
389
- }
390
-
391
- /**
392
- * @param $item
393
- *
394
- * @return User\Activity
395
- */
396
- protected function fetchUserActivity($item)
397
- {
398
- $userActivity = new User\Activity();
399
-
400
- $item = new Data\Collection($item);
401
-
402
- $userActivity->id = $item->get('id');
403
- $userActivity->date = $item->get('created_time');
404
-
405
- if ('video' == $item->get('type') || 'link' == $item->get('type')) {
406
- $userActivity->text = $item->get('link');
407
- }
408
-
409
- if (empty($userActivity->text) && $item->exists('story')) {
410
- $userActivity->text = $item->get('link');
411
- }
412
-
413
- if (empty($userActivity->text) && $item->exists('message')) {
414
- $userActivity->text = $item->get('message');
415
- }
416
-
417
- if (!empty($userActivity->text) && $item->exists('from')) {
418
- $userActivity->user->identifier = $item->filter('from')->get('id');
419
- $userActivity->user->displayName = $item->filter('from')->get('name');
420
-
421
- $userActivity->user->profileURL = $this->getProfileUrl($userActivity->user->identifier);
422
-
423
- $userActivity->user->photoURL = $this->apiBaseUrl . $userActivity->user->identifier;
424
- $userActivity->user->photoURL .= '/picture?width=150&height=150';
425
- }
426
-
427
- return $userActivity;
428
- }
429
-
430
- /**
431
- * Get profile URL.
432
- *
433
- * @param int $identity User ID.
434
- * @return string|null NULL when identity is not provided.
435
- */
436
- protected function getProfileUrl($identity)
437
- {
438
- if (!is_numeric($identity)) {
439
- return null;
440
- }
441
-
442
- return sprintf($this->profileUrlTemplate, $identity);
443
- }
444
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Exception\InvalidArgumentException;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Adapter\OAuth2;
13
+ use Hybridauth\Data;
14
+ use Hybridauth\User;
15
+
16
+ /**
17
+ * Facebook OAuth2 provider adapter.
18
+ *
19
+ * Facebook doesn't use standard OAuth refresh tokens.
20
+ * Instead it has a "token exchange" system. You exchange the token prior to
21
+ * expiry, to push back expiry. You start with a short-lived token and each
22
+ * exchange gives you a long-lived one (90 days).
23
+ * We control this with the 'exchange_by_expiry_days' option.
24
+ *
25
+ * Example:
26
+ *
27
+ * $config = [
28
+ * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
29
+ * 'keys' => [ 'id' => '', 'secret' => '' ],
30
+ * 'scope' => 'email, user_status, user_posts',
31
+ * 'exchange_by_expiry_days' => 45, // null for no token exchange
32
+ * ];
33
+ *
34
+ * $adapter = new Hybridauth\Provider\Facebook( $config );
35
+ *
36
+ * try {
37
+ * $adapter->authenticate();
38
+ *
39
+ * $userProfile = $adapter->getUserProfile();
40
+ * $tokens = $adapter->getAccessToken();
41
+ * $response = $adapter->setUserStatus("Hybridauth test message..");
42
+ * }
43
+ * catch( Exception $e ){
44
+ * echo $e->getMessage() ;
45
+ * }
46
+ */
47
+ class Facebook extends OAuth2
48
+ {
49
+ /**
50
+ * {@inheritdoc}
51
+ */
52
+ protected $scope = 'email, public_profile';
53
+
54
+ /**
55
+ * {@inheritdoc}
56
+ */
57
+ protected $apiBaseUrl = 'https://graph.facebook.com/v6.0/';
58
+
59
+ /**
60
+ * {@inheritdoc}
61
+ */
62
+ protected $authorizeUrl = 'https://www.facebook.com/dialog/oauth';
63
+
64
+ /**
65
+ * {@inheritdoc}
66
+ */
67
+ protected $accessTokenUrl = 'https://graph.facebook.com/oauth/access_token';
68
+
69
+ /**
70
+ * {@inheritdoc}
71
+ */
72
+ protected $apiDocumentation = 'https://developers.facebook.com/docs/facebook-login/overview';
73
+
74
+ /**
75
+ * @var string Profile URL template as the fallback when no `link` returned from the API.
76
+ */
77
+ protected $profileUrlTemplate = 'https://www.facebook.com/%s';
78
+
79
+ /**
80
+ * {@inheritdoc}
81
+ */
82
+ protected function initialize()
83
+ {
84
+ parent::initialize();
85
+
86
+ // Require proof on all Facebook api calls
87
+ // https://developers.facebook.com/docs/graph-api/securing-requests#appsecret_proof
88
+ if ($accessToken = $this->getStoredData('access_token')) {
89
+ $this->apiRequestParameters['appsecret_proof'] = hash_hmac('sha256', $accessToken, $this->clientSecret);
90
+ }
91
+ }
92
+
93
+ /**
94
+ * {@inheritdoc}
95
+ */
96
+ public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
97
+ {
98
+ // Handle token exchange prior to the standard handler for an API request
99
+ $exchange_by_expiry_days = $this->config->get('exchange_by_expiry_days') ?: 45;
100
+ if ($exchange_by_expiry_days !== null) {
101
+ $projected_timestamp = time() + 60 * 60 * 24 * $exchange_by_expiry_days;
102
+ if (!$this->hasAccessTokenExpired() && $this->hasAccessTokenExpired($projected_timestamp)) {
103
+ $this->exchangeAccessToken();
104
+ }
105
+ }
106
+
107
+ return parent::apiRequest($url, $method, $parameters, $headers, $multipart);
108
+ }
109
+
110
+ /**
111
+ * Exchange the Access Token with one that expires further in the future.
112
+ *
113
+ * @return string Raw Provider API response
114
+ * @throws \Hybridauth\Exception\HttpClientFailureException
115
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
116
+ * @throws InvalidAccessTokenException
117
+ */
118
+ public function exchangeAccessToken()
119
+ {
120
+ $exchangeTokenParameters = [
121
+ 'grant_type' => 'fb_exchange_token',
122
+ 'client_id' => $this->clientId,
123
+ 'client_secret' => $this->clientSecret,
124
+ 'fb_exchange_token' => $this->getStoredData('access_token'),
125
+ ];
126
+
127
+ $response = $this->httpClient->request(
128
+ $this->accessTokenUrl,
129
+ 'GET',
130
+ $exchangeTokenParameters
131
+ );
132
+
133
+ $this->validateApiResponse('Unable to exchange the access token');
134
+
135
+ $this->validateAccessTokenExchange($response);
136
+
137
+ return $response;
138
+ }
139
+
140
+ /**
141
+ * {@inheritdoc}
142
+ */
143
+ public function getUserProfile()
144
+ {
145
+ $fields = [
146
+ 'id',
147
+ 'name',
148
+ 'first_name',
149
+ 'last_name',
150
+ 'link',
151
+ 'website',
152
+ 'gender',
153
+ 'locale',
154
+ 'about',
155
+ 'email',
156
+ 'hometown',
157
+ 'birthday',
158
+ ];
159
+
160
+ // Note that en_US is needed for gender fields to match convention.
161
+ $locale = $this->config->get('locale') ?: 'en_US';
162
+ $response = $this->apiRequest('me', 'GET', [
163
+ 'fields' => implode(',', $fields),
164
+ 'locale' => $locale,
165
+ ]);
166
+
167
+ $data = new Data\Collection($response);
168
+
169
+ if (!$data->exists('id')) {
170
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
171
+ }
172
+
173
+ $userProfile = new User\Profile();
174
+
175
+ $userProfile->identifier = $data->get('id');
176
+ $userProfile->displayName = $data->get('name');
177
+ $userProfile->firstName = $data->get('first_name');
178
+ $userProfile->lastName = $data->get('last_name');
179
+ $userProfile->profileURL = $data->get('link');
180
+ $userProfile->webSiteURL = $data->get('website');
181
+ $userProfile->gender = $data->get('gender');
182
+ $userProfile->language = $data->get('locale');
183
+ $userProfile->description = $data->get('about');
184
+ $userProfile->email = $data->get('email');
185
+
186
+ // Fallback for profile URL in case Facebook does not provide "pretty" link with username (if user set it).
187
+ if (empty($userProfile->profileURL)) {
188
+ $userProfile->profileURL = $this->getProfileUrl($userProfile->identifier);
189
+ }
190
+
191
+ $userProfile->region = $data->filter('hometown')->get('name');
192
+
193
+ $photoSize = $this->config->get('photo_size') ?: '150';
194
+
195
+ $userProfile->photoURL = $this->apiBaseUrl . $userProfile->identifier;
196
+ $userProfile->photoURL .= '/picture?width=' . $photoSize . '&height=' . $photoSize;
197
+
198
+ $userProfile->emailVerified = $userProfile->email;
199
+
200
+ $userProfile = $this->fetchUserRegion($userProfile);
201
+
202
+ $userProfile = $this->fetchBirthday($userProfile, $data->get('birthday'));
203
+
204
+ return $userProfile;
205
+ }
206
+
207
+ /**
208
+ * Retrieve the user region.
209
+ *
210
+ * @param User\Profile $userProfile
211
+ *
212
+ * @return \Hybridauth\User\Profile
213
+ */
214
+ protected function fetchUserRegion(User\Profile $userProfile)
215
+ {
216
+ if (!empty($userProfile->region)) {
217
+ $regionArr = explode(',', $userProfile->region);
218
+
219
+ if (count($regionArr) > 1) {
220
+ $userProfile->city = trim($regionArr[0]);
221
+ $userProfile->country = trim($regionArr[1]);
222
+ }
223
+ }
224
+
225
+ return $userProfile;
226
+ }
227
+
228
+ /**
229
+ * Retrieve the user birthday.
230
+ *
231
+ * @param User\Profile $userProfile
232
+ * @param string $birthday
233
+ *
234
+ * @return \Hybridauth\User\Profile
235
+ */
236
+ protected function fetchBirthday(User\Profile $userProfile, $birthday)
237
+ {
238
+ $result = (new Data\Parser())->parseBirthday($birthday, '/');
239
+
240
+ $userProfile->birthYear = (int)$result[0];
241
+ $userProfile->birthMonth = (int)$result[1];
242
+ $userProfile->birthDay = (int)$result[2];
243
+
244
+ return $userProfile;
245
+ }
246
+
247
+ /**
248
+ * /v2.0/me/friends only returns the user's friends who also use the app.
249
+ * In the cases where you want to let people tag their friends in stories published by your app,
250
+ * you can use the Taggable Friends API.
251
+ *
252
+ * https://developers.facebook.com/docs/apps/faq#unable_full_friend_list
253
+ */
254
+ public function getUserContacts()
255
+ {
256
+ $contacts = [];
257
+
258
+ $apiUrl = 'me/friends?fields=link,name';
259
+
260
+ do {
261
+ $response = $this->apiRequest($apiUrl);
262
+
263
+ $data = new Data\Collection($response);
264
+
265
+ if (!$data->exists('data')) {
266
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
267
+ }
268
+
269
+ if (!$data->filter('data')->isEmpty()) {
270
+ foreach ($data->filter('data')->toArray() as $item) {
271
+ $contacts[] = $this->fetchUserContact($item);
272
+ }
273
+ }
274
+
275
+ if ($data->filter('paging')->exists('next')) {
276
+ $apiUrl = $data->filter('paging')->get('next');
277
+
278
+ $pagedList = true;
279
+ } else {
280
+ $pagedList = false;
281
+ }
282
+ } while ($pagedList);
283
+
284
+ return $contacts;
285
+ }
286
+
287
+ /**
288
+ * Parse the user contact.
289
+ *
290
+ * @param array $item
291
+ *
292
+ * @return \Hybridauth\User\Contact
293
+ */
294
+ protected function fetchUserContact($item)
295
+ {
296
+ $userContact = new User\Contact();
297
+
298
+ $item = new Data\Collection($item);
299
+
300
+ $userContact->identifier = $item->get('id');
301
+ $userContact->displayName = $item->get('name');
302
+
303
+ $userContact->profileURL = $item->exists('link')
304
+ ?: $this->getProfileUrl($userContact->identifier);
305
+
306
+ $userContact->photoURL = $this->apiBaseUrl . $userContact->identifier . '/picture?width=150&height=150';
307
+
308
+ return $userContact;
309
+ }
310
+
311
+ /**
312
+ * {@inheritdoc}
313
+ */
314
+ public function setPageStatus($status, $pageId)
315
+ {
316
+ $status = is_string($status) ? ['message' => $status] : $status;
317
+
318
+ // Post on user wall.
319
+ if ($pageId === 'me') {
320
+ return $this->setUserStatus($status);
321
+ }
322
+
323
+ // Retrieve writable user pages and filter by given one.
324
+ $pages = $this->getUserPages(true);
325
+ $pages = array_filter($pages, function ($page) use ($pageId) {
326
+ return $page->id == $pageId;
327
+ });
328
+
329
+ if (!$pages) {
330
+ throw new InvalidArgumentException('Could not find a page with given id.');
331
+ }
332
+
333
+ $page = reset($pages);
334
+
335
+ // Use page access token instead of user access token.
336
+ $headers = [
337
+ 'Authorization' => 'Bearer ' . $page->access_token,
338
+ ];
339
+
340
+ // Refresh proof for API call.
341
+ $parameters = $status + [
342
+ 'appsecret_proof' => hash_hmac('sha256', $page->access_token, $this->clientSecret),
343
+ ];
344
+
345
+ $response = $this->apiRequest("{$pageId}/feed", 'POST', $parameters, $headers);
346
+
347
+ return $response;
348
+ }
349
+
350
+ /**
351
+ * {@inheritdoc}
352
+ */
353
+ public function getUserPages($writable = false)
354
+ {
355
+ $pages = $this->apiRequest('me/accounts');
356
+
357
+ if (!$writable) {
358
+ return $pages->data;
359
+ }
360
+
361
+ // Filter user pages by CREATE_CONTENT permission.
362
+ return array_filter($pages->data, function ($page) {
363
+ return in_array('CREATE_CONTENT', $page->tasks);
364
+ });
365
+ }
366
+
367
+ /**
368
+ * {@inheritdoc}
369
+ */
370
+ public function getUserActivity($stream = 'me')
371
+ {
372
+ $apiUrl = $stream == 'me' ? 'me/feed' : 'me/home';
373
+
374
+ $response = $this->apiRequest($apiUrl);
375
+
376
+ $data = new Data\Collection($response);
377
+
378
+ if (!$data->exists('data')) {
379
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
380
+ }
381
+
382
+ $activities = [];
383
+
384
+ foreach ($data->filter('data')->toArray() as $item) {
385
+ $activities[] = $this->fetchUserActivity($item);
386
+ }
387
+
388
+ return $activities;
389
+ }
390
+
391
+ /**
392
+ * @param $item
393
+ *
394
+ * @return User\Activity
395
+ */
396
+ protected function fetchUserActivity($item)
397
+ {
398
+ $userActivity = new User\Activity();
399
+
400
+ $item = new Data\Collection($item);
401
+
402
+ $userActivity->id = $item->get('id');
403
+ $userActivity->date = $item->get('created_time');
404
+
405
+ if ('video' == $item->get('type') || 'link' == $item->get('type')) {
406
+ $userActivity->text = $item->get('link');
407
+ }
408
+
409
+ if (empty($userActivity->text) && $item->exists('story')) {
410
+ $userActivity->text = $item->get('link');
411
+ }
412
+
413
+ if (empty($userActivity->text) && $item->exists('message')) {
414
+ $userActivity->text = $item->get('message');
415
+ }
416
+
417
+ if (!empty($userActivity->text) && $item->exists('from')) {
418
+ $userActivity->user->identifier = $item->filter('from')->get('id');
419
+ $userActivity->user->displayName = $item->filter('from')->get('name');
420
+
421
+ $userActivity->user->profileURL = $this->getProfileUrl($userActivity->user->identifier);
422
+
423
+ $userActivity->user->photoURL = $this->apiBaseUrl . $userActivity->user->identifier;
424
+ $userActivity->user->photoURL .= '/picture?width=150&height=150';
425
+ }
426
+
427
+ return $userActivity;
428
+ }
429
+
430
+ /**
431
+ * Get profile URL.
432
+ *
433
+ * @param int $identity User ID.
434
+ * @return string|null NULL when identity is not provided.
435
+ */
436
+ protected function getProfileUrl($identity)
437
+ {
438
+ if (!is_numeric($identity)) {
439
+ return null;
440
+ }
441
+
442
+ return sprintf($this->profileUrlTemplate, $identity);
443
+ }
444
+ }
hybridauth/library/src/Provider/Foursquare.php CHANGED
@@ -1,140 +1,140 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Foursquare OAuth2 provider adapter.
17
- */
18
- class Foursquare extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $apiBaseUrl = 'https://api.foursquare.com/v2/';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $authorizeUrl = 'https://foursquare.com/oauth2/authenticate';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $accessTokenUrl = 'https://foursquare.com/oauth2/access_token';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenName = 'oauth_token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://developer.foursquare.com/overview/auth';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected function initialize()
49
- {
50
- parent::initialize();
51
-
52
- $apiVersion = $this->config->get('api_version') ?: '20140201';
53
-
54
- $this->apiRequestParameters = [
55
- 'oauth_token' => $this->getStoredData('access_token'),
56
- 'v' => $apiVersion,
57
- ];
58
- }
59
-
60
- /**
61
- * {@inheritdoc}
62
- */
63
- public function getUserProfile()
64
- {
65
- $response = $this->apiRequest('users/self');
66
-
67
- $data = new Data\Collection($response);
68
-
69
- if (! $data->exists('response')) {
70
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
71
- }
72
-
73
- $userProfile = new User\Profile();
74
-
75
- $data = $data->filter('response')->filter('user');
76
-
77
- $userProfile->identifier = $data->get('id');
78
- $userProfile->firstName = $data->get('firstName');
79
- $userProfile->lastName = $data->get('lastName');
80
- $userProfile->gender = $data->get('gender');
81
- $userProfile->city = $data->get('homeCity');
82
- $userProfile->email = $data->filter('contact')->get('email');
83
- $userProfile->emailVerified = $userProfile->email;
84
- $userProfile->profileURL = 'https://www.foursquare.com/user/' . $userProfile->identifier;
85
- $userProfile->displayName = trim($userProfile->firstName . ' ' . $userProfile->lastName);
86
-
87
- if ($data->exists('photo')) {
88
- $photoSize = $this->config->get('photo_size') ?: '150x150';
89
-
90
- $userProfile->photoURL = $data->filter('photo')->get('prefix');
91
- $userProfile->photoURL .= $photoSize . $data->filter('photo')->get('suffix');
92
- }
93
-
94
- return $userProfile;
95
- }
96
-
97
- /**
98
- * {@inheritdoc}
99
- */
100
- public function getUserContacts()
101
- {
102
- $response = $this->apiRequest('users/self/friends');
103
-
104
- $data = new Data\Collection($response);
105
-
106
- if (! $data->exists('response')) {
107
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
108
- }
109
-
110
- $contacts = [];
111
-
112
- foreach ($data->filter('response')->filter('friends')->filter('items')->toArray() as $item) {
113
- $contacts[] = $this->fetchUserContact($item);
114
- }
115
-
116
- return $contacts;
117
- }
118
-
119
- /**
120
- * @param $item
121
- *
122
- * @return User\Contact
123
- */
124
- protected function fetchUserContact($item)
125
- {
126
- $photoSize = $this->config->get('photo_size') ?: '150x150';
127
-
128
- $item = new Data\Collection($item);
129
-
130
- $userContact = new User\Contact();
131
-
132
- $userContact->identifier = $item->get('id');
133
- $userContact->photoURL = $item->filter('photo')->get('prefix');
134
- $userContact->photoURL .= $photoSize . $item->filter('photo')->get('suffix');
135
- $userContact->displayName = trim($item->get('firstName') . ' ' . $item->get('lastName'));
136
- $userContact->email = $item->filter('contact')->get('email');
137
-
138
- return $userContact;
139
- }
140
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Foursquare OAuth2 provider adapter.
17
+ */
18
+ class Foursquare extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $apiBaseUrl = 'https://api.foursquare.com/v2/';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $authorizeUrl = 'https://foursquare.com/oauth2/authenticate';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $accessTokenUrl = 'https://foursquare.com/oauth2/access_token';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenName = 'oauth_token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://developer.foursquare.com/overview/auth';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function initialize()
49
+ {
50
+ parent::initialize();
51
+
52
+ $apiVersion = $this->config->get('api_version') ?: '20140201';
53
+
54
+ $this->apiRequestParameters = [
55
+ 'oauth_token' => $this->getStoredData('access_token'),
56
+ 'v' => $apiVersion,
57
+ ];
58
+ }
59
+
60
+ /**
61
+ * {@inheritdoc}
62
+ */
63
+ public function getUserProfile()
64
+ {
65
+ $response = $this->apiRequest('users/self');
66
+
67
+ $data = new Data\Collection($response);
68
+
69
+ if (! $data->exists('response')) {
70
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
71
+ }
72
+
73
+ $userProfile = new User\Profile();
74
+
75
+ $data = $data->filter('response')->filter('user');
76
+
77
+ $userProfile->identifier = $data->get('id');
78
+ $userProfile->firstName = $data->get('firstName');
79
+ $userProfile->lastName = $data->get('lastName');
80
+ $userProfile->gender = $data->get('gender');
81
+ $userProfile->city = $data->get('homeCity');
82
+ $userProfile->email = $data->filter('contact')->get('email');
83
+ $userProfile->emailVerified = $userProfile->email;
84
+ $userProfile->profileURL = 'https://www.foursquare.com/user/' . $userProfile->identifier;
85
+ $userProfile->displayName = trim($userProfile->firstName . ' ' . $userProfile->lastName);
86
+
87
+ if ($data->exists('photo')) {
88
+ $photoSize = $this->config->get('photo_size') ?: '150x150';
89
+
90
+ $userProfile->photoURL = $data->filter('photo')->get('prefix');
91
+ $userProfile->photoURL .= $photoSize . $data->filter('photo')->get('suffix');
92
+ }
93
+
94
+ return $userProfile;
95
+ }
96
+
97
+ /**
98
+ * {@inheritdoc}
99
+ */
100
+ public function getUserContacts()
101
+ {
102
+ $response = $this->apiRequest('users/self/friends');
103
+
104
+ $data = new Data\Collection($response);
105
+
106
+ if (! $data->exists('response')) {
107
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
108
+ }
109
+
110
+ $contacts = [];
111
+
112
+ foreach ($data->filter('response')->filter('friends')->filter('items')->toArray() as $item) {
113
+ $contacts[] = $this->fetchUserContact($item);
114
+ }
115
+
116
+ return $contacts;
117
+ }
118
+
119
+ /**
120
+ * @param $item
121
+ *
122
+ * @return User\Contact
123
+ */
124
+ protected function fetchUserContact($item)
125
+ {
126
+ $photoSize = $this->config->get('photo_size') ?: '150x150';
127
+
128
+ $item = new Data\Collection($item);
129
+
130
+ $userContact = new User\Contact();
131
+
132
+ $userContact->identifier = $item->get('id');
133
+ $userContact->photoURL = $item->filter('photo')->get('prefix');
134
+ $userContact->photoURL .= $photoSize . $item->filter('photo')->get('suffix');
135
+ $userContact->displayName = trim($item->get('firstName') . ' ' . $item->get('lastName'));
136
+ $userContact->email = $item->filter('contact')->get('email');
137
+
138
+ return $userContact;
139
+ }
140
+ }
hybridauth/library/src/Provider/GitHub.php CHANGED
@@ -1,110 +1,110 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Github OAuth2 provider adapter.
17
- */
18
- class GitHub extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'user:email';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://api.github.com/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://github.com/login/oauth/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://github.com/login/oauth/access_token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://developer.github.com/v3/oauth/';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('user');
51
-
52
- $data = new Data\Collection($response);
53
-
54
- if (!$data->exists('id')) {
55
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
- }
57
-
58
- $userProfile = new User\Profile();
59
-
60
- $userProfile->identifier = $data->get('id');
61
- $userProfile->displayName = $data->get('name');
62
- $userProfile->description = $data->get('bio');
63
- $userProfile->photoURL = $data->get('avatar_url');
64
- $userProfile->profileURL = $data->get('html_url');
65
- $userProfile->email = $data->get('email');
66
- $userProfile->webSiteURL = $data->get('blog');
67
- $userProfile->region = $data->get('location');
68
-
69
- $userProfile->displayName = $userProfile->displayName ?: $data->get('login');
70
-
71
- if (empty($userProfile->email) && strpos($this->scope, 'user:email') !== false) {
72
- try {
73
- // user email is not mandatory so keep it quite.
74
- $userProfile = $this->requestUserEmail($userProfile);
75
- } catch (\Exception $e) {
76
- }
77
- }
78
-
79
- return $userProfile;
80
- }
81
-
82
- /**
83
- * Request connected user email
84
- *
85
- * https://developer.github.com/v3/users/emails/
86
- * @param User\Profile $userProfile
87
- *
88
- * @return User\Profile
89
- *
90
- * @throws \Exception
91
- */
92
- protected function requestUserEmail(User\Profile $userProfile)
93
- {
94
- $response = $this->apiRequest('user/emails');
95
-
96
- foreach ($response as $idx => $item) {
97
- if (!empty($item->primary) && $item->primary == 1) {
98
- $userProfile->email = $item->email;
99
-
100
- if (!empty($item->verified) && $item->verified == 1) {
101
- $userProfile->emailVerified = $userProfile->email;
102
- }
103
-
104
- break;
105
- }
106
- }
107
-
108
- return $userProfile;
109
- }
110
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Github OAuth2 provider adapter.
17
+ */
18
+ class GitHub extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'user:email';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://api.github.com/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://github.com/login/oauth/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://github.com/login/oauth/access_token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://developer.github.com/v3/oauth/';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('user');
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ if (!$data->exists('id')) {
55
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
+ }
57
+
58
+ $userProfile = new User\Profile();
59
+
60
+ $userProfile->identifier = $data->get('id');
61
+ $userProfile->displayName = $data->get('name');
62
+ $userProfile->description = $data->get('bio');
63
+ $userProfile->photoURL = $data->get('avatar_url');
64
+ $userProfile->profileURL = $data->get('html_url');
65
+ $userProfile->email = $data->get('email');
66
+ $userProfile->webSiteURL = $data->get('blog');
67
+ $userProfile->region = $data->get('location');
68
+
69
+ $userProfile->displayName = $userProfile->displayName ?: $data->get('login');
70
+
71
+ if (empty($userProfile->email) && strpos($this->scope, 'user:email') !== false) {
72
+ try {
73
+ // user email is not mandatory so keep it quite.
74
+ $userProfile = $this->requestUserEmail($userProfile);
75
+ } catch (\Exception $e) {
76
+ }
77
+ }
78
+
79
+ return $userProfile;
80
+ }
81
+
82
+ /**
83
+ * Request connected user email
84
+ *
85
+ * https://developer.github.com/v3/users/emails/
86
+ * @param User\Profile $userProfile
87
+ *
88
+ * @return User\Profile
89
+ *
90
+ * @throws \Exception
91
+ */
92
+ protected function requestUserEmail(User\Profile $userProfile)
93
+ {
94
+ $response = $this->apiRequest('user/emails');
95
+
96
+ foreach ($response as $idx => $item) {
97
+ if (!empty($item->primary) && $item->primary == 1) {
98
+ $userProfile->email = $item->email;
99
+
100
+ if (!empty($item->verified) && $item->verified == 1) {
101
+ $userProfile->emailVerified = $userProfile->email;
102
+ }
103
+
104
+ break;
105
+ }
106
+ }
107
+
108
+ return $userProfile;
109
+ }
110
+ }
hybridauth/library/src/Provider/GitLab.php CHANGED
@@ -1,72 +1,72 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * GitLab OAuth2 provider adapter.
17
- */
18
- class GitLab extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'api';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://gitlab.com/api/v3/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://gitlab.com/oauth/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://gitlab.com/oauth/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://docs.gitlab.com/ee/api/oauth2.html';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('user');
51
-
52
- $data = new Data\Collection($response);
53
-
54
- if (! $data->exists('id')) {
55
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
- }
57
-
58
- $userProfile = new User\Profile();
59
-
60
- $userProfile->identifier = $data->get('id');
61
- $userProfile->displayName = $data->get('name');
62
- $userProfile->description = $data->get('bio');
63
- $userProfile->photoURL = $data->get('avatar_url');
64
- $userProfile->profileURL = $data->get('web_url');
65
- $userProfile->email = $data->get('email');
66
- $userProfile->webSiteURL = $data->get('website_url');
67
-
68
- $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
69
-
70
- return $userProfile;
71
- }
72
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * GitLab OAuth2 provider adapter.
17
+ */
18
+ class GitLab extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'api';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://gitlab.com/api/v3/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://gitlab.com/oauth/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://gitlab.com/oauth/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://docs.gitlab.com/ee/api/oauth2.html';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('user');
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ if (! $data->exists('id')) {
55
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
+ }
57
+
58
+ $userProfile = new User\Profile();
59
+
60
+ $userProfile->identifier = $data->get('id');
61
+ $userProfile->displayName = $data->get('name');
62
+ $userProfile->description = $data->get('bio');
63
+ $userProfile->photoURL = $data->get('avatar_url');
64
+ $userProfile->profileURL = $data->get('web_url');
65
+ $userProfile->email = $data->get('email');
66
+ $userProfile->webSiteURL = $data->get('website_url');
67
+
68
+ $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
69
+
70
+ return $userProfile;
71
+ }
72
+ }
hybridauth/library/src/Provider/Google.php CHANGED
@@ -1,200 +1,200 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Google OAuth2 provider adapter.
17
- *
18
- * Example:
19
- *
20
- * $config = [
21
- * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
22
- * 'keys' => [ 'id' => '', 'secret' => '' ],
23
- * 'scope' => 'https://www.googleapis.com/auth/userinfo.profile',
24
- *
25
- * // google's custom auth url params
26
- * 'authorize_url_parameters' => [
27
- * 'approval_prompt' => 'force', // to pass only when you need to acquire a new refresh token.
28
- * 'access_type' => .., // is set to 'offline' by default
29
- * 'hd' => ..,
30
- * 'state' => ..,
31
- * // etc.
32
- * ]
33
- * ];
34
- *
35
- * $adapter = new Hybridauth\Provider\Google( $config );
36
- *
37
- * try {
38
- * $adapter->authenticate();
39
- *
40
- * $userProfile = $adapter->getUserProfile();
41
- * $tokens = $adapter->getAccessToken();
42
- * $contacts = $adapter->getUserContacts(['max-results' => 75]);
43
- * }
44
- * catch( Exception $e ){
45
- * echo $e->getMessage() ;
46
- * }
47
- */
48
- class Google extends OAuth2
49
- {
50
- /**
51
- * {@inheritdoc}
52
- */
53
- // phpcs:ignore
54
- protected $scope = 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email';
55
-
56
- /**
57
- * {@inheritdoc}
58
- */
59
- protected $apiBaseUrl = 'https://www.googleapis.com/';
60
-
61
- /**
62
- * {@inheritdoc}
63
- */
64
- protected $authorizeUrl = 'https://accounts.google.com/o/oauth2/auth';
65
-
66
- /**
67
- * {@inheritdoc}
68
- */
69
- protected $accessTokenUrl = 'https://accounts.google.com/o/oauth2/token';
70
-
71
- /**
72
- * {@inheritdoc}
73
- */
74
- protected $apiDocumentation = 'https://developers.google.com/identity/protocols/OAuth2';
75
-
76
- /**
77
- * {@inheritdoc}
78
- */
79
- protected function initialize()
80
- {
81
- parent::initialize();
82
-
83
- $this->AuthorizeUrlParameters += [
84
- 'access_type' => 'offline'
85
- ];
86
-
87
- if ($this->isRefreshTokenAvailable()) {
88
- $this->tokenRefreshParameters += [
89
- 'client_id' => $this->clientId,
90
- 'client_secret' => $this->clientSecret
91
- ];
92
- }
93
- }
94
-
95
- /**
96
- * {@inheritdoc}
97
- *
98
- * See: https://developers.google.com/identity/protocols/OpenIDConnect#obtainuserinfo
99
- */
100
- public function getUserProfile()
101
- {
102
- $response = $this->apiRequest('oauth2/v3/userinfo');
103
-
104
- $data = new Data\Collection($response);
105
-
106
- if (! $data->exists('sub')) {
107
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
108
- }
109
-
110
- $userProfile = new User\Profile();
111
-
112
- $userProfile->identifier = $data->get('sub');
113
- $userProfile->firstName = $data->get('given_name');
114
- $userProfile->lastName = $data->get('family_name');
115
- $userProfile->displayName = $data->get('name');
116
- $userProfile->photoURL = $data->get('picture');
117
- $userProfile->profileURL = $data->get('profile');
118
- $userProfile->gender = $data->get('gender');
119
- $userProfile->language = $data->get('locale');
120
- $userProfile->email = $data->get('email');
121
-
122
- $userProfile->emailVerified = $data->get('email_verified') ? $userProfile->email : '';
123
-
124
- if ($this->config->get('photo_size')) {
125
- $userProfile->photoURL .= '?sz=' . $this->config->get('photo_size');
126
- }
127
-
128
- return $userProfile;
129
- }
130
-
131
- /**
132
- * {@inheritdoc}
133
- */
134
- public function getUserContacts($parameters = [])
135
- {
136
- $parameters = ['max-results' => 500] + $parameters;
137
-
138
- // Google Gmail and Android contacts
139
- if (false !== strpos($this->scope, '/m8/feeds/') || false !== strpos($this->scope, '/auth/contacts.readonly')) {
140
- return $this->getGmailContacts($parameters);
141
- }
142
-
143
- return [];
144
- }
145
-
146
- /**
147
- * Retrieve Gmail contacts
148
- *
149
- * @param array $parameters
150
- *
151
- * @return array
152
- *
153
- * @throws \Exception
154
- */
155
- protected function getGmailContacts($parameters = [])
156
- {
157
- $url = 'https://www.google.com/m8/feeds/contacts/default/full?'
158
- . http_build_query(array_replace([ 'alt' => 'json', 'v' => '3.0' ], (array)$parameters));
159
-
160
- $response = $this->apiRequest($url);
161
-
162
- if (! $response) {
163
- return [];
164
- }
165
-
166
- $contacts = [];
167
-
168
- if (isset($response->feed->entry)) {
169
- foreach ($response->feed->entry as $idx => $entry) {
170
- $uc = new User\Contact();
171
-
172
- $uc->email = isset($entry->{'gd$email'}[0]->address)
173
- ? (string) $entry->{'gd$email'}[0]->address
174
- : '';
175
-
176
- $uc->displayName = isset($entry->title->{'$t'}) ? (string) $entry->title->{'$t'} : '';
177
- $uc->identifier = ($uc->email != '') ? $uc->email : '';
178
- $uc->description = '';
179
-
180
- if (property_exists($response, 'website')) {
181
- if (is_array($response->website)) {
182
- foreach ($response->website as $w) {
183
- if ($w->primary == true) {
184
- $uc->webSiteURL = $w->value;
185
- }
186
- }
187
- } else {
188
- $uc->webSiteURL = $response->website->value;
189
- }
190
- } else {
191
- $uc->webSiteURL = '';
192
- }
193
-
194
- $contacts[] = $uc;
195
- }
196
- }
197
-
198
- return $contacts;
199
- }
200
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Google OAuth2 provider adapter.
17
+ *
18
+ * Example:
19
+ *
20
+ * $config = [
21
+ * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
22
+ * 'keys' => [ 'id' => '', 'secret' => '' ],
23
+ * 'scope' => 'https://www.googleapis.com/auth/userinfo.profile',
24
+ *
25
+ * // google's custom auth url params
26
+ * 'authorize_url_parameters' => [
27
+ * 'approval_prompt' => 'force', // to pass only when you need to acquire a new refresh token.
28
+ * 'access_type' => .., // is set to 'offline' by default
29
+ * 'hd' => ..,
30
+ * 'state' => ..,
31
+ * // etc.
32
+ * ]
33
+ * ];
34
+ *
35
+ * $adapter = new Hybridauth\Provider\Google( $config );
36
+ *
37
+ * try {
38
+ * $adapter->authenticate();
39
+ *
40
+ * $userProfile = $adapter->getUserProfile();
41
+ * $tokens = $adapter->getAccessToken();
42
+ * $contacts = $adapter->getUserContacts(['max-results' => 75]);
43
+ * }
44
+ * catch( Exception $e ){
45
+ * echo $e->getMessage() ;
46
+ * }
47
+ */
48
+ class Google extends OAuth2
49
+ {
50
+ /**
51
+ * {@inheritdoc}
52
+ */
53
+ // phpcs:ignore
54
+ protected $scope = 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email';
55
+
56
+ /**
57
+ * {@inheritdoc}
58
+ */
59
+ protected $apiBaseUrl = 'https://www.googleapis.com/';
60
+
61
+ /**
62
+ * {@inheritdoc}
63
+ */
64
+ protected $authorizeUrl = 'https://accounts.google.com/o/oauth2/auth';
65
+
66
+ /**
67
+ * {@inheritdoc}
68
+ */
69
+ protected $accessTokenUrl = 'https://accounts.google.com/o/oauth2/token';
70
+
71
+ /**
72
+ * {@inheritdoc}
73
+ */
74
+ protected $apiDocumentation = 'https://developers.google.com/identity/protocols/OAuth2';
75
+
76
+ /**
77
+ * {@inheritdoc}
78
+ */
79
+ protected function initialize()
80
+ {
81
+ parent::initialize();
82
+
83
+ $this->AuthorizeUrlParameters += [
84
+ 'access_type' => 'offline'
85
+ ];
86
+
87
+ if ($this->isRefreshTokenAvailable()) {
88
+ $this->tokenRefreshParameters += [
89
+ 'client_id' => $this->clientId,
90
+ 'client_secret' => $this->clientSecret
91
+ ];
92
+ }
93
+ }
94
+
95
+ /**
96
+ * {@inheritdoc}
97
+ *
98
+ * See: https://developers.google.com/identity/protocols/OpenIDConnect#obtainuserinfo
99
+ */
100
+ public function getUserProfile()
101
+ {
102
+ $response = $this->apiRequest('oauth2/v3/userinfo');
103
+
104
+ $data = new Data\Collection($response);
105
+
106
+ if (! $data->exists('sub')) {
107
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
108
+ }
109
+
110
+ $userProfile = new User\Profile();
111
+
112
+ $userProfile->identifier = $data->get('sub');
113
+ $userProfile->firstName = $data->get('given_name');
114
+ $userProfile->lastName = $data->get('family_name');
115
+ $userProfile->displayName = $data->get('name');
116
+ $userProfile->photoURL = $data->get('picture');
117
+ $userProfile->profileURL = $data->get('profile');
118
+ $userProfile->gender = $data->get('gender');
119
+ $userProfile->language = $data->get('locale');
120
+ $userProfile->email = $data->get('email');
121
+
122
+ $userProfile->emailVerified = $data->get('email_verified') ? $userProfile->email : '';
123
+
124
+ if ($this->config->get('photo_size')) {
125
+ $userProfile->photoURL .= '?sz=' . $this->config->get('photo_size');
126
+ }
127
+
128
+ return $userProfile;
129
+ }
130
+
131
+ /**
132
+ * {@inheritdoc}
133
+ */
134
+ public function getUserContacts($parameters = [])
135
+ {
136
+ $parameters = ['max-results' => 500] + $parameters;
137
+
138
+ // Google Gmail and Android contacts
139
+ if (false !== strpos($this->scope, '/m8/feeds/') || false !== strpos($this->scope, '/auth/contacts.readonly')) {
140
+ return $this->getGmailContacts($parameters);
141
+ }
142
+
143
+ return [];
144
+ }
145
+
146
+ /**
147
+ * Retrieve Gmail contacts
148
+ *
149
+ * @param array $parameters
150
+ *
151
+ * @return array
152
+ *
153
+ * @throws \Exception
154
+ */
155
+ protected function getGmailContacts($parameters = [])
156
+ {
157
+ $url = 'https://www.google.com/m8/feeds/contacts/default/full?'
158
+ . http_build_query(array_replace([ 'alt' => 'json', 'v' => '3.0' ], (array)$parameters));
159
+
160
+ $response = $this->apiRequest($url);
161
+
162
+ if (! $response) {
163
+ return [];
164
+ }
165
+
166
+ $contacts = [];
167
+
168
+ if (isset($response->feed->entry)) {
169
+ foreach ($response->feed->entry as $idx => $entry) {
170
+ $uc = new User\Contact();
171
+
172
+ $uc->email = isset($entry->{'gd$email'}[0]->address)
173
+ ? (string) $entry->{'gd$email'}[0]->address
174
+ : '';
175
+
176
+ $uc->displayName = isset($entry->title->{'$t'}) ? (string) $entry->title->{'$t'} : '';
177
+ $uc->identifier = ($uc->email != '') ? $uc->email : '';
178
+ $uc->description = '';
179
+
180
+ if (property_exists($response, 'website')) {
181
+ if (is_array($response->website)) {
182
+ foreach ($response->website as $w) {
183
+ if ($w->primary == true) {
184
+ $uc->webSiteURL = $w->value;
185
+ }
186
+ }
187
+ } else {
188
+ $uc->webSiteURL = $response->website->value;
189
+ }
190
+ } else {
191
+ $uc->webSiteURL = '';
192
+ }
193
+
194
+ $contacts[] = $uc;
195
+ }
196
+ }
197
+
198
+ return $contacts;
199
+ }
200
+ }
hybridauth/library/src/Provider/Instagram.php CHANGED
@@ -1,170 +1,170 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2020 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Data\Collection;
12
- use Hybridauth\Exception\UnexpectedApiResponseException;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Instagram OAuth2 provider adapter via Instagram Basic Display API.
17
- */
18
- class Instagram extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'user_profile,user_media';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://graph.instagram.com';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://api.instagram.com/oauth/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://api.instagram.com/oauth/access_token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://developers.facebook.com/docs/instagram-basic-display-api';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected function initialize()
49
- {
50
- parent::initialize();
51
-
52
- // The Instagram API requires an access_token from authenticated users
53
- // for each endpoint.
54
- $accessToken = $this->getStoredData($this->accessTokenName);
55
- $this->apiRequestParameters[$this->accessTokenName] = $accessToken;
56
- }
57
-
58
- /**
59
- * {@inheritdoc}
60
- */
61
- public function getUserProfile()
62
- {
63
- $response = $this->apiRequest('me', 'GET', [
64
- 'fields' => 'id,username,account_type,media_count',
65
- ]);
66
-
67
- $data = new Collection($response);
68
- if (!$data->exists('id')) {
69
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
70
- }
71
-
72
- $userProfile = new User\Profile();
73
- $userProfile->identifier = $data->get('id');
74
- $userProfile->displayName = $data->get('username');
75
- $userProfile->profileURL = "https://instagram.com/{$userProfile->displayName}";
76
- $userProfile->data = [
77
- 'account_type' => $data->get('account_type'),
78
- 'media_count' => $data->get('media_count'),
79
- ];
80
-
81
- return $userProfile;
82
- }
83
-
84
- /**
85
- * Fetch user medias.
86
- *
87
- * @param int $limit Number of elements per page.
88
- * @param string $pageId Current pager ID.
89
- * @param array|null $fields Fields to fetch per media.
90
- *
91
- * @return \Hybridauth\Data\Collection
92
- *
93
- * @throws \Hybridauth\Exception\HttpClientFailureException
94
- * @throws \Hybridauth\Exception\HttpRequestFailedException
95
- * @throws \Hybridauth\Exception\InvalidAccessTokenException
96
- * @throws \Hybridauth\Exception\UnexpectedApiResponseException
97
- */
98
- public function getUserMedia($limit = 12, $pageId = null, array $fields = null)
99
- {
100
- if (empty($fields)) {
101
- $fields = [
102
- 'id',
103
- 'caption',
104
- 'media_type',
105
- 'media_url',
106
- 'thumbnail_url',
107
- 'permalink',
108
- 'timestamp',
109
- 'username',
110
- ];
111
- }
112
-
113
- $params = [
114
- 'fields' => implode(',', $fields),
115
- 'limit' => $limit,
116
- ];
117
- if ($pageId !== null) {
118
- $params['after'] = $pageId;
119
- }
120
-
121
- $response = $this->apiRequest('me/media', 'GET', $params);
122
-
123
- $data = new Collection($response);
124
- if (!$data->exists('data')) {
125
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
126
- }
127
-
128
- return $data;
129
- }
130
-
131
- /**
132
- * Fetches a single user's media.
133
- *
134
- * @param string $mediaId Media ID.
135
- * @param array|null $fields Fields to fetch per media.
136
- *
137
- * @return \Hybridauth\Data\Collection
138
- *
139
- * @throws \Hybridauth\Exception\HttpClientFailureException
140
- * @throws \Hybridauth\Exception\HttpRequestFailedException
141
- * @throws \Hybridauth\Exception\InvalidAccessTokenException
142
- * @throws \Hybridauth\Exception\UnexpectedApiResponseException
143
- */
144
- public function getMedia($mediaId, array $fields = null)
145
- {
146
- if (empty($fields)) {
147
- $fields = [
148
- 'id',
149
- 'caption',
150
- 'media_type',
151
- 'media_url',
152
- 'thumbnail_url',
153
- 'permalink',
154
- 'timestamp',
155
- 'username',
156
- ];
157
- }
158
-
159
- $response = $this->apiRequest($mediaId, 'GET', [
160
- 'fields' => implode(',', $fields),
161
- ]);
162
-
163
- $data = new Collection($response);
164
- if (!$data->exists('id')) {
165
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
166
- }
167
-
168
- return $data;
169
- }
170
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2020 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Data\Collection;
12
+ use Hybridauth\Exception\UnexpectedApiResponseException;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Instagram OAuth2 provider adapter via Instagram Basic Display API.
17
+ */
18
+ class Instagram extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'user_profile,user_media';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://graph.instagram.com';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://api.instagram.com/oauth/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://api.instagram.com/oauth/access_token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://developers.facebook.com/docs/instagram-basic-display-api';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function initialize()
49
+ {
50
+ parent::initialize();
51
+
52
+ // The Instagram API requires an access_token from authenticated users
53
+ // for each endpoint.
54
+ $accessToken = $this->getStoredData($this->accessTokenName);
55
+ $this->apiRequestParameters[$this->accessTokenName] = $accessToken;
56
+ }
57
+
58
+ /**
59
+ * {@inheritdoc}
60
+ */
61
+ public function getUserProfile()
62
+ {
63
+ $response = $this->apiRequest('me', 'GET', [
64
+ 'fields' => 'id,username,account_type,media_count',
65
+ ]);
66
+
67
+ $data = new Collection($response);
68
+ if (!$data->exists('id')) {
69
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
70
+ }
71
+
72
+ $userProfile = new User\Profile();
73
+ $userProfile->identifier = $data->get('id');
74
+ $userProfile->displayName = $data->get('username');
75
+ $userProfile->profileURL = "https://instagram.com/{$userProfile->displayName}";
76
+ $userProfile->data = [
77
+ 'account_type' => $data->get('account_type'),
78
+ 'media_count' => $data->get('media_count'),
79
+ ];
80
+
81
+ return $userProfile;
82
+ }
83
+
84
+ /**
85
+ * Fetch user medias.
86
+ *
87
+ * @param int $limit Number of elements per page.
88
+ * @param string $pageId Current pager ID.
89
+ * @param array|null $fields Fields to fetch per media.
90
+ *
91
+ * @return \Hybridauth\Data\Collection
92
+ *
93
+ * @throws \Hybridauth\Exception\HttpClientFailureException
94
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
95
+ * @throws \Hybridauth\Exception\InvalidAccessTokenException
96
+ * @throws \Hybridauth\Exception\UnexpectedApiResponseException
97
+ */
98
+ public function getUserMedia($limit = 12, $pageId = null, array $fields = null)
99
+ {
100
+ if (empty($fields)) {
101
+ $fields = [
102
+ 'id',
103
+ 'caption',
104
+ 'media_type',
105
+ 'media_url',
106
+ 'thumbnail_url',
107
+ 'permalink',
108
+ 'timestamp',
109
+ 'username',
110
+ ];
111
+ }
112
+
113
+ $params = [
114
+ 'fields' => implode(',', $fields),
115
+ 'limit' => $limit,
116
+ ];
117
+ if ($pageId !== null) {
118
+ $params['after'] = $pageId;
119
+ }
120
+
121
+ $response = $this->apiRequest('me/media', 'GET', $params);
122
+
123
+ $data = new Collection($response);
124
+ if (!$data->exists('data')) {
125
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
126
+ }
127
+
128
+ return $data;
129
+ }
130
+
131
+ /**
132
+ * Fetches a single user's media.
133
+ *
134
+ * @param string $mediaId Media ID.
135
+ * @param array|null $fields Fields to fetch per media.
136
+ *
137
+ * @return \Hybridauth\Data\Collection
138
+ *
139
+ * @throws \Hybridauth\Exception\HttpClientFailureException
140
+ * @throws \Hybridauth\Exception\HttpRequestFailedException
141
+ * @throws \Hybridauth\Exception\InvalidAccessTokenException
142
+ * @throws \Hybridauth\Exception\UnexpectedApiResponseException
143
+ */
144
+ public function getMedia($mediaId, array $fields = null)
145
+ {
146
+ if (empty($fields)) {
147
+ $fields = [
148
+ 'id',
149
+ 'caption',
150
+ 'media_type',
151
+ 'media_url',
152
+ 'thumbnail_url',
153
+ 'permalink',
154
+ 'timestamp',
155
+ 'username',
156
+ ];
157
+ }
158
+
159
+ $response = $this->apiRequest($mediaId, 'GET', [
160
+ 'fields' => implode(',', $fields),
161
+ ]);
162
+
163
+ $data = new Collection($response);
164
+ if (!$data->exists('id')) {
165
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
166
+ }
167
+
168
+ return $data;
169
+ }
170
+ }
hybridauth/library/src/Provider/LinkedIn.php CHANGED
@@ -1,200 +1,200 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Data;
12
- use Hybridauth\Exception\UnexpectedApiResponseException;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * LinkedIn OAuth2 provider adapter.
17
- */
18
- class LinkedIn extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'r_liteprofile r_emailaddress w_member_social';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://api.linkedin.com/v2/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://www.linkedin.com/oauth/v2/authorization';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://www.linkedin.com/oauth/v2/accessToken';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://docs.microsoft.com/en-us/linkedin/shared/authentication/authentication';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $fields = [
51
- 'id',
52
- 'firstName',
53
- 'lastName',
54
- 'profilePicture(displayImage~:playableStreams)',
55
- ];
56
-
57
-
58
- $response = $this->apiRequest('me', 'GET', [ 'projection' => '(' . implode(',', $fields) . ')' ]);
59
- $data = new Data\Collection($response);
60
-
61
- if (!$data->exists('id')) {
62
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
63
- }
64
-
65
- $userProfile = new User\Profile();
66
-
67
- // Handle localized names.
68
- $userProfile->firstName = $data
69
- ->filter('firstName')
70
- ->filter('localized')
71
- ->get($this->getPreferredLocale($data, 'firstName'));
72
-
73
- $userProfile->lastName = $data
74
- ->filter('lastName')
75
- ->filter('localized')
76
- ->get($this->getPreferredLocale($data, 'lastName'));
77
-
78
- $userProfile->identifier = $data->get('id');
79
- $userProfile->email = $this->getUserEmail();
80
- $userProfile->emailVerified = $userProfile->email;
81
- $userProfile->displayName = trim($userProfile->firstName . ' ' . $userProfile->lastName);
82
-
83
- $photo_elements = $data
84
- ->filter('profilePicture')
85
- ->filter('displayImage~')
86
- ->get('elements');
87
- $userProfile->photoURL = $this->getUserPhotoUrl($photo_elements);
88
-
89
- return $userProfile;
90
- }
91
-
92
- /**
93
- * Returns a user photo.
94
- *
95
- * @param array $elements
96
- * List of file identifiers related to this artifact.
97
- *
98
- * @return string
99
- * The user photo URL.
100
- *
101
- * @see https://docs.microsoft.com/en-us/linkedin/shared/references/v2/profile/profile-picture
102
- */
103
- public function getUserPhotoUrl($elements)
104
- {
105
- if (is_array($elements)) {
106
- // Get the largest picture from the list which is the last one.
107
- $element = end($elements);
108
- if (!empty($element->identifiers)) {
109
- return reset($element->identifiers)->identifier;
110
- }
111
- }
112
-
113
- return null;
114
- }
115
-
116
- /**
117
- * Returns an email address of user.
118
- *
119
- * @return string
120
- * The user email address.
121
- *
122
- * @throws \Exception
123
- */
124
- public function getUserEmail()
125
- {
126
- $response = $this->apiRequest('emailAddress', 'GET', [
127
- 'q' => 'members',
128
- 'projection' => '(elements*(handle~))',
129
- ]);
130
- $data = new Data\Collection($response);
131
-
132
- foreach ($data->filter('elements')->toArray() as $element) {
133
- $item = new Data\Collection($element);
134
-
135
- if ($email = $item->filter('handle~')->get('emailAddress')) {
136
- return $email;
137
- }
138
- }
139
-
140
- return null;
141
- }
142
-
143
- /**
144
- * {@inheritdoc}
145
- *
146
- * @see https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/share-on-linkedin
147
- */
148
- public function setUserStatus($status, $userID = null)
149
- {
150
- if (is_string($status)) {
151
- $status = [
152
- 'author' => 'urn:li:person:' . $userID,
153
- 'lifecycleState' => 'PUBLISHED',
154
- 'specificContent' => [
155
- 'com.linkedin.ugc.ShareContent' => [
156
- 'shareCommentary' => [
157
- 'text' => $status,
158
- ],
159
- 'shareMediaCategory' => 'NONE',
160
- ],
161
- ],
162
- 'visibility' => [
163
- 'com.linkedin.ugc.MemberNetworkVisibility' => 'PUBLIC',
164
- ],
165
- ];
166
- }
167
-
168
-
169
- $headers = [
170
- 'Content-Type' => 'application/json',
171
- 'x-li-format' => 'json',
172
- 'X-Restli-Protocol-Version' => '2.0.0',
173
- ];
174
-
175
- $response = $this->apiRequest("ugcPosts", 'POST', $status, $headers);
176
-
177
- return $response;
178
- }
179
-
180
- /**
181
- * Returns a preferred locale for given field.
182
- *
183
- * @param \Hybridauth\Data\Collection $data
184
- * A data to check.
185
- * @param string $field_name
186
- * A field name to perform.
187
- *
188
- * @return string
189
- * A field locale.
190
- */
191
- protected function getPreferredLocale($data, $field_name)
192
- {
193
- $locale = $data->filter($field_name)->filter('preferredLocale');
194
- if ($locale) {
195
- return $locale->get('language') . '_' . $locale->get('country');
196
- }
197
-
198
- return 'en_US';
199
- }
200
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Data;
12
+ use Hybridauth\Exception\UnexpectedApiResponseException;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * LinkedIn OAuth2 provider adapter.
17
+ */
18
+ class LinkedIn extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'r_liteprofile r_emailaddress w_member_social';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://api.linkedin.com/v2/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://www.linkedin.com/oauth/v2/authorization';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://www.linkedin.com/oauth/v2/accessToken';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://docs.microsoft.com/en-us/linkedin/shared/authentication/authentication';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $fields = [
51
+ 'id',
52
+ 'firstName',
53
+ 'lastName',
54
+ 'profilePicture(displayImage~:playableStreams)',
55
+ ];
56
+
57
+
58
+ $response = $this->apiRequest('me', 'GET', [ 'projection' => '(' . implode(',', $fields) . ')' ]);
59
+ $data = new Data\Collection($response);
60
+
61
+ if (!$data->exists('id')) {
62
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
63
+ }
64
+
65
+ $userProfile = new User\Profile();
66
+
67
+ // Handle localized names.
68
+ $userProfile->firstName = $data
69
+ ->filter('firstName')
70
+ ->filter('localized')
71
+ ->get($this->getPreferredLocale($data, 'firstName'));
72
+
73
+ $userProfile->lastName = $data
74
+ ->filter('lastName')
75
+ ->filter('localized')
76
+ ->get($this->getPreferredLocale($data, 'lastName'));
77
+
78
+ $userProfile->identifier = $data->get('id');
79
+ $userProfile->email = $this->getUserEmail();
80
+ $userProfile->emailVerified = $userProfile->email;
81
+ $userProfile->displayName = trim($userProfile->firstName . ' ' . $userProfile->lastName);
82
+
83
+ $photo_elements = $data
84
+ ->filter('profilePicture')
85
+ ->filter('displayImage~')
86
+ ->get('elements');
87
+ $userProfile->photoURL = $this->getUserPhotoUrl($photo_elements);
88
+
89
+ return $userProfile;
90
+ }
91
+
92
+ /**
93
+ * Returns a user photo.
94
+ *
95
+ * @param array $elements
96
+ * List of file identifiers related to this artifact.
97
+ *
98
+ * @return string
99
+ * The user photo URL.
100
+ *
101
+ * @see https://docs.microsoft.com/en-us/linkedin/shared/references/v2/profile/profile-picture
102
+ */
103
+ public function getUserPhotoUrl($elements)
104
+ {
105
+ if (is_array($elements)) {
106
+ // Get the largest picture from the list which is the last one.
107
+ $element = end($elements);
108
+ if (!empty($element->identifiers)) {
109
+ return reset($element->identifiers)->identifier;
110
+ }
111
+ }
112
+
113
+ return null;
114
+ }
115
+
116
+ /**
117
+ * Returns an email address of user.
118
+ *
119
+ * @return string
120
+ * The user email address.
121
+ *
122
+ * @throws \Exception
123
+ */
124
+ public function getUserEmail()
125
+ {
126
+ $response = $this->apiRequest('emailAddress', 'GET', [
127
+ 'q' => 'members',
128
+ 'projection' => '(elements*(handle~))',
129
+ ]);
130
+ $data = new Data\Collection($response);
131
+
132
+ foreach ($data->filter('elements')->toArray() as $element) {
133
+ $item = new Data\Collection($element);
134
+
135
+ if ($email = $item->filter('handle~')->get('emailAddress')) {
136
+ return $email;
137
+ }
138
+ }
139
+
140
+ return null;
141
+ }
142
+
143
+ /**
144
+ * {@inheritdoc}
145
+ *
146
+ * @see https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/share-on-linkedin
147
+ */
148
+ public function setUserStatus($status, $userID = null)
149
+ {
150
+ if (is_string($status)) {
151
+ $status = [
152
+ 'author' => 'urn:li:person:' . $userID,
153
+ 'lifecycleState' => 'PUBLISHED',
154
+ 'specificContent' => [
155
+ 'com.linkedin.ugc.ShareContent' => [
156
+ 'shareCommentary' => [
157
+ 'text' => $status,
158
+ ],
159
+ 'shareMediaCategory' => 'NONE',
160
+ ],
161
+ ],
162
+ 'visibility' => [
163
+ 'com.linkedin.ugc.MemberNetworkVisibility' => 'PUBLIC',
164
+ ],
165
+ ];
166
+ }
167
+
168
+
169
+ $headers = [
170
+ 'Content-Type' => 'application/json',
171
+ 'x-li-format' => 'json',
172
+ 'X-Restli-Protocol-Version' => '2.0.0',
173
+ ];
174
+
175
+ $response = $this->apiRequest("ugcPosts", 'POST', $status, $headers);
176
+
177
+ return $response;
178
+ }
179
+
180
+ /**
181
+ * Returns a preferred locale for given field.
182
+ *
183
+ * @param \Hybridauth\Data\Collection $data
184
+ * A data to check.
185
+ * @param string $field_name
186
+ * A field name to perform.
187
+ *
188
+ * @return string
189
+ * A field locale.
190
+ */
191
+ protected function getPreferredLocale($data, $field_name)
192
+ {
193
+ $locale = $data->filter($field_name)->filter('preferredLocale');
194
+ if ($locale) {
195
+ return $locale->get('language') . '_' . $locale->get('country');
196
+ }
197
+
198
+ return 'en_US';
199
+ }
200
+ }
hybridauth/library/src/Provider/Mailru.php CHANGED
@@ -1,83 +1,83 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data\Collection;
13
- use Hybridauth\User\Profile;
14
-
15
- /**
16
- * Mailru OAuth2 provider adapter.
17
- */
18
- class Mailru extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $apiBaseUrl = 'http://www.appsmail.ru/platform/api';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $authorizeUrl = 'https://connect.mail.ru/oauth/authorize';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $accessTokenUrl = 'https://connect.mail.ru/oauth/token';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $apiDocumentation = ''; // Not available
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- public function getUserProfile()
44
- {
45
- $params = [
46
- 'app_id' => $this->clientId,
47
- 'method' => 'users.getInfo',
48
- 'secure' => 1,
49
- 'session_key' => $this->getStoredData('access_token'),
50
- ];
51
- $sign = md5(http_build_query($params, null, '') . $this->clientSecret);
52
-
53
- $param = [
54
- 'app_id' => $this->clientId,
55
- 'method' => 'users.getInfo',
56
- 'secure' => 1,
57
- 'session_key' => $this->getStoredData('access_token'),
58
- 'sig' => $sign,
59
- ];
60
-
61
- $response = $this->apiRequest('', 'GET', $param);
62
-
63
- $data = new Collection($response[0]);
64
-
65
- if (!$data->exists('uid')) {
66
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
67
- }
68
-
69
- $userProfile = new Profile();
70
-
71
- $userProfile->identifier = $data->get('uid');
72
- $userProfile->email = $data->get('email');
73
- $userProfile->firstName = $data->get('first_name');
74
- $userProfile->lastName = $data->get('last_name');
75
- $userProfile->displayName = $data->get('nick');
76
- $userProfile->photoURL = $data->get('pic');
77
- $userProfile->profileURL = $data->get('link');
78
- $userProfile->gender = $data->get('sex');
79
- $userProfile->age = $data->get('age');
80
-
81
- return $userProfile;
82
- }
83
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data\Collection;
13
+ use Hybridauth\User\Profile;
14
+
15
+ /**
16
+ * Mailru OAuth2 provider adapter.
17
+ */
18
+ class Mailru extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $apiBaseUrl = 'http://www.appsmail.ru/platform/api';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $authorizeUrl = 'https://connect.mail.ru/oauth/authorize';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $accessTokenUrl = 'https://connect.mail.ru/oauth/token';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $apiDocumentation = ''; // Not available
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ public function getUserProfile()
44
+ {
45
+ $params = [
46
+ 'app_id' => $this->clientId,
47
+ 'method' => 'users.getInfo',
48
+ 'secure' => 1,
49
+ 'session_key' => $this->getStoredData('access_token'),
50
+ ];
51
+ $sign = md5(http_build_query($params, null, '') . $this->clientSecret);
52
+
53
+ $param = [
54
+ 'app_id' => $this->clientId,
55
+ 'method' => 'users.getInfo',
56
+ 'secure' => 1,
57
+ 'session_key' => $this->getStoredData('access_token'),
58
+ 'sig' => $sign,
59
+ ];
60
+
61
+ $response = $this->apiRequest('', 'GET', $param);
62
+
63
+ $data = new Collection($response[0]);
64
+
65
+ if (!$data->exists('uid')) {
66
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
67
+ }
68
+
69
+ $userProfile = new Profile();
70
+
71
+ $userProfile->identifier = $data->get('uid');
72
+ $userProfile->email = $data->get('email');
73
+ $userProfile->firstName = $data->get('first_name');
74
+ $userProfile->lastName = $data->get('last_name');
75
+ $userProfile->displayName = $data->get('nick');
76
+ $userProfile->photoURL = $data->get('pic');
77
+ $userProfile->profileURL = $data->get('link');
78
+ $userProfile->gender = $data->get('sex');
79
+ $userProfile->age = $data->get('age');
80
+
81
+ return $userProfile;
82
+ }
83
+ }
hybridauth/library/src/Provider/MicrosoftGraph.php CHANGED
@@ -1,169 +1,169 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Data;
12
- use Hybridauth\Exception\UnexpectedApiResponseException;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Microsoft Graph OAuth2 provider adapter.
17
- *
18
- * Create an "Azure Active Directory" resource at https://portal.azure.com/
19
- * (not from the Visual Studio site).
20
- *
21
- * The "Supported account types" choice maps to the 'tenant' setting, see "Authority" @
22
- * https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-client-application-configuration
23
- *
24
- * Example:
25
- *
26
- * $config = [
27
- * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
28
- * 'keys' => [ 'id' => '', 'secret' => '' ],
29
- * 'tenant' => 'user',
30
- * // ^ May be 'common', 'organizations' or 'consumers' or a specific tenant ID or a domain
31
- * ];
32
- *
33
- * $adapter = new Hybridauth\Provider\MicrosoftGraph( $config );
34
- *
35
- * try {
36
- * $adapter->authenticate();
37
- *
38
- * $userProfile = $adapter->getUserProfile();
39
- * $tokens = $adapter->getAccessToken();
40
- * }
41
- * catch( Exception $e ){
42
- * echo $e->getMessage() ;
43
- * }
44
- */
45
- class MicrosoftGraph extends OAuth2
46
- {
47
- /**
48
- * {@inheritdoc}
49
- */
50
- protected $scope = 'openid user.read contacts.read';
51
-
52
- /**
53
- * {@inheritdoc}
54
- */
55
- protected $apiBaseUrl = 'https://graph.microsoft.com/v1.0/';
56
-
57
- /**
58
- * {@inheritdoc}
59
- */
60
- protected $authorizeUrl = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize';
61
-
62
- /**
63
- * {@inheritdoc}
64
- */
65
- protected $accessTokenUrl = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
66
-
67
- /**
68
- * {@inheritdoc}
69
- */
70
- protected $apiDocumentation = 'https://developer.microsoft.com/en-us/graph/docs/concepts/php';
71
-
72
- /**
73
- * {@inheritdoc}
74
- */
75
- protected function initialize()
76
- {
77
- parent::initialize();
78
-
79
- $tenant = $this->config->get('tenant');
80
- if (!empty($tenant)) {
81
- $adjustedEndpoints = [
82
- 'authorize_url' => str_replace('/common/', '/'. $tenant .'/', $this->authorizeUrl),
83
- 'access_token_url' => str_replace('/common/', '/'. $tenant .'/', $this->accessTokenUrl),
84
- ];
85
-
86
- $this->setApiEndpoints($adjustedEndpoints);
87
- }
88
- }
89
-
90
- /**
91
- * {@inheritdoc}
92
- */
93
- public function getUserProfile()
94
- {
95
- $response = $this->apiRequest('me');
96
-
97
- $data = new Data\Collection($response);
98
-
99
- if (!$data->exists('id')) {
100
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
101
- }
102
-
103
- $userProfile = new User\Profile();
104
-
105
- $userProfile->identifier = $data->get('id');
106
- $userProfile->displayName = $data->get('displayName');
107
- $userProfile->firstName = $data->get('givenName');
108
- $userProfile->lastName = $data->get('surname');
109
- $userProfile->language = $data->get('preferredLanguage');
110
-
111
- $userProfile->phone = $data->get('mobilePhone');
112
- if (empty($userProfile->phone)) {
113
- $businessPhones = $data->get('businessPhones');
114
- if (isset($businessPhones[0])) {
115
- $userProfile->phone = $businessPhones[0];
116
- }
117
- }
118
-
119
- $userProfile->email = $data->get('mail');
120
- if (empty($userProfile->email)) {
121
- $email = $data->get('userPrincipalName');
122
- if (strpos($email, '@') !== false) {
123
- $userProfile->email = $email;
124
- }
125
- }
126
-
127
- return $userProfile;
128
- }
129
-
130
- /**
131
- * {@inheritdoc}
132
- */
133
- public function getUserContacts()
134
- {
135
- $apiUrl = 'me/contacts?$top=50';
136
- $contacts = [];
137
-
138
- do {
139
- $response = $this->apiRequest($apiUrl);
140
- $data = new Data\Collection($response);
141
- if (!$data->exists('value')) {
142
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
143
- }
144
- foreach ($data->filter('value')->toArray() as $entry) {
145
- $entry = new Data\Collection($entry);
146
- $userContact = new User\Contact();
147
- $userContact->identifier = $entry->get('id');
148
- $userContact->displayName = $entry->get('displayName');
149
- if (!empty($entry->get('emailAddresses'))) {
150
- $userContact->email = $entry->get('emailAddresses')[0]->address;
151
- }
152
- // only add to collection if we have usefull data
153
- if (!empty($userContact->displayName) || !empty($userContact->email)) {
154
- $contacts[] = $userContact;
155
- }
156
- }
157
-
158
- if ($data->exists('@odata.nextLink')) {
159
- $apiUrl = $data->get('@odata.nextLink');
160
-
161
- $pagedList = true;
162
- } else {
163
- $pagedList = false;
164
- }
165
- } while ($pagedList);
166
-
167
- return $contacts;
168
- }
169
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Data;
12
+ use Hybridauth\Exception\UnexpectedApiResponseException;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Microsoft Graph OAuth2 provider adapter.
17
+ *
18
+ * Create an "Azure Active Directory" resource at https://portal.azure.com/
19
+ * (not from the Visual Studio site).
20
+ *
21
+ * The "Supported account types" choice maps to the 'tenant' setting, see "Authority" @
22
+ * https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-client-application-configuration
23
+ *
24
+ * Example:
25
+ *
26
+ * $config = [
27
+ * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
28
+ * 'keys' => [ 'id' => '', 'secret' => '' ],
29
+ * 'tenant' => 'user',
30
+ * // ^ May be 'common', 'organizations' or 'consumers' or a specific tenant ID or a domain
31
+ * ];
32
+ *
33
+ * $adapter = new Hybridauth\Provider\MicrosoftGraph( $config );
34
+ *
35
+ * try {
36
+ * $adapter->authenticate();
37
+ *
38
+ * $userProfile = $adapter->getUserProfile();
39
+ * $tokens = $adapter->getAccessToken();
40
+ * }
41
+ * catch( Exception $e ){
42
+ * echo $e->getMessage() ;
43
+ * }
44
+ */
45
+ class MicrosoftGraph extends OAuth2
46
+ {
47
+ /**
48
+ * {@inheritdoc}
49
+ */
50
+ protected $scope = 'openid user.read contacts.read';
51
+
52
+ /**
53
+ * {@inheritdoc}
54
+ */
55
+ protected $apiBaseUrl = 'https://graph.microsoft.com/v1.0/';
56
+
57
+ /**
58
+ * {@inheritdoc}
59
+ */
60
+ protected $authorizeUrl = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize';
61
+
62
+ /**
63
+ * {@inheritdoc}
64
+ */
65
+ protected $accessTokenUrl = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
66
+
67
+ /**
68
+ * {@inheritdoc}
69
+ */
70
+ protected $apiDocumentation = 'https://developer.microsoft.com/en-us/graph/docs/concepts/php';
71
+
72
+ /**
73
+ * {@inheritdoc}
74
+ */
75
+ protected function initialize()
76
+ {
77
+ parent::initialize();
78
+
79
+ $tenant = $this->config->get('tenant');
80
+ if (!empty($tenant)) {
81
+ $adjustedEndpoints = [
82
+ 'authorize_url' => str_replace('/common/', '/'. $tenant .'/', $this->authorizeUrl),
83
+ 'access_token_url' => str_replace('/common/', '/'. $tenant .'/', $this->accessTokenUrl),
84
+ ];
85
+
86
+ $this->setApiEndpoints($adjustedEndpoints);
87
+ }
88
+ }
89
+
90
+ /**
91
+ * {@inheritdoc}
92
+ */
93
+ public function getUserProfile()
94
+ {
95
+ $response = $this->apiRequest('me');
96
+
97
+ $data = new Data\Collection($response);
98
+
99
+ if (!$data->exists('id')) {
100
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
101
+ }
102
+
103
+ $userProfile = new User\Profile();
104
+
105
+ $userProfile->identifier = $data->get('id');
106
+ $userProfile->displayName = $data->get('displayName');
107
+ $userProfile->firstName = $data->get('givenName');
108
+ $userProfile->lastName = $data->get('surname');
109
+ $userProfile->language = $data->get('preferredLanguage');
110
+
111
+ $userProfile->phone = $data->get('mobilePhone');
112
+ if (empty($userProfile->phone)) {
113
+ $businessPhones = $data->get('businessPhones');
114
+ if (isset($businessPhones[0])) {
115
+ $userProfile->phone = $businessPhones[0];
116
+ }
117
+ }
118
+
119
+ $userProfile->email = $data->get('mail');
120
+ if (empty($userProfile->email)) {
121
+ $email = $data->get('userPrincipalName');
122
+ if (strpos($email, '@') !== false) {
123
+ $userProfile->email = $email;
124
+ }
125
+ }
126
+
127
+ return $userProfile;
128
+ }
129
+
130
+ /**
131
+ * {@inheritdoc}
132
+ */
133
+ public function getUserContacts()
134
+ {
135
+ $apiUrl = 'me/contacts?$top=50';
136
+ $contacts = [];
137
+
138
+ do {
139
+ $response = $this->apiRequest($apiUrl);
140
+ $data = new Data\Collection($response);
141
+ if (!$data->exists('value')) {
142
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
143
+ }
144
+ foreach ($data->filter('value')->toArray() as $entry) {
145
+ $entry = new Data\Collection($entry);
146
+ $userContact = new User\Contact();
147
+ $userContact->identifier = $entry->get('id');
148
+ $userContact->displayName = $entry->get('displayName');
149
+ if (!empty($entry->get('emailAddresses'))) {
150
+ $userContact->email = $entry->get('emailAddresses')[0]->address;
151
+ }
152
+ // only add to collection if we have usefull data
153
+ if (!empty($userContact->displayName) || !empty($userContact->email)) {
154
+ $contacts[] = $userContact;
155
+ }
156
+ }
157
+
158
+ if ($data->exists('@odata.nextLink')) {
159
+ $apiUrl = $data->get('@odata.nextLink');
160
+
161
+ $pagedList = true;
162
+ } else {
163
+ $pagedList = false;
164
+ }
165
+ } while ($pagedList);
166
+
167
+ return $contacts;
168
+ }
169
+ }
hybridauth/library/src/Provider/ORCID.php CHANGED
@@ -1,242 +1,242 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * ORCID OAuth2 provider adapter.
17
- */
18
- class ORCID extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = '/authenticate';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://pub.orcid.org/v2.1/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://orcid.org/oauth/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://orcid.org/oauth/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://members.orcid.org/api/';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected function validateAccessTokenExchange($response)
49
- {
50
- $data = parent::validateAccessTokenExchange($response);
51
- $this->storeData('orcid', $data->get('orcid'));
52
- return $data;
53
- }
54
-
55
- /**
56
- * {@inheritdoc}
57
- */
58
- public function getUserProfile()
59
- {
60
- $response = $this->apiRequest($this->getStoredData('orcid') . '/record');
61
- $data = new Data\Collection($response['record']);
62
-
63
- if (!$data->exists('orcid-identifier')) {
64
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
65
- }
66
-
67
- $profile = new User\Profile();
68
-
69
- $profile = $this->getDetails($profile, $data);
70
- $profile = $this->getBiography($profile, $data);
71
- $profile = $this->getWebsite($profile, $data);
72
- $profile = $this->getName($profile, $data);
73
- $profile = $this->getEmail($profile, $data);
74
- $profile = $this->getLanguage($profile, $data);
75
- $profile = $this->getAddress($profile, $data);
76
-
77
- return $profile;
78
- }
79
-
80
- /**
81
- * Get profile details.
82
- *
83
- * @param User\Profile $profile
84
- * @param Data\Collection $data
85
- *
86
- * @return User\Profile
87
- */
88
- protected function getDetails(User\Profile $profile, Data\Collection $data)
89
- {
90
- $data = new Data\Collection($data->get('orcid-identifier'));
91
-
92
- $profile->identifier = $data->get('path');
93
- $profile->profileURL = $data->get('uri');
94
-
95
- return $profile;
96
- }
97
-
98
- /**
99
- * Get profile biography.
100
- *
101
- * @param User\Profile $profile
102
- * @param Data\Collection $data
103
- *
104
- * @return User\Profile
105
- */
106
- protected function getBiography(User\Profile $profile, Data\Collection $data)
107
- {
108
- $data = new Data\Collection($data->get('person'));
109
- $data = new Data\Collection($data->get('biography'));
110
-
111
- $profile->description = $data->get('content');
112
-
113
- return $profile;
114
- }
115
-
116
- /**
117
- * Get profile website.
118
- *
119
- * @param User\Profile $profile
120
- * @param Data\Collection $data
121
- *
122
- * @return User\Profile
123
- */
124
- protected function getWebsite(User\Profile $profile, Data\Collection $data)
125
- {
126
- $data = new Data\Collection($data->get('person'));
127
- $data = new Data\Collection($data->get('researcher-urls'));
128
- $data = new Data\Collection($data->get('researcher-url'));
129
-
130
- if ($data->exists(0)) {
131
- $data = new Data\Collection($data->get(0));
132
- }
133
-
134
- $profile->webSiteURL = $data->get('url');
135
-
136
- return $profile;
137
- }
138
-
139
- /**
140
- * Get profile name.
141
- *
142
- * @param User\Profile $profile
143
- * @param Data\Collection $data
144
- *
145
- * @return User\Profile
146
- */
147
- protected function getName(User\Profile $profile, Data\Collection $data)
148
- {
149
- $data = new Data\Collection($data->get('person'));
150
- $data = new Data\Collection($data->get('name'));
151
-
152
- if ($data->exists('credit-name')) {
153
- $profile->displayName = $data->get('credit-name');
154
- } else {
155
- $profile->displayName = $data->get('given-names') . ' ' . $data->get('family-name');
156
- }
157
-
158
- $profile->firstName = $data->get('given-names');
159
- $profile->lastName = $data->get('family-name');
160
-
161
- return $profile;
162
- }
163
-
164
- /**
165
- * Get profile email.
166
- *
167
- * @param User\Profile $profile
168
- * @param Data\Collection $data
169
- *
170
- * @return User\Profile
171
- */
172
- protected function getEmail(User\Profile $profile, Data\Collection $data)
173
- {
174
- $data = new Data\Collection($data->get('person'));
175
- $data = new Data\Collection($data->get('emails'));
176
- $data = new Data\Collection($data->get('email'));
177
-
178
- if (!$data->exists(0)) {
179
- $email = $data;
180
- } else {
181
- $email = new Data\Collection($data->get(0));
182
-
183
- $i = 1;
184
- while ($email->get('@attributes')['primary'] == 'false') {
185
- $email = new Data\Collection($data->get($i));
186
- $i++;
187
- }
188
- }
189
-
190
- if ($email->get('@attributes')['primary'] == 'false') {
191
- return $profile;
192
- }
193
-
194
- $profile->email = $email->get('email');
195
-
196
- if ($email->get('@attributes')['verified'] == 'true') {
197
- $profile->emailVerified = $email->get('email');
198
- }
199
-
200
- return $profile;
201
- }
202
-
203
- /**
204
- * Get profile language.
205
- *
206
- * @param User\Profile $profile
207
- * @param Data\Collection $data
208
- *
209
- * @return User\Profile
210
- */
211
- protected function getLanguage(User\Profile $profile, Data\Collection $data)
212
- {
213
- $data = new Data\Collection($data->get('preferences'));
214
-
215
- $profile->language = $data->get('locale');
216
-
217
- return $profile;
218
- }
219
-
220
- /**
221
- * Get profile address.
222
- *
223
- * @param User\Profile $profile
224
- * @param Data\Collection $data
225
- *
226
- * @return User\Profile
227
- */
228
- protected function getAddress(User\Profile $profile, Data\Collection $data)
229
- {
230
- $data = new Data\Collection($data->get('person'));
231
- $data = new Data\Collection($data->get('addresses'));
232
- $data = new Data\Collection($data->get('address'));
233
-
234
- if ($data->exists(0)) {
235
- $data = new Data\Collection($data->get(0));
236
- }
237
-
238
- $profile->country = $data->get('country');
239
-
240
- return $profile;
241
- }
242
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * ORCID OAuth2 provider adapter.
17
+ */
18
+ class ORCID extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = '/authenticate';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://pub.orcid.org/v2.1/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://orcid.org/oauth/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://orcid.org/oauth/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://members.orcid.org/api/';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function validateAccessTokenExchange($response)
49
+ {
50
+ $data = parent::validateAccessTokenExchange($response);
51
+ $this->storeData('orcid', $data->get('orcid'));
52
+ return $data;
53
+ }
54
+
55
+ /**
56
+ * {@inheritdoc}
57
+ */
58
+ public function getUserProfile()
59
+ {
60
+ $response = $this->apiRequest($this->getStoredData('orcid') . '/record');
61
+ $data = new Data\Collection($response['record']);
62
+
63
+ if (!$data->exists('orcid-identifier')) {
64
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
65
+ }
66
+
67
+ $profile = new User\Profile();
68
+
69
+ $profile = $this->getDetails($profile, $data);
70
+ $profile = $this->getBiography($profile, $data);
71
+ $profile = $this->getWebsite($profile, $data);
72
+ $profile = $this->getName($profile, $data);
73
+ $profile = $this->getEmail($profile, $data);
74
+ $profile = $this->getLanguage($profile, $data);
75
+ $profile = $this->getAddress($profile, $data);
76
+
77
+ return $profile;
78
+ }
79
+
80
+ /**
81
+ * Get profile details.
82
+ *
83
+ * @param User\Profile $profile
84
+ * @param Data\Collection $data
85
+ *
86
+ * @return User\Profile
87
+ */
88
+ protected function getDetails(User\Profile $profile, Data\Collection $data)
89
+ {
90
+ $data = new Data\Collection($data->get('orcid-identifier'));
91
+
92
+ $profile->identifier = $data->get('path');
93
+ $profile->profileURL = $data->get('uri');
94
+
95
+ return $profile;
96
+ }
97
+
98
+ /**
99
+ * Get profile biography.
100
+ *
101
+ * @param User\Profile $profile
102
+ * @param Data\Collection $data
103
+ *
104
+ * @return User\Profile
105
+ */
106
+ protected function getBiography(User\Profile $profile, Data\Collection $data)
107
+ {
108
+ $data = new Data\Collection($data->get('person'));
109
+ $data = new Data\Collection($data->get('biography'));
110
+
111
+ $profile->description = $data->get('content');
112
+
113
+ return $profile;
114
+ }
115
+
116
+ /**
117
+ * Get profile website.
118
+ *
119
+ * @param User\Profile $profile
120
+ * @param Data\Collection $data
121
+ *
122
+ * @return User\Profile
123
+ */
124
+ protected function getWebsite(User\Profile $profile, Data\Collection $data)
125
+ {
126
+ $data = new Data\Collection($data->get('person'));
127
+ $data = new Data\Collection($data->get('researcher-urls'));
128
+ $data = new Data\Collection($data->get('researcher-url'));
129
+
130
+ if ($data->exists(0)) {
131
+ $data = new Data\Collection($data->get(0));
132
+ }
133
+
134
+ $profile->webSiteURL = $data->get('url');
135
+
136
+ return $profile;
137
+ }
138
+
139
+ /**
140
+ * Get profile name.
141
+ *
142
+ * @param User\Profile $profile
143
+ * @param Data\Collection $data
144
+ *
145
+ * @return User\Profile
146
+ */
147
+ protected function getName(User\Profile $profile, Data\Collection $data)
148
+ {
149
+ $data = new Data\Collection($data->get('person'));
150
+ $data = new Data\Collection($data->get('name'));
151
+
152
+ if ($data->exists('credit-name')) {
153
+ $profile->displayName = $data->get('credit-name');
154
+ } else {
155
+ $profile->displayName = $data->get('given-names') . ' ' . $data->get('family-name');
156
+ }
157
+
158
+ $profile->firstName = $data->get('given-names');
159
+ $profile->lastName = $data->get('family-name');
160
+
161
+ return $profile;
162
+ }
163
+
164
+ /**
165
+ * Get profile email.
166
+ *
167
+ * @param User\Profile $profile
168
+ * @param Data\Collection $data
169
+ *
170
+ * @return User\Profile
171
+ */
172
+ protected function getEmail(User\Profile $profile, Data\Collection $data)
173
+ {
174
+ $data = new Data\Collection($data->get('person'));
175
+ $data = new Data\Collection($data->get('emails'));
176
+ $data = new Data\Collection($data->get('email'));
177
+
178
+ if (!$data->exists(0)) {
179
+ $email = $data;
180
+ } else {
181
+ $email = new Data\Collection($data->get(0));
182
+
183
+ $i = 1;
184
+ while ($email->get('@attributes')['primary'] == 'false') {
185
+ $email = new Data\Collection($data->get($i));
186
+ $i++;
187
+ }
188
+ }
189
+
190
+ if ($email->get('@attributes')['primary'] == 'false') {
191
+ return $profile;
192
+ }
193
+
194
+ $profile->email = $email->get('email');
195
+
196
+ if ($email->get('@attributes')['verified'] == 'true') {
197
+ $profile->emailVerified = $email->get('email');
198
+ }
199
+
200
+ return $profile;
201
+ }
202
+
203
+ /**
204
+ * Get profile language.
205
+ *
206
+ * @param User\Profile $profile
207
+ * @param Data\Collection $data
208
+ *
209
+ * @return User\Profile
210
+ */
211
+ protected function getLanguage(User\Profile $profile, Data\Collection $data)
212
+ {
213
+ $data = new Data\Collection($data->get('preferences'));
214
+
215
+ $profile->language = $data->get('locale');
216
+
217
+ return $profile;
218
+ }
219
+
220
+ /**
221
+ * Get profile address.
222
+ *
223
+ * @param User\Profile $profile
224
+ * @param Data\Collection $data
225
+ *
226
+ * @return User\Profile
227
+ */
228
+ protected function getAddress(User\Profile $profile, Data\Collection $data)
229
+ {
230
+ $data = new Data\Collection($data->get('person'));
231
+ $data = new Data\Collection($data->get('addresses'));
232
+ $data = new Data\Collection($data->get('address'));
233
+
234
+ if ($data->exists(0)) {
235
+ $data = new Data\Collection($data->get(0));
236
+ }
237
+
238
+ $profile->country = $data->get('country');
239
+
240
+ return $profile;
241
+ }
242
+ }
hybridauth/library/src/Provider/Odnoklassniki.php CHANGED
@@ -1,110 +1,110 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Data;
12
- use Hybridauth\Exception\UnexpectedApiResponseException;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Odnoklassniki OAuth2 provider adapter.
17
- */
18
- class Odnoklassniki extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $apiBaseUrl = 'https://api.ok.ru/';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $authorizeUrl = 'https://connect.ok.ru/oauth/authorize';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $accessTokenUrl = 'https://api.ok.ru/oauth/token.do';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $apiDocumentation = 'https://apiok.ru/en/ext/oauth/';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected function initialize()
44
- {
45
- parent::initialize();
46
-
47
- if ($this->isRefreshTokenAvailable()) {
48
- $this->tokenRefreshParameters += [
49
- 'client_id' => $this->clientId,
50
- 'client_secret' => $this->clientSecret
51
- ];
52
- }
53
- }
54
-
55
- /**
56
- * {@inheritdoc}
57
- */
58
- public function getUserProfile()
59
- {
60
- $fields = array(
61
- 'uid', 'locale', 'first_name', 'last_name', 'name', 'gender', 'age', 'birthday',
62
- 'has_email', 'current_status', 'current_status_id', 'current_status_date','online',
63
- 'photo_id', 'pic_1', 'pic_2', 'pic1024x768', 'location', 'email'
64
- );
65
-
66
- $sig = md5(
67
- 'application_key=' . $this->config->get('keys')['key'] .
68
- 'fields=' . implode(',', $fields) .
69
- 'method=users.getCurrentUser' .
70
- md5($this->getStoredData('access_token') . $this->config->get('keys')['secret'])
71
- );
72
-
73
- $parameters = [
74
- 'access_token' => $this->getStoredData('access_token'),
75
- 'application_key' => $this->config->get('keys')['key'],
76
- 'method' => 'users.getCurrentUser',
77
- 'fields' => implode(',', $fields),
78
- 'sig' => $sig,
79
- ];
80
-
81
- $response = $this->apiRequest('fb.do', 'GET', $parameters);
82
-
83
- $data = new Data\Collection($response);
84
-
85
- if (! $data->exists('uid')) {
86
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
87
- }
88
-
89
- $userProfile = new User\Profile();
90
-
91
-
92
- $userProfile->identifier = $data->get('uid');
93
- $userProfile->email = $data->get('email');
94
- $userProfile->firstName = $data->get('first_name');
95
- $userProfile->lastName = $data->get('last_name');
96
- $userProfile->displayName = $data->get('name');
97
- $userProfile->photoURL = $data->get('pic1024x768');
98
- $userProfile->profileURL = 'http://ok.ru/profile/' . $data->get('uid');
99
-
100
- // Handle birthday.
101
- if ($data->get('birthday')) {
102
- $bday = explode('-', $data->get('birthday'));
103
- $userProfile->birthDay = (int)$bday[0];
104
- $userProfile->birthMonth = (int)$bday[1];
105
- $userProfile->birthYear = (int)$bday[2];
106
- }
107
-
108
- return $userProfile;
109
- }
110
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Data;
12
+ use Hybridauth\Exception\UnexpectedApiResponseException;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Odnoklassniki OAuth2 provider adapter.
17
+ */
18
+ class Odnoklassniki extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $apiBaseUrl = 'https://api.ok.ru/';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $authorizeUrl = 'https://connect.ok.ru/oauth/authorize';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $accessTokenUrl = 'https://api.ok.ru/oauth/token.do';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $apiDocumentation = 'https://apiok.ru/en/ext/oauth/';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected function initialize()
44
+ {
45
+ parent::initialize();
46
+
47
+ if ($this->isRefreshTokenAvailable()) {
48
+ $this->tokenRefreshParameters += [
49
+ 'client_id' => $this->clientId,
50
+ 'client_secret' => $this->clientSecret
51
+ ];
52
+ }
53
+ }
54
+
55
+ /**
56
+ * {@inheritdoc}
57
+ */
58
+ public function getUserProfile()
59
+ {
60
+ $fields = array(
61
+ 'uid', 'locale', 'first_name', 'last_name', 'name', 'gender', 'age', 'birthday',
62
+ 'has_email', 'current_status', 'current_status_id', 'current_status_date','online',
63
+ 'photo_id', 'pic_1', 'pic_2', 'pic1024x768', 'location', 'email'
64
+ );
65
+
66
+ $sig = md5(
67
+ 'application_key=' . $this->config->get('keys')['key'] .
68
+ 'fields=' . implode(',', $fields) .
69
+ 'method=users.getCurrentUser' .
70
+ md5($this->getStoredData('access_token') . $this->config->get('keys')['secret'])
71
+ );
72
+
73
+ $parameters = [
74
+ 'access_token' => $this->getStoredData('access_token'),
75
+ 'application_key' => $this->config->get('keys')['key'],
76
+ 'method' => 'users.getCurrentUser',
77
+ 'fields' => implode(',', $fields),
78
+ 'sig' => $sig,
79
+ ];
80
+
81
+ $response = $this->apiRequest('fb.do', 'GET', $parameters);
82
+
83
+ $data = new Data\Collection($response);
84
+
85
+ if (! $data->exists('uid')) {
86
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
87
+ }
88
+
89
+ $userProfile = new User\Profile();
90
+
91
+
92
+ $userProfile->identifier = $data->get('uid');
93
+ $userProfile->email = $data->get('email');
94
+ $userProfile->firstName = $data->get('first_name');
95
+ $userProfile->lastName = $data->get('last_name');
96
+ $userProfile->displayName = $data->get('name');
97
+ $userProfile->photoURL = $data->get('pic1024x768');
98
+ $userProfile->profileURL = 'http://ok.ru/profile/' . $data->get('uid');
99
+
100
+ // Handle birthday.
101
+ if ($data->get('birthday')) {
102
+ $bday = explode('-', $data->get('birthday'));
103
+ $userProfile->birthDay = (int)$bday[0];
104
+ $userProfile->birthMonth = (int)$bday[1];
105
+ $userProfile->birthYear = (int)$bday[2];
106
+ }
107
+
108
+ return $userProfile;
109
+ }
110
+ }
hybridauth/library/src/Provider/OpenID.php CHANGED
@@ -1,45 +1,45 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter;
11
-
12
- /**
13
- * Generic OpenID providers adapter.
14
- *
15
- * Example:
16
- *
17
- * $config = [
18
- * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
19
- *
20
- * // authenticate with Yahoo openid
21
- * 'openid_identifier' => 'https://open.login.yahooapis.com/openid20/www.yahoo.com/xrds'
22
- *
23
- * // authenticate with stackexchange network openid
24
- * // 'openid_identifier' => 'https://openid.stackexchange.com/',
25
- *
26
- * // authenticate with Steam openid
27
- * // 'openid_identifier' => 'http://steamcommunity.com/openid',
28
- *
29
- * // etc.
30
- * ];
31
- *
32
- * $adapter = new Hybridauth\Provider\OpenID( $config );
33
- *
34
- * try {
35
- * $adapter->authenticate();
36
- *
37
- * $userProfile = $adapter->getUserProfile();
38
- * }
39
- * catch( \Exception $e ){
40
- * echo $e->getMessage() ;
41
- * }
42
- */
43
- class OpenID extends Adapter\OpenID
44
- {
45
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter;
11
+
12
+ /**
13
+ * Generic OpenID providers adapter.
14
+ *
15
+ * Example:
16
+ *
17
+ * $config = [
18
+ * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
19
+ *
20
+ * // authenticate with Yahoo openid
21
+ * 'openid_identifier' => 'https://open.login.yahooapis.com/openid20/www.yahoo.com/xrds'
22
+ *
23
+ * // authenticate with stackexchange network openid
24
+ * // 'openid_identifier' => 'https://openid.stackexchange.com/',
25
+ *
26
+ * // authenticate with Steam openid
27
+ * // 'openid_identifier' => 'http://steamcommunity.com/openid',
28
+ *
29
+ * // etc.
30
+ * ];
31
+ *
32
+ * $adapter = new Hybridauth\Provider\OpenID( $config );
33
+ *
34
+ * try {
35
+ * $adapter->authenticate();
36
+ *
37
+ * $userProfile = $adapter->getUserProfile();
38
+ * }
39
+ * catch( \Exception $e ){
40
+ * echo $e->getMessage() ;
41
+ * }
42
+ */
43
+ class OpenID extends Adapter\OpenID
44
+ {
45
+ }
hybridauth/library/src/Provider/Patreon.php CHANGED
@@ -1,91 +1,91 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2020 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\User\Profile;
13
- use Hybridauth\Data\Collection;
14
-
15
- /**
16
- * Patreon OAuth2 provider adapter.
17
- */
18
- class Patreon extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'identity identity[email]';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://www.patreon.com/api';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://www.patreon.com/oauth2/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://www.patreon.com/api/oauth2/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://docs.patreon.com/#oauth';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected function initialize()
49
- {
50
- parent::initialize();
51
-
52
- if ($this->isRefreshTokenAvailable()) {
53
- $this->tokenRefreshParameters += [
54
- 'client_id' => $this->clientId,
55
- 'client_secret' => $this->clientSecret,
56
- ];
57
- }
58
- }
59
-
60
- /**
61
- * {@inheritdoc}
62
- */
63
- public function getUserProfile()
64
- {
65
- $response = $this->apiRequest('oauth2/v2/identity', 'GET', [
66
- 'fields[user]' => 'created,first_name,last_name,email,full_name,is_email_verified,thumb_url,url',
67
- ]);
68
-
69
- $collection = new Collection($response);
70
- if (!$collection->exists('data')) {
71
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
72
- }
73
-
74
- $userProfile = new Profile();
75
-
76
- $data = $collection->filter('data');
77
- $attributes = $data->filter('attributes');
78
-
79
- $userProfile->identifier = $data->get('id');
80
- $userProfile->email = $attributes->get('email');
81
- $userProfile->firstName = $attributes->get('first_name');
82
- $userProfile->lastName = $attributes->get('last_name');
83
- $userProfile->displayName = $attributes->get('full_name') ?: $data->get('id');
84
- $userProfile->photoURL = $attributes->get('thumb_url');
85
- $userProfile->profileURL = $attributes->get('url');
86
-
87
- $userProfile->emailVerified = $attributes->get('is_email_verified') ? $userProfile->email : '';
88
-
89
- return $userProfile;
90
- }
91
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2020 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\User\Profile;
13
+ use Hybridauth\Data\Collection;
14
+
15
+ /**
16
+ * Patreon OAuth2 provider adapter.
17
+ */
18
+ class Patreon extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'identity identity[email]';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://www.patreon.com/api';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://www.patreon.com/oauth2/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://www.patreon.com/api/oauth2/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://docs.patreon.com/#oauth';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function initialize()
49
+ {
50
+ parent::initialize();
51
+
52
+ if ($this->isRefreshTokenAvailable()) {
53
+ $this->tokenRefreshParameters += [
54
+ 'client_id' => $this->clientId,
55
+ 'client_secret' => $this->clientSecret,
56
+ ];
57
+ }
58
+ }
59
+
60
+ /**
61
+ * {@inheritdoc}
62
+ */
63
+ public function getUserProfile()
64
+ {
65
+ $response = $this->apiRequest('oauth2/v2/identity', 'GET', [
66
+ 'fields[user]' => 'created,first_name,last_name,email,full_name,is_email_verified,thumb_url,url',
67
+ ]);
68
+
69
+ $collection = new Collection($response);
70
+ if (!$collection->exists('data')) {
71
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
72
+ }
73
+
74
+ $userProfile = new Profile();
75
+
76
+ $data = $collection->filter('data');
77
+ $attributes = $data->filter('attributes');
78
+
79
+ $userProfile->identifier = $data->get('id');
80
+ $userProfile->email = $attributes->get('email');
81
+ $userProfile->firstName = $attributes->get('first_name');
82
+ $userProfile->lastName = $attributes->get('last_name');
83
+ $userProfile->displayName = $attributes->get('full_name') ?: $data->get('id');
84
+ $userProfile->photoURL = $attributes->get('thumb_url');
85
+ $userProfile->profileURL = $attributes->get('url');
86
+
87
+ $userProfile->emailVerified = $attributes->get('is_email_verified') ? $userProfile->email : '';
88
+
89
+ return $userProfile;
90
+ }
91
+ }
hybridauth/library/src/Provider/Paypal.php CHANGED
@@ -1,113 +1,113 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Paypal OAuth2 provider adapter.
17
- */
18
- class Paypal extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'openid profile email address';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://api.paypal.com/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://www.paypal.com/signin/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://api.paypal.com/v1/oauth2/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://developer.paypal.com/docs/api/overview/#';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected function initialize()
49
- {
50
- parent::initialize();
51
-
52
- $this->AuthorizeUrlParameters += [
53
- 'flowEntry' => 'static'
54
- ];
55
-
56
- $this->tokenExchangeHeaders = [
57
- 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
58
- ];
59
-
60
- $this->tokenRefreshHeaders = [
61
- 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
62
- ];
63
- }
64
-
65
- /**
66
- * {@inheritdoc}
67
- *
68
- * See: https://developer.paypal.com/docs/api/identity/v1/
69
- * See: https://developer.paypal.com/docs/connect-with-paypal/integrate/
70
- */
71
- public function getUserProfile()
72
- {
73
- $headers = [
74
- 'Content-Type' => 'application/json',
75
- ];
76
-
77
- $parameters = [
78
- 'schema' => 'paypalv1.1'
79
- ];
80
-
81
- $response = $this->apiRequest('v1/identity/oauth2/userinfo', 'GET', $parameters, $headers);
82
- $data = new Data\Collection($response);
83
-
84
- if (! $data->exists('user_id')) {
85
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
86
- }
87
-
88
- $userProfile = new User\Profile();
89
- $userProfile->identifier = $data->get('user_id');
90
- $userProfile->firstName = $data->get('given_name');
91
- $userProfile->lastName = $data->get('family_name');
92
- $userProfile->displayName = $data->get('name');
93
- $userProfile->address = $data->filter('address')->get('street_address');
94
- $userProfile->city = $data->filter('address')->get('locality');
95
- $userProfile->country = $data->filter('address')->get('country');
96
- $userProfile->region = $data->filter('address')->get('region');
97
- $userProfile->zip = $data->filter('address')->get('postal_code');
98
-
99
- $emails = $data->filter('emails')->toArray();
100
- foreach ($emails as $email) {
101
- $email = new Data\Collection($email);
102
- if ($email->get('confirmed')) {
103
- $userProfile->emailVerified = $email->get('value');
104
- }
105
-
106
- if ($email->get('primary')) {
107
- $userProfile->email = $email->get('value');
108
- }
109
- }
110
-
111
- return $userProfile;
112
- }
113
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Paypal OAuth2 provider adapter.
17
+ */
18
+ class Paypal extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'openid profile email address';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://api.paypal.com/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://www.paypal.com/signin/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://api.paypal.com/v1/oauth2/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://developer.paypal.com/docs/api/overview/#';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function initialize()
49
+ {
50
+ parent::initialize();
51
+
52
+ $this->AuthorizeUrlParameters += [
53
+ 'flowEntry' => 'static'
54
+ ];
55
+
56
+ $this->tokenExchangeHeaders = [
57
+ 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
58
+ ];
59
+
60
+ $this->tokenRefreshHeaders = [
61
+ 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
62
+ ];
63
+ }
64
+
65
+ /**
66
+ * {@inheritdoc}
67
+ *
68
+ * See: https://developer.paypal.com/docs/api/identity/v1/
69
+ * See: https://developer.paypal.com/docs/connect-with-paypal/integrate/
70
+ */
71
+ public function getUserProfile()
72
+ {
73
+ $headers = [
74
+ 'Content-Type' => 'application/json',
75
+ ];
76
+
77
+ $parameters = [
78
+ 'schema' => 'paypalv1.1'
79
+ ];
80
+
81
+ $response = $this->apiRequest('v1/identity/oauth2/userinfo', 'GET', $parameters, $headers);
82
+ $data = new Data\Collection($response);
83
+
84
+ if (! $data->exists('user_id')) {
85
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
86
+ }
87
+
88
+ $userProfile = new User\Profile();
89
+ $userProfile->identifier = $data->get('user_id');
90
+ $userProfile->firstName = $data->get('given_name');
91
+ $userProfile->lastName = $data->get('family_name');
92
+ $userProfile->displayName = $data->get('name');
93
+ $userProfile->address = $data->filter('address')->get('street_address');
94
+ $userProfile->city = $data->filter('address')->get('locality');
95
+ $userProfile->country = $data->filter('address')->get('country');
96
+ $userProfile->region = $data->filter('address')->get('region');
97
+ $userProfile->zip = $data->filter('address')->get('postal_code');
98
+
99
+ $emails = $data->filter('emails')->toArray();
100
+ foreach ($emails as $email) {
101
+ $email = new Data\Collection($email);
102
+ if ($email->get('confirmed')) {
103
+ $userProfile->emailVerified = $email->get('value');
104
+ }
105
+
106
+ if ($email->get('primary')) {
107
+ $userProfile->email = $email->get('value');
108
+ }
109
+ }
110
+
111
+ return $userProfile;
112
+ }
113
+ }
hybridauth/library/src/Provider/PaypalOpenID.php CHANGED
@@ -1,71 +1,71 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OpenID;
11
- use Hybridauth\HttpClient;
12
-
13
- /**
14
- * PayPal OpenID provider adapter.
15
- */
16
- class PaypalOpenID extends OpenID
17
- {
18
- /**
19
- * {@inheritdoc}
20
- */
21
- protected $openidIdentifier = 'https://www.sandbox.paypal.com/webapps/auth/server';
22
-
23
- /**
24
- * {@inheritdoc}
25
- */
26
- protected $apiDocumentation = 'https://developer.paypal.com/docs/connect-with-paypal/';
27
-
28
- /**
29
- * {@inheritdoc}
30
- */
31
- public function authenticateBegin()
32
- {
33
- $this->openIdClient->identity = $this->openidIdentifier;
34
- $this->openIdClient->returnUrl = $this->callback;
35
- $this->openIdClient->required = [
36
- 'namePerson/prefix',
37
- 'namePerson/first',
38
- 'namePerson/last',
39
- 'namePerson/middle',
40
- 'namePerson/suffix',
41
- 'namePerson/friendly',
42
- 'person/guid',
43
- 'birthDate/birthYear',
44
- 'birthDate/birthMonth',
45
- 'birthDate/birthday',
46
- 'gender',
47
- 'language/pref',
48
- 'contact/phone/default',
49
- 'contact/phone/home',
50
- 'contact/phone/business',
51
- 'contact/phone/cell',
52
- 'contact/phone/fax',
53
- 'contact/postaladdress/home',
54
- 'contact/postaladdressadditional/home',
55
- 'contact/city/home',
56
- 'contact/state/home',
57
- 'contact/country/home',
58
- 'contact/postalcode/home',
59
- 'contact/postaladdress/business',
60
- 'contact/postaladdressadditional/business',
61
- 'contact/city/business',
62
- 'contact/state/business',
63
- 'contact/country/business',
64
- 'contact/postalcode/business',
65
- 'company/name',
66
- 'company/title',
67
- ];
68
-
69
- HttpClient\Util::redirect($this->openIdClient->authUrl());
70
- }
71
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OpenID;
11
+ use Hybridauth\HttpClient;
12
+
13
+ /**
14
+ * PayPal OpenID provider adapter.
15
+ */
16
+ class PaypalOpenID extends OpenID
17
+ {
18
+ /**
19
+ * {@inheritdoc}
20
+ */
21
+ protected $openidIdentifier = 'https://www.sandbox.paypal.com/webapps/auth/server';
22
+
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ protected $apiDocumentation = 'https://developer.paypal.com/docs/connect-with-paypal/';
27
+
28
+ /**
29
+ * {@inheritdoc}
30
+ */
31
+ public function authenticateBegin()
32
+ {
33
+ $this->openIdClient->identity = $this->openidIdentifier;
34
+ $this->openIdClient->returnUrl = $this->callback;
35
+ $this->openIdClient->required = [
36
+ 'namePerson/prefix',
37
+ 'namePerson/first',
38
+ 'namePerson/last',
39
+ 'namePerson/middle',
40
+ 'namePerson/suffix',
41
+ 'namePerson/friendly',
42
+ 'person/guid',
43
+ 'birthDate/birthYear',
44
+ 'birthDate/birthMonth',
45
+ 'birthDate/birthday',
46
+ 'gender',
47
+ 'language/pref',
48
+ 'contact/phone/default',
49
+ 'contact/phone/home',
50
+ 'contact/phone/business',
51
+ 'contact/phone/cell',
52
+ 'contact/phone/fax',
53
+ 'contact/postaladdress/home',
54
+ 'contact/postaladdressadditional/home',
55
+ 'contact/city/home',
56
+ 'contact/state/home',
57
+ 'contact/country/home',
58
+ 'contact/postalcode/home',
59
+ 'contact/postaladdress/business',
60
+ 'contact/postaladdressadditional/business',
61
+ 'contact/city/business',
62
+ 'contact/state/business',
63
+ 'contact/country/business',
64
+ 'contact/postalcode/business',
65
+ 'company/name',
66
+ 'company/title',
67
+ ];
68
+
69
+ HttpClient\Util::redirect($this->openIdClient->authUrl());
70
+ }
71
+ }
hybridauth/library/src/Provider/Pinterest.php CHANGED
@@ -1,74 +1,74 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Pinterest OAuth2 provider adapter.
17
- */
18
- class Pinterest extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'read_public';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://api.pinterest.com/v1/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://api.pinterest.com/oauth';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://api.pinterest.com/v1/oauth/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://developers.pinterest.com/docs/api/overview/';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('me');
51
-
52
- $data = new Data\Collection($response);
53
-
54
- $data = $data->filter('data');
55
-
56
- if (! $data->exists('id')) {
57
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
58
- }
59
-
60
- $userProfile = new User\Profile();
61
-
62
- $userProfile->identifier = $data->get('id');
63
- $userProfile->description = $data->get('bio');
64
- $userProfile->photoURL = $data->get('image');
65
- $userProfile->displayName = $data->get('username');
66
- $userProfile->firstName = $data->get('first_name');
67
- $userProfile->lastName = $data->get('last_name');
68
- $userProfile->profileURL = "https://pinterest.com/{$data->get('username')}";
69
-
70
- $userProfile->data = (array) $data->get('counts');
71
-
72
- return $userProfile;
73
- }
74
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Pinterest OAuth2 provider adapter.
17
+ */
18
+ class Pinterest extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'read_public';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://api.pinterest.com/v1/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://api.pinterest.com/oauth';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://api.pinterest.com/v1/oauth/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://developers.pinterest.com/docs/api/overview/';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('me');
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ $data = $data->filter('data');
55
+
56
+ if (! $data->exists('id')) {
57
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
58
+ }
59
+
60
+ $userProfile = new User\Profile();
61
+
62
+ $userProfile->identifier = $data->get('id');
63
+ $userProfile->description = $data->get('bio');
64
+ $userProfile->photoURL = $data->get('image');
65
+ $userProfile->displayName = $data->get('username');
66
+ $userProfile->firstName = $data->get('first_name');
67
+ $userProfile->lastName = $data->get('last_name');
68
+ $userProfile->profileURL = "https://pinterest.com/{$data->get('username')}";
69
+
70
+ $userProfile->data = (array) $data->get('counts');
71
+
72
+ return $userProfile;
73
+ }
74
+ }
hybridauth/library/src/Provider/QQ.php CHANGED
@@ -1,138 +1,138 @@
1
- <?php
2
-
3
- namespace Hybridauth\Provider;
4
-
5
- use Hybridauth\Adapter\OAuth2;
6
- use Hybridauth\Exception\UnexpectedApiResponseException;
7
- use Hybridauth\Data;
8
- use Hybridauth\User\Profile;
9
-
10
- /**
11
- * Tencent QQ International OAuth2 provider adapter.
12
- */
13
- class QQ extends OAuth2
14
- {
15
- /**
16
- * {@inheritdoc}
17
- */
18
- protected $scope = 'get_user_info';
19
-
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $apiBaseUrl = 'https://graph.qq.com/oauth2.0/';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $authorizeUrl = 'https://graph.qq.com/oauth2.0/authorize';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $accessTokenUrl = 'https://graph.qq.com/oauth2.0/token';
34
-
35
- /**
36
- * {@ịnheritdoc}
37
- */
38
- protected $accessTokenInfoUrl = 'https://graph.qq.com/oauth2.0/me';
39
-
40
- /**
41
- * User Information Endpoint
42
- * @var string
43
- */
44
- protected $accessUserInfo = 'https://graph.qq.com/user/get_user_info';
45
-
46
- /**
47
- * {@inheritdoc}
48
- */
49
- protected $tokenExchangeMethod = 'GET';
50
-
51
- /**
52
- * {@inheritdoc}
53
- */
54
- protected $tokenRefreshMethod = 'GET';
55
-
56
- /**
57
- * {@inheritdoc}
58
- */
59
- protected $apiDocumentation = ''; // Not available
60
-
61
- /**
62
- * {@inheritdoc}
63
- */
64
- protected function initialize()
65
- {
66
- parent::initialize();
67
-
68
- if ($this->isRefreshTokenAvailable()) {
69
- $this->tokenRefreshParameters += [
70
- 'client_id' => $this->clientId,
71
- 'client_secret' => $this->clientSecret,
72
- ];
73
- }
74
-
75
- $this->apiRequestParameters = [
76
- 'access_token' => $this->getStoredData('access_token')
77
- ];
78
-
79
- $this->apiRequestHeaders = [];
80
- }
81
-
82
- /**
83
- * {@inheritdoc}
84
- */
85
- protected function validateAccessTokenExchange($response)
86
- {
87
- $collection = parent::validateAccessTokenExchange($response);
88
-
89
- $resp = $this->apiRequest($this->accessTokenInfoUrl);
90
- $resp = key($resp);
91
-
92
- $len = strlen($resp);
93
- $res = substr($resp, 10, $len - 14);
94
-
95
- $response = (new Data\Parser())->parse($res);
96
-
97
- if (!isset($response->openid)) {
98
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
99
- }
100
-
101
- $this->storeData('openid', $response->openid);
102
-
103
- return $collection;
104
- }
105
-
106
- /**
107
- * {@inheritdoc}
108
- */
109
- public function getUserProfile()
110
- {
111
- $openid = $this->getStoredData('openid');
112
-
113
- $userRequestParameters = [
114
- 'oauth_consumer_key' => $this->clientId,
115
- 'openid' => $openid,
116
- 'format' => 'json'
117
- ];
118
-
119
- $response = $this->apiRequest($this->accessUserInfo, 'GET', $userRequestParameters);
120
-
121
- $data = new Data\Collection($response);
122
-
123
- if ($data->get('ret') < 0) {
124
- throw new UnexpectedApiResponseException('Provider API returned an error: ' . $data->get('msg'));
125
- }
126
-
127
- $userProfile = new Profile();
128
-
129
- $userProfile->identifier = $openid;
130
- $userProfile->displayName = $data->get('nickname');
131
- $userProfile->photoURL = $data->get('figureurl_2');
132
- $userProfile->gender = $data->get('gender');
133
- $userProfile->region = $data->get('province');
134
- $userProfile->city = $data->get('city');
135
-
136
- return $userProfile;
137
- }
138
- }
1
+ <?php
2
+
3
+ namespace Hybridauth\Provider;
4
+
5
+ use Hybridauth\Adapter\OAuth2;
6
+ use Hybridauth\Exception\UnexpectedApiResponseException;
7
+ use Hybridauth\Data;
8
+ use Hybridauth\User\Profile;
9
+
10
+ /**
11
+ * Tencent QQ International OAuth2 provider adapter.
12
+ */
13
+ class QQ extends OAuth2
14
+ {
15
+ /**
16
+ * {@inheritdoc}
17
+ */
18
+ protected $scope = 'get_user_info';
19
+
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $apiBaseUrl = 'https://graph.qq.com/oauth2.0/';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $authorizeUrl = 'https://graph.qq.com/oauth2.0/authorize';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $accessTokenUrl = 'https://graph.qq.com/oauth2.0/token';
34
+
35
+ /**
36
+ * {@ịnheritdoc}
37
+ */
38
+ protected $accessTokenInfoUrl = 'https://graph.qq.com/oauth2.0/me';
39
+
40
+ /**
41
+ * User Information Endpoint
42
+ * @var string
43
+ */
44
+ protected $accessUserInfo = 'https://graph.qq.com/user/get_user_info';
45
+
46
+ /**
47
+ * {@inheritdoc}
48
+ */
49
+ protected $tokenExchangeMethod = 'GET';
50
+
51
+ /**
52
+ * {@inheritdoc}
53
+ */
54
+ protected $tokenRefreshMethod = 'GET';
55
+
56
+ /**
57
+ * {@inheritdoc}
58
+ */
59
+ protected $apiDocumentation = ''; // Not available
60
+
61
+ /**
62
+ * {@inheritdoc}
63
+ */
64
+ protected function initialize()
65
+ {
66
+ parent::initialize();
67
+
68
+ if ($this->isRefreshTokenAvailable()) {
69
+ $this->tokenRefreshParameters += [
70
+ 'client_id' => $this->clientId,
71
+ 'client_secret' => $this->clientSecret,
72
+ ];
73
+ }
74
+
75
+ $this->apiRequestParameters = [
76
+ 'access_token' => $this->getStoredData('access_token')
77
+ ];
78
+
79
+ $this->apiRequestHeaders = [];
80
+ }
81
+
82
+ /**
83
+ * {@inheritdoc}
84
+ */
85
+ protected function validateAccessTokenExchange($response)
86
+ {
87
+ $collection = parent::validateAccessTokenExchange($response);
88
+
89
+ $resp = $this->apiRequest($this->accessTokenInfoUrl);
90
+ $resp = key($resp);
91
+
92
+ $len = strlen($resp);
93
+ $res = substr($resp, 10, $len - 14);
94
+
95
+ $response = (new Data\Parser())->parse($res);
96
+
97
+ if (!isset($response->openid)) {
98
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
99
+ }
100
+
101
+ $this->storeData('openid', $response->openid);
102
+
103
+ return $collection;
104
+ }
105
+
106
+ /**
107
+ * {@inheritdoc}
108
+ */
109
+ public function getUserProfile()
110
+ {
111
+ $openid = $this->getStoredData('openid');
112
+
113
+ $userRequestParameters = [
114
+ 'oauth_consumer_key' => $this->clientId,
115
+ 'openid' => $openid,
116
+ 'format' => 'json'
117
+ ];
118
+
119
+ $response = $this->apiRequest($this->accessUserInfo, 'GET', $userRequestParameters);
120
+
121
+ $data = new Data\Collection($response);
122
+
123
+ if ($data->get('ret') < 0) {
124
+ throw new UnexpectedApiResponseException('Provider API returned an error: ' . $data->get('msg'));
125
+ }
126
+
127
+ $userProfile = new Profile();
128
+
129
+ $userProfile->identifier = $openid;
130
+ $userProfile->displayName = $data->get('nickname');
131
+ $userProfile->photoURL = $data->get('figureurl_2');
132
+ $userProfile->gender = $data->get('gender');
133
+ $userProfile->region = $data->get('province');
134
+ $userProfile->city = $data->get('city');
135
+
136
+ return $userProfile;
137
+ }
138
+ }
hybridauth/library/src/Provider/Reddit.php CHANGED
@@ -1,91 +1,91 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Reddit OAuth2 provider adapter.
17
- */
18
- class Reddit extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'identity';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://oauth.reddit.com/api/v1/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://ssl.reddit.com/api/v1/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://ssl.reddit.com/api/v1/access_token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://github.com/reddit/reddit/wiki/OAuth2';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected function initialize()
49
- {
50
- parent::initialize();
51
-
52
- $this->AuthorizeUrlParameters += [
53
- 'duration' => 'permanent'
54
- ];
55
-
56
- $this->tokenExchangeParameters = [
57
- 'client_id' => $this->clientId,
58
- 'grant_type' => 'authorization_code',
59
- 'redirect_uri' => $this->callback
60
- ];
61
-
62
- $this->tokenExchangeHeaders = [
63
- 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
64
- ];
65
-
66
- $this->tokenRefreshHeaders = $this->tokenExchangeHeaders;
67
- }
68
-
69
- /**
70
- * {@inheritdoc}
71
- */
72
- public function getUserProfile()
73
- {
74
- $response = $this->apiRequest('me.json');
75
-
76
- $data = new Data\Collection($response);
77
-
78
- if (! $data->exists('id')) {
79
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
80
- }
81
-
82
- $userProfile = new User\Profile();
83
-
84
- $userProfile->identifier = $data->get('id');
85
- $userProfile->displayName = $data->get('name');
86
- $userProfile->profileURL = 'https://www.reddit.com/user/' . $data->get('name') . '/';
87
- $userProfile->photoURL = $data->get('icon_img');
88
-
89
- return $userProfile;
90
- }
91
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Reddit OAuth2 provider adapter.
17
+ */
18
+ class Reddit extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'identity';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://oauth.reddit.com/api/v1/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://ssl.reddit.com/api/v1/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://ssl.reddit.com/api/v1/access_token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://github.com/reddit/reddit/wiki/OAuth2';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function initialize()
49
+ {
50
+ parent::initialize();
51
+
52
+ $this->AuthorizeUrlParameters += [
53
+ 'duration' => 'permanent'
54
+ ];
55
+
56
+ $this->tokenExchangeParameters = [
57
+ 'client_id' => $this->clientId,
58
+ 'grant_type' => 'authorization_code',
59
+ 'redirect_uri' => $this->callback
60
+ ];
61
+
62
+ $this->tokenExchangeHeaders = [
63
+ 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
64
+ ];
65
+
66
+ $this->tokenRefreshHeaders = $this->tokenExchangeHeaders;
67
+ }
68
+
69
+ /**
70
+ * {@inheritdoc}
71
+ */
72
+ public function getUserProfile()
73
+ {
74
+ $response = $this->apiRequest('me.json');
75
+
76
+ $data = new Data\Collection($response);
77
+
78
+ if (! $data->exists('id')) {
79
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
80
+ }
81
+
82
+ $userProfile = new User\Profile();
83
+
84
+ $userProfile->identifier = $data->get('id');
85
+ $userProfile->displayName = $data->get('name');
86
+ $userProfile->profileURL = 'https://www.reddit.com/user/' . $data->get('name') . '/';
87
+ $userProfile->photoURL = $data->get('icon_img');
88
+
89
+ return $userProfile;
90
+ }
91
+ }
hybridauth/library/src/Provider/Slack.php CHANGED
@@ -1,100 +1,100 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2019 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Slack OAuth2 provider adapter.
17
- */
18
- class Slack extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'identity.basic identity.email identity.avatar';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://slack.com/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://slack.com/oauth/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://slack.com/api/oauth.access';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://api.slack.com/docs/sign-in-with-slack';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('api/users.identity');
51
-
52
- $data = new Data\Collection($response);
53
-
54
- if (!$data->exists('ok') || !$data->get('ok')) {
55
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
- }
57
-
58
- $userProfile = new User\Profile();
59
-
60
- $userProfile->identifier = $data->filter('user')->get('id');
61
- $userProfile->displayName = $data->filter('user')->get('name');
62
- $userProfile->email = $data->filter('user')->get('email');
63
- $userProfile->photoURL = $this->findLargestImage($data);
64
-
65
- return $userProfile;
66
- }
67
-
68
- /**
69
- * Returns the url of the image with the highest resolution in the user
70
- * object.
71
- *
72
- * Slack sends multiple image urls with different resolutions. As they make
73
- * no guarantees which resolutions will be included we have to search all
74
- * <code>image_*</code> properties for the one with the highest resolution.
75
- * The resolution is attached to the property name such as
76
- * <code>image_32</code> or <code>image_192</code>.
77
- *
78
- * @param Data\Collection $data response object as returned by
79
- * <code>api/users.identity</code>
80
- *
81
- * @return string|null the value of the <code>image_*</code> property with
82
- * the highest resolution.
83
- */
84
- private function findLargestImage(Data\Collection $data)
85
- {
86
- $maxSize = 0;
87
- foreach ($data->filter('user')->properties() as $property) {
88
- if (preg_match('/^image_(\d+)$/', $property, $matches) === 1) {
89
- $availableSize = (int)$matches[1];
90
- if ($maxSize < $availableSize) {
91
- $maxSize = $availableSize;
92
- }
93
- }
94
- }
95
- if ($maxSize > 0) {
96
- return $data->filter('user')->get('image_' . $maxSize);
97
- }
98
- return null;
99
- }
100
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2019 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Slack OAuth2 provider adapter.
17
+ */
18
+ class Slack extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'identity.basic identity.email identity.avatar';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://slack.com/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://slack.com/oauth/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://slack.com/api/oauth.access';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://api.slack.com/docs/sign-in-with-slack';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('api/users.identity');
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ if (!$data->exists('ok') || !$data->get('ok')) {
55
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
+ }
57
+
58
+ $userProfile = new User\Profile();
59
+
60
+ $userProfile->identifier = $data->filter('user')->get('id');
61
+ $userProfile->displayName = $data->filter('user')->get('name');
62
+ $userProfile->email = $data->filter('user')->get('email');
63
+ $userProfile->photoURL = $this->findLargestImage($data);
64
+
65
+ return $userProfile;
66
+ }
67
+
68
+ /**
69
+ * Returns the url of the image with the highest resolution in the user
70
+ * object.
71
+ *
72
+ * Slack sends multiple image urls with different resolutions. As they make
73
+ * no guarantees which resolutions will be included we have to search all
74
+ * <code>image_*</code> properties for the one with the highest resolution.
75
+ * The resolution is attached to the property name such as
76
+ * <code>image_32</code> or <code>image_192</code>.
77
+ *
78
+ * @param Data\Collection $data response object as returned by
79
+ * <code>api/users.identity</code>
80
+ *
81
+ * @return string|null the value of the <code>image_*</code> property with
82
+ * the highest resolution.
83
+ */
84
+ private function findLargestImage(Data\Collection $data)
85
+ {
86
+ $maxSize = 0;
87
+ foreach ($data->filter('user')->properties() as $property) {
88
+ if (preg_match('/^image_(\d+)$/', $property, $matches) === 1) {
89
+ $availableSize = (int)$matches[1];
90
+ if ($maxSize < $availableSize) {
91
+ $maxSize = $availableSize;
92
+ }
93
+ }
94
+ }
95
+ if ($maxSize > 0) {
96
+ return $data->filter('user')->get('image_' . $maxSize);
97
+ }
98
+ return null;
99
+ }
100
+ }
hybridauth/library/src/Provider/Spotify.php CHANGED
@@ -1,93 +1,93 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Spotify OAuth2 provider adapter.
17
- */
18
- class Spotify extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'user-read-email';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- public $apiBaseUrl = 'https://api.spotify.com/v1/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- public $authorizeUrl = 'https://accounts.spotify.com/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://accounts.spotify.com/api/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://developer.spotify.com/documentation/general/guides/authorization-guide/';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('me');
51
-
52
- $data = new Data\Collection($response);
53
-
54
- if (!$data->exists('id')) {
55
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
- }
57
-
58
- $userProfile = new User\Profile();
59
-
60
- $userProfile->identifier = $data->get('id');
61
- $userProfile->displayName = $data->get('display_name');
62
- $userProfile->email = $data->get('email');
63
- $userProfile->emailVerified = $data->get('email');
64
- $userProfile->profileURL = $data->filter('external_urls')->get('spotify');
65
- $userProfile->photoURL = $data->filter('images')->get('url');
66
- $userProfile->country = $data->get('country');
67
-
68
- if ($data->exists('birthdate')) {
69
- $this->fetchBirthday($userProfile, $data->get('birthdate'));
70
- }
71
-
72
- return $userProfile;
73
- }
74
-
75
- /**
76
- * Fetch use birthday
77
- *
78
- * @param User\Profile $userProfile
79
- * @param $birthday
80
- *
81
- * @return User\Profile
82
- */
83
- protected function fetchBirthday(User\Profile $userProfile, $birthday)
84
- {
85
- $result = (new Data\Parser())->parseBirthday($birthday, '-');
86
-
87
- $userProfile->birthDay = (int)$result[0];
88
- $userProfile->birthMonth = (int)$result[1];
89
- $userProfile->birthYear = (int)$result[2];
90
-
91
- return $userProfile;
92
- }
93
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Spotify OAuth2 provider adapter.
17
+ */
18
+ class Spotify extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'user-read-email';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ public $apiBaseUrl = 'https://api.spotify.com/v1/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ public $authorizeUrl = 'https://accounts.spotify.com/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://accounts.spotify.com/api/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://developer.spotify.com/documentation/general/guides/authorization-guide/';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('me');
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ if (!$data->exists('id')) {
55
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
+ }
57
+
58
+ $userProfile = new User\Profile();
59
+
60
+ $userProfile->identifier = $data->get('id');
61
+ $userProfile->displayName = $data->get('display_name');
62
+ $userProfile->email = $data->get('email');
63
+ $userProfile->emailVerified = $data->get('email');
64
+ $userProfile->profileURL = $data->filter('external_urls')->get('spotify');
65
+ $userProfile->photoURL = $data->filter('images')->get('url');
66
+ $userProfile->country = $data->get('country');
67
+
68
+ if ($data->exists('birthdate')) {
69
+ $this->fetchBirthday($userProfile, $data->get('birthdate'));
70
+ }
71
+
72
+ return $userProfile;
73
+ }
74
+
75
+ /**
76
+ * Fetch use birthday
77
+ *
78
+ * @param User\Profile $userProfile
79
+ * @param $birthday
80
+ *
81
+ * @return User\Profile
82
+ */
83
+ protected function fetchBirthday(User\Profile $userProfile, $birthday)
84
+ {
85
+ $result = (new Data\Parser())->parseBirthday($birthday, '-');
86
+
87
+ $userProfile->birthDay = (int)$result[0];
88
+ $userProfile->birthMonth = (int)$result[1];
89
+ $userProfile->birthYear = (int)$result[2];
90
+
91
+ return $userProfile;
92
+ }
93
+ }
hybridauth/library/src/Provider/StackExchange.php CHANGED
@@ -1,107 +1,107 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * StackExchange OAuth2 provider adapter.
17
- *
18
- * Example:
19
- *
20
- * $config = [
21
- * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
22
- * 'keys' => [ 'id' => '', 'secret' => '' ],
23
- * 'site' => 'stackoverflow' // required parameter to call getUserProfile()
24
- * 'api_key' => '...' // that thing to receive a higher request quota.
25
- * ];
26
- *
27
- * $adapter = new Hybridauth\Provider\StackExchange( $config );
28
- *
29
- * try {
30
- * $adapter->authenticate();
31
- *
32
- * $userProfile = $adapter->getUserProfile();
33
- * $tokens = $adapter->getAccessToken();
34
- * }
35
- * catch( \Exception $e ){
36
- * echo $e->getMessage() ;
37
- * }
38
- */
39
- class StackExchange extends OAuth2
40
- {
41
- /**
42
- * {@inheritdoc}
43
- */
44
- protected $scope = null;
45
-
46
- /**
47
- * {@inheritdoc}
48
- */
49
- protected $apiBaseUrl = 'https://api.stackexchange.com/2.2/';
50
-
51
- /**
52
- * {@inheritdoc}
53
- */
54
- protected $authorizeUrl = 'https://stackexchange.com/oauth';
55
-
56
- /**
57
- * {@inheritdoc}
58
- */
59
- protected $accessTokenUrl = 'https://stackexchange.com/oauth/access_token';
60
-
61
- /**
62
- * {@inheritdoc}
63
- */
64
- protected $apiDocumentation = 'https://api.stackexchange.com/docs/authentication';
65
-
66
- /**
67
- * {@inheritdoc}
68
- */
69
- protected function initialize()
70
- {
71
- parent::initialize();
72
-
73
- $apiKey = $this->config->get('api_key');
74
-
75
- $this->apiRequestParameters = [ 'key' => $apiKey];
76
- }
77
-
78
- /**
79
- * {@inheritdoc}
80
- */
81
- public function getUserProfile()
82
- {
83
- $site = $this->config->get('site');
84
-
85
- $response = $this->apiRequest('me', 'GET', [
86
- 'site' => $site,
87
- 'access_token' => $this->getStoredData('access_token'),
88
- ]);
89
-
90
- if (! $response || !isset($response->items) || !isset($response->items[0])) {
91
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
92
- }
93
-
94
- $data = new Data\Collection($response->items[0]);
95
-
96
- $userProfile = new User\Profile();
97
-
98
- $userProfile->identifier = strval($data->get('user_id'));
99
- $userProfile->displayName = $data->get('display_name');
100
- $userProfile->photoURL = $data->get('profile_image');
101
- $userProfile->profileURL = $data->get('link');
102
- $userProfile->region = $data->get('location');
103
- $userProfile->age = $data->get('age');
104
-
105
- return $userProfile;
106
- }
107
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * StackExchange OAuth2 provider adapter.
17
+ *
18
+ * Example:
19
+ *
20
+ * $config = [
21
+ * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
22
+ * 'keys' => [ 'id' => '', 'secret' => '' ],
23
+ * 'site' => 'stackoverflow' // required parameter to call getUserProfile()
24
+ * 'api_key' => '...' // that thing to receive a higher request quota.
25
+ * ];
26
+ *
27
+ * $adapter = new Hybridauth\Provider\StackExchange( $config );
28
+ *
29
+ * try {
30
+ * $adapter->authenticate();
31
+ *
32
+ * $userProfile = $adapter->getUserProfile();
33
+ * $tokens = $adapter->getAccessToken();
34
+ * }
35
+ * catch( \Exception $e ){
36
+ * echo $e->getMessage() ;
37
+ * }
38
+ */
39
+ class StackExchange extends OAuth2
40
+ {
41
+ /**
42
+ * {@inheritdoc}
43
+ */
44
+ protected $scope = null;
45
+
46
+ /**
47
+ * {@inheritdoc}
48
+ */
49
+ protected $apiBaseUrl = 'https://api.stackexchange.com/2.2/';
50
+
51
+ /**
52
+ * {@inheritdoc}
53
+ */
54
+ protected $authorizeUrl = 'https://stackexchange.com/oauth';
55
+
56
+ /**
57
+ * {@inheritdoc}
58
+ */
59
+ protected $accessTokenUrl = 'https://stackexchange.com/oauth/access_token';
60
+
61
+ /**
62
+ * {@inheritdoc}
63
+ */
64
+ protected $apiDocumentation = 'https://api.stackexchange.com/docs/authentication';
65
+
66
+ /**
67
+ * {@inheritdoc}
68
+ */
69
+ protected function initialize()
70
+ {
71
+ parent::initialize();
72
+
73
+ $apiKey = $this->config->get('api_key');
74
+
75
+ $this->apiRequestParameters = [ 'key' => $apiKey];
76
+ }
77
+
78
+ /**
79
+ * {@inheritdoc}
80
+ */
81
+ public function getUserProfile()
82
+ {
83
+ $site = $this->config->get('site');
84
+
85
+ $response = $this->apiRequest('me', 'GET', [
86
+ 'site' => $site,
87
+ 'access_token' => $this->getStoredData('access_token'),
88
+ ]);
89
+
90
+ if (! $response || !isset($response->items) || !isset($response->items[0])) {
91
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
92
+ }
93
+
94
+ $data = new Data\Collection($response->items[0]);
95
+
96
+ $userProfile = new User\Profile();
97
+
98
+ $userProfile->identifier = strval($data->get('user_id'));
99
+ $userProfile->displayName = $data->get('display_name');
100
+ $userProfile->photoURL = $data->get('profile_image');
101
+ $userProfile->profileURL = $data->get('link');
102
+ $userProfile->region = $data->get('location');
103
+ $userProfile->age = $data->get('age');
104
+
105
+ return $userProfile;
106
+ }
107
+ }
hybridauth/library/src/Provider/StackExchangeOpenID.php CHANGED
@@ -1,42 +1,42 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OpenID;
11
-
12
- /**
13
- * StackExchange OpenID provider adapter.
14
- */
15
- class StackExchangeOpenID extends OpenID
16
- {
17
- /**
18
- * {@inheritdoc}
19
- */
20
- protected $openidIdentifier = 'https://openid.stackexchange.com/';
21
-
22
- /**
23
- * {@inheritdoc}
24
- */
25
- protected $apiDocumentation = 'https://openid.stackexchange.com/';
26
-
27
- /**
28
- * {@inheritdoc}
29
- */
30
- public function authenticateFinish()
31
- {
32
- parent::authenticateFinish();
33
-
34
- $userProfile = $this->storage->get($this->providerId . '.user');
35
-
36
- $userProfile->identifier = !empty($userProfile->identifier) ? $userProfile->identifier : $userProfile->email;
37
- $userProfile->emailVerified = $userProfile->email;
38
-
39
- // re store the user profile
40
- $this->storage->set($this->providerId . '.user', $userProfile);
41
- }
42
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OpenID;
11
+
12
+ /**
13
+ * StackExchange OpenID provider adapter.
14
+ */
15
+ class StackExchangeOpenID extends OpenID
16
+ {
17
+ /**
18
+ * {@inheritdoc}
19
+ */
20
+ protected $openidIdentifier = 'https://openid.stackexchange.com/';
21
+
22
+ /**
23
+ * {@inheritdoc}
24
+ */
25
+ protected $apiDocumentation = 'https://openid.stackexchange.com/';
26
+
27
+ /**
28
+ * {@inheritdoc}
29
+ */
30
+ public function authenticateFinish()
31
+ {
32
+ parent::authenticateFinish();
33
+
34
+ $userProfile = $this->storage->get($this->providerId . '.user');
35
+
36
+ $userProfile->identifier = !empty($userProfile->identifier) ? $userProfile->identifier : $userProfile->email;
37
+ $userProfile->emailVerified = $userProfile->email;
38
+
39
+ // re store the user profile
40
+ $this->storage->set($this->providerId . '.user', $userProfile);
41
+ }
42
+ }
hybridauth/library/src/Provider/Steam.php CHANGED
@@ -1,150 +1,150 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OpenID;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Steam OpenID provider adapter.
17
- *
18
- * Example:
19
- *
20
- * $config = [
21
- * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
22
- * 'keys' => [ 'secret' => 'steam-api-key' ]
23
- * ];
24
- *
25
- * $adapter = new Hybridauth\Provider\Steam( $config );
26
- *
27
- * try {
28
- * $adapter->authenticate();
29
- *
30
- * $userProfile = $adapter->getUserProfile();
31
- * }
32
- * catch( \Exception $e ){
33
- * echo $e->getMessage() ;
34
- * }
35
- */
36
- class Steam extends OpenID
37
- {
38
- /**
39
- * {@inheritdoc}
40
- */
41
- protected $openidIdentifier = 'http://steamcommunity.com/openid';
42
-
43
- /**
44
- * {@inheritdoc}
45
- */
46
- protected $apiDocumentation = 'https://steamcommunity.com/dev';
47
-
48
- /**
49
- * {@inheritdoc}
50
- */
51
- public function authenticateFinish()
52
- {
53
- parent::authenticateFinish();
54
-
55
- $userProfile = $this->storage->get($this->providerId . '.user');
56
-
57
- $userProfile->identifier = str_ireplace([
58
- 'http://steamcommunity.com/openid/id/',
59
- 'https://steamcommunity.com/openid/id/',
60
- ], '', $userProfile->identifier);
61
-
62
- if (!$userProfile->identifier) {
63
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
64
- }
65
-
66
- try {
67
- $apiKey = $this->config->filter('keys')->get('secret');
68
-
69
- // if api key is provided, we attempt to use steam web api
70
- if ($apiKey) {
71
- $result = $this->getUserProfileWebAPI($apiKey, $userProfile->identifier);
72
- } else {
73
- // otherwise we fallback to community data
74
- $result = $this->getUserProfileLegacyAPI($userProfile->identifier);
75
- }
76
-
77
- // fetch user profile
78
- foreach ($result as $k => $v) {
79
- $userProfile->$k = $v ?: $userProfile->$k;
80
- }
81
- } catch (\Exception $e) {
82
- }
83
-
84
- // store user profile
85
- $this->storage->set($this->providerId . '.user', $userProfile);
86
- }
87
-
88
- /**
89
- * Fetch user profile on Steam web API
90
- *
91
- * @param $apiKey
92
- * @param $steam64
93
- *
94
- * @return array
95
- */
96
- public function getUserProfileWebAPI($apiKey, $steam64)
97
- {
98
- $q = http_build_query(['key' => $apiKey, 'steamids' => $steam64]);
99
- $apiUrl = 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?' . $q;
100
-
101
- $response = $this->httpClient->request($apiUrl);
102
-
103
- $data = json_decode($response);
104
-
105
- $data = isset($data->response->players[0]) ? $data->response->players[0] : null;
106
-
107
- $data = new Data\Collection($data);
108
-
109
- $userProfile = [];
110
-
111
- $userProfile['displayName'] = (string)$data->get('personaname');
112
- $userProfile['firstName'] = (string)$data->get('realname');
113
- $userProfile['photoURL'] = (string)$data->get('avatarfull');
114
- $userProfile['profileURL'] = (string)$data->get('profileurl');
115
- $userProfile['country'] = (string)$data->get('loccountrycode');
116
-
117
- return $userProfile;
118
- }
119
-
120
- /**
121
- * Fetch user profile on community API
122
- * @param $steam64
123
- * @return array
124
- */
125
- public function getUserProfileLegacyAPI($steam64)
126
- {
127
- libxml_use_internal_errors(false);
128
-
129
- $apiUrl = 'http://steamcommunity.com/profiles/' . $steam64 . '/?xml=1';
130
-
131
- $response = $this->httpClient->request($apiUrl);
132
-
133
- $data = new \SimpleXMLElement($response);
134
-
135
- $data = new Data\Collection($data);
136
-
137
- $userProfile = [];
138
-
139
- $userProfile['displayName'] = (string)$data->get('steamID');
140
- $userProfile['firstName'] = (string)$data->get('realname');
141
- $userProfile['photoURL'] = (string)$data->get('avatarFull');
142
- $userProfile['description'] = (string)$data->get('summary');
143
- $userProfile['region'] = (string)$data->get('location');
144
- $userProfile['profileURL'] = (string)$data->get('customURL')
145
- ? 'http://steamcommunity.com/id/' . (string)$data->get('customURL')
146
- : 'http://steamcommunity.com/profiles/' . $steam64;
147
-
148
- return $userProfile;
149
- }
150
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OpenID;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Steam OpenID provider adapter.
17
+ *
18
+ * Example:
19
+ *
20
+ * $config = [
21
+ * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
22
+ * 'keys' => [ 'secret' => 'steam-api-key' ]
23
+ * ];
24
+ *
25
+ * $adapter = new Hybridauth\Provider\Steam( $config );
26
+ *
27
+ * try {
28
+ * $adapter->authenticate();
29
+ *
30
+ * $userProfile = $adapter->getUserProfile();
31
+ * }
32
+ * catch( \Exception $e ){
33
+ * echo $e->getMessage() ;
34
+ * }
35
+ */
36
+ class Steam extends OpenID
37
+ {
38
+ /**
39
+ * {@inheritdoc}
40
+ */
41
+ protected $openidIdentifier = 'http://steamcommunity.com/openid';
42
+
43
+ /**
44
+ * {@inheritdoc}
45
+ */
46
+ protected $apiDocumentation = 'https://steamcommunity.com/dev';
47
+
48
+ /**
49
+ * {@inheritdoc}
50
+ */
51
+ public function authenticateFinish()
52
+ {
53
+ parent::authenticateFinish();
54
+
55
+ $userProfile = $this->storage->get($this->providerId . '.user');
56
+
57
+ $userProfile->identifier = str_ireplace([
58
+ 'http://steamcommunity.com/openid/id/',
59
+ 'https://steamcommunity.com/openid/id/',
60
+ ], '', $userProfile->identifier);
61
+
62
+ if (!$userProfile->identifier) {
63
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
64
+ }
65
+
66
+ try {
67
+ $apiKey = $this->config->filter('keys')->get('secret');
68
+
69
+ // if api key is provided, we attempt to use steam web api
70
+ if ($apiKey) {
71
+ $result = $this->getUserProfileWebAPI($apiKey, $userProfile->identifier);
72
+ } else {
73
+ // otherwise we fallback to community data
74
+ $result = $this->getUserProfileLegacyAPI($userProfile->identifier);
75
+ }
76
+
77
+ // fetch user profile
78
+ foreach ($result as $k => $v) {
79
+ $userProfile->$k = $v ?: $userProfile->$k;
80
+ }
81
+ } catch (\Exception $e) {
82
+ }
83
+
84
+ // store user profile
85
+ $this->storage->set($this->providerId . '.user', $userProfile);
86
+ }
87
+
88
+ /**
89
+ * Fetch user profile on Steam web API
90
+ *
91
+ * @param $apiKey
92
+ * @param $steam64
93
+ *
94
+ * @return array
95
+ */
96
+ public function getUserProfileWebAPI($apiKey, $steam64)
97
+ {
98
+ $q = http_build_query(['key' => $apiKey, 'steamids' => $steam64]);
99
+ $apiUrl = 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?' . $q;
100
+
101
+ $response = $this->httpClient->request($apiUrl);
102
+
103
+ $data = json_decode($response);
104
+
105
+ $data = isset($data->response->players[0]) ? $data->response->players[0] : null;
106
+
107
+ $data = new Data\Collection($data);
108
+
109
+ $userProfile = [];
110
+
111
+ $userProfile['displayName'] = (string)$data->get('personaname');
112
+ $userProfile['firstName'] = (string)$data->get('realname');
113
+ $userProfile['photoURL'] = (string)$data->get('avatarfull');
114
+ $userProfile['profileURL'] = (string)$data->get('profileurl');
115
+ $userProfile['country'] = (string)$data->get('loccountrycode');
116
+
117
+ return $userProfile;
118
+ }
119
+
120
+ /**
121
+ * Fetch user profile on community API
122
+ * @param $steam64
123
+ * @return array
124
+ */
125
+ public function getUserProfileLegacyAPI($steam64)
126
+ {
127
+ libxml_use_internal_errors(false);
128
+
129
+ $apiUrl = 'http://steamcommunity.com/profiles/' . $steam64 . '/?xml=1';
130
+
131
+ $response = $this->httpClient->request($apiUrl);
132
+
133
+ $data = new \SimpleXMLElement($response);
134
+
135
+ $data = new Data\Collection($data);
136
+
137
+ $userProfile = [];
138
+
139
+ $userProfile['displayName'] = (string)$data->get('steamID');
140
+ $userProfile['firstName'] = (string)$data->get('realname');
141
+ $userProfile['photoURL'] = (string)$data->get('avatarFull');
142
+ $userProfile['description'] = (string)$data->get('summary');
143
+ $userProfile['region'] = (string)$data->get('location');
144
+ $userProfile['profileURL'] = (string)$data->get('customURL')
145
+ ? 'http://steamcommunity.com/id/' . (string)$data->get('customURL')
146
+ : 'http://steamcommunity.com/profiles/' . $steam64;
147
+
148
+ return $userProfile;
149
+ }
150
+ }
hybridauth/library/src/Provider/SteemConnect.php CHANGED
@@ -1,70 +1,70 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Instagram OAuth2 provider adapter.
17
- */
18
- class SteemConnect extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'login,vote';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://v2.steemconnect.com/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://v2.steemconnect.com/oauth2/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://v2.steemconnect.com/api/oauth2/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://steemconnect.com/';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('api/me');
51
-
52
- $data = new Data\Collection($response);
53
-
54
- if (! $data->exists('result')) {
55
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
- }
57
-
58
- $userProfile = new User\Profile();
59
-
60
- $data = $data->filter('result');
61
-
62
- $userProfile->identifier = $data->get('id');
63
- $userProfile->description = $data->get('about');
64
- $userProfile->photoURL = $data->get('profile_image');
65
- $userProfile->webSiteURL = $data->get('website');
66
- $userProfile->displayName = $data->get('name');
67
-
68
- return $userProfile;
69
- }
70
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Instagram OAuth2 provider adapter.
17
+ */
18
+ class SteemConnect extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'login,vote';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://v2.steemconnect.com/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://v2.steemconnect.com/oauth2/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://v2.steemconnect.com/api/oauth2/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://steemconnect.com/';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('api/me');
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ if (! $data->exists('result')) {
55
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
+ }
57
+
58
+ $userProfile = new User\Profile();
59
+
60
+ $data = $data->filter('result');
61
+
62
+ $userProfile->identifier = $data->get('id');
63
+ $userProfile->description = $data->get('about');
64
+ $userProfile->photoURL = $data->get('profile_image');
65
+ $userProfile->webSiteURL = $data->get('website');
66
+ $userProfile->displayName = $data->get('name');
67
+
68
+ return $userProfile;
69
+ }
70
+ }
hybridauth/library/src/Provider/Strava.php CHANGED
@@ -1,72 +1,72 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * GitLab OAuth2 provider adapter.
17
- */
18
- class Strava extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'profile:read_all';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://www.strava.com/api/v3/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://www.strava.com/oauth/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://www.strava.com/oauth/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://developers.strava.com/docs/reference/';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('athlete');
51
-
52
- $data = new Data\Collection($response);
53
-
54
- if (! $data->exists('id')) {
55
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
- }
57
-
58
- $userProfile = new User\Profile();
59
-
60
- $userProfile->identifier = $data->get('id');
61
- $userProfile->firstName = $data->get('firstname');
62
- $userProfile->lastName = $data->get('lastname');
63
- $userProfile->gender = $data->get('sex');
64
- $userProfile->country = $data->get('country');
65
- $userProfile->city = $data->get('city');
66
- $userProfile->email = $data->get('email');
67
-
68
- $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
69
-
70
- return $userProfile;
71
- }
72
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * GitLab OAuth2 provider adapter.
17
+ */
18
+ class Strava extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'profile:read_all';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://www.strava.com/api/v3/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://www.strava.com/oauth/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://www.strava.com/oauth/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://developers.strava.com/docs/reference/';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('athlete');
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ if (! $data->exists('id')) {
55
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
+ }
57
+
58
+ $userProfile = new User\Profile();
59
+
60
+ $userProfile->identifier = $data->get('id');
61
+ $userProfile->firstName = $data->get('firstname');
62
+ $userProfile->lastName = $data->get('lastname');
63
+ $userProfile->gender = $data->get('sex');
64
+ $userProfile->country = $data->get('country');
65
+ $userProfile->city = $data->get('city');
66
+ $userProfile->email = $data->get('email');
67
+
68
+ $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
69
+
70
+ return $userProfile;
71
+ }
72
+ }
hybridauth/library/src/Provider/Telegram.php CHANGED
@@ -1,217 +1,217 @@
1
- <?php
2
-
3
- namespace Hybridauth\Provider;
4
-
5
- use Hybridauth\HttpClient\Util;
6
- use Hybridauth\Data\Collection;
7
- use Hybridauth\User\Profile;
8
- use Hybridauth\Adapter\AbstractAdapter;
9
- use Hybridauth\Adapter\AdapterInterface;
10
- use Hybridauth\Exception\InvalidApplicationCredentialsException;
11
- use Hybridauth\Exception\InvalidAuthorizationCodeException;
12
- use Hybridauth\Exception\UnexpectedApiResponseException;
13
-
14
- /**
15
- * Telegram provider adapter.
16
- *
17
- * To set up Telegram you need to interactively create a bot using the
18
- * Telegram mobile app, talking to botfather. The minimum conversation
19
- * will look like:
20
- *
21
- * /newbot
22
- * My Bot Title
23
- * nameofmynewbot
24
- * /setdomain
25
- * @nameofmynewbot
26
- * mydomain.com
27
- *
28
- * Example:
29
- *
30
- * $config = [
31
- * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
32
- * 'keys' => ['id' => 'your_bot_name', 'secret' => 'your_bot_token'],
33
- * ];
34
- *
35
- * $adapter = new Hybridauth\Provider\Telegram($config);
36
- *
37
- * try {
38
- * $adapter->authenticate();
39
- *
40
- * $userProfile = $adapter->getUserProfile();
41
- * }
42
- * catch(\Exception $e) {
43
- * print $e->getMessage();
44
- * }
45
- */
46
- class Telegram extends AbstractAdapter implements AdapterInterface
47
- {
48
- protected $botId = '';
49
-
50
- protected $botSecret = '';
51
-
52
- protected $callbackUrl = '';
53
-
54
- /**
55
- * {@inheritdoc}
56
- */
57
- protected $apiDocumentation = 'https://core.telegram.org/bots';
58
-
59
- /**
60
- * {@inheritdoc}
61
- */
62
- protected function configure()
63
- {
64
- $this->botId = $this->config->filter('keys')->get('id');
65
- $this->botSecret = $this->config->filter('keys')->get('secret');
66
- $this->callbackUrl = $this->config->get('callback');
67
-
68
- if (!$this->botId || !$this->botSecret) {
69
- throw new InvalidApplicationCredentialsException(
70
- 'Your application id is required in order to connect to ' . $this->providerId
71
- );
72
- }
73
- }
74
-
75
- /**
76
- * {@inheritdoc}
77
- */
78
- protected function initialize()
79
- {
80
- }
81
-
82
- /**
83
- * {@inheritdoc}
84
- */
85
- public function authenticate()
86
- {
87
- $this->logger->info(sprintf('%s::authenticate()', get_class($this)));
88
- if (!filter_input(INPUT_GET, 'hash')) {
89
- $this->authenticateBegin();
90
- } else {
91
- $this->authenticateCheckError();
92
- $this->authenticateFinish();
93
- }
94
- return null;
95
- }
96
-
97
- /**
98
- * {@inheritdoc}
99
- */
100
- public function isConnected()
101
- {
102
- return !empty($this->getStoredData('auth_data'));
103
- }
104
-
105
- /**
106
- * {@inheritdoc}
107
- */
108
- public function getUserProfile()
109
- {
110
- $data = new Collection($this->getStoredData('auth_data'));
111
-
112
- if (!$data->exists('id')) {
113
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
114
- }
115
-
116
- $userProfile = new Profile();
117
-
118
- $userProfile->identifier = $data->get('id');
119
- $userProfile->firstName = $data->get('first_name');
120
- $userProfile->lastName = $data->get('last_name');
121
- $userProfile->displayName = $data->get('username');
122
- $userProfile->photoURL = $data->get('photo_url');
123
- $username = $data->get('username');
124
- if (!empty($username)) {
125
- // Only some accounts have usernames.
126
- $userProfile->profileURL = "https://t.me/{$username}";
127
- }
128
-
129
- return $userProfile;
130
- }
131
-
132
- /**
133
- * See: https://telegram.im/widget-login.php
134
- * See: https://gist.github.com/anonymous/6516521b1fb3b464534fbc30ea3573c2
135
- */
136
- protected function authenticateCheckError()
137
- {
138
- $auth_data = $this->parseAuthData();
139
-
140
- $check_hash = $auth_data['hash'];
141
- unset($auth_data['hash']);
142
- $data_check_arr = [];
143
-
144
- foreach ($auth_data as $key => $value) {
145
- if (!empty($value)) {
146
- $data_check_arr[] = $key . '=' . $value;
147
- }
148
- }
149
- sort($data_check_arr);
150
-
151
- $data_check_string = implode("\n", $data_check_arr);
152
- $secret_key = hash('sha256', $this->botSecret, true);
153
- $hash = hash_hmac('sha256', $data_check_string, $secret_key);
154
-
155
- if (strcmp($hash, $check_hash) !== 0) {
156
- throw new InvalidAuthorizationCodeException(
157
- sprintf('Provider returned an error: %s', 'Data is NOT from Telegram')
158
- );
159
- }
160
-
161
- if ((time() - $auth_data['auth_date']) > 86400) {
162
- throw new InvalidAuthorizationCodeException(
163
- sprintf('Provider returned an error: %s', 'Data is outdated')
164
- );
165
- }
166
- }
167
-
168
- /**
169
- * See: https://telegram.im/widget-login.php
170
- */
171
- protected function authenticateBegin()
172
- {
173
- $this->logger->debug(sprintf('%s::authenticateBegin(), redirecting user to:', get_class($this)));
174
-
175
- $nonce = $this->config->get('nonce');
176
- $nonce_code = empty($nonce) ? '' : "nonce=\"{$nonce}\"";
177
-
178
- exit(
179
- <<<HTML
180
- <center>
181
- <script async src="https://telegram.org/js/telegram-widget.js?7"
182
- {$nonce_code}
183
- data-telegram-login="{$this->botId}"
184
- data-size="large"
185
- data-auth-url="{$this->callbackUrl}"
186
- data-request-access="write">
187
- </script>
188
- </center>
189
- HTML
190
- );
191
- }
192
-
193
- protected function authenticateFinish()
194
- {
195
- $this->logger->debug(
196
- sprintf('%s::authenticateFinish(), callback url:', get_class($this)),
197
- [Util::getCurrentUrl(true)]
198
- );
199
-
200
- $this->storeData('auth_data', $this->parseAuthData());
201
-
202
- $this->initialize();
203
- }
204
-
205
- protected function parseAuthData()
206
- {
207
- return [
208
- 'id' => filter_input(INPUT_GET, 'id'),
209
- 'first_name' => filter_input(INPUT_GET, 'first_name'),
210
- 'last_name' => filter_input(INPUT_GET, 'last_name'),
211
- 'username' => filter_input(INPUT_GET, 'username'),
212
- 'photo_url' => filter_input(INPUT_GET, 'photo_url'),
213
- 'auth_date' => filter_input(INPUT_GET, 'auth_date'),
214
- 'hash' => filter_input(INPUT_GET, 'hash'),
215
- ];
216
- }
217
- }
1
+ <?php
2
+
3
+ namespace Hybridauth\Provider;
4
+
5
+ use Hybridauth\HttpClient\Util;
6
+ use Hybridauth\Data\Collection;
7
+ use Hybridauth\User\Profile;
8
+ use Hybridauth\Adapter\AbstractAdapter;
9
+ use Hybridauth\Adapter\AdapterInterface;
10
+ use Hybridauth\Exception\InvalidApplicationCredentialsException;
11
+ use Hybridauth\Exception\InvalidAuthorizationCodeException;
12
+ use Hybridauth\Exception\UnexpectedApiResponseException;
13
+
14
+ /**
15
+ * Telegram provider adapter.
16
+ *
17
+ * To set up Telegram you need to interactively create a bot using the
18
+ * Telegram mobile app, talking to botfather. The minimum conversation
19
+ * will look like:
20
+ *
21
+ * /newbot
22
+ * My Bot Title
23
+ * nameofmynewbot
24
+ * /setdomain
25
+ * @nameofmynewbot
26
+ * mydomain.com
27
+ *
28
+ * Example:
29
+ *
30
+ * $config = [
31
+ * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
32
+ * 'keys' => ['id' => 'your_bot_name', 'secret' => 'your_bot_token'],
33
+ * ];
34
+ *
35
+ * $adapter = new Hybridauth\Provider\Telegram($config);
36
+ *
37
+ * try {
38
+ * $adapter->authenticate();
39
+ *
40
+ * $userProfile = $adapter->getUserProfile();
41
+ * }
42
+ * catch(\Exception $e) {
43
+ * print $e->getMessage();
44
+ * }
45
+ */
46
+ class Telegram extends AbstractAdapter implements AdapterInterface
47
+ {
48
+ protected $botId = '';
49
+
50
+ protected $botSecret = '';
51
+
52
+ protected $callbackUrl = '';
53
+
54
+ /**
55
+ * {@inheritdoc}
56
+ */
57
+ protected $apiDocumentation = 'https://core.telegram.org/bots';
58
+
59
+ /**
60
+ * {@inheritdoc}
61
+ */
62
+ protected function configure()
63
+ {
64
+ $this->botId = $this->config->filter('keys')->get('id');
65
+ $this->botSecret = $this->config->filter('keys')->get('secret');
66
+ $this->callbackUrl = $this->config->get('callback');
67
+
68
+ if (!$this->botId || !$this->botSecret) {
69
+ throw new InvalidApplicationCredentialsException(
70
+ 'Your application id is required in order to connect to ' . $this->providerId
71
+ );
72
+ }
73
+ }
74
+
75
+ /**
76
+ * {@inheritdoc}
77
+ */
78
+ protected function initialize()
79
+ {
80
+ }
81
+
82
+ /**
83
+ * {@inheritdoc}
84
+ */
85
+ public function authenticate()
86
+ {
87
+ $this->logger->info(sprintf('%s::authenticate()', get_class($this)));
88
+ if (!filter_input(INPUT_GET, 'hash')) {
89
+ $this->authenticateBegin();
90
+ } else {
91
+ $this->authenticateCheckError();
92
+ $this->authenticateFinish();
93
+ }
94
+ return null;
95
+ }
96
+
97
+ /**
98
+ * {@inheritdoc}
99
+ */
100
+ public function isConnected()
101
+ {
102
+ return !empty($this->getStoredData('auth_data'));
103
+ }
104
+
105
+ /**
106
+ * {@inheritdoc}
107
+ */
108
+ public function getUserProfile()
109
+ {
110
+ $data = new Collection($this->getStoredData('auth_data'));
111
+
112
+ if (!$data->exists('id')) {
113
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
114
+ }
115
+
116
+ $userProfile = new Profile();
117
+
118
+ $userProfile->identifier = $data->get('id');
119
+ $userProfile->firstName = $data->get('first_name');
120
+ $userProfile->lastName = $data->get('last_name');
121
+ $userProfile->displayName = $data->get('username');
122
+ $userProfile->photoURL = $data->get('photo_url');
123
+ $username = $data->get('username');
124
+ if (!empty($username)) {
125
+ // Only some accounts have usernames.
126
+ $userProfile->profileURL = "https://t.me/{$username}";
127
+ }
128
+
129
+ return $userProfile;
130
+ }
131
+
132
+ /**
133
+ * See: https://telegram.im/widget-login.php
134
+ * See: https://gist.github.com/anonymous/6516521b1fb3b464534fbc30ea3573c2
135
+ */
136
+ protected function authenticateCheckError()
137
+ {
138
+ $auth_data = $this->parseAuthData();
139
+
140
+ $check_hash = $auth_data['hash'];
141
+ unset($auth_data['hash']);
142
+ $data_check_arr = [];
143
+
144
+ foreach ($auth_data as $key => $value) {
145
+ if (!empty($value)) {
146
+ $data_check_arr[] = $key . '=' . $value;
147
+ }
148
+ }
149
+ sort($data_check_arr);
150
+
151
+ $data_check_string = implode("\n", $data_check_arr);
152
+ $secret_key = hash('sha256', $this->botSecret, true);
153
+ $hash = hash_hmac('sha256', $data_check_string, $secret_key);
154
+
155
+ if (strcmp($hash, $check_hash) !== 0) {
156
+ throw new InvalidAuthorizationCodeException(
157
+ sprintf('Provider returned an error: %s', 'Data is NOT from Telegram')
158
+ );
159
+ }
160
+
161
+ if ((time() - $auth_data['auth_date']) > 86400) {
162
+ throw new InvalidAuthorizationCodeException(
163
+ sprintf('Provider returned an error: %s', 'Data is outdated')
164
+ );
165
+ }
166
+ }
167
+
168
+ /**
169
+ * See: https://telegram.im/widget-login.php
170
+ */
171
+ protected function authenticateBegin()
172
+ {
173
+ $this->logger->debug(sprintf('%s::authenticateBegin(), redirecting user to:', get_class($this)));
174
+
175
+ $nonce = $this->config->get('nonce');
176
+ $nonce_code = empty($nonce) ? '' : "nonce=\"{$nonce}\"";
177
+
178
+ exit(
179
+ <<<HTML
180
+ <center>
181
+ <script async src="https://telegram.org/js/telegram-widget.js?7"
182
+ {$nonce_code}
183
+ data-telegram-login="{$this->botId}"
184
+ data-size="large"
185
+ data-auth-url="{$this->callbackUrl}"
186
+ data-request-access="write">
187
+ </script>
188
+ </center>
189
+ HTML
190
+ );
191
+ }
192
+
193
+ protected function authenticateFinish()
194
+ {
195
+ $this->logger->debug(
196
+ sprintf('%s::authenticateFinish(), callback url:', get_class($this)),
197
+ [Util::getCurrentUrl(true)]
198
+ );
199
+
200
+ $this->storeData('auth_data', $this->parseAuthData());
201
+
202
+ $this->initialize();
203
+ }
204
+
205
+ protected function parseAuthData()
206
+ {
207
+ return [
208
+ 'id' => filter_input(INPUT_GET, 'id'),
209
+ 'first_name' => filter_input(INPUT_GET, 'first_name'),
210
+ 'last_name' => filter_input(INPUT_GET, 'last_name'),
211
+ 'username' => filter_input(INPUT_GET, 'username'),
212
+ 'photo_url' => filter_input(INPUT_GET, 'photo_url'),
213
+ 'auth_date' => filter_input(INPUT_GET, 'auth_date'),
214
+ 'hash' => filter_input(INPUT_GET, 'hash'),
215
+ ];
216
+ }
217
+ }
hybridauth/library/src/Provider/Tumblr.php CHANGED
@@ -1,97 +1,97 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth1;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Tumblr OAuth1 provider adapter.
17
- */
18
- class Tumblr extends OAuth1
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $apiBaseUrl = 'https://api.tumblr.com/v2/';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $authorizeUrl = 'https://www.tumblr.com/oauth/authorize';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $requestTokenUrl = 'https://www.tumblr.com/oauth/request_token';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://www.tumblr.com/oauth/access_token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://www.tumblr.com/docs/en/api/v2';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('user/info');
51
-
52
- $data = new Data\Collection($response);
53
-
54
- if (! $data->exists('response')) {
55
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
- }
57
-
58
- $userProfile = new User\Profile();
59
-
60
- $userProfile->displayName = $data->filter('response')->filter('user')->get('name');
61
-
62
- foreach ($data->filter('response')->filter('user')->filter('blogs')->toArray() as $blog) {
63
- $blog = new Data\Collection($blog);
64
-
65
- if ($blog->get('primary') && $blog->exists('url')) {
66
- $userProfile->identifier = $blog->get('url');
67
- $userProfile->profileURL = $blog->get('url');
68
- $userProfile->webSiteURL = $blog->get('url');
69
- $userProfile->description = strip_tags($blog->get('description'));
70
-
71
- $bloghostname = explode('://', $blog->get('url'));
72
- $bloghostname = substr($bloghostname[1], 0, -1);
73
-
74
- // store user's primary blog which will be used as target by setUserStatus
75
- $this->storeData('primary_blog', $bloghostname);
76
-
77
- break;
78
- }
79
- }
80
-
81
- return $userProfile;
82
- }
83
-
84
- /**
85
- * {@inheritdoc}
86
- */
87
- public function setUserStatus($status)
88
- {
89
- $status = is_string($status)
90
- ? [ 'type' => 'text', 'body' => $status ]
91
- : $status;
92
-
93
- $response = $this->apiRequest('blog/' . $this->getStoredData('primary_blog') . '/post', 'POST', $status);
94
-
95
- return $response;
96
- }
97
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth1;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Tumblr OAuth1 provider adapter.
17
+ */
18
+ class Tumblr extends OAuth1
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $apiBaseUrl = 'https://api.tumblr.com/v2/';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $authorizeUrl = 'https://www.tumblr.com/oauth/authorize';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $requestTokenUrl = 'https://www.tumblr.com/oauth/request_token';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://www.tumblr.com/oauth/access_token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://www.tumblr.com/docs/en/api/v2';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('user/info');
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ if (! $data->exists('response')) {
55
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
+ }
57
+
58
+ $userProfile = new User\Profile();
59
+
60
+ $userProfile->displayName = $data->filter('response')->filter('user')->get('name');
61
+
62
+ foreach ($data->filter('response')->filter('user')->filter('blogs')->toArray() as $blog) {
63
+ $blog = new Data\Collection($blog);
64
+
65
+ if ($blog->get('primary') && $blog->exists('url')) {
66
+ $userProfile->identifier = $blog->get('url');
67
+ $userProfile->profileURL = $blog->get('url');
68
+ $userProfile->webSiteURL = $blog->get('url');
69
+ $userProfile->description = strip_tags($blog->get('description'));
70
+
71
+ $bloghostname = explode('://', $blog->get('url'));
72
+ $bloghostname = substr($bloghostname[1], 0, -1);
73
+
74
+ // store user's primary blog which will be used as target by setUserStatus
75
+ $this->storeData('primary_blog', $bloghostname);
76
+
77
+ break;
78
+ }
79
+ }
80
+
81
+ return $userProfile;
82
+ }
83
+
84
+ /**
85
+ * {@inheritdoc}
86
+ */
87
+ public function setUserStatus($status)
88
+ {
89
+ $status = is_string($status)
90
+ ? [ 'type' => 'text', 'body' => $status ]
91
+ : $status;
92
+
93
+ $response = $this->apiRequest('blog/' . $this->getStoredData('primary_blog') . '/post', 'POST', $status);
94
+
95
+ return $response;
96
+ }
97
+ }
hybridauth/library/src/Provider/TwitchTV.php CHANGED
@@ -1,82 +1,82 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * TwitchTV OAuth2 provider adapter.
17
- */
18
- class TwitchTV extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'user:read:email';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://api.twitch.tv/helix/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://id.twitch.tv/oauth2/authorize';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://id.twitch.tv/oauth2/token';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://dev.twitch.tv/docs/authentication/';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected function initialize()
49
- {
50
- parent::initialize();
51
-
52
- $this->apiRequestHeaders['Client-ID'] = $this->clientId;
53
- }
54
-
55
- /**
56
- * {@inheritdoc}
57
- */
58
- public function getUserProfile()
59
- {
60
- $response = $this->apiRequest('users');
61
-
62
- $data = new Data\Collection($response);
63
-
64
- if (!$data->exists('data')) {
65
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
66
- }
67
-
68
- $users = $data->filter('data')->values();
69
- $user = new Data\Collection($users[0]);
70
-
71
- $userProfile = new User\Profile();
72
-
73
- $userProfile->identifier = $user->get('id');
74
- $userProfile->displayName = $user->get('display_name');
75
- $userProfile->photoURL = $user->get('profile_image_url');
76
- $userProfile->email = $user->get('email');
77
- $userProfile->description = strip_tags($user->get('description'));
78
- $userProfile->profileURL = "https://www.twitch.tv/{$userProfile->displayName}";
79
-
80
- return $userProfile;
81
- }
82
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * TwitchTV OAuth2 provider adapter.
17
+ */
18
+ class TwitchTV extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'user:read:email';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://api.twitch.tv/helix/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://id.twitch.tv/oauth2/authorize';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://id.twitch.tv/oauth2/token';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://dev.twitch.tv/docs/authentication/';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function initialize()
49
+ {
50
+ parent::initialize();
51
+
52
+ $this->apiRequestHeaders['Client-ID'] = $this->clientId;
53
+ }
54
+
55
+ /**
56
+ * {@inheritdoc}
57
+ */
58
+ public function getUserProfile()
59
+ {
60
+ $response = $this->apiRequest('users');
61
+
62
+ $data = new Data\Collection($response);
63
+
64
+ if (!$data->exists('data')) {
65
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
66
+ }
67
+
68
+ $users = $data->filter('data')->values();
69
+ $user = new Data\Collection($users[0]);
70
+
71
+ $userProfile = new User\Profile();
72
+
73
+ $userProfile->identifier = $user->get('id');
74
+ $userProfile->displayName = $user->get('display_name');
75
+ $userProfile->photoURL = $user->get('profile_image_url');
76
+ $userProfile->email = $user->get('email');
77
+ $userProfile->description = strip_tags($user->get('description'));
78
+ $userProfile->profileURL = "https://www.twitch.tv/{$userProfile->displayName}";
79
+
80
+ return $userProfile;
81
+ }
82
+ }
hybridauth/library/src/Provider/Twitter.php CHANGED
@@ -1,265 +1,265 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth1;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Twitter OAuth1 provider adapter.
17
- * Uses OAuth1 not OAuth2 because many Twitter endpoints are built around OAuth1.
18
- *
19
- * Example:
20
- *
21
- * $config = [
22
- * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
23
- * 'keys' => [ 'key' => '', 'secret' => '' ], // OAuth1 uses 'key' not 'id'
24
- * 'authorize' => true // Needed to perform actions on behalf of users (see below link)
25
- * // https://developer.twitter.com/en/docs/authentication/oauth-1-0a/obtaining-user-access-tokens
26
- * ];
27
- *
28
- * $adapter = new Hybridauth\Provider\Twitter( $config );
29
- *
30
- * try {
31
- * $adapter->authenticate();
32
- *
33
- * $userProfile = $adapter->getUserProfile();
34
- * $tokens = $adapter->getAccessToken();
35
- * $contacts = $adapter->getUserContacts(['screen_name' =>'andypiper']); // get those of @andypiper
36
- * $activity = $adapter->getUserActivity('me');
37
- * }
38
- * catch( Exception $e ){
39
- * echo $e->getMessage() ;
40
- * }
41
- */
42
- class Twitter extends OAuth1
43
- {
44
- /**
45
- * {@inheritdoc}
46
- */
47
- protected $apiBaseUrl = 'https://api.twitter.com/1.1/';
48
-
49
- /**
50
- * {@inheritdoc}
51
- */
52
- protected $authorizeUrl = 'https://api.twitter.com/oauth/authenticate';
53
-
54
- /**
55
- * {@inheritdoc}
56
- */
57
- protected $requestTokenUrl = 'https://api.twitter.com/oauth/request_token';
58
-
59
- /**
60
- * {@inheritdoc}
61
- */
62
- protected $accessTokenUrl = 'https://api.twitter.com/oauth/access_token';
63
-
64
- /**
65
- * {@inheritdoc}
66
- */
67
- protected $apiDocumentation = 'https://dev.twitter.com/web/sign-in/implementing';
68
-
69
- /**
70
- * {@inheritdoc}
71
- */
72
- protected function getAuthorizeUrl($parameters = [])
73
- {
74
- if ($this->config->get('authorize') === true) {
75
- $this->authorizeUrl = 'https://api.twitter.com/oauth/authorize';
76
- }
77
-
78
- return parent::getAuthorizeUrl($parameters);
79
- }
80
-
81
- /**
82
- * {@inheritdoc}
83
- */
84
- public function getUserProfile()
85
- {
86
- $response = $this->apiRequest('account/verify_credentials.json', 'GET', [
87
- 'include_email' => $this->config->get('include_email') === false ? 'false' : 'true',
88
- ]);
89
-
90
- $data = new Data\Collection($response);
91
-
92
- if (!$data->exists('id_str')) {
93
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
94
- }
95
-
96
- $userProfile = new User\Profile();
97
-
98
- $userProfile->identifier = $data->get('id_str');
99
- $userProfile->displayName = $data->get('screen_name');
100
- $userProfile->description = $data->get('description');
101
- $userProfile->firstName = $data->get('name');
102
- $userProfile->email = $data->get('email');
103
- $userProfile->emailVerified = $data->get('email');
104
- $userProfile->webSiteURL = $data->get('url');
105
- $userProfile->region = $data->get('location');
106
-
107
- $userProfile->profileURL = $data->exists('screen_name')
108
- ? ('http://twitter.com/' . $data->get('screen_name'))
109
- : '';
110
-
111
- $photoSize = $this->config->get('photo_size') ?: 'original';
112
- $photoSize = $photoSize === 'original' ? '' : "_{$photoSize}";
113
- $userProfile->photoURL = $data->exists('profile_image_url_https')
114
- ? str_replace('_normal', $photoSize, $data->get('profile_image_url_https'))
115
- : '';
116
-
117
- $userProfile->data = [
118
- 'followed_by' => $data->get('followers_count'),
119
- 'follows' => $data->get('friends_count'),
120
- ];
121
-
122
- return $userProfile;
123
- }
124
-
125
- /**
126
- * {@inheritdoc}
127
- */
128
- public function getUserContacts($parameters = [])
129
- {
130
- $parameters = [ 'cursor' => '-1'] + $parameters;
131
-
132
- $response = $this->apiRequest('friends/ids.json', 'GET', $parameters);
133
-
134
- $data = new Data\Collection($response);
135
-
136
- if (! $data->exists('ids')) {
137
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
138
- }
139
-
140
- if ($data->filter('ids')->isEmpty()) {
141
- return [];
142
- }
143
-
144
- $contacts = [];
145
-
146
- // 75 id per time should be okey
147
- $contactsIds = array_chunk((array) $data->get('ids'), 75);
148
-
149
- foreach ($contactsIds as $chunk) {
150
- $parameters = [ 'user_id' => implode(',', $chunk) ];
151
-
152
- try {
153
- $response = $this->apiRequest('users/lookup.json', 'GET', $parameters);
154
-
155
- if ($response && count($response)) {
156
- foreach ($response as $item) {
157
- $contacts[] = $this->fetchUserContact($item);
158
- }
159
- }
160
- } catch (\Exception $e) {
161
- continue;
162
- }
163
- }
164
-
165
- return $contacts;
166
- }
167
-
168
- /**
169
- * @param $item
170
- *
171
- * @return User\Contact
172
- */
173
- protected function fetchUserContact($item)
174
- {
175
- $item = new Data\Collection($item);
176
-
177
- $userContact = new User\Contact();
178
-
179
- $userContact->identifier = $item->get('id_str');
180
- $userContact->displayName = $item->get('name');
181
- $userContact->photoURL = $item->get('profile_image_url');
182
- $userContact->description = $item->get('description');
183
-
184
- $userContact->profileURL = $item->exists('screen_name')
185
- ? ('http://twitter.com/' . $item->get('screen_name'))
186
- : '';
187
-
188
- return $userContact;
189
- }
190
-
191
- /**
192
- * {@inheritdoc}
193
- */
194
- public function setUserStatus($status)
195
- {
196
- if (is_string($status)) {
197
- $status = ['status' => $status];
198
- }
199
-
200
- // Prepare request parameters.
201
- $params = [];
202
- if (isset($status['status'])) {
203
- $params['status'] = $status['status'];
204
- }
205
- if (isset($status['picture'])) {
206
- $media = $this->apiRequest('https://upload.twitter.com/1.1/media/upload.json', 'POST', [
207
- 'media' => base64_encode(file_get_contents($status['picture'])),
208
- ]);
209
- $params['media_ids'] = $media->media_id;
210
- }
211
-
212
- $response = $this->apiRequest('statuses/update.json', 'POST', $params);
213
-
214
- return $response;
215
- }
216
-
217
- /**
218
- * {@inheritdoc}
219
- */
220
- public function getUserActivity($stream = 'me')
221
- {
222
- $apiUrl = ($stream == 'me')
223
- ? 'statuses/user_timeline.json'
224
- : 'statuses/home_timeline.json';
225
-
226
- $response = $this->apiRequest($apiUrl);
227
-
228
- if (!$response) {
229
- return [];
230
- }
231
-
232
- $activities = [];
233
-
234
- foreach ($response as $item) {
235
- $activities[] = $this->fetchUserActivity($item);
236
- }
237
-
238
- return $activities;
239
- }
240
-
241
- /**
242
- * @param $item
243
- * @return User\Activity
244
- */
245
- protected function fetchUserActivity($item)
246
- {
247
- $item = new Data\Collection($item);
248
-
249
- $userActivity = new User\Activity();
250
-
251
- $userActivity->id = $item->get('id_str');
252
- $userActivity->date = $item->get('created_at');
253
- $userActivity->text = $item->get('text');
254
-
255
- $userActivity->user->identifier = $item->filter('user')->get('id_str');
256
- $userActivity->user->displayName = $item->filter('user')->get('name');
257
- $userActivity->user->photoURL = $item->filter('user')->get('profile_image_url');
258
-
259
- $userActivity->user->profileURL = $item->filter('user')->get('screen_name')
260
- ? ('http://twitter.com/' . $item->filter('user')->get('screen_name'))
261
- : '';
262
-
263
- return $userActivity;
264
- }
265
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth1;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Twitter OAuth1 provider adapter.
17
+ * Uses OAuth1 not OAuth2 because many Twitter endpoints are built around OAuth1.
18
+ *
19
+ * Example:
20
+ *
21
+ * $config = [
22
+ * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
23
+ * 'keys' => [ 'key' => '', 'secret' => '' ], // OAuth1 uses 'key' not 'id'
24
+ * 'authorize' => true // Needed to perform actions on behalf of users (see below link)
25
+ * // https://developer.twitter.com/en/docs/authentication/oauth-1-0a/obtaining-user-access-tokens
26
+ * ];
27
+ *
28
+ * $adapter = new Hybridauth\Provider\Twitter( $config );
29
+ *
30
+ * try {
31
+ * $adapter->authenticate();
32
+ *
33
+ * $userProfile = $adapter->getUserProfile();
34
+ * $tokens = $adapter->getAccessToken();
35
+ * $contacts = $adapter->getUserContacts(['screen_name' =>'andypiper']); // get those of @andypiper
36
+ * $activity = $adapter->getUserActivity('me');
37
+ * }
38
+ * catch( Exception $e ){
39
+ * echo $e->getMessage() ;
40
+ * }
41
+ */
42
+ class Twitter extends OAuth1
43
+ {
44
+ /**
45
+ * {@inheritdoc}
46
+ */
47
+ protected $apiBaseUrl = 'https://api.twitter.com/1.1/';
48
+
49
+ /**
50
+ * {@inheritdoc}
51
+ */
52
+ protected $authorizeUrl = 'https://api.twitter.com/oauth/authenticate';
53
+
54
+ /**
55
+ * {@inheritdoc}
56
+ */
57
+ protected $requestTokenUrl = 'https://api.twitter.com/oauth/request_token';
58
+
59
+ /**
60
+ * {@inheritdoc}
61
+ */
62
+ protected $accessTokenUrl = 'https://api.twitter.com/oauth/access_token';
63
+
64
+ /**
65
+ * {@inheritdoc}
66
+ */
67
+ protected $apiDocumentation = 'https://dev.twitter.com/web/sign-in/implementing';
68
+
69
+ /**
70
+ * {@inheritdoc}
71
+ */
72
+ protected function getAuthorizeUrl($parameters = [])
73
+ {
74
+ if ($this->config->get('authorize') === true) {
75
+ $this->authorizeUrl = 'https://api.twitter.com/oauth/authorize';
76
+ }
77
+
78
+ return parent::getAuthorizeUrl($parameters);
79
+ }
80
+
81
+ /**
82
+ * {@inheritdoc}
83
+ */
84
+ public function getUserProfile()
85
+ {
86
+ $response = $this->apiRequest('account/verify_credentials.json', 'GET', [
87
+ 'include_email' => $this->config->get('include_email') === false ? 'false' : 'true',
88
+ ]);
89
+
90
+ $data = new Data\Collection($response);
91
+
92
+ if (!$data->exists('id_str')) {
93
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
94
+ }
95
+
96
+ $userProfile = new User\Profile();
97
+
98
+ $userProfile->identifier = $data->get('id_str');
99
+ $userProfile->displayName = $data->get('screen_name');
100
+ $userProfile->description = $data->get('description');
101
+ $userProfile->firstName = $data->get('name');
102
+ $userProfile->email = $data->get('email');
103
+ $userProfile->emailVerified = $data->get('email');
104
+ $userProfile->webSiteURL = $data->get('url');
105
+ $userProfile->region = $data->get('location');
106
+
107
+ $userProfile->profileURL = $data->exists('screen_name')
108
+ ? ('http://twitter.com/' . $data->get('screen_name'))
109
+ : '';
110
+
111
+ $photoSize = $this->config->get('photo_size') ?: 'original';
112
+ $photoSize = $photoSize === 'original' ? '' : "_{$photoSize}";
113
+ $userProfile->photoURL = $data->exists('profile_image_url_https')
114
+ ? str_replace('_normal', $photoSize, $data->get('profile_image_url_https'))
115
+ : '';
116
+
117
+ $userProfile->data = [
118
+ 'followed_by' => $data->get('followers_count'),
119
+ 'follows' => $data->get('friends_count'),
120
+ ];
121
+
122
+ return $userProfile;
123
+ }
124
+
125
+ /**
126
+ * {@inheritdoc}
127
+ */
128
+ public function getUserContacts($parameters = [])
129
+ {
130
+ $parameters = [ 'cursor' => '-1'] + $parameters;
131
+
132
+ $response = $this->apiRequest('friends/ids.json', 'GET', $parameters);
133
+
134
+ $data = new Data\Collection($response);
135
+
136
+ if (! $data->exists('ids')) {
137
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
138
+ }
139
+
140
+ if ($data->filter('ids')->isEmpty()) {
141
+ return [];
142
+ }
143
+
144
+ $contacts = [];
145
+
146
+ // 75 id per time should be okey
147
+ $contactsIds = array_chunk((array) $data->get('ids'), 75);
148
+
149
+ foreach ($contactsIds as $chunk) {
150
+ $parameters = [ 'user_id' => implode(',', $chunk) ];
151
+
152
+ try {
153
+ $response = $this->apiRequest('users/lookup.json', 'GET', $parameters);
154
+
155
+ if ($response && count($response)) {
156
+ foreach ($response as $item) {
157
+ $contacts[] = $this->fetchUserContact($item);
158
+ }
159
+ }
160
+ } catch (\Exception $e) {
161
+ continue;
162
+ }
163
+ }
164
+
165
+ return $contacts;
166
+ }
167
+
168
+ /**
169
+ * @param $item
170
+ *
171
+ * @return User\Contact
172
+ */
173
+ protected function fetchUserContact($item)
174
+ {
175
+ $item = new Data\Collection($item);
176
+
177
+ $userContact = new User\Contact();
178
+
179
+ $userContact->identifier = $item->get('id_str');
180
+ $userContact->displayName = $item->get('name');
181
+ $userContact->photoURL = $item->get('profile_image_url');
182
+ $userContact->description = $item->get('description');
183
+
184
+ $userContact->profileURL = $item->exists('screen_name')
185
+ ? ('http://twitter.com/' . $item->get('screen_name'))
186
+ : '';
187
+
188
+ return $userContact;
189
+ }
190
+
191
+ /**
192
+ * {@inheritdoc}
193
+ */
194
+ public function setUserStatus($status)
195
+ {
196
+ if (is_string($status)) {
197
+ $status = ['status' => $status];
198
+ }
199
+
200
+ // Prepare request parameters.
201
+ $params = [];
202
+ if (isset($status['status'])) {
203
+ $params['status'] = $status['status'];
204
+ }
205
+ if (isset($status['picture'])) {
206
+ $media = $this->apiRequest('https://upload.twitter.com/1.1/media/upload.json', 'POST', [
207
+ 'media' => base64_encode(file_get_contents($status['picture'])),
208
+ ]);
209
+ $params['media_ids'] = $media->media_id;
210
+ }
211
+
212
+ $response = $this->apiRequest('statuses/update.json', 'POST', $params);
213
+
214
+ return $response;
215
+ }
216
+
217
+ /**
218
+ * {@inheritdoc}
219
+ */
220
+ public function getUserActivity($stream = 'me')
221
+ {
222
+ $apiUrl = ($stream == 'me')
223
+ ? 'statuses/user_timeline.json'
224
+ : 'statuses/home_timeline.json';
225
+
226
+ $response = $this->apiRequest($apiUrl);
227
+
228
+ if (!$response) {
229
+ return [];
230
+ }
231
+
232
+ $activities = [];
233
+
234
+ foreach ($response as $item) {
235
+ $activities[] = $this->fetchUserActivity($item);
236
+ }
237
+
238
+ return $activities;
239
+ }
240
+
241
+ /**
242
+ * @param $item
243
+ * @return User\Activity
244
+ */
245
+ protected function fetchUserActivity($item)
246
+ {
247
+ $item = new Data\Collection($item);
248
+
249
+ $userActivity = new User\Activity();
250
+
251
+ $userActivity->id = $item->get('id_str');
252
+ $userActivity->date = $item->get('created_at');
253
+ $userActivity->text = $item->get('text');
254
+
255
+ $userActivity->user->identifier = $item->filter('user')->get('id_str');
256
+ $userActivity->user->displayName = $item->filter('user')->get('name');
257
+ $userActivity->user->photoURL = $item->filter('user')->get('profile_image_url');
258
+
259
+ $userActivity->user->profileURL = $item->filter('user')->get('screen_name')
260
+ ? ('http://twitter.com/' . $item->filter('user')->get('screen_name'))
261
+ : '';
262
+
263
+ return $userActivity;
264
+ }
265
+ }
hybridauth/library/src/Provider/Vkontakte.php CHANGED
@@ -1,217 +1,217 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data\Collection;
13
- use Hybridauth\User\Profile;
14
- use Hybridauth\Data;
15
- use Hybridauth\User;
16
-
17
- /**
18
- * Vkontakte OAuth2 provider adapter.
19
- *
20
- * Example:
21
- *
22
- * $config = [
23
- * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
24
- * 'keys' => [
25
- * 'id' => '', // App ID
26
- * 'secret' => '' // Secure key
27
- * ],
28
- * ];
29
- *
30
- * $adapter = new Hybridauth\Provider\Vkontakte($config);
31
- *
32
- * try {
33
- * if (!$adapter->isConnected()) {
34
- * $adapter->authenticate();
35
- * }
36
- *
37
- * $userProfile = $adapter->getUserProfile();
38
- * }
39
- * catch(\Exception $e) {
40
- * print $e->getMessage() ;
41
- * }
42
- */
43
- class Vkontakte extends OAuth2
44
- {
45
- const API_VERSION = '5.95';
46
-
47
- const URL = 'https://vk.com/';
48
-
49
- /**
50
- * {@inheritdoc}
51
- */
52
- protected $apiBaseUrl = 'https://api.vk.com/method/';
53
-
54
- /**
55
- * {@inheritdoc}
56
- */
57
- protected $authorizeUrl = 'https://api.vk.com/oauth/authorize';
58
-
59
- /**
60
- * {@inheritdoc}
61
- */
62
- protected $accessTokenUrl = 'https://api.vk.com/oauth/token';
63
-
64
- /**
65
- * {@inheritdoc}
66
- */
67
- protected $scope = 'email,offline';
68
-
69
- /**
70
- * {@inheritdoc}
71
- */
72
- protected $apiDocumentation = ''; // Not available
73
-
74
- /**
75
- * {@inheritdoc}
76
- */
77
- protected function initialize()
78
- {
79
- parent::initialize();
80
-
81
- // The VK API requires version and access_token from authenticated users
82
- // for each endpoint.
83
- $accessToken = $this->getStoredData($this->accessTokenName);
84
- $this->apiRequestParameters[$this->accessTokenName] = $accessToken;
85
- $this->apiRequestParameters['v'] = static::API_VERSION;
86
- }
87
-
88
- /**
89
- * {@inheritdoc}
90
- */
91
- protected function validateAccessTokenExchange($response)
92
- {
93
- $data = parent::validateAccessTokenExchange($response);
94
-
95
- // Need to store email for later use.
96
- $this->storeData('email', $data->get('email'));
97
- }
98
-
99
- /**
100
- * {@inheritdoc}
101
- */
102
- public function hasAccessTokenExpired($time = null)
103
- {
104
- if ($time === null) {
105
- $time = time();
106
- }
107
-
108
- // If we are using offline scope, $expired will be false.
109
- $expired = $this->getStoredData('expires_in')
110
- ? $this->getStoredData('expires_at') <= $time
111
- : false;
112
-
113
- return $expired;
114
- }
115
-
116
- /**
117
- * {@inheritdoc}
118
- */
119
- public function getUserProfile()
120
- {
121
- $photoField = 'photo_' . ($this->config->get('photo_size') ?: 'max_orig');
122
-
123
- $response = $this->apiRequest('users.get', 'GET', [
124
- 'fields' => 'screen_name,sex,education,bdate,has_photo,' . $photoField,
125
- ]);
126
-
127
- if (property_exists($response, 'error')) {
128
- throw new UnexpectedApiResponseException($response->error->error_msg);
129
- }
130
-
131
- $data = new Collection($response->response[0]);
132
-
133
- if (!$data->exists('id')) {
134
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
135
- }
136
-
137
- $userProfile = new Profile();
138
-
139
- $userProfile->identifier = $data->get('id');
140
- $userProfile->email = $this->getStoredData('email');
141
- $userProfile->firstName = $data->get('first_name');
142
- $userProfile->lastName = $data->get('last_name');
143
- $userProfile->displayName = $data->get('screen_name');
144
- $userProfile->photoURL = $data->get('has_photo') === 1 ? $data->get($photoField) : '';
145
-
146
- // Handle b-date.
147
- if ($data->get('bdate')) {
148
- $bday = explode('.', $data->get('bdate'));
149
- $userProfile->birthDay = (int) $bday[0];
150
- $userProfile->birthMonth = (int) $bday[1];
151
- $userProfile->birthYear = (int) $bday[2];
152
- }
153
-
154
- $userProfile->data = [
155
- 'education' => $data->get('education'),
156
- ];
157
-
158
- $screen_name = static::URL . ($data->get('screen_name') ?: 'id' . $data->get('id'));
159
- $userProfile->profileURL = $screen_name;
160
-
161
- switch ($data->get('sex')) {
162
- case 1:
163
- $userProfile->gender = 'female';
164
- break;
165
-
166
- case 2:
167
- $userProfile->gender = 'male';
168
- break;
169
- }
170
-
171
- return $userProfile;
172
- }
173
-
174
- /**
175
- * {@inheritdoc}
176
- */
177
- public function getUserContacts()
178
- {
179
- $response = $this->apiRequest('friends.get', 'GET', [
180
- 'fields' => 'uid,name,photo_200_orig',
181
- ]);
182
-
183
- $data = new Data\Collection($response);
184
- if (!$data->exists('response')) {
185
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
186
- }
187
-
188
- $contacts = [];
189
- if (!$data->filter('response')->filter('items')->isEmpty()) {
190
- foreach ($data->filter('response')->filter('items')->toArray() as $item) {
191
- $contacts[] = $this->fetchUserContact($item);
192
- }
193
- }
194
-
195
- return $contacts;
196
- }
197
-
198
- /**
199
- * Parse the user contact.
200
- *
201
- * @param array $item
202
- *
203
- * @return \Hybridauth\User\Contact
204
- */
205
- protected function fetchUserContact($item)
206
- {
207
- $userContact = new User\Contact();
208
- $data = new Data\Collection($item);
209
-
210
- $userContact->identifier = $data->get('id');
211
- $userContact->displayName = sprintf('%s %s', $data->get('first_name'), $data->get('last_name'));
212
- $userContact->profileURL = static::URL . ($data->get('screen_name') ?: 'id' . $data->get('id'));
213
- $userContact->photoURL = $data->get('photo_200_orig');
214
-
215
- return $userContact;
216
- }
217
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data\Collection;
13
+ use Hybridauth\User\Profile;
14
+ use Hybridauth\Data;
15
+ use Hybridauth\User;
16
+
17
+ /**
18
+ * Vkontakte OAuth2 provider adapter.
19
+ *
20
+ * Example:
21
+ *
22
+ * $config = [
23
+ * 'callback' => Hybridauth\HttpClient\Util::getCurrentUrl(),
24
+ * 'keys' => [
25
+ * 'id' => '', // App ID
26
+ * 'secret' => '' // Secure key
27
+ * ],
28
+ * ];
29
+ *
30
+ * $adapter = new Hybridauth\Provider\Vkontakte($config);
31
+ *
32
+ * try {
33
+ * if (!$adapter->isConnected()) {
34
+ * $adapter->authenticate();
35
+ * }
36
+ *
37
+ * $userProfile = $adapter->getUserProfile();
38
+ * }
39
+ * catch(\Exception $e) {
40
+ * print $e->getMessage() ;
41
+ * }
42
+ */
43
+ class Vkontakte extends OAuth2
44
+ {
45
+ const API_VERSION = '5.95';
46
+
47
+ const URL = 'https://vk.com/';
48
+
49
+ /**
50
+ * {@inheritdoc}
51
+ */
52
+ protected $apiBaseUrl = 'https://api.vk.com/method/';
53
+
54
+ /**
55
+ * {@inheritdoc}
56
+ */
57
+ protected $authorizeUrl = 'https://api.vk.com/oauth/authorize';
58
+
59
+ /**
60
+ * {@inheritdoc}
61
+ */
62
+ protected $accessTokenUrl = 'https://api.vk.com/oauth/token';
63
+
64
+ /**
65
+ * {@inheritdoc}
66
+ */
67
+ protected $scope = 'email,offline';
68
+
69
+ /**
70
+ * {@inheritdoc}
71
+ */
72
+ protected $apiDocumentation = ''; // Not available
73
+
74
+ /**
75
+ * {@inheritdoc}
76
+ */
77
+ protected function initialize()
78
+ {
79
+ parent::initialize();
80
+
81
+ // The VK API requires version and access_token from authenticated users
82
+ // for each endpoint.
83
+ $accessToken = $this->getStoredData($this->accessTokenName);
84
+ $this->apiRequestParameters[$this->accessTokenName] = $accessToken;
85
+ $this->apiRequestParameters['v'] = static::API_VERSION;
86
+ }
87
+
88
+ /**
89
+ * {@inheritdoc}
90
+ */
91
+ protected function validateAccessTokenExchange($response)
92
+ {
93
+ $data = parent::validateAccessTokenExchange($response);
94
+
95
+ // Need to store email for later use.
96
+ $this->storeData('email', $data->get('email'));
97
+ }
98
+
99
+ /**
100
+ * {@inheritdoc}
101
+ */
102
+ public function hasAccessTokenExpired($time = null)
103
+ {
104
+ if ($time === null) {
105
+ $time = time();
106
+ }
107
+
108
+ // If we are using offline scope, $expired will be false.
109
+ $expired = $this->getStoredData('expires_in')
110
+ ? $this->getStoredData('expires_at') <= $time
111
+ : false;
112
+
113
+ return $expired;
114
+ }
115
+
116
+ /**
117
+ * {@inheritdoc}
118
+ */
119
+ public function getUserProfile()
120
+ {
121
+ $photoField = 'photo_' . ($this->config->get('photo_size') ?: 'max_orig');
122
+
123
+ $response = $this->apiRequest('users.get', 'GET', [
124
+ 'fields' => 'screen_name,sex,education,bdate,has_photo,' . $photoField,
125
+ ]);
126
+
127
+ if (property_exists($response, 'error')) {
128
+ throw new UnexpectedApiResponseException($response->error->error_msg);
129
+ }
130
+
131
+ $data = new Collection($response->response[0]);
132
+
133
+ if (!$data->exists('id')) {
134
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
135
+ }
136
+
137
+ $userProfile = new Profile();
138
+
139
+ $userProfile->identifier = $data->get('id');
140
+ $userProfile->email = $this->getStoredData('email');
141
+ $userProfile->firstName = $data->get('first_name');
142
+ $userProfile->lastName = $data->get('last_name');
143
+ $userProfile->displayName = $data->get('screen_name');
144
+ $userProfile->photoURL = $data->get('has_photo') === 1 ? $data->get($photoField) : '';
145
+
146
+ // Handle b-date.
147
+ if ($data->get('bdate')) {
148
+ $bday = explode('.', $data->get('bdate'));
149
+ $userProfile->birthDay = (int) $bday[0];
150
+ $userProfile->birthMonth = (int) $bday[1];
151
+ $userProfile->birthYear = (int) $bday[2];
152
+ }
153
+
154
+ $userProfile->data = [
155
+ 'education' => $data->get('education'),
156
+ ];
157
+
158
+ $screen_name = static::URL . ($data->get('screen_name') ?: 'id' . $data->get('id'));
159
+ $userProfile->profileURL = $screen_name;
160
+
161
+ switch ($data->get('sex')) {
162
+ case 1:
163
+ $userProfile->gender = 'female';
164
+ break;
165
+
166
+ case 2:
167
+ $userProfile->gender = 'male';
168
+ break;
169
+ }
170
+
171
+ return $userProfile;
172
+ }
173
+
174
+ /**
175
+ * {@inheritdoc}
176
+ */
177
+ public function getUserContacts()
178
+ {
179
+ $response = $this->apiRequest('friends.get', 'GET', [
180
+ 'fields' => 'uid,name,photo_200_orig',
181
+ ]);
182
+
183
+ $data = new Data\Collection($response);
184
+ if (!$data->exists('response')) {
185
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
186
+ }
187
+
188
+ $contacts = [];
189
+ if (!$data->filter('response')->filter('items')->isEmpty()) {
190
+ foreach ($data->filter('response')->filter('items')->toArray() as $item) {
191
+ $contacts[] = $this->fetchUserContact($item);
192
+ }
193
+ }
194
+
195
+ return $contacts;
196
+ }
197
+
198
+ /**
199
+ * Parse the user contact.
200
+ *
201
+ * @param array $item
202
+ *
203
+ * @return \Hybridauth\User\Contact
204
+ */
205
+ protected function fetchUserContact($item)
206
+ {
207
+ $userContact = new User\Contact();
208
+ $data = new Data\Collection($item);
209
+
210
+ $userContact->identifier = $data->get('id');
211
+ $userContact->displayName = sprintf('%s %s', $data->get('first_name'), $data->get('last_name'));
212
+ $userContact->profileURL = static::URL . ($data->get('screen_name') ?: 'id' . $data->get('id'));
213
+ $userContact->photoURL = $data->get('photo_200_orig');
214
+
215
+ return $userContact;
216
+ }
217
+ }
hybridauth/library/src/Provider/WeChat.php CHANGED
@@ -1,134 +1,134 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * WeChat International OAuth2 provider adapter.
17
- */
18
- class WeChat extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'snsapi_login,snsapi_userinfo,scope.userInfo';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://api.wechat.com/sns/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://open.weixin.qq.com/connect/qrconnect';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://api.wechat.com/sns/oauth2/access_token';
39
-
40
- /**
41
- * Refresh Token Endpoint
42
- * @var string
43
- */
44
- protected $tokenRefreshUrl = 'https://api.wechat.com/sns/oauth2/refresh_token';
45
-
46
- /**
47
- * {@ịnheritdoc}
48
- */
49
- protected $accessTokenInfoUrl = 'https://api.wechat.com/sns/auth';
50
-
51
- /**
52
- * {@inheritdoc}
53
- */
54
- protected $tokenExchangeMethod = 'GET';
55
-
56
- /**
57
- * {@inheritdoc}
58
- */
59
- protected $tokenRefreshMethod = 'GET';
60
-
61
- /**
62
- * {@inheritdoc}
63
- */
64
- protected $apiDocumentation = ''; // Not available
65
-
66
- /**
67
- * {@inheritdoc}
68
- */
69
- protected function initialize()
70
- {
71
- parent::initialize();
72
-
73
- $this->AuthorizeUrlParameters += [
74
- 'appid' => $this->clientId
75
- ];
76
- unset($this->AuthorizeUrlParameters['client_id']);
77
-
78
- $this->tokenExchangeParameters += [
79
- 'appid' => $this->clientId,
80
- 'secret' => $this->clientSecret
81
- ];
82
- unset($this->tokenExchangeParameters['client_id']);
83
- unset($this->tokenExchangeParameters['client_secret']);
84
-
85
- $this->tokenRefreshParameters += [
86
- 'appid' => $this->clientId
87
- ];
88
-
89
- $this->apiRequestParameters = [
90
- 'appid' => $this->clientId,
91
- 'secret' => $this->clientSecret
92
- ];
93
- }
94
-
95
- /**
96
- * {@inheritdoc}
97
- */
98
- protected function validateAccessTokenExchange($response)
99
- {
100
- $collection = parent::validateAccessTokenExchange($response);
101
-
102
- $this->storeData('openid', $collection->get('openid'));
103
- $this->storeData('access_token', $collection->get('access_token'));
104
- }
105
-
106
- /**
107
- * {@inheritdoc}
108
- */
109
- public function getUserProfile()
110
- {
111
- $openid = $this->getStoredData('openid');
112
- $access_token = $this->getStoredData('access_token');
113
-
114
- $response = $this->apiRequest('userinfo', 'GET', ['openid' => $openid, 'access_token' => $access_token]);
115
-
116
- $data = new Data\Collection($response);
117
-
118
- if (!$data->exists('openid')) {
119
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
120
- }
121
-
122
- $userProfile = new User\Profile();
123
-
124
- $userProfile->identifier = $data->get('openid');
125
- $userProfile->displayName = $data->get('nickname');
126
- $userProfile->photoURL = $data->get('headimgurl');
127
- $userProfile->city = $data->get('city');
128
- $userProfile->region = $data->get('province');
129
- $userProfile->country = $data->get('country');
130
- $userProfile->gender = ['', 'male', 'female'][(int)$data->get('sex')];
131
-
132
- return $userProfile;
133
- }
134
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * WeChat International OAuth2 provider adapter.
17
+ */
18
+ class WeChat extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'snsapi_login,snsapi_userinfo,scope.userInfo';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://api.wechat.com/sns/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://open.weixin.qq.com/connect/qrconnect';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://api.wechat.com/sns/oauth2/access_token';
39
+
40
+ /**
41
+ * Refresh Token Endpoint
42
+ * @var string
43
+ */
44
+ protected $tokenRefreshUrl = 'https://api.wechat.com/sns/oauth2/refresh_token';
45
+
46
+ /**
47
+ * {@ịnheritdoc}
48
+ */
49
+ protected $accessTokenInfoUrl = 'https://api.wechat.com/sns/auth';
50
+
51
+ /**
52
+ * {@inheritdoc}
53
+ */
54
+ protected $tokenExchangeMethod = 'GET';
55
+
56
+ /**
57
+ * {@inheritdoc}
58
+ */
59
+ protected $tokenRefreshMethod = 'GET';
60
+
61
+ /**
62
+ * {@inheritdoc}
63
+ */
64
+ protected $apiDocumentation = ''; // Not available
65
+
66
+ /**
67
+ * {@inheritdoc}
68
+ */
69
+ protected function initialize()
70
+ {
71
+ parent::initialize();
72
+
73
+ $this->AuthorizeUrlParameters += [
74
+ 'appid' => $this->clientId
75
+ ];
76
+ unset($this->AuthorizeUrlParameters['client_id']);
77
+
78
+ $this->tokenExchangeParameters += [
79
+ 'appid' => $this->clientId,
80
+ 'secret' => $this->clientSecret
81
+ ];
82
+ unset($this->tokenExchangeParameters['client_id']);
83
+ unset($this->tokenExchangeParameters['client_secret']);
84
+
85
+ $this->tokenRefreshParameters += [
86
+ 'appid' => $this->clientId
87
+ ];
88
+
89
+ $this->apiRequestParameters = [
90
+ 'appid' => $this->clientId,
91
+ 'secret' => $this->clientSecret
92
+ ];
93
+ }
94
+
95
+ /**
96
+ * {@inheritdoc}
97
+ */
98
+ protected function validateAccessTokenExchange($response)
99
+ {
100
+ $collection = parent::validateAccessTokenExchange($response);
101
+
102
+ $this->storeData('openid', $collection->get('openid'));
103
+ $this->storeData('access_token', $collection->get('access_token'));
104
+ }
105
+
106
+ /**
107
+ * {@inheritdoc}
108
+ */
109
+ public function getUserProfile()
110
+ {
111
+ $openid = $this->getStoredData('openid');
112
+ $access_token = $this->getStoredData('access_token');
113
+
114
+ $response = $this->apiRequest('userinfo', 'GET', ['openid' => $openid, 'access_token' => $access_token]);
115
+
116
+ $data = new Data\Collection($response);
117
+
118
+ if (!$data->exists('openid')) {
119
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
120
+ }
121
+
122
+ $userProfile = new User\Profile();
123
+
124
+ $userProfile->identifier = $data->get('openid');
125
+ $userProfile->displayName = $data->get('nickname');
126
+ $userProfile->photoURL = $data->get('headimgurl');
127
+ $userProfile->city = $data->get('city');
128
+ $userProfile->region = $data->get('province');
129
+ $userProfile->country = $data->get('country');
130
+ $userProfile->gender = ['', 'male', 'female'][(int)$data->get('sex')];
131
+
132
+ return $userProfile;
133
+ }
134
+ }
hybridauth/library/src/Provider/WeChatChina.php CHANGED
@@ -1,34 +1,34 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- /**
11
- * WeChat China OAuth2 provider adapter.
12
- */
13
- class WeChatChina extends WeChat
14
- {
15
- /**
16
- * {@inheritdoc}
17
- */
18
- protected $apiBaseUrl = 'https://api.weixin.qq.com/sns/';
19
-
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $accessTokenUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $tokenRefreshUrl = 'https://api.weixin.qq.com/sns/oauth2/refresh_token';
29
-
30
- /**
31
- * {@ịnheritdoc}
32
- */
33
- protected $accessTokenInfoUrl = 'https://api.weixin.qq.com/sns/auth';
34
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ /**
11
+ * WeChat China OAuth2 provider adapter.
12
+ */
13
+ class WeChatChina extends WeChat
14
+ {
15
+ /**
16
+ * {@inheritdoc}
17
+ */
18
+ protected $apiBaseUrl = 'https://api.weixin.qq.com/sns/';
19
+
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $accessTokenUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $tokenRefreshUrl = 'https://api.weixin.qq.com/sns/oauth2/refresh_token';
29
+
30
+ /**
31
+ * {@ịnheritdoc}
32
+ */
33
+ protected $accessTokenInfoUrl = 'https://api.weixin.qq.com/sns/auth';
34
+ }
hybridauth/library/src/Provider/WindowsLive.php CHANGED
@@ -1,103 +1,103 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * Windows Live OAuth2 provider adapter.
17
- */
18
- class WindowsLive extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $scope = 'wl.basic wl.contacts_emails wl.emails wl.signin wl.share wl.birthday';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $apiBaseUrl = 'https://apis.live.net/v5.0/';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $authorizeUrl = 'https://login.live.com/oauth20_authorize.srf';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $accessTokenUrl = 'https://login.live.com/oauth20_token.srf';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $apiDocumentation = 'https://msdn.microsoft.com/en-us/library/hh243647.aspx';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- public function getUserProfile()
49
- {
50
- $response = $this->apiRequest('me');
51
-
52
- $data = new Data\Collection($response);
53
-
54
- if (! $data->exists('id')) {
55
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
- }
57
-
58
- $userProfile = new User\Profile();
59
-
60
- $userProfile->identifier = $data->get('id');
61
- $userProfile->displayName = $data->get('name');
62
- $userProfile->firstName = $data->get('first_name');
63
- $userProfile->lastName = $data->get('last_name');
64
- $userProfile->gender = $data->get('gender');
65
- $userProfile->profileURL = $data->get('link');
66
- $userProfile->email = $data->filter('emails')->get('preferred');
67
- $userProfile->emailVerified = $data->filter('emails')->get('account');
68
- $userProfile->birthDay = $data->get('birth_day');
69
- $userProfile->birthMonth = $data->get('birth_month');
70
- $userProfile->birthYear = $data->get('birth_year');
71
- $userProfile->language = $data->get('locale');
72
-
73
- return $userProfile;
74
- }
75
-
76
- /**
77
- * {@inheritdoc}
78
- */
79
- public function getUserContacts()
80
- {
81
- $response = $this->apiRequest('me/contacts');
82
-
83
- $data = new Data\Collection($response);
84
-
85
- if (! $data->exists('data')) {
86
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
87
- }
88
-
89
- $contacts = [];
90
-
91
- foreach ($data->filter('data')->toArray() as $idx => $entry) {
92
- $userContact = new User\Contact();
93
-
94
- $userContact->identifier = $entry->get('id');
95
- $userContact->displayName = $entry->get('name');
96
- $userContact->email = $entry->filter('emails')->get('preferred');
97
-
98
- $contacts[] = $userContact;
99
- }
100
-
101
- return $contacts;
102
- }
103
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * Windows Live OAuth2 provider adapter.
17
+ */
18
+ class WindowsLive extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $scope = 'wl.basic wl.contacts_emails wl.emails wl.signin wl.share wl.birthday';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $apiBaseUrl = 'https://apis.live.net/v5.0/';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $authorizeUrl = 'https://login.live.com/oauth20_authorize.srf';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $accessTokenUrl = 'https://login.live.com/oauth20_token.srf';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $apiDocumentation = 'https://msdn.microsoft.com/en-us/library/hh243647.aspx';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getUserProfile()
49
+ {
50
+ $response = $this->apiRequest('me');
51
+
52
+ $data = new Data\Collection($response);
53
+
54
+ if (! $data->exists('id')) {
55
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
56
+ }
57
+
58
+ $userProfile = new User\Profile();
59
+
60
+ $userProfile->identifier = $data->get('id');
61
+ $userProfile->displayName = $data->get('name');
62
+ $userProfile->firstName = $data->get('first_name');
63
+ $userProfile->lastName = $data->get('last_name');
64
+ $userProfile->gender = $data->get('gender');
65
+ $userProfile->profileURL = $data->get('link');
66
+ $userProfile->email = $data->filter('emails')->get('preferred');
67
+ $userProfile->emailVerified = $data->filter('emails')->get('account');
68
+ $userProfile->birthDay = $data->get('birth_day');
69
+ $userProfile->birthMonth = $data->get('birth_month');
70
+ $userProfile->birthYear = $data->get('birth_year');
71
+ $userProfile->language = $data->get('locale');
72
+
73
+ return $userProfile;
74
+ }
75
+
76
+ /**
77
+ * {@inheritdoc}
78
+ */
79
+ public function getUserContacts()
80
+ {
81
+ $response = $this->apiRequest('me/contacts');
82
+
83
+ $data = new Data\Collection($response);
84
+
85
+ if (! $data->exists('data')) {
86
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
87
+ }
88
+
89
+ $contacts = [];
90
+
91
+ foreach ($data->filter('data')->toArray() as $idx => $entry) {
92
+ $userContact = new User\Contact();
93
+
94
+ $userContact->identifier = $entry->get('id');
95
+ $userContact->displayName = $entry->get('name');
96
+ $userContact->email = $entry->filter('emails')->get('preferred');
97
+
98
+ $contacts[] = $userContact;
99
+ }
100
+
101
+ return $contacts;
102
+ }
103
+ }
hybridauth/library/src/Provider/WordPress.php CHANGED
@@ -1,68 +1,68 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * WordPress OAuth2 provider adapter.
17
- */
18
- class WordPress extends OAuth2
19
- {
20
- /**
21
- * {@inheritdoc}
22
- */
23
- protected $apiBaseUrl = 'https://public-api.wordpress.com/rest/v1/';
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $authorizeUrl = 'https://public-api.wordpress.com/oauth2/authenticate';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $accessTokenUrl = 'https://public-api.wordpress.com/oauth2/token';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $apiDocumentation = 'https://developer.wordpress.com/docs/api/';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- public function getUserProfile()
44
- {
45
- $response = $this->apiRequest('me/');
46
-
47
- $data = new Data\Collection($response);
48
-
49
- if (! $data->exists('ID')) {
50
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
51
- }
52
-
53
- $userProfile = new User\Profile();
54
-
55
- $userProfile->identifier = $data->get('ID');
56
- $userProfile->displayName = $data->get('display_name');
57
- $userProfile->photoURL = $data->get('avatar_URL');
58
- $userProfile->profileURL = $data->get('profile_URL');
59
- $userProfile->email = $data->get('email');
60
- $userProfile->language = $data->get('language');
61
-
62
- $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
63
-
64
- $userProfile->emailVerified = $data->get('email_verified') ? $data->get('email') : '';
65
-
66
- return $userProfile;
67
- }
68
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * WordPress OAuth2 provider adapter.
17
+ */
18
+ class WordPress extends OAuth2
19
+ {
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ protected $apiBaseUrl = 'https://public-api.wordpress.com/rest/v1/';
24
+
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $authorizeUrl = 'https://public-api.wordpress.com/oauth2/authenticate';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $accessTokenUrl = 'https://public-api.wordpress.com/oauth2/token';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $apiDocumentation = 'https://developer.wordpress.com/docs/api/';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ public function getUserProfile()
44
+ {
45
+ $response = $this->apiRequest('me/');
46
+
47
+ $data = new Data\Collection($response);
48
+
49
+ if (! $data->exists('ID')) {
50
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
51
+ }
52
+
53
+ $userProfile = new User\Profile();
54
+
55
+ $userProfile->identifier = $data->get('ID');
56
+ $userProfile->displayName = $data->get('display_name');
57
+ $userProfile->photoURL = $data->get('avatar_URL');
58
+ $userProfile->profileURL = $data->get('profile_URL');
59
+ $userProfile->email = $data->get('email');
60
+ $userProfile->language = $data->get('language');
61
+
62
+ $userProfile->displayName = $userProfile->displayName ?: $data->get('username');
63
+
64
+ $userProfile->emailVerified = $data->get('email_verified') ? $data->get('email') : '';
65
+
66
+ return $userProfile;
67
+ }
68
+ }
hybridauth/library/src/Provider/Yahoo.php CHANGED
@@ -1,104 +1,104 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\UnexpectedApiResponseException;
12
- use Hybridauth\Data;
13
- use Hybridauth\User;
14
-
15
- /**
16
- * For this provider to work it is necessary to assign the "OpenID Connect Permissions",
17
- * even if you only use basic OAuth2.
18
- */
19
-
20
- /**
21
- * Yahoo OAuth2 provider adapter.
22
- */
23
- class Yahoo extends OAuth2
24
- {
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected $scope = 'profile';
29
-
30
- /**
31
- * {@inheritdoc}
32
- */
33
- protected $apiBaseUrl = 'https://api.login.yahoo.com/openid/v1/';
34
-
35
- /**
36
- * {@inheritdoc}
37
- */
38
- protected $authorizeUrl = 'https://api.login.yahoo.com/oauth2/request_auth';
39
-
40
- /**
41
- * {@inheritdoc}
42
- */
43
- protected $accessTokenUrl = 'https://api.login.yahoo.com/oauth2/get_token';
44
-
45
- /**
46
- * {@inheritdoc}
47
- */
48
- protected $apiDocumentation = 'https://developer.yahoo.com/oauth2/guide/';
49
-
50
- /**
51
- * Currently authenticated user
52
- */
53
- protected $userId = null;
54
-
55
- /**
56
- * {@inheritdoc}
57
- */
58
- protected function initialize()
59
- {
60
- parent::initialize();
61
-
62
- $this->tokenExchangeHeaders = [
63
- 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
64
- ];
65
-
66
- $this->tokenRefreshHeaders = $this->tokenExchangeHeaders;
67
- }
68
-
69
- /**
70
- * {@inheritdoc}
71
- */
72
- public function getUserProfile()
73
- {
74
- $response = $this->apiRequest('userinfo');
75
-
76
- $data = new Data\Collection($response);
77
-
78
- if (!$data->exists('sub')) {
79
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
80
- }
81
-
82
- $userProfile = new User\Profile();
83
-
84
- $userProfile->identifier = $data->get('sub');
85
- $userProfile->firstName = $data->get('given_name');
86
- $userProfile->lastName = $data->get('family_name');
87
- $userProfile->displayName = $data->get('name');
88
- $userProfile->gender = $data->get('gender');
89
- $userProfile->language = $data->get('locale');
90
- $userProfile->email = $data->get('email');
91
-
92
- $userProfile->emailVerified = $data->get('email_verified') ? $userProfile->email : '';
93
-
94
- $profileImages = $data->get('profile_images');
95
- if ($this->config->get('photo_size')) {
96
- $prop = 'image' . $this->config->get('photo_size');
97
- } else {
98
- $prop = 'image192';
99
- }
100
- $userProfile->photoURL = $profileImages->$prop;
101
-
102
- return $userProfile;
103
- }
104
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\UnexpectedApiResponseException;
12
+ use Hybridauth\Data;
13
+ use Hybridauth\User;
14
+
15
+ /**
16
+ * For this provider to work it is necessary to assign the "OpenID Connect Permissions",
17
+ * even if you only use basic OAuth2.
18
+ */
19
+
20
+ /**
21
+ * Yahoo OAuth2 provider adapter.
22
+ */
23
+ class Yahoo extends OAuth2
24
+ {
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected $scope = 'profile';
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ protected $apiBaseUrl = 'https://api.login.yahoo.com/openid/v1/';
34
+
35
+ /**
36
+ * {@inheritdoc}
37
+ */
38
+ protected $authorizeUrl = 'https://api.login.yahoo.com/oauth2/request_auth';
39
+
40
+ /**
41
+ * {@inheritdoc}
42
+ */
43
+ protected $accessTokenUrl = 'https://api.login.yahoo.com/oauth2/get_token';
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected $apiDocumentation = 'https://developer.yahoo.com/oauth2/guide/';
49
+
50
+ /**
51
+ * Currently authenticated user
52
+ */
53
+ protected $userId = null;
54
+
55
+ /**
56
+ * {@inheritdoc}
57
+ */
58
+ protected function initialize()
59
+ {
60
+ parent::initialize();
61
+
62
+ $this->tokenExchangeHeaders = [
63
+ 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)
64
+ ];
65
+
66
+ $this->tokenRefreshHeaders = $this->tokenExchangeHeaders;
67
+ }
68
+
69
+ /**
70
+ * {@inheritdoc}
71
+ */
72
+ public function getUserProfile()
73
+ {
74
+ $response = $this->apiRequest('userinfo');
75
+
76
+ $data = new Data\Collection($response);
77
+
78
+ if (!$data->exists('sub')) {
79
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
80
+ }
81
+
82
+ $userProfile = new User\Profile();
83
+
84
+ $userProfile->identifier = $data->get('sub');
85
+ $userProfile->firstName = $data->get('given_name');
86
+ $userProfile->lastName = $data->get('family_name');
87
+ $userProfile->displayName = $data->get('name');
88
+ $userProfile->gender = $data->get('gender');
89
+ $userProfile->language = $data->get('locale');
90
+ $userProfile->email = $data->get('email');
91
+
92
+ $userProfile->emailVerified = $data->get('email_verified') ? $userProfile->email : '';
93
+
94
+ $profileImages = $data->get('profile_images');
95
+ if ($this->config->get('photo_size')) {
96
+ $prop = 'image' . $this->config->get('photo_size');
97
+ } else {
98
+ $prop = 'image192';
99
+ }
100
+ $userProfile->photoURL = $profileImages->$prop;
101
+
102
+ return $userProfile;
103
+ }
104
+ }
hybridauth/library/src/Provider/Yandex.php CHANGED
@@ -1,83 +1,83 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Provider;
9
-
10
- use Hybridauth\Adapter\OAuth2;
11
- use Hybridauth\Exception\Exception;
12
- use Hybridauth\Exception\UnexpectedApiResponseException;
13
- use Hybridauth\Data\Collection;
14
- use Hybridauth\User\Profile;
15
-
16
- /**
17
- * Yandex OAuth2 provider adapter.
18
- */
19
- class Yandex extends OAuth2
20
- {
21
- /**
22
- * {@inheritdoc}
23
- */
24
- protected $apiBaseUrl = 'https://login.yandex.ru/info';
25
-
26
- /**
27
- * {@inheritdoc}
28
- */
29
- protected $authorizeUrl = 'https://oauth.yandex.ru/authorize';
30
-
31
- /**
32
- * {@inheritdoc}
33
- */
34
- protected $accessTokenUrl = 'https://oauth.yandex.ru/token';
35
-
36
- /**
37
- * {@inheritdoc}
38
- */
39
- protected $apiDocumentation = 'https://yandex.com/dev/oauth/doc/dg/concepts/about-docpage/';
40
-
41
- /**
42
- * load the user profile from the IDp api client
43
- *
44
- * @throws Exception
45
- */
46
- public function getUserProfile()
47
- {
48
- $this->scope = implode(',', []);
49
-
50
- $response = $this->apiRequest($this->apiBaseUrl, 'GET', [ 'format' => 'json' ]);
51
-
52
- if (!isset($response->id)) {
53
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
54
- }
55
-
56
- $data = new Collection($response);
57
-
58
- if (!$data->exists('id')) {
59
- throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
60
- }
61
-
62
- $userProfile = new Profile();
63
-
64
- $userProfile->identifier = $data->get('id');
65
- $userProfile->firstName = $data->get('real_name');
66
- $userProfile->lastName = $data->get('family_name');
67
- $userProfile->displayName = $data->get('display_name');
68
- $userProfile->photoURL = 'http://upics.yandex.net/' . $userProfile->identifier . '/normal';
69
- $userProfile->profileURL = "";
70
- $userProfile->gender = $data->get('sex');
71
- $userProfile->email = $data->get('default_email');
72
- $userProfile->emailVerified = $data->get('default_email');
73
-
74
- if ($data->get('birthday')) {
75
- list($birthday_year, $birthday_month, $birthday_day) = explode('-', $response->birthday);
76
- $userProfile->birthDay = (int)$birthday_day;
77
- $userProfile->birthMonth = (int)$birthday_month;
78
- $userProfile->birthYear = (int)$birthday_year;
79
- }
80
-
81
- return $userProfile;
82
- }
83
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Provider;
9
+
10
+ use Hybridauth\Adapter\OAuth2;
11
+ use Hybridauth\Exception\Exception;
12
+ use Hybridauth\Exception\UnexpectedApiResponseException;
13
+ use Hybridauth\Data\Collection;
14
+ use Hybridauth\User\Profile;
15
+
16
+ /**
17
+ * Yandex OAuth2 provider adapter.
18
+ */
19
+ class Yandex extends OAuth2
20
+ {
21
+ /**
22
+ * {@inheritdoc}
23
+ */
24
+ protected $apiBaseUrl = 'https://login.yandex.ru/info';
25
+
26
+ /**
27
+ * {@inheritdoc}
28
+ */
29
+ protected $authorizeUrl = 'https://oauth.yandex.ru/authorize';
30
+
31
+ /**
32
+ * {@inheritdoc}
33
+ */
34
+ protected $accessTokenUrl = 'https://oauth.yandex.ru/token';
35
+
36
+ /**
37
+ * {@inheritdoc}
38
+ */
39
+ protected $apiDocumentation = 'https://yandex.com/dev/oauth/doc/dg/concepts/about-docpage/';
40
+
41
+ /**
42
+ * load the user profile from the IDp api client
43
+ *
44
+ * @throws Exception
45
+ */
46
+ public function getUserProfile()
47
+ {
48
+ $this->scope = implode(',', []);
49
+
50
+ $response = $this->apiRequest($this->apiBaseUrl, 'GET', [ 'format' => 'json' ]);
51
+
52
+ if (!isset($response->id)) {
53
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
54
+ }
55
+
56
+ $data = new Collection($response);
57
+
58
+ if (!$data->exists('id')) {
59
+ throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
60
+ }
61
+
62
+ $userProfile = new Profile();
63
+
64
+ $userProfile->identifier = $data->get('id');
65
+ $userProfile->firstName = $data->get('real_name');
66
+ $userProfile->lastName = $data->get('family_name');
67
+ $userProfile->displayName = $data->get('display_name');
68
+ $userProfile->photoURL = 'http://upics.yandex.net/' . $userProfile->identifier . '/normal';
69
+ $userProfile->profileURL = "";
70
+ $userProfile->gender = $data->get('sex');
71
+ $userProfile->email = $data->get('default_email');
72
+ $userProfile->emailVerified = $data->get('default_email');
73
+
74
+ if ($data->get('birthday')) {
75
+ list($birthday_year, $birthday_month, $birthday_day) = explode('-', $response->birthday);
76
+ $userProfile->birthDay = (int)$birthday_day;
77
+ $userProfile->birthMonth = (int)$birthday_month;
78
+ $userProfile->birthYear = (int)$birthday_year;
79
+ }
80
+
81
+ return $userProfile;
82
+ }
83
+ }
hybridauth/library/src/Storage/Session.php CHANGED
@@ -1,119 +1,119 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Storage;
9
-
10
- use Hybridauth\Exception\RuntimeException;
11
-
12
- /**
13
- * Hybridauth storage manager
14
- */
15
- class Session implements StorageInterface
16
- {
17
- /**
18
- * Namespace
19
- *
20
- * @var string
21
- */
22
- protected $storeNamespace = 'HYBRIDAUTH::STORAGE';
23
-
24
- /**
25
- * Key prefix
26
- *
27
- * @var string
28
- */
29
- protected $keyPrefix = '';
30
-
31
- /**
32
- * Initiate a new session
33
- *
34
- * @throws RuntimeException
35
- */
36
- public function __construct()
37
- {
38
- if (session_id()) {
39
- return;
40
- }
41
-
42
- if (headers_sent()) {
43
- // phpcs:ignore
44
- throw new RuntimeException('HTTP headers already sent to browser and Hybridauth won\'t be able to start/resume PHP session. To resolve this, session_start() must be called before outputing any data.');
45
- }
46
-
47
- if (! session_start()) {
48
- throw new RuntimeException('PHP session failed to start.');
49
- }
50
- }
51
-
52
- /**
53
- * {@inheritdoc}
54
- */
55
- public function get($key)
56
- {
57
- $key = $this->keyPrefix . strtolower($key);
58
-
59
- if (isset($_SESSION[$this->storeNamespace], $_SESSION[$this->storeNamespace][$key])) {
60
- return $_SESSION[$this->storeNamespace][$key];
61
- }
62
-
63
- return null;
64
- }
65
-
66
- /**
67
- * {@inheritdoc}
68
- */
69
- public function set($key, $value)
70
- {
71
- $key = $this->keyPrefix . strtolower($key);
72
-
73
- $_SESSION[$this->storeNamespace][$key] = $value;
74
- }
75
-
76
- /**
77
- * {@inheritdoc}
78
- */
79
- public function clear()
80
- {
81
- $_SESSION[$this->storeNamespace] = [];
82
- }
83
-
84
- /**
85
- * {@inheritdoc}
86
- */
87
- public function delete($key)
88
- {
89
- $key = $this->keyPrefix . strtolower($key);
90
-
91
- if (isset($_SESSION[$this->storeNamespace], $_SESSION[$this->storeNamespace][$key])) {
92
- $tmp = $_SESSION[$this->storeNamespace];
93
-
94
- unset($tmp[$key]);
95
-
96
- $_SESSION[$this->storeNamespace] = $tmp;
97
- }
98
- }
99
-
100
- /**
101
- * {@inheritdoc}
102
- */
103
- public function deleteMatch($key)
104
- {
105
- $key = $this->keyPrefix . strtolower($key);
106
-
107
- if (isset($_SESSION[$this->storeNamespace]) && count($_SESSION[$this->storeNamespace])) {
108
- $tmp = $_SESSION[$this->storeNamespace];
109
-
110
- foreach ($tmp as $k => $v) {
111
- if (strstr($k, $key)) {
112
- unset($tmp[ $k ]);
113
- }
114
- }
115
-
116
- $_SESSION[$this->storeNamespace] = $tmp;
117
- }
118
- }
119
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Storage;
9
+
10
+ use Hybridauth\Exception\RuntimeException;
11
+
12
+ /**
13
+ * Hybridauth storage manager
14
+ */
15
+ class Session implements StorageInterface
16
+ {
17
+ /**
18
+ * Namespace
19
+ *
20
+ * @var string
21
+ */
22
+ protected $storeNamespace = 'HYBRIDAUTH::STORAGE';
23
+
24
+ /**
25
+ * Key prefix
26
+ *
27
+ * @var string
28
+ */
29
+ protected $keyPrefix = '';
30
+
31
+ /**
32
+ * Initiate a new session
33
+ *
34
+ * @throws RuntimeException
35
+ */
36
+ public function __construct()
37
+ {
38
+ if (session_id()) {
39
+ return;
40
+ }
41
+
42
+ if (headers_sent()) {
43
+ // phpcs:ignore
44
+ throw new RuntimeException('HTTP headers already sent to browser and Hybridauth won\'t be able to start/resume PHP session. To resolve this, session_start() must be called before outputing any data.');
45
+ }
46
+
47
+ if (! session_start()) {
48
+ throw new RuntimeException('PHP session failed to start.');
49
+ }
50
+ }
51
+
52
+ /**
53
+ * {@inheritdoc}
54
+ */
55
+ public function get($key)
56
+ {
57
+ $key = $this->keyPrefix . strtolower($key);
58
+
59
+ if (isset($_SESSION[$this->storeNamespace], $_SESSION[$this->storeNamespace][$key])) {
60
+ return $_SESSION[$this->storeNamespace][$key];
61
+ }
62
+
63
+ return null;
64
+ }
65
+
66
+ /**
67
+ * {@inheritdoc}
68
+ */
69
+ public function set($key, $value)
70
+ {
71
+ $key = $this->keyPrefix . strtolower($key);
72
+
73
+ $_SESSION[$this->storeNamespace][$key] = $value;
74
+ }
75
+
76
+ /**
77
+ * {@inheritdoc}
78
+ */
79
+ public function clear()
80
+ {
81
+ $_SESSION[$this->storeNamespace] = [];
82
+ }
83
+
84
+ /**
85
+ * {@inheritdoc}
86
+ */
87
+ public function delete($key)
88
+ {
89
+ $key = $this->keyPrefix . strtolower($key);
90
+
91
+ if (isset($_SESSION[$this->storeNamespace], $_SESSION[$this->storeNamespace][$key])) {
92
+ $tmp = $_SESSION[$this->storeNamespace];
93
+
94
+ unset($tmp[$key]);
95
+
96
+ $_SESSION[$this->storeNamespace] = $tmp;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * {@inheritdoc}
102
+ */
103
+ public function deleteMatch($key)
104
+ {
105
+ $key = $this->keyPrefix . strtolower($key);
106
+
107
+ if (isset($_SESSION[$this->storeNamespace]) && count($_SESSION[$this->storeNamespace])) {
108
+ $tmp = $_SESSION[$this->storeNamespace];
109
+
110
+ foreach ($tmp as $k => $v) {
111
+ if (strstr($k, $key)) {
112
+ unset($tmp[ $k ]);
113
+ }
114
+ }
115
+
116
+ $_SESSION[$this->storeNamespace] = $tmp;
117
+ }
118
+ }
119
+ }
hybridauth/library/src/Storage/StorageInterface.php CHANGED
@@ -1,50 +1,50 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\Storage;
9
-
10
- /**
11
- * Hybridauth storage manager interface
12
- */
13
- interface StorageInterface
14
- {
15
- /**
16
- * Retrieve a item from storage
17
- *
18
- * @param string $key
19
- *
20
- * @return mixed
21
- */
22
- public function get($key);
23
-
24
- /**
25
- * Add or Update an item to storage
26
- *
27
- * @param string $key
28
- * @param string $value
29
- */
30
- public function set($key, $value);
31
-
32
- /**
33
- * Delete an item from storage
34
- *
35
- * @param string $key
36
- */
37
- public function delete($key);
38
-
39
- /**
40
- * Delete a item from storage
41
- *
42
- * @param string $key
43
- */
44
- public function deleteMatch($key);
45
-
46
- /**
47
- * Clear all items in storage
48
- */
49
- public function clear();
50
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\Storage;
9
+
10
+ /**
11
+ * Hybridauth storage manager interface
12
+ */
13
+ interface StorageInterface
14
+ {
15
+ /**
16
+ * Retrieve a item from storage
17
+ *
18
+ * @param string $key
19
+ *
20
+ * @return mixed
21
+ */
22
+ public function get($key);
23
+
24
+ /**
25
+ * Add or Update an item to storage
26
+ *
27
+ * @param string $key
28
+ * @param string $value
29
+ */
30
+ public function set($key, $value);
31
+
32
+ /**
33
+ * Delete an item from storage
34
+ *
35
+ * @param string $key
36
+ */
37
+ public function delete($key);
38
+
39
+ /**
40
+ * Delete a item from storage
41
+ *
42
+ * @param string $key
43
+ */
44
+ public function deleteMatch($key);
45
+
46
+ /**
47
+ * Clear all items in storage
48
+ */
49
+ public function clear();
50
+ }
hybridauth/library/src/Thirdparty/OAuth/OAuthConsumer.php CHANGED
@@ -1,41 +1,41 @@
1
- <?php
2
- /*!
3
- * This file is part of the OAuth PHP Library (https://code.google.com/p/oauth/)
4
- *
5
- * OAuth `PHP' Library is an open source software available under the MIT License.
6
- */
7
-
8
- namespace Hybridauth\Thirdparty\OAuth;
9
-
10
- /**
11
- * Class OAuthConsumer
12
- *
13
- * @package Hybridauth\Thirdparty\OAuth
14
- */
15
- class OAuthConsumer
16
- {
17
- public $key;
18
- public $secret;
19
-
20
- /**
21
- * OAuthConsumer constructor.
22
- *
23
- * @param $key
24
- * @param $secret
25
- * @param null $callback_url
26
- */
27
- public function __construct($key, $secret, $callback_url = null)
28
- {
29
- $this->key = $key;
30
- $this->secret = $secret;
31
- $this->callback_url = $callback_url;
32
- }
33
-
34
- /**
35
- * @return string
36
- */
37
- public function __toString()
38
- {
39
- return "OAuthConsumer[key=$this->key,secret=$this->secret]";
40
- }
41
- }
1
+ <?php
2
+ /*!
3
+ * This file is part of the OAuth PHP Library (https://code.google.com/p/oauth/)
4
+ *
5
+ * OAuth `PHP' Library is an open source software available under the MIT License.
6
+ */
7
+
8
+ namespace Hybridauth\Thirdparty\OAuth;
9
+
10
+ /**
11
+ * Class OAuthConsumer
12
+ *
13
+ * @package Hybridauth\Thirdparty\OAuth
14
+ */
15
+ class OAuthConsumer
16
+ {
17
+ public $key;
18
+ public $secret;
19
+
20
+ /**
21
+ * OAuthConsumer constructor.
22
+ *
23
+ * @param $key
24
+ * @param $secret
25
+ * @param null $callback_url
26
+ */
27
+ public function __construct($key, $secret, $callback_url = null)
28
+ {
29
+ $this->key = $key;
30
+ $this->secret = $secret;
31
+ $this->callback_url = $callback_url;
32
+ }
33
+
34
+ /**
35
+ * @return string
36
+ */
37
+ public function __toString()
38
+ {
39
+ return "OAuthConsumer[key=$this->key,secret=$this->secret]";
40
+ }
41
+ }
hybridauth/library/src/Thirdparty/OAuth/OAuthRequest.php CHANGED
@@ -1,331 +1,331 @@
1
- <?php
2
- /*!
3
- * This file is part of the OAuth PHP Library (https://code.google.com/p/oauth/)
4
- *
5
- * OAuth `PHP' Library is an open source software available under the MIT License.
6
- */
7
-
8
- namespace Hybridauth\Thirdparty\OAuth;
9
-
10
- /**
11
- * Class OAuthRequest
12
- *
13
- * @package Hybridauth\Thirdparty\OAuth
14
- */
15
- class OAuthRequest
16
- {
17
- public $parameters;
18
- public $http_method;
19
- public $http_url;
20
- // for debug purposes
21
- public $base_string;
22
- public static $version = '1.0';
23
- public static $POST_INPUT = 'php://input';
24
-
25
- /**
26
- * OAuthRequest constructor.
27
- *
28
- * @param $http_method
29
- * @param $http_url
30
- * @param null $parameters
31
- */
32
- public function __construct($http_method, $http_url, $parameters = null)
33
- {
34
- $parameters = ($parameters) ? $parameters : array();
35
- $parameters = array_merge(OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters);
36
- $this->parameters = $parameters;
37
- $this->http_method = $http_method;
38
- $this->http_url = $http_url;
39
- }
40
-
41
- /**
42
- * attempt to build up a request from what was passed to the server
43
- *
44
- * @param null $http_method
45
- * @param null $http_url
46
- * @param null $parameters
47
- *
48
- * @return OAuthRequest
49
- */
50
- public static function from_request($http_method = null, $http_url = null, $parameters = null)
51
- {
52
- $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https';
53
- $http_url = ($http_url) ? $http_url : $scheme . '://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'];
54
- $http_method = ($http_method) ? $http_method : $_SERVER['REQUEST_METHOD'];
55
-
56
- // We weren't handed any parameters, so let's find the ones relevant to
57
- // this request.
58
- // If you run XML-RPC or similar you should use this to provide your own
59
- // parsed parameter-list
60
- if (!$parameters) {
61
- // Find request headers
62
- $request_headers = OAuthUtil::get_headers();
63
-
64
- // Parse the query-string to find GET parameters
65
- $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']);
66
-
67
- // It's a POST request of the proper content-type, so parse POST
68
- // parameters and add those overriding any duplicates from GET
69
- if ($http_method == "POST" && isset($request_headers['Content-Type']) && strstr($request_headers['Content-Type'], 'application/x-www-form-urlencoded')) {
70
- $post_data = OAuthUtil::parse_parameters(file_get_contents(self::$POST_INPUT));
71
- $parameters = array_merge($parameters, $post_data);
72
- }
73
-
74
- // We have a Authorization-header with OAuth data. Parse the header
75
- // and add those overriding any duplicates from GET or POST
76
- if (isset($request_headers['Authorization']) && substr($request_headers['Authorization'], 0, 6) == 'OAuth ') {
77
- $header_parameters = OAuthUtil::split_header($request_headers['Authorization']);
78
- $parameters = array_merge($parameters, $header_parameters);
79
- }
80
- }
81
-
82
- return new OAuthRequest($http_method, $http_url, $parameters);
83
- }
84
-
85
- /**
86
- * pretty much a helper function to set up the request
87
- * @param $consumer
88
- * @param $token
89
- * @param $http_method
90
- * @param $http_url
91
- * @param null $parameters
92
- * @return OAuthRequest
93
- */
94
- public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters = null)
95
- {
96
- $parameters = ($parameters) ? $parameters : array();
97
- $defaults = array(
98
- "oauth_version" => OAuthRequest::$version,
99
- "oauth_nonce" => OAuthRequest::generate_nonce(),
100
- "oauth_timestamp" => OAuthRequest::generate_timestamp(),
101
- "oauth_consumer_key" => $consumer->key
102
- );
103
- if ($token) {
104
- $defaults['oauth_token'] = $token->key;
105
- }
106
-
107
- $parameters = array_merge($defaults, $parameters);
108
-
109
- return new OAuthRequest($http_method, $http_url, $parameters);
110
- }
111
-
112
- /**
113
- * @param $name
114
- * @param $value
115
- * @param bool $allow_duplicates
116
- */
117
- public function set_parameter($name, $value, $allow_duplicates = true)
118
- {
119
- if ($allow_duplicates && isset($this->parameters[$name])) {
120
- // We have already added parameter(s) with this name, so add to the list
121
- if (is_scalar($this->parameters[$name])) {
122
- // This is the first duplicate, so transform scalar (string)
123
- // into an array so we can add the duplicates
124
- $this->parameters[$name] = array(
125
- $this->parameters[$name]
126
- );
127
- }
128
-
129
- $this->parameters[$name][] = $value;
130
- } else {
131
- $this->parameters[$name] = $value;
132
- }
133
- }
134
-
135
- /**
136
- * @param $name
137
- *
138
- * @return |null
139
- */
140
- public function get_parameter($name)
141
- {
142
- return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
143
- }
144
-
145
- /**
146
- * @return array
147
- */
148
- public function get_parameters()
149
- {
150
- return $this->parameters;
151
- }
152
-
153
- /**
154
- * @param $name
155
- */
156
- public function unset_parameter($name)
157
- {
158
- unset($this->parameters[$name]);
159
- }
160
-
161
- /**
162
- * The request parameters, sorted and concatenated into a normalized string.
163
- *
164
- * @return string
165
- */
166
- public function get_signable_parameters()
167
- {
168
- // Grab all parameters
169
- $params = $this->parameters;
170
-
171
- // Remove oauth_signature if present
172
- // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
173
- if (isset($params['oauth_signature'])) {
174
- unset($params['oauth_signature']);
175
- }
176
-
177
- return OAuthUtil::build_http_query($params);
178
- }
179
-
180
- /**
181
- * Returns the base string of this request
182
- *
183
- * The base string defined as the method, the url
184
- * and the parameters (normalized), each urlencoded
185
- * and the concated with &.
186
- */
187
- public function get_signature_base_string()
188
- {
189
- $parts = array(
190
- $this->get_normalized_http_method(),
191
- $this->get_normalized_http_url(),
192
- $this->get_signable_parameters()
193
- );
194
-
195
- $parts = OAuthUtil::urlencode_rfc3986($parts);
196
-
197
- return implode('&', $parts);
198
- }
199
-
200
- /**
201
- * just uppercases the http method
202
- */
203
- public function get_normalized_http_method()
204
- {
205
- return strtoupper($this->http_method);
206
- }
207
-
208
- /**
209
- * parses the url and rebuilds it to be
210
- * scheme://host/path
211
- */
212
- public function get_normalized_http_url()
213
- {
214
- $parts = parse_url($this->http_url);
215
-
216
- $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
217
- $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80');
218
- $host = (isset($parts['host'])) ? strtolower($parts['host']) : '';
219
- $path = (isset($parts['path'])) ? $parts['path'] : '';
220
-
221
- if (($scheme == 'https' && $port != '443') || ($scheme == 'http' && $port != '80')) {
222
- $host = "$host:$port";
223
- }
224
- return "$scheme://$host$path";
225
- }
226
-
227
- /**
228
- * builds a url usable for a GET request
229
- */
230
- public function to_url()
231
- {
232
- $post_data = $this->to_postdata();
233
- $out = $this->get_normalized_http_url();
234
- if ($post_data) {
235
- $out .= '?' . $post_data;
236
- }
237
- return $out;
238
- }
239
-
240
- /**
241
- * builds the data one would send in a POST request
242
- */
243
- public function to_postdata()
244
- {
245
- return OAuthUtil::build_http_query($this->parameters);
246
- }
247
-
248
- /**
249
- * builds the Authorization: header
250
- * @param null $realm
251
- * @return array
252
- */
253
- public function to_header($realm = null)
254
- {
255
- $first = true;
256
- if ($realm) {
257
- $out = 'OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"';
258
- $first = false;
259
- } else {
260
- $out = 'OAuth';
261
- }
262
-
263
- foreach ($this->parameters as $k => $v) {
264
- if (substr($k, 0, 5) != "oauth") {
265
- continue;
266
- }
267
- if (is_array($v)) {
268
- continue;
269
- }
270
- $out .= ($first) ? ' ' : ',';
271
- $out .= OAuthUtil::urlencode_rfc3986($k) . '="' . OAuthUtil::urlencode_rfc3986($v) . '"';
272
- $first = false;
273
- }
274
-
275
- return array(
276
- 'Authorization' => $out
277
- ); //- hacked into this to make it return an array. 15/11/2014.
278
- }
279
-
280
- /**
281
- * @return string
282
- */
283
- public function __toString()
284
- {
285
- return $this->to_url();
286
- }
287
-
288
- /**
289
- * @param $signature_method
290
- * @param $consumer
291
- * @param $token
292
- */
293
- public function sign_request($signature_method, $consumer, $token)
294
- {
295
- $this->set_parameter("oauth_signature_method", $signature_method->get_name(), false);
296
- $signature = $this->build_signature($signature_method, $consumer, $token);
297
- $this->set_parameter("oauth_signature", $signature, false);
298
- }
299
-
300
- /**
301
- * @param $signature_method
302
- * @param $consumer
303
- * @param $token
304
- *
305
- * @return mixed
306
- */
307
- public function build_signature($signature_method, $consumer, $token)
308
- {
309
- $signature = $signature_method->build_signature($this, $consumer, $token);
310
- return $signature;
311
- }
312
-
313
- /**
314
- * util function: current timestamp
315
- */
316
- private static function generate_timestamp()
317
- {
318
- return time();
319
- }
320
-
321
- /**
322
- * util function: current nonce
323
- */
324
- private static function generate_nonce()
325
- {
326
- $mt = microtime();
327
- $rand = mt_rand();
328
-
329
- return md5($mt . $rand); // md5s look nicer than numbers
330
- }
331
- }
1
+ <?php
2
+ /*!
3
+ * This file is part of the OAuth PHP Library (https://code.google.com/p/oauth/)
4
+ *
5
+ * OAuth `PHP' Library is an open source software available under the MIT License.
6
+ */
7
+
8
+ namespace Hybridauth\Thirdparty\OAuth;
9
+
10
+ /**
11
+ * Class OAuthRequest
12
+ *
13
+ * @package Hybridauth\Thirdparty\OAuth
14
+ */
15
+ class OAuthRequest
16
+ {
17
+ public $parameters;
18
+ public $http_method;
19
+ public $http_url;
20
+ // for debug purposes
21
+ public $base_string;
22
+ public static $version = '1.0';
23
+ public static $POST_INPUT = 'php://input';
24
+
25
+ /**
26
+ * OAuthRequest constructor.
27
+ *
28
+ * @param $http_method
29
+ * @param $http_url
30
+ * @param null $parameters
31
+ */
32
+ public function __construct($http_method, $http_url, $parameters = null)
33
+ {
34
+ $parameters = ($parameters) ? $parameters : array();
35
+ $parameters = array_merge(OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters);
36
+ $this->parameters = $parameters;
37
+ $this->http_method = $http_method;
38
+ $this->http_url = $http_url;
39
+ }
40
+
41
+ /**
42
+ * attempt to build up a request from what was passed to the server
43
+ *
44
+ * @param null $http_method
45
+ * @param null $http_url
46
+ * @param null $parameters
47
+ *
48
+ * @return OAuthRequest
49
+ */
50
+ public static function from_request($http_method = null, $http_url = null, $parameters = null)
51
+ {
52
+ $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https';
53
+ $http_url = ($http_url) ? $http_url : $scheme . '://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'];
54
+ $http_method = ($http_method) ? $http_method : $_SERVER['REQUEST_METHOD'];
55
+
56
+ // We weren't handed any parameters, so let's find the ones relevant to
57
+ // this request.
58
+ // If you run XML-RPC or similar you should use this to provide your own
59
+ // parsed parameter-list
60
+ if (!$parameters) {
61
+ // Find request headers
62
+ $request_headers = OAuthUtil::get_headers();
63
+
64
+ // Parse the query-string to find GET parameters
65
+ $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']);
66
+
67
+ // It's a POST request of the proper content-type, so parse POST
68
+ // parameters and add those overriding any duplicates from GET
69
+ if ($http_method == "POST" && isset($request_headers['Content-Type']) && strstr($request_headers['Content-Type'], 'application/x-www-form-urlencoded')) {
70
+ $post_data = OAuthUtil::parse_parameters(file_get_contents(self::$POST_INPUT));
71
+ $parameters = array_merge($parameters, $post_data);
72
+ }
73
+
74
+ // We have a Authorization-header with OAuth data. Parse the header
75
+ // and add those overriding any duplicates from GET or POST
76
+ if (isset($request_headers['Authorization']) && substr($request_headers['Authorization'], 0, 6) == 'OAuth ') {
77
+ $header_parameters = OAuthUtil::split_header($request_headers['Authorization']);
78
+ $parameters = array_merge($parameters, $header_parameters);
79
+ }
80
+ }
81
+
82
+ return new OAuthRequest($http_method, $http_url, $parameters);
83
+ }
84
+
85
+ /**
86
+ * pretty much a helper function to set up the request
87
+ * @param $consumer
88
+ * @param $token
89
+ * @param $http_method
90
+ * @param $http_url
91
+ * @param null $parameters
92
+ * @return OAuthRequest
93
+ */
94
+ public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters = null)
95
+ {
96
+ $parameters = ($parameters) ? $parameters : array();
97
+ $defaults = array(
98
+ "oauth_version" => OAuthRequest::$version,
99
+ "oauth_nonce" => OAuthRequest::generate_nonce(),
100
+ "oauth_timestamp" => OAuthRequest::generate_timestamp(),
101
+ "oauth_consumer_key" => $consumer->key
102
+ );
103
+ if ($token) {
104
+ $defaults['oauth_token'] = $token->key;
105
+ }
106
+
107
+ $parameters = array_merge($defaults, $parameters);
108
+
109
+ return new OAuthRequest($http_method, $http_url, $parameters);
110
+ }
111
+
112
+ /**
113
+ * @param $name
114
+ * @param $value
115
+ * @param bool $allow_duplicates
116
+ */
117
+ public function set_parameter($name, $value, $allow_duplicates = true)
118
+ {
119
+ if ($allow_duplicates && isset($this->parameters[$name])) {
120
+ // We have already added parameter(s) with this name, so add to the list
121
+ if (is_scalar($this->parameters[$name])) {
122
+ // This is the first duplicate, so transform scalar (string)
123
+ // into an array so we can add the duplicates
124
+ $this->parameters[$name] = array(
125
+ $this->parameters[$name]
126
+ );
127
+ }
128
+
129
+ $this->parameters[$name][] = $value;
130
+ } else {
131
+ $this->parameters[$name] = $value;
132
+ }
133
+ }
134
+
135
+ /**
136
+ * @param $name
137
+ *
138
+ * @return |null
139
+ */
140
+ public function get_parameter($name)
141
+ {
142
+ return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
143
+ }
144
+
145
+ /**
146
+ * @return array
147
+ */
148
+ public function get_parameters()
149
+ {
150
+ return $this->parameters;
151
+ }
152
+
153
+ /**
154
+ * @param $name
155
+ */
156
+ public function unset_parameter($name)
157
+ {
158
+ unset($this->parameters[$name]);
159
+ }
160
+
161
+ /**
162
+ * The request parameters, sorted and concatenated into a normalized string.
163
+ *
164
+ * @return string
165
+ */
166
+ public function get_signable_parameters()
167
+ {
168
+ // Grab all parameters
169
+ $params = $this->parameters;
170
+
171
+ // Remove oauth_signature if present
172
+ // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
173
+ if (isset($params['oauth_signature'])) {
174
+ unset($params['oauth_signature']);
175
+ }
176
+
177
+ return OAuthUtil::build_http_query($params);
178
+ }
179
+
180
+ /**
181
+ * Returns the base string of this request
182
+ *
183
+ * The base string defined as the method, the url
184
+ * and the parameters (normalized), each urlencoded
185
+ * and the concated with &.
186
+ */
187
+ public function get_signature_base_string()
188
+ {
189
+ $parts = array(
190
+ $this->get_normalized_http_method(),
191
+ $this->get_normalized_http_url(),
192
+ $this->get_signable_parameters()
193
+ );
194
+
195
+ $parts = OAuthUtil::urlencode_rfc3986($parts);
196
+
197
+ return implode('&', $parts);
198
+ }
199
+
200
+ /**
201
+ * just uppercases the http method
202
+ */
203
+ public function get_normalized_http_method()
204
+ {
205
+ return strtoupper($this->http_method);
206
+ }
207
+
208
+ /**
209
+ * parses the url and rebuilds it to be
210
+ * scheme://host/path
211
+ */
212
+ public function get_normalized_http_url()
213
+ {
214
+ $parts = parse_url($this->http_url);
215
+
216
+ $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
217
+ $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80');
218
+ $host = (isset($parts['host'])) ? strtolower($parts['host']) : '';
219
+ $path = (isset($parts['path'])) ? $parts['path'] : '';
220
+
221
+ if (($scheme == 'https' && $port != '443') || ($scheme == 'http' && $port != '80')) {
222
+ $host = "$host:$port";
223
+ }
224
+ return "$scheme://$host$path";
225
+ }
226
+
227
+ /**
228
+ * builds a url usable for a GET request
229
+ */
230
+ public function to_url()
231
+ {
232
+ $post_data = $this->to_postdata();
233
+ $out = $this->get_normalized_http_url();
234
+ if ($post_data) {
235
+ $out .= '?' . $post_data;
236
+ }
237
+ return $out;
238
+ }
239
+
240
+ /**
241
+ * builds the data one would send in a POST request
242
+ */
243
+ public function to_postdata()
244
+ {
245
+ return OAuthUtil::build_http_query($this->parameters);
246
+ }
247
+
248
+ /**
249
+ * builds the Authorization: header
250
+ * @param null $realm
251
+ * @return array
252
+ */
253
+ public function to_header($realm = null)
254
+ {
255
+ $first = true;
256
+ if ($realm) {
257
+ $out = 'OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"';
258
+ $first = false;
259
+ } else {
260
+ $out = 'OAuth';
261
+ }
262
+
263
+ foreach ($this->parameters as $k => $v) {
264
+ if (substr($k, 0, 5) != "oauth") {
265
+ continue;
266
+ }
267
+ if (is_array($v)) {
268
+ continue;
269
+ }
270
+ $out .= ($first) ? ' ' : ',';
271
+ $out .= OAuthUtil::urlencode_rfc3986($k) . '="' . OAuthUtil::urlencode_rfc3986($v) . '"';
272
+ $first = false;
273
+ }
274
+
275
+ return array(
276
+ 'Authorization' => $out
277
+ ); //- hacked into this to make it return an array. 15/11/2014.
278
+ }
279
+
280
+ /**
281
+ * @return string
282
+ */
283
+ public function __toString()
284
+ {
285
+ return $this->to_url();
286
+ }
287
+
288
+ /**
289
+ * @param $signature_method
290
+ * @param $consumer
291
+ * @param $token
292
+ */
293
+ public function sign_request($signature_method, $consumer, $token)
294
+ {
295
+ $this->set_parameter("oauth_signature_method", $signature_method->get_name(), false);
296
+ $signature = $this->build_signature($signature_method, $consumer, $token);
297
+ $this->set_parameter("oauth_signature", $signature, false);
298
+ }
299
+
300
+ /**
301
+ * @param $signature_method
302
+ * @param $consumer
303
+ * @param $token
304
+ *
305
+ * @return mixed
306
+ */
307
+ public function build_signature($signature_method, $consumer, $token)
308
+ {
309
+ $signature = $signature_method->build_signature($this, $consumer, $token);
310
+ return $signature;
311
+ }
312
+
313
+ /**
314
+ * util function: current timestamp
315
+ */
316
+ private static function generate_timestamp()
317
+ {
318
+ return time();
319
+ }
320
+
321
+ /**
322
+ * util function: current nonce
323
+ */
324
+ private static function generate_nonce()
325
+ {
326
+ $mt = microtime();
327
+ $rand = mt_rand();
328
+
329
+ return md5($mt . $rand); // md5s look nicer than numbers
330
+ }
331
+ }
hybridauth/library/src/Thirdparty/OAuth/OAuthSignatureMethod.php CHANGED
@@ -1,67 +1,67 @@
1
- <?php
2
- /*!
3
- * This file is part of the OAuth PHP Library (https://code.google.com/p/oauth/)
4
- *
5
- * OAuth `PHP' Library is an open source software available under the MIT License.
6
- */
7
-
8
- namespace Hybridauth\Thirdparty\OAuth;
9
-
10
- /**
11
- * Class OAuthSignatureMethod
12
- *
13
- * @package Hybridauth\Thirdparty\OAuth
14
- */
15
- abstract class OAuthSignatureMethod
16
- {
17
- /**
18
- * Needs to return the name of the Signature Method (ie HMAC-SHA1)
19
- *
20
- * @return string
21
- */
22
- abstract public function get_name();
23
-
24
- /**
25
- * Build up the signature
26
- * NOTE: The output of this function MUST NOT be urlencoded.
27
- * the encoding is handled in OAuthRequest when the final
28
- * request is serialized
29
- *
30
- * @param OAuthRequest $request
31
- * @param OAuthConsumer $consumer
32
- * @param OAuthToken $token
33
- * @return string
34
- */
35
- abstract public function build_signature($request, $consumer, $token);
36
-
37
- /**
38
- * Verifies that a given signature is correct
39
- *
40
- * @param OAuthRequest $request
41
- * @param OAuthConsumer $consumer
42
- * @param OAuthToken $token
43
- * @param string $signature
44
- * @return bool
45
- */
46
- public function check_signature($request, $consumer, $token, $signature)
47
- {
48
- $built = $this->build_signature($request, $consumer, $token);
49
-
50
- // Check for zero length, although unlikely here
51
- if (strlen($built) == 0 || strlen($signature) == 0) {
52
- return false;
53
- }
54
-
55
- if (strlen($built) != strlen($signature)) {
56
- return false;
57
- }
58
-
59
- // Avoid a timing leak with a (hopefully) time insensitive compare
60
- $result = 0;
61
- for ($i = 0; $i < strlen($signature); $i ++) {
62
- $result |= ord($built[$i]) ^ ord($signature[$i]);
63
- }
64
-
65
- return $result == 0;
66
- }
67
- }
1
+ <?php
2
+ /*!
3
+ * This file is part of the OAuth PHP Library (https://code.google.com/p/oauth/)
4
+ *
5
+ * OAuth `PHP' Library is an open source software available under the MIT License.
6
+ */
7
+
8
+ namespace Hybridauth\Thirdparty\OAuth;
9
+
10
+ /**
11
+ * Class OAuthSignatureMethod
12
+ *
13
+ * @package Hybridauth\Thirdparty\OAuth
14
+ */
15
+ abstract class OAuthSignatureMethod
16
+ {
17
+ /**
18
+ * Needs to return the name of the Signature Method (ie HMAC-SHA1)
19
+ *
20
+ * @return string
21
+ */
22
+ abstract public function get_name();
23
+
24
+ /**
25
+ * Build up the signature
26
+ * NOTE: The output of this function MUST NOT be urlencoded.
27
+ * the encoding is handled in OAuthRequest when the final
28
+ * request is serialized
29
+ *
30
+ * @param OAuthRequest $request
31
+ * @param OAuthConsumer $consumer
32
+ * @param OAuthToken $token
33
+ * @return string
34
+ */
35
+ abstract public function build_signature($request, $consumer, $token);
36
+
37
+ /**
38
+ * Verifies that a given signature is correct
39
+ *
40
+ * @param OAuthRequest $request
41
+ * @param OAuthConsumer $consumer
42
+ * @param OAuthToken $token
43
+ * @param string $signature
44
+ * @return bool
45
+ */
46
+ public function check_signature($request, $consumer, $token, $signature)
47
+ {
48
+ $built = $this->build_signature($request, $consumer, $token);
49
+
50
+ // Check for zero length, although unlikely here
51
+ if (strlen($built) == 0 || strlen($signature) == 0) {
52
+ return false;
53
+ }
54
+
55
+ if (strlen($built) != strlen($signature)) {
56
+ return false;
57
+ }
58
+
59
+ // Avoid a timing leak with a (hopefully) time insensitive compare
60
+ $result = 0;
61
+ for ($i = 0; $i < strlen($signature); $i ++) {
62
+ $result |= ord($built[$i]) ^ ord($signature[$i]);
63
+ }
64
+
65
+ return $result == 0;
66
+ }
67
+ }
hybridauth/library/src/Thirdparty/OAuth/OAuthSignatureMethodHMACSHA1.php CHANGED
@@ -1,44 +1,44 @@
1
- <?php
2
- /*!
3
- * This file is part of the OAuth PHP Library (https://code.google.com/p/oauth/)
4
- *
5
- * OAuth `PHP' Library is an open source software available under the MIT License.
6
- */
7
-
8
- namespace Hybridauth\Thirdparty\OAuth;
9
-
10
- /**
11
- * Class OAuthSignatureMethodHMACSHA1
12
- *
13
- * @package Hybridauth\Thirdparty\OAuth
14
- */
15
- class OAuthSignatureMethodHMACSHA1 extends OAuthSignatureMethod
16
- {
17
- /**
18
- * @return string
19
- */
20
- public function get_name()
21
- {
22
- return "HMAC-SHA1";
23
- }
24
-
25
- /**
26
- * @param $request
27
- * @param $consumer
28
- * @param $token
29
- *
30
- * @return string
31
- */
32
- public function build_signature($request, $consumer, $token)
33
- {
34
- $base_string = $request->get_signature_base_string();
35
- $request->base_string = $base_string;
36
-
37
- $key_parts = array( $consumer->secret, $token ? $token->secret : '' );
38
-
39
- $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
40
- $key = implode('&', $key_parts);
41
-
42
- return base64_encode(hash_hmac('sha1', $base_string, $key, true));
43
- }
44
- }
1
+ <?php
2
+ /*!
3
+ * This file is part of the OAuth PHP Library (https://code.google.com/p/oauth/)
4
+ *
5
+ * OAuth `PHP' Library is an open source software available under the MIT License.
6
+ */
7
+
8
+ namespace Hybridauth\Thirdparty\OAuth;
9
+
10
+ /**
11
+ * Class OAuthSignatureMethodHMACSHA1
12
+ *
13
+ * @package Hybridauth\Thirdparty\OAuth
14
+ */
15
+ class OAuthSignatureMethodHMACSHA1 extends OAuthSignatureMethod
16
+ {
17
+ /**
18
+ * @return string
19
+ */
20
+ public function get_name()
21
+ {
22
+ return "HMAC-SHA1";
23
+ }
24
+
25
+ /**
26
+ * @param $request
27
+ * @param $consumer
28
+ * @param $token
29
+ *
30
+ * @return string
31
+ */
32
+ public function build_signature($request, $consumer, $token)
33
+ {
34
+ $base_string = $request->get_signature_base_string();
35
+ $request->base_string = $base_string;
36
+
37
+ $key_parts = array( $consumer->secret, $token ? $token->secret : '' );
38
+
39
+ $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
40
+ $key = implode('&', $key_parts);
41
+
42
+ return base64_encode(hash_hmac('sha1', $base_string, $key, true));
43
+ }
44
+ }
hybridauth/library/src/Thirdparty/OAuth/OAuthUtil.php CHANGED
@@ -1,199 +1,199 @@
1
- <?php
2
- /*!
3
- * This file is part of the OAuth PHP Library (https://code.google.com/p/oauth/)
4
- *
5
- * OAuth `PHP' Library is an open source software available under the MIT License.
6
- */
7
-
8
- namespace Hybridauth\Thirdparty\OAuth;
9
-
10
- /**
11
- * Class OAuthUtil
12
- *
13
- * @package Hybridauth\Thirdparty\OAuth
14
- */
15
- class OAuthUtil
16
- {
17
- /**
18
- * @param $input
19
- *
20
- * @return array|mixed|string
21
- */
22
- public static function urlencode_rfc3986($input)
23
- {
24
- if (is_array($input)) {
25
- return array_map(array(
26
- '\Hybridauth\Thirdparty\OAuth\OAuthUtil',
27
- 'urlencode_rfc3986'
28
- ), $input);
29
- } elseif (is_scalar($input)) {
30
- return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode($input)));
31
- } else {
32
- return '';
33
- }
34
- }
35
-
36
- // This decode function isn't taking into consideration the above
37
- // modifications to the encoding process. However, this method doesn't
38
- // seem to be used anywhere so leaving it as is.
39
- /**
40
- * @param $string
41
- *
42
- * @return string
43
- */
44
- public static function urldecode_rfc3986($string)
45
- {
46
- return urldecode($string);
47
- }
48
-
49
- // Utility function for turning the Authorization: header into
50
- // parameters, has to do some unescaping
51
- // Can filter out any non-oauth parameters if needed (default behaviour)
52
- // May 28th, 2010 - method updated to tjerk.meesters for a speed improvement.
53
- // see http://code.google.com/p/oauth/issues/detail?id=163
54
- /**
55
- * @param $header
56
- * @param bool $only_allow_oauth_parameters
57
- *
58
- * @return array
59
- */
60
- public static function split_header($header, $only_allow_oauth_parameters = true)
61
- {
62
- $params = array();
63
- if (preg_match_all('/(' . ($only_allow_oauth_parameters ? 'oauth_' : '') . '[a-z_-]*)=(:?"([^"]*)"|([^,]*))/', $header, $matches)) {
64
- foreach ($matches[1] as $i => $h) {
65
- $params[$h] = OAuthUtil::urldecode_rfc3986(empty($matches[3][$i]) ? $matches[4][$i] : $matches[3][$i]);
66
- }
67
- if (isset($params['realm'])) {
68
- unset($params['realm']);
69
- }
70
- }
71
- return $params;
72
- }
73
-
74
- // helper to try to sort out headers for people who aren't running apache
75
-
76
- /**
77
- * @return array
78
- */
79
- public static function get_headers()
80
- {
81
- if (function_exists('apache_request_headers')) {
82
- // we need this to get the actual Authorization: header
83
- // because apache tends to tell us it doesn't exist
84
- $headers = apache_request_headers();
85
-
86
- // sanitize the output of apache_request_headers because
87
- // we always want the keys to be Cased-Like-This and arh()
88
- // returns the headers in the same case as they are in the
89
- // request
90
- $out = array();
91
- foreach ($headers as $key => $value) {
92
- $key = str_replace(" ", "-", ucwords(strtolower(str_replace("-", " ", $key))));
93
- $out[$key] = $value;
94
- }
95
- } else {
96
- // otherwise we don't have apache and are just going to have to hope
97
- // that $_SERVER actually contains what we need
98
- $out = array();
99
- if (isset($_SERVER['CONTENT_TYPE'])) {
100
- $out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
101
- }
102
- if (isset($_ENV['CONTENT_TYPE'])) {
103
- $out['Content-Type'] = $_ENV['CONTENT_TYPE'];
104
- }
105
-
106
- foreach ($_SERVER as $key => $value) {
107
- if (substr($key, 0, 5) == "HTTP_") {
108
- // this is chaos, basically it is just there to capitalize the first
109
- // letter of every word that is not an initial HTTP and strip HTTP
110
- // code from przemek
111
- $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
112
- $out[$key] = $value;
113
- }
114
- }
115
- }
116
- return $out;
117
- }
118
-
119
- // This function takes a input like a=b&a=c&d=e and returns the parsed
120
- // parameters like this
121
- // array('a' => array('b','c'), 'd' => 'e')
122
- /**
123
- * @param $input
124
- *
125
- * @return array
126
- */
127
- public static function parse_parameters($input)
128
- {
129
- if (!isset($input) || !$input) {
130
- return array();
131
- }
132
-
133
- $pairs = explode('&', $input);
134
-
135
- $parsed_parameters = array();
136
- foreach ($pairs as $pair) {
137
- $split = explode('=', $pair, 2);
138
- $parameter = OAuthUtil::urldecode_rfc3986($split[0]);
139
- $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : '';
140
-
141
- if (isset($parsed_parameters[$parameter])) {
142
- // We have already recieved parameter(s) with this name, so add to the list
143
- // of parameters with this name
144
-
145
- if (is_scalar($parsed_parameters[$parameter])) {
146
- // This is the first duplicate, so transform scalar (string) into an array
147
- // so we can add the duplicates
148
- $parsed_parameters[$parameter] = array(
149
- $parsed_parameters[$parameter]
150
- );
151
- }
152
-
153
- $parsed_parameters[$parameter][] = $value;
154
- } else {
155
- $parsed_parameters[$parameter] = $value;
156
- }
157
- }
158
- return $parsed_parameters;
159
- }
160
-
161
- /**
162
- * @param $params
163
- *
164
- * @return string
165
- */
166
- public static function build_http_query($params)
167
- {
168
- if (!$params) {
169
- return '';
170
- }
171
-
172
- // Urlencode both keys and values
173
- $keys = OAuthUtil::urlencode_rfc3986(array_keys($params));
174
- $values = OAuthUtil::urlencode_rfc3986(array_values($params));
175
- $params = array_combine($keys, $values);
176
-
177
- // Parameters are sorted by name, using lexicographical byte value ordering.
178
- // Ref: Spec: 9.1.1 (1)
179
- uksort($params, 'strcmp');
180
-
181
- $pairs = array();
182
- foreach ($params as $parameter => $value) {
183
- if (is_array($value)) {
184
- // If two or more parameters share the same name, they are sorted by their value
185
- // Ref: Spec: 9.1.1 (1)
186
- // June 12th, 2010 - changed to sort because of issue 164 by hidetaka
187
- sort($value, SORT_STRING);
188
- foreach ($value as $duplicate_value) {
189
- $pairs[] = $parameter . '=' . $duplicate_value;
190
- }
191
- } else {
192
- $pairs[] = $parameter . '=' . $value;
193
- }
194
- }
195
- // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61)
196
- // Each name-value pair is separated by an '&' character (ASCII code 38)
197
- return implode('&', $pairs);
198
- }
199
- }
1
+ <?php
2
+ /*!
3
+ * This file is part of the OAuth PHP Library (https://code.google.com/p/oauth/)
4
+ *
5
+ * OAuth `PHP' Library is an open source software available under the MIT License.
6
+ */
7
+
8
+ namespace Hybridauth\Thirdparty\OAuth;
9
+
10
+ /**
11
+ * Class OAuthUtil
12
+ *
13
+ * @package Hybridauth\Thirdparty\OAuth
14
+ */
15
+ class OAuthUtil
16
+ {
17
+ /**
18
+ * @param $input
19
+ *
20
+ * @return array|mixed|string
21
+ */
22
+ public static function urlencode_rfc3986($input)
23
+ {
24
+ if (is_array($input)) {
25
+ return array_map(array(
26
+ '\Hybridauth\Thirdparty\OAuth\OAuthUtil',
27
+ 'urlencode_rfc3986'
28
+ ), $input);
29
+ } elseif (is_scalar($input)) {
30
+ return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode($input)));
31
+ } else {
32
+ return '';
33
+ }
34
+ }
35
+
36
+ // This decode function isn't taking into consideration the above
37
+ // modifications to the encoding process. However, this method doesn't
38
+ // seem to be used anywhere so leaving it as is.
39
+ /**
40
+ * @param $string
41
+ *
42
+ * @return string
43
+ */
44
+ public static function urldecode_rfc3986($string)
45
+ {
46
+ return urldecode($string);
47
+ }
48
+
49
+ // Utility function for turning the Authorization: header into
50
+ // parameters, has to do some unescaping
51
+ // Can filter out any non-oauth parameters if needed (default behaviour)
52
+ // May 28th, 2010 - method updated to tjerk.meesters for a speed improvement.
53
+ // see http://code.google.com/p/oauth/issues/detail?id=163
54
+ /**
55
+ * @param $header
56
+ * @param bool $only_allow_oauth_parameters
57
+ *
58
+ * @return array
59
+ */
60
+ public static function split_header($header, $only_allow_oauth_parameters = true)
61
+ {
62
+ $params = array();
63
+ if (preg_match_all('/(' . ($only_allow_oauth_parameters ? 'oauth_' : '') . '[a-z_-]*)=(:?"([^"]*)"|([^,]*))/', $header, $matches)) {
64
+ foreach ($matches[1] as $i => $h) {
65
+ $params[$h] = OAuthUtil::urldecode_rfc3986(empty($matches[3][$i]) ? $matches[4][$i] : $matches[3][$i]);
66
+ }
67
+ if (isset($params['realm'])) {
68
+ unset($params['realm']);
69
+ }
70
+ }
71
+ return $params;
72
+ }
73
+
74
+ // helper to try to sort out headers for people who aren't running apache
75
+
76
+ /**
77
+ * @return array
78
+ */
79
+ public static function get_headers()
80
+ {
81
+ if (function_exists('apache_request_headers')) {
82
+ // we need this to get the actual Authorization: header
83
+ // because apache tends to tell us it doesn't exist
84
+ $headers = apache_request_headers();
85
+
86
+ // sanitize the output of apache_request_headers because
87
+ // we always want the keys to be Cased-Like-This and arh()
88
+ // returns the headers in the same case as they are in the
89
+ // request
90
+ $out = array();
91
+ foreach ($headers as $key => $value) {
92
+ $key = str_replace(" ", "-", ucwords(strtolower(str_replace("-", " ", $key))));
93
+ $out[$key] = $value;
94
+ }
95
+ } else {
96
+ // otherwise we don't have apache and are just going to have to hope
97
+ // that $_SERVER actually contains what we need
98
+ $out = array();
99
+ if (isset($_SERVER['CONTENT_TYPE'])) {
100
+ $out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
101
+ }
102
+ if (isset($_ENV['CONTENT_TYPE'])) {
103
+ $out['Content-Type'] = $_ENV['CONTENT_TYPE'];
104
+ }
105
+
106
+ foreach ($_SERVER as $key => $value) {
107
+ if (substr($key, 0, 5) == "HTTP_") {
108
+ // this is chaos, basically it is just there to capitalize the first
109
+ // letter of every word that is not an initial HTTP and strip HTTP
110
+ // code from przemek
111
+ $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
112
+ $out[$key] = $value;
113
+ }
114
+ }
115
+ }
116
+ return $out;
117
+ }
118
+
119
+ // This function takes a input like a=b&a=c&d=e and returns the parsed
120
+ // parameters like this
121
+ // array('a' => array('b','c'), 'd' => 'e')
122
+ /**
123
+ * @param $input
124
+ *
125
+ * @return array
126
+ */
127
+ public static function parse_parameters($input)
128
+ {
129
+ if (!isset($input) || !$input) {
130
+ return array();
131
+ }
132
+
133
+ $pairs = explode('&', $input);
134
+
135
+ $parsed_parameters = array();
136
+ foreach ($pairs as $pair) {
137
+ $split = explode('=', $pair, 2);
138
+ $parameter = OAuthUtil::urldecode_rfc3986($split[0]);
139
+ $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : '';
140
+
141
+ if (isset($parsed_parameters[$parameter])) {
142
+ // We have already recieved parameter(s) with this name, so add to the list
143
+ // of parameters with this name
144
+
145
+ if (is_scalar($parsed_parameters[$parameter])) {
146
+ // This is the first duplicate, so transform scalar (string) into an array
147
+ // so we can add the duplicates
148
+ $parsed_parameters[$parameter] = array(
149
+ $parsed_parameters[$parameter]
150
+ );
151
+ }
152
+
153
+ $parsed_parameters[$parameter][] = $value;
154
+ } else {
155
+ $parsed_parameters[$parameter] = $value;
156
+ }
157
+ }
158
+ return $parsed_parameters;
159
+ }
160
+
161
+ /**
162
+ * @param $params
163
+ *
164
+ * @return string
165
+ */
166
+ public static function build_http_query($params)
167
+ {
168
+ if (!$params) {
169
+ return '';
170
+ }
171
+
172
+ // Urlencode both keys and values
173
+ $keys = OAuthUtil::urlencode_rfc3986(array_keys($params));
174
+ $values = OAuthUtil::urlencode_rfc3986(array_values($params));
175
+ $params = array_combine($keys, $values);
176
+
177
+ // Parameters are sorted by name, using lexicographical byte value ordering.
178
+ // Ref: Spec: 9.1.1 (1)
179
+ uksort($params, 'strcmp');
180
+
181
+ $pairs = array();
182
+ foreach ($params as $parameter => $value) {
183
+ if (is_array($value)) {
184
+ // If two or more parameters share the same name, they are sorted by their value
185
+ // Ref: Spec: 9.1.1 (1)
186
+ // June 12th, 2010 - changed to sort because of issue 164 by hidetaka
187
+ sort($value, SORT_STRING);
188
+ foreach ($value as $duplicate_value) {
189
+ $pairs[] = $parameter . '=' . $duplicate_value;
190
+ }
191
+ } else {
192
+ $pairs[] = $parameter . '=' . $value;
193
+ }
194
+ }
195
+ // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61)
196
+ // Each name-value pair is separated by an '&' character (ASCII code 38)
197
+ return implode('&', $pairs);
198
+ }
199
+ }
hybridauth/library/src/Thirdparty/OAuth/README.md CHANGED
@@ -1,7 +1,7 @@
1
- This package contains OAuth PHP Library.
2
-
3
- OAuth PHP Library is an open source software available under the MIT License.
4
-
5
- https://code.google.com/p/oauth/
6
-
7
- http://oauth.googlecode.com/svn/code/php/LICENSE.txt
1
+ This package contains OAuth PHP Library.
2
+
3
+ OAuth PHP Library is an open source software available under the MIT License.
4
+
5
+ https://code.google.com/p/oauth/
6
+
7
+ http://oauth.googlecode.com/svn/code/php/LICENSE.txt
hybridauth/library/src/Thirdparty/OpenID/LightOpenID.php CHANGED
@@ -1,1256 +1,1256 @@
1
- <?php
2
- /*!
3
- * This file is part of the LightOpenID PHP Library (https://github.com/iignatov/LightOpenID)
4
- *
5
- * LightOpenID is an open source software available under the MIT License.
6
- *
7
- * Updated: 52f9910 on 4 Mar 2016.
8
- */
9
-
10
- namespace Hybridauth\Thirdparty\OpenID;
11
-
12
- use Hybridauth\Exception\Exception;
13
- use Hybridauth\Exception\ExceptionInterface;
14
-
15
- /**
16
- * Class ErrorException
17
- *
18
- * @package Hybridauth\Thirdparty\OpenID
19
- */
20
- class ErrorException extends Exception implements ExceptionInterface
21
- {
22
- }
23
-
24
- /**
25
- * This class provides a simple interface for OpenID 1.1/2.0 authentication.
26
- *
27
- * It requires PHP >= 5.1.2 with cURL or HTTP/HTTPS stream wrappers enabled.
28
- *
29
- * @version v1.3.1 (2016-03-04)
30
- * @link https://code.google.com/p/lightopenid/ Project URL
31
- * @link https://github.com/iignatov/LightOpenID GitHub Repo
32
- * @author Mewp <mewp151 at gmail dot com>
33
- * @copyright Copyright (c) 2013 Mewp
34
- * @license http://opensource.org/licenses/mit-license.php MIT License
35
- */
36
- class LightOpenID
37
- {
38
- public $returnUrl
39
- ;
40
- public $required = array()
41
- ;
42
- public $optional = array()
43
- ;
44
- public $verify_peer = null
45
- ;
46
- public $capath = null
47
- ;
48
- public $cainfo = null
49
- ;
50
- public $cnmatch = null
51
- ;
52
- public $data
53
- ;
54
- public $oauth = array()
55
- ;
56
- public $curl_time_out = 30 // in seconds
57
- ;
58
- public $curl_connect_time_out = 30; // in seconds
59
- private $identity;
60
- private $claimed_id;
61
- protected $server;
62
- protected $version;
63
- protected $trustRoot;
64
- protected $aliases;
65
- protected $identifier_select = false
66
- ;
67
- protected $ax = false;
68
- protected $sreg = false;
69
- protected $setup_url = null;
70
- protected $headers = array()
71
- ;
72
- protected $proxy = null;
73
- protected $user_agent = 'LightOpenID'
74
- ;
75
- protected $xrds_override_pattern = null;
76
- protected $xrds_override_replacement = null;
77
- protected static $ax_to_sreg = array(
78
- 'namePerson/friendly' => 'nickname',
79
- 'contact/email' => 'email',
80
- 'namePerson' => 'fullname',
81
- 'birthDate' => 'dob',
82
- 'person/gender' => 'gender',
83
- 'contact/postalCode/home' => 'postcode',
84
- 'contact/country/home' => 'country',
85
- 'pref/language' => 'language',
86
- 'pref/timezone' => 'timezone',
87
- );
88
-
89
- /**
90
- * LightOpenID constructor.
91
- *
92
- * @param $host
93
- * @param null $proxy
94
- *
95
- * @throws ErrorException
96
- */
97
- public function __construct($host, $proxy = null)
98
- {
99
- $this->set_realm($host);
100
- $this->set_proxy($proxy);
101
-
102
- $uri = rtrim(preg_replace('#((?<=\?)|&)openid\.[^&]+#', '', $_SERVER['REQUEST_URI']), '?');
103
- $this->returnUrl = $this->trustRoot . $uri;
104
-
105
- $this->data = ($_SERVER['REQUEST_METHOD'] === 'POST') ? $_POST : $_GET;
106
-
107
- if (!function_exists('curl_init') && !in_array('https', stream_get_wrappers())) {
108
- throw new ErrorException('You must have either https wrappers or curl enabled.');
109
- }
110
- }
111
-
112
- /**
113
- * @param $name
114
- *
115
- * @return bool
116
- */
117
- public function __isset($name)
118
- {
119
- return in_array($name, array('identity', 'trustRoot', 'realm', 'xrdsOverride', 'mode'));
120
- }
121
-
122
- /**
123
- * @param $name
124
- * @param $value
125
- */
126
- public function __set($name, $value)
127
- {
128
- switch ($name) {
129
- case 'identity':
130
- if (strlen($value = trim((String) $value))) {
131
- if (preg_match('#^xri:/*#i', $value, $m)) {
132
- $value = substr($value, strlen($m[0]));
133
- } elseif (!preg_match('/^(?:[=@+\$!\(]|https?:)/i', $value)) {
134
- $value = "http://$value";
135
- }
136
- if (preg_match('#^https?://[^/]+$#i', $value, $m)) {
137
- $value .= '/';
138
- }
139
- }
140
- $this->$name = $this->claimed_id = $value;
141
- break;
142
- case 'trustRoot':
143
- case 'realm':
144
- $this->trustRoot = trim($value);
145
- break;
146
- case 'xrdsOverride':
147
- if (is_array($value)) {
148
- list($pattern, $replacement) = $value;
149
- $this->xrds_override_pattern = $pattern;
150
- $this->xrds_override_replacement = $replacement;
151
- } else {
152
- trigger_error('Invalid value specified for "xrdsOverride".', E_USER_ERROR);
153
- }
154
- break;
155
- }
156
- }
157
-
158
- /**
159
- * @param $name
160
- *
161
- * @return |null
162
- */
163
- public function __get($name)
164
- {
165
- switch ($name) {
166
- case 'identity':
167
- # We return claimed_id instead of identity,
168
- # because the developer should see the claimed identifier,
169
- # i.e. what he set as identity, not the op-local identifier (which is what we verify)
170
- return $this->claimed_id;
171
- case 'trustRoot':
172
- case 'realm':
173
- return $this->trustRoot;
174
- case 'mode':
175
- return empty($this->data['openid_mode']) ? null : $this->data['openid_mode'];
176
- }
177
- }
178
-
179
- /**
180
- * @param $proxy
181
- *
182
- * @throws ErrorException
183
- */
184
- public function set_proxy($proxy)
185
- {
186
- if (!empty($proxy)) {
187
- // When the proxy is a string - try to parse it.
188
- if (!is_array($proxy)) {
189
- $proxy = parse_url($proxy);
190
- }
191
-
192
- // Check if $proxy is valid after the parsing.
193
- if ($proxy && !empty($proxy['host'])) {
194
- // Make sure that a valid port number is specified.
195
- if (array_key_exists('port', $proxy)) {
196
- if (!is_int($proxy['port'])) {
197
- $proxy['port'] = is_numeric($proxy['port']) ? intval($proxy['port']) : 0;
198
- }
199
-
200
- if ($proxy['port'] <= 0) {
201
- throw new ErrorException('The specified proxy port number is invalid.');
202
- }
203
- }
204
-
205
- $this->proxy = $proxy;
206
- }
207
- }
208
- }
209
-
210
- /**
211
- * Checks if the server specified in the url exists.
212
- *
213
- * @param $url string url to check
214
- * @return true, if the server exists; false otherwise
215
- */
216
- public function hostExists($url)
217
- {
218
- if (strpos($url, '/') === false) {
219
- $server = $url;
220
- } else {
221
- $server = @parse_url($url, PHP_URL_HOST);
222
- }
223
-
224
- if (!$server) {
225
- return false;
226
- }
227
-
228
- return !!gethostbynamel($server);
229
- }
230
-
231
- /**
232
- * @param $uri
233
- */
234
- protected function set_realm($uri)
235
- {
236
- $realm = '';
237
-
238
- # Set a protocol, if not specified.
239
- $realm .= (($offset = strpos($uri, '://')) === false) ? $this->get_realm_protocol() : '';
240
-
241
- # Set the offset properly.
242
- $offset = (($offset !== false) ? $offset + 3 : 0);
243
-
244
- # Get only the root, without the path.
245
- $realm .= (($end = strpos($uri, '/', $offset)) === false) ? $uri : substr($uri, 0, $end);
246
-
247
- $this->trustRoot = $realm;
248
- }
249
-
250
- /**
251
- * @return string
252
- */
253
- protected function get_realm_protocol()
254
- {
255
- if (!empty($_SERVER['HTTPS'])) {
256
- $use_secure_protocol = ($_SERVER['HTTPS'] !== 'off');
257
- } elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
258
- $use_secure_protocol = ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https');
259
- } elseif (isset($_SERVER['HTTP__WSSC'])) {
260
- $use_secure_protocol = ($_SERVER['HTTP__WSSC'] == 'https');
261
- } else {
262
- $use_secure_protocol = false;
263
- }
264
-
265
- return $use_secure_protocol ? 'https://' : 'http://';
266
- }
267
-
268
- /**
269
- * @param $url
270
- * @param string $method
271
- * @param array $params
272
- * @param $update_claimed_id
273
- *
274
- * @return array|bool|string
275
- * @throws ErrorException
276
- */
277
- protected function request_curl($url, $method='GET', $params=array(), $update_claimed_id)
278
- {
279
- $params = http_build_query($params, '', '&');
280
- $curl = curl_init($url . ($method == 'GET' && $params ? '?' . $params : ''));
281
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
282
- curl_setopt($curl, CURLOPT_HEADER, false);
283
- curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent);
284
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
285
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
286
-
287
- if ($method == 'POST') {
288
- curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
289
- } else {
290
- curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/xrds+xml, */*'));
291
- }
292
-
293
- curl_setopt($curl, CURLOPT_TIMEOUT, $this->curl_time_out); // defaults to infinite
294
- curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $this->curl_connect_time_out); // defaults to 300s
295
-
296
- if (!empty($this->proxy)) {
297
- curl_setopt($curl, CURLOPT_PROXY, $this->proxy['host']);
298
-
299
- if (!empty($this->proxy['port'])) {
300
- curl_setopt($curl, CURLOPT_PROXYPORT, $this->proxy['port']);
301
- }
302
-
303
- if (!empty($this->proxy['user'])) {
304
- curl_setopt($curl, CURLOPT_PROXYUSERPWD, $this->proxy['user'] . ':' . $this->proxy['pass']);
305
- }
306
- }
307
-
308
- if ($this->verify_peer !== null) {
309
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
310
- if ($this->capath) {
311
- curl_setopt($curl, CURLOPT_CAPATH, $this->capath);
312
- }
313
-
314
- if ($this->cainfo) {
315
- curl_setopt($curl, CURLOPT_CAINFO, $this->cainfo);
316
- }
317
- }
318
-
319
- if ($method == 'POST') {
320
- curl_setopt($curl, CURLOPT_POST, true);
321
- curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
322
- } elseif ($method == 'HEAD') {
323
- curl_setopt($curl, CURLOPT_HEADER, true);
324
- curl_setopt($curl, CURLOPT_NOBODY, true);
325
- } else {
326
- curl_setopt($curl, CURLOPT_HEADER, true);
327
- curl_setopt($curl, CURLOPT_HTTPGET, true);
328
- }
329
- $response = curl_exec($curl);
330
-
331
- if ($method == 'HEAD' && curl_getinfo($curl, CURLINFO_HTTP_CODE) == 405) {
332
- curl_setopt($curl, CURLOPT_HTTPGET, true);
333
- $response = curl_exec($curl);
334
- $response = substr($response, 0, strpos($response, "\r\n\r\n"));
335
- }
336
-
337
- if ($method == 'HEAD' || $method == 'GET') {
338
- $header_response = $response;
339
-
340
- # If it's a GET request, we want to only parse the header part.
341
- if ($method == 'GET') {
342
- $header_response = substr($response, 0, strpos($response, "\r\n\r\n"));
343
- }
344
-
345
- $headers = array();
346
- foreach (explode("\n", $header_response) as $header) {
347
- $pos = strpos($header, ':');
348
- if ($pos !== false) {
349
- $name = strtolower(trim(substr($header, 0, $pos)));
350
- $headers[$name] = trim(substr($header, $pos+1));
351
- }
352
- }
353
-
354
- if ($update_claimed_id) {
355
- # Update the claimed_id value in case of redirections.
356
- $effective_url = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
357
- # Ignore the fragment (some cURL versions don't handle it well).
358
- if (strtok($effective_url, '#') != strtok($url, '#')) {
359
- $this->identity = $this->claimed_id = $effective_url;
360
- }
361
- }
362
-
363
- if ($method == 'HEAD') {
364
- return $headers;
365
- } else {
366
- $this->headers = $headers;
367
- }
368
- }
369
-
370
- if (curl_errno($curl)) {
371
- throw new ErrorException(curl_error($curl), curl_errno($curl));
372
- }
373
-
374
- return $response;
375
- }
376
-
377
- /**
378
- * @param $array
379
- * @param $update_claimed_id
380
- *
381
- * @return array
382
- */
383
- protected function parse_header_array($array, $update_claimed_id)
384
- {
385
- $headers = array();
386
- foreach ($array as $header) {
387
- $pos = strpos($header, ':');
388
- if ($pos !== false) {
389
- $name = strtolower(trim(substr($header, 0, $pos)));
390
- $headers[$name] = trim(substr($header, $pos+1));
391
-
392
- # Following possible redirections. The point is just to have
393
- # claimed_id change with them, because the redirections
394
- # are followed automatically.
395
- # We ignore redirections with relative paths.
396
- # If any known provider uses them, file a bug report.
397
- if ($name == 'location' && $update_claimed_id) {
398
- if (strpos($headers[$name], 'http') === 0) {
399
- $this->identity = $this->claimed_id = $headers[$name];
400
- } elseif ($headers[$name][0] == '/') {
401
- $parsed_url = parse_url($this->claimed_id);
402
- $this->identity =
403
- $this->claimed_id = $parsed_url['scheme'] . '://'
404
- . $parsed_url['host']
405
- . $headers[$name];
406
- }
407
- }
408
- }
409
- }
410
- return $headers;
411
- }
412
-
413
- /**
414
- * @param $url
415
- * @param string $method
416
- * @param array $params
417
- * @param $update_claimed_id
418
- *
419
- * @return array|false|string
420
- * @throws ErrorException
421
- */
422
- protected function request_streams($url, $method='GET', $params=array(), $update_claimed_id)
423
- {
424
- if (!$this->hostExists($url)) {
425
- throw new ErrorException("Could not connect to $url.", 404);
426
- }
427
-
428
- if (empty($this->cnmatch)) {
429
- $this->cnmatch = parse_url($url, PHP_URL_HOST);
430
- }
431
-
432
- $params = http_build_query($params, '', '&');
433
- switch ($method) {
434
- case 'GET':
435
- $opts = array(
436
- 'http' => array(
437
- 'method' => 'GET',
438
- 'header' => 'Accept: application/xrds+xml, */*',
439
- 'user_agent' => $this->user_agent,
440
- 'ignore_errors' => true,
441
- ),
442
- 'ssl' => array(
443
- 'CN_match' => $this->cnmatch
444
- )
445
- );
446
- $url = $url . ($params ? '?' . $params : '');
447
- if (!empty($this->proxy)) {
448
- $opts['http']['proxy'] = $this->proxy_url();
449
- }
450
- break;
451
- case 'POST':
452
- $opts = array(
453
- 'http' => array(
454
- 'method' => 'POST',
455
- 'header' => 'Content-type: application/x-www-form-urlencoded',
456
- 'user_agent' => $this->user_agent,
457
- 'content' => $params,
458
- 'ignore_errors' => true,
459
- ),
460
- 'ssl' => array(
461
- 'CN_match' => $this->cnmatch
462
- )
463
- );
464
- if (!empty($this->proxy)) {
465
- $opts['http']['proxy'] = $this->proxy_url();
466
- }
467
- break;
468
- case 'HEAD':
469
- // We want to send a HEAD request, but since get_headers() doesn't
470
- // accept $context parameter, we have to change the defaults.
471
- $default = stream_context_get_options(stream_context_get_default());
472
-
473
- // PHP does not reset all options. Instead, it just sets the options
474
- // available in the passed array, therefore set the defaults manually.
475
- $default += array(
476
- 'http' => array(),
477
- 'ssl' => array()
478
- );
479
- $default['http'] += array(
480
- 'method' => 'GET',
481
- 'header' => '',
482
- 'user_agent' => '',
483
- 'ignore_errors' => false
484
- );
485
- $default['ssl'] += array(
486
- 'CN_match' => ''
487
- );
488
-
489
- $opts = array(
490
- 'http' => array(
491
- 'method' => 'HEAD',
492
- 'header' => 'Accept: application/xrds+xml, */*',
493
- 'user_agent' => $this->user_agent,
494
- 'ignore_errors' => true,
495
- ),
496
- 'ssl' => array(
497
- 'CN_match' => $this->cnmatch
498
- )
499
- );
500
-
501
- // Enable validation of the SSL certificates.
502
- if ($this->verify_peer) {
503
- $default['ssl'] += array(
504
- 'verify_peer' => false,
505
- 'capath' => '',
506
- 'cafile' => ''
507
- );
508
- $opts['ssl'] += array(
509
- 'verify_peer' => true,
510
- 'capath' => $this->capath,
511
- 'cafile' => $this->cainfo
512
- );
513
- }
514
-
515
- // Change the stream context options.
516
- stream_context_get_default($opts);
517
-
518
- $headers = get_headers($url . ($params ? '?' . $params : ''));
519
-
520
- // Restore the stream context options.
521
- stream_context_get_default($default);
522
-
523
- if (!empty($headers)) {
524
- if (intval(substr($headers[0], strlen('HTTP/1.1 '))) == 405) {
525
- // The server doesn't support HEAD - emulate it with a GET.
526
- $args = func_get_args();
527
- $args[1] = 'GET';
528
- call_user_func_array(array($this, 'request_streams'), $args);
529
- $headers = $this->headers;
530
- } else {
531
- $headers = $this->parse_header_array($headers, $update_claimed_id);
532
- }
533
- } else {
534
- $headers = array();
535
- }
536
-
537
- return $headers;
538
- }
539
-
540
- if ($this->verify_peer) {
541
- $opts['ssl'] += array(
542
- 'verify_peer' => true,
543
- 'capath' => $this->capath,
544
- 'cafile' => $this->cainfo
545
- );
546
- }
547
-
548
- $context = stream_context_create($opts);
549
- $data = file_get_contents($url, false, $context);
550
- # This is a hack for providers who don't support HEAD requests.
551
- # It just creates the headers array for the last request in $this->headers.
552
- if (isset($http_response_header)) {
553
- $this->headers = $this->parse_header_array($http_response_header, $update_claimed_id);
554
- }
555
-
556
- return $data;
557
- }
558
-
559
- /**
560
- * @param $url
561
- * @param string $method
562
- * @param array $params
563
- * @param bool $update_claimed_id
564
- *
565
- * @return array|bool|false|string
566
- * @throws ErrorException
567
- */
568
- protected function request($url, $method='GET', $params=array(), $update_claimed_id=false)
569
- {
570
- $use_curl = false;
571
-
572
- if (function_exists('curl_init')) {
573
- if (!$use_curl) {
574
- # When allow_url_fopen is disabled, PHP streams will not work.
575
- $use_curl = !ini_get('allow_url_fopen');
576
- }
577
-
578
- if (!$use_curl) {
579
- # When there is no HTTPS wrapper, PHP streams cannott be used.
580
- $use_curl = !in_array('https', stream_get_wrappers());
581
- }
582
-
583
- if (!$use_curl) {
584
- # With open_basedir or safe_mode set, cURL can't follow redirects.
585
- $use_curl = !(ini_get('safe_mode') || ini_get('open_basedir'));
586
- }
587
- }
588
-
589
- return
590
- $use_curl
591
- ? $this->request_curl($url, $method, $params, $update_claimed_id)
592
- : $this->request_streams($url, $method, $params, $update_claimed_id);
593
- }
594
-
595
- /**
596
- * @return string
597
- */
598
- protected function proxy_url()
599
- {
600
- $result = '';
601
-
602
- if (!empty($this->proxy)) {
603
- $result = $this->proxy['host'];
604
-
605
- if (!empty($this->proxy['port'])) {
606
- $result = $result . ':' . $this->proxy['port'];
607
- }
608
-
609
- if (!empty($this->proxy['user'])) {
610
- $result = $this->proxy['user'] . ':' . $this->proxy['pass'] . '@' . $result;
611
- }
612
-
613
- $result = 'http://' . $result;
614
- }
615
-
616
- return $result;
617
- }
618
-
619
- /**
620
- * @param $url
621
- * @param $parts
622
- *
623
- * @return string
624
- */
625
- protected function build_url($url, $parts)
626
- {
627
- if (isset($url['query'], $parts['query'])) {
628
- $parts['query'] = $url['query'] . '&' . $parts['query'];
629
- }
630
-
631
- $url = $parts + $url;
632
- $url = $url['scheme'] . '://'
633
- . (empty($url['username'])?''
634
- :(empty($url['password'])? "{$url['username']}@"
635
- :"{$url['username']}:{$url['password']}@"))
636
- . $url['host']
637
- . (empty($url['port'])?'':":{$url['port']}")
638
- . (empty($url['path'])?'':$url['path'])
639
- . (empty($url['query'])?'':"?{$url['query']}")
640
- . (empty($url['fragment'])?'':"#{$url['fragment']}");
641
- return $url;
642
- }
643
-
644
- /**
645
- * Helper function used to scan for <meta>/<link> tags and extract information
646
- * from them
647
- *
648
- * @param $content
649
- * @param $tag
650
- * @param $attrName
651
- * @param $attrValue
652
- * @param $valueName
653
- *
654
- * @return bool
655
- */
656
- protected function htmlTag($content, $tag, $attrName, $attrValue, $valueName)
657
- {
658
- preg_match_all("#<{$tag}[^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*$valueName=['\"](.+?)['\"][^>]*/?>#i", $content, $matches1);
659
- preg_match_all("#<{$tag}[^>]*$valueName=['\"](.+?)['\"][^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*/?>#i", $content, $matches2);
660
-
661
- $result = array_merge($matches1[1], $matches2[1]);
662
- return empty($result)?false:$result[0];
663
- }
664
-
665
- /**
666
- * Performs Yadis and HTML discovery. Normally not used.
667
- * @param $url Identity URL.
668
- * @return String OP Endpoint (i.e. OpenID provider address).
669
- * @throws ErrorException
670
- */
671
- public function discover($url)
672
- {
673
- if (!$url) {
674
- throw new ErrorException('No identity supplied.');
675
- }
676
- # Use xri.net proxy to resolve i-name identities
677
- if (!preg_match('#^https?:#', $url)) {
678
- $url = "https://xri.net/$url";
679
- }
680
-
681
- # We save the original url in case of Yadis discovery failure.
682
- # It can happen when we'll be lead to an XRDS document
683
- # which does not have any OpenID2 services.
684
- $originalUrl = $url;
685
-
686
- # A flag to disable yadis discovery in case of failure in headers.
687
- $yadis = true;
688
-
689
- # Allows optional regex replacement of the URL, e.g. to use Google Apps
690
- # as an OpenID provider without setting up XRDS on the domain hosting.
691
- if (!is_null($this->xrds_override_pattern) && !is_null($this->xrds_override_replacement)) {
692
- $url = preg_replace($this->xrds_override_pattern, $this->xrds_override_replacement, $url);
693
- }
694
-
695
- # We'll jump a maximum of 5 times, to avoid endless redirections.
696
- for ($i = 0; $i < 5; $i ++) {
697
- if ($yadis) {
698
- $headers = $this->request($url, 'HEAD', array(), true);
699
-
700
- $next = false;
701
- if (isset($headers['x-xrds-location'])) {
702
- $url = $this->build_url(parse_url($url), parse_url(trim($headers['x-xrds-location'])));
703
- $next = true;
704
- }
705
-
706
- if (isset($headers['content-type']) && $this->is_allowed_type($headers['content-type'])) {
707
- # Found an XRDS document, now let's find the server, and optionally delegate.
708
- $content = $this->request($url, 'GET');
709
-
710
- preg_match_all('#<Service.*?>(.*?)</Service>#s', $content, $m);
711
- foreach ($m[1] as $content) {
712
- $content = ' ' . $content; # The space is added, so that strpos doesn't return 0.
713
-
714
- # OpenID 2
715
- $ns = preg_quote('http://specs.openid.net/auth/2.0/', '#');
716
- if (preg_match('#<Type>\s*'.$ns.'(server|signon)\s*</Type>#s', $content, $type)) {
717
- if ($type[1] == 'server') {
718
- $this->identifier_select = true;
719
- }
720
-
721
- preg_match('#<URI.*?>(.*)</URI>#', $content, $server);
722
- preg_match('#<(Local|Canonical)ID>(.*)</\1ID>#', $content, $delegate);
723
- if (empty($server)) {
724
- return false;
725
- }
726
- # Does the server advertise support for either AX or SREG?
727
- $this->ax = (bool) strpos($content, '<Type>http://openid.net/srv/ax/1.0</Type>');
728
- $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>')
729
- || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>');
730
-
731
- $server = $server[1];
732
- if (isset($delegate[2])) {
733
- $this->identity = trim($delegate[2]);
734
- }
735
- $this->version = 2;
736
-
737
- $this->server = $server;
738
- return $server;
739
- }
740
-
741
- # OpenID 1.1
742
- $ns = preg_quote('http://openid.net/signon/1.1', '#');
743
- if (preg_match('#<Type>\s*'.$ns.'\s*</Type>#s', $content)) {
744
- preg_match('#<URI.*?>(.*)</URI>#', $content, $server);
745
- preg_match('#<.*?Delegate>(.*)</.*?Delegate>#', $content, $delegate);
746
- if (empty($server)) {
747
- return false;
748
- }
749
- # AX can be used only with OpenID 2.0, so checking only SREG
750
- $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>')
751
- || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>');
752
-
753
- $server = $server[1];
754
- if (isset($delegate[1])) {
755
- $this->identity = $delegate[1];
756
- }
757
- $this->version = 1;
758
-
759
- $this->server = $server;
760
- return $server;
761
- }
762
- }
763
-
764
- $next = true;
765
- $yadis = false;
766
- $url = $originalUrl;
767
- $content = null;
768
- break;
769
- }
770
- if ($next) {
771
- continue;
772
- }
773
-
774
- # There are no relevant information in headers, so we search the body.
775
- $content = $this->request($url, 'GET', array(), true);
776
-
777
- if (isset($this->headers['x-xrds-location'])) {
778
- $url = $this->build_url(parse_url($url), parse_url(trim($this->headers['x-xrds-location'])));
779
- continue;
780
- }
781
-
782
- $location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'content');
783
- if ($location) {
784
- $url = $this->build_url(parse_url($url), parse_url($location));
785
- continue;
786
- }
787
- }
788
-
789
- if (!$content) {
790
- $content = $this->request($url, 'GET');
791
- }
792
-
793
- # At this point, the YADIS Discovery has failed, so we'll switch
794
- # to openid2 HTML discovery, then fallback to openid 1.1 discovery.
795
- $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href');
796
- $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href');
797
- $this->version = 2;
798
-
799
- if (!$server) {
800
- # The same with openid 1.1
801
- $server = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href');
802
- $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href');
803
- $this->version = 1;
804
- }
805
-
806
- if ($server) {
807
- # We found an OpenID2 OP Endpoint
808
- if ($delegate) {
809
- # We have also found an OP-Local ID.
810
- $this->identity = $delegate;
811
- }
812
- $this->server = $server;
813
- return $server;
814
- }
815
-
816
- throw new ErrorException("No OpenID Server found at $url", 404);
817
- }
818
- throw new ErrorException('Endless redirection!', 500);
819
- }
820
-
821
- /**
822
- * @param $content_type
823
- *
824
- * @return bool
825
- */
826
- protected function is_allowed_type($content_type)
827
- {
828
- # Apparently, some providers return XRDS documents as text/html.
829
- # While it is against the spec, allowing this here shouldn't break
830
- # compatibility with anything.
831
- $allowed_types = array('application/xrds+xml', 'text/xml');
832
-
833
- # Only allow text/html content type for the Yahoo logins, since
834
- # it might cause an endless redirection for the other providers.
835
- if ($this->get_provider_name($this->claimed_id) == 'yahoo') {
836
- $allowed_types[] = 'text/html';
837
- }
838
-
839
- foreach ($allowed_types as $type) {
840
- if (strpos($content_type, $type) !== false) {
841
- return true;
842
- }
843
- }
844
-
845
- return false;
846
- }
847
-
848
- /**
849
- * @param $provider_url
850
- *
851
- * @return string
852
- */
853
- protected function get_provider_name($provider_url)
854
- {
855
- $result = '';
856
-
857
- if (!empty($provider_url)) {
858
- $tokens = array_reverse(
859
- explode('.', parse_url($provider_url, PHP_URL_HOST))
860
- );
861
- $result = strtolower(
862
- (count($tokens) > 1 && strlen($tokens[1]) > 3)
863
- ? $tokens[1]
864
- : (count($tokens) > 2 ? $tokens[2] : '')
865
- );
866
- }
867
-
868
- return $result;
869
- }
870
-
871
- /**
872
- * @return array
873
- */
874
- protected function sregParams()
875
- {
876
- $params = array();
877
- # We always use SREG 1.1, even if the server is advertising only support for 1.0.
878
- # That's because it's fully backwards compatible with 1.0, and some providers
879
- # advertise 1.0 even if they accept only 1.1. One such provider is myopenid.com
880
- $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1';
881
- if ($this->required) {
882
- $params['openid.sreg.required'] = array();
883
- foreach ($this->required as $required) {
884
- if (!isset(self::$ax_to_sreg[$required])) {
885
- continue;
886
- }
887
- $params['openid.sreg.required'][] = self::$ax_to_sreg[$required];
888
- }
889
- $params['openid.sreg.required'] = implode(',', $params['openid.sreg.required']);
890
- }
891
-
892
- if ($this->optional) {
893
- $params['openid.sreg.optional'] = array();
894
- foreach ($this->optional as $optional) {
895
- if (!isset(self::$ax_to_sreg[$optional])) {
896
- continue;
897
- }
898
- $params['openid.sreg.optional'][] = self::$ax_to_sreg[$optional];
899
- }
900
- $params['openid.sreg.optional'] = implode(',', $params['openid.sreg.optional']);
901
- }
902
- return $params;
903
- }
904
-
905
- /**
906
- * @return array
907
- */
908
- protected function axParams()
909
- {
910
- $params = array();
911
- if ($this->required || $this->optional) {
912
- $params['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0';
913
- $params['openid.ax.mode'] = 'fetch_request';
914
- $this->aliases = array();
915
- $counts = array();
916
- $required = array();
917
- $optional = array();
918
- foreach (array('required','optional') as $type) {
919
- foreach ($this->$type as $alias => $field) {
920
- if (is_int($alias)) {
921
- $alias = strtr($field, '/', '_');
922
- }
923
- $this->aliases[$alias] = 'http://axschema.org/' . $field;
924
- if (empty($counts[$alias])) {
925
- $counts[$alias] = 0;
926
- }
927
- $counts[$alias] += 1;
928
- ${$type}[] = $alias;
929
- }
930
- }
931
- foreach ($this->aliases as $alias => $ns) {
932
- $params['openid.ax.type.' . $alias] = $ns;
933
- }
934
- foreach ($counts as $alias => $count) {
935
- if ($count == 1) {
936
- continue;
937
- }
938
- $params['openid.ax.count.' . $alias] = $count;
939
- }
940
-
941
- # Don't send empty ax.required and ax.if_available.
942
- # Google and possibly other providers refuse to support ax when one of these is empty.
943
- if ($required) {
944
- $params['openid.ax.required'] = implode(',', $required);
945
- }
946
- if ($optional) {
947
- $params['openid.ax.if_available'] = implode(',', $optional);
948
- }
949
- }
950
- return $params;
951
- }
952
-
953
- /**
954
- * @param $immediate
955
- *
956
- * @return string
957
- */
958
- protected function authUrl_v1($immediate)
959
- {
960
- $returnUrl = $this->returnUrl;
961
- # If we have an openid.delegate that is different from our claimed id,
962
- # we need to somehow preserve the claimed id between requests.
963
- # The simplest way is to just send it along with the return_to url.
964
- if ($this->identity != $this->claimed_id) {
965
- $returnUrl .= (strpos($returnUrl, '?') ? '&' : '?') . 'openid.claimed_id=' . $this->claimed_id;
966
- }
967
-
968
- $params = array(
969
- 'openid.return_to' => $returnUrl,
970
- 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
971
- 'openid.identity' => $this->identity,
972
- 'openid.trust_root' => $this->trustRoot,
973
- ) + $this->sregParams();
974
-
975
- return $this->build_url(parse_url($this->server), array('query' => http_build_query($params, '', '&')));
976
- }
977
-
978
- /**
979
- * @param $immediate
980
- *
981
- * @return string
982
- */
983
- protected function authUrl_v2($immediate)
984
- {
985
- $params = array(
986
- 'openid.ns' => 'http://specs.openid.net/auth/2.0',
987
- 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
988
- 'openid.return_to' => $this->returnUrl,
989
- 'openid.realm' => $this->trustRoot,
990
- );
991
-
992
- if ($this->ax) {
993
- $params += $this->axParams();
994
- }
995
-
996
- if ($this->sreg) {
997
- $params += $this->sregParams();
998
- }
999
-
1000
- if (!$this->ax && !$this->sreg) {
1001
- # If OP doesn't advertise either SREG, nor AX, let's send them both
1002
- # in worst case we don't get anything in return.
1003
- $params += $this->axParams() + $this->sregParams();
1004
- }
1005
-
1006
- if (!empty($this->oauth) && is_array($this->oauth)) {
1007
- $params['openid.ns.oauth'] = 'http://specs.openid.net/extensions/oauth/1.0';
1008
- $params['openid.oauth.consumer'] = str_replace(array('http://', 'https://'), '', $this->trustRoot);
1009
- $params['openid.oauth.scope'] = implode(' ', $this->oauth);
1010
- }
1011
-
1012
- if ($this->identifier_select) {
1013
- $params['openid.identity'] = $params['openid.claimed_id']
1014
- = 'http://specs.openid.net/auth/2.0/identifier_select';
1015
- } else {
1016
- $params['openid.identity'] = $this->identity;
1017
- $params['openid.claimed_id'] = $this->claimed_id;
1018
- }
1019
-
1020
- return $this->build_url(parse_url($this->server), array('query' => http_build_query($params, '', '&')));
1021
- }
1022
-
1023
- /**
1024
- * Returns authentication url. Usually, you want to redirect your user to it.
1025
- * @param bool $immediate
1026
- * @return String The authentication url.
1027
- * @throws ErrorException
1028
- */
1029
- public function authUrl($immediate = false)
1030
- {
1031
- if ($this->setup_url && !$immediate) {
1032
- return $this->setup_url;
1033
- }
1034
- if (!$this->server) {
1035
- $this->discover($this->identity);
1036
- }
1037
-
1038
- if ($this->version == 2) {
1039
- return $this->authUrl_v2($immediate);
1040
- }
1041
- return $this->authUrl_v1($immediate);
1042
- }
1043
-
1044
- /**
1045
- * Performs OpenID verification with the OP.
1046
- * @return Bool Whether the verification was successful.
1047
- * @throws ErrorException
1048
- */
1049
- public function validate()
1050
- {
1051
- # If the request was using immediate mode, a failure may be reported
1052
- # by presenting user_setup_url (for 1.1) or reporting
1053
- # mode 'setup_needed' (for 2.0). Also catching all modes other than
1054
- # id_res, in order to avoid throwing errors.
1055
- if (isset($this->data['openid_user_setup_url'])) {
1056
- $this->setup_url = $this->data['openid_user_setup_url'];
1057
- return false;
1058
- }
1059
- if ($this->mode != 'id_res') {
1060
- return false;
1061
- }
1062
-
1063
- $this->claimed_id = isset($this->data['openid_claimed_id'])?$this->data['openid_claimed_id']:$this->data['openid_identity'];
1064
- $params = array(
1065
- 'openid.assoc_handle' => $this->data['openid_assoc_handle'],
1066
- 'openid.signed' => $this->data['openid_signed'],
1067
- 'openid.sig' => $this->data['openid_sig'],
1068
- );
1069
-
1070
- if (isset($this->data['openid_ns'])) {
1071
- # We're dealing with an OpenID 2.0 server, so let's set an ns
1072
- # Even though we should know location of the endpoint,
1073
- # we still need to verify it by discovery, so $server is not set here
1074
- $params['openid.ns'] = 'http://specs.openid.net/auth/2.0';
1075
- } elseif (isset($this->data['openid_claimed_id'])
1076
- && $this->data['openid_claimed_id'] != $this->data['openid_identity']
1077
- ) {
1078
- # If it's an OpenID 1 provider, and we've got claimed_id,
1079
- # we have to append it to the returnUrl, like authUrl_v1 does.
1080
- $this->returnUrl .= (strpos($this->returnUrl, '?') ? '&' : '?')
1081
- . 'openid.claimed_id=' . $this->claimed_id;
1082
- }
1083
-
1084
- if ($this->data['openid_return_to'] != $this->returnUrl) {
1085
- # The return_to url must match the url of current request.
1086
- # I'm assuming that no one will set the returnUrl to something that doesn't make sense.
1087
- return false;
1088
- }
1089
-
1090
- $server = $this->discover($this->claimed_id);
1091
-
1092
- foreach (explode(',', $this->data['openid_signed']) as $item) {
1093
- $value = $this->data['openid_' . str_replace('.', '_', $item)];
1094
- $params['openid.' . $item] = $value;
1095
- }
1096
-
1097
- $params['openid.mode'] = 'check_authentication';
1098
-
1099
- $response = $this->request($server, 'POST', $params);
1100
-
1101
- return preg_match('/is_valid\s*:\s*true/i', $response);
1102
- }
1103
-
1104
- /**
1105
- * @return array
1106
- */
1107
- protected function getAxAttributes()
1108
- {
1109
- $result = array();
1110
-
1111
- if ($alias = $this->getNamespaceAlias('http://openid.net/srv/ax/1.0', 'ax')) {
1112
- $prefix = 'openid_' . $alias;
1113
- $length = strlen('http://axschema.org/');
1114
-
1115
- foreach (explode(',', $this->data['openid_signed']) as $key) {
1116
- $keyMatch = $alias . '.type.';
1117
-
1118
- if (strncmp($key, $keyMatch, strlen($keyMatch)) !== 0) {
1119
- continue;
1120
- }
1121
-
1122
- $key = substr($key, strlen($keyMatch));
1123
- $idv = $prefix . '_value_' . $key;
1124
- $idc = $prefix . '_count_' . $key;
1125
- $key = substr($this->getItem($prefix . '_type_' . $key), $length);
1126
-
1127
- if (!empty($key)) {
1128
- if (($count = intval($this->getItem($idc))) > 0) {
1129
- $value = array();
1130
-
1131
- for ($i = 1; $i <= $count; $i++) {
1132
- $value[] = $this->getItem($idv . '_' . $i);
1133
- }
1134
-
1135
- $value = ($count == 1) ? reset($value) : $value;
1136
- } else {
1137
- $value = $this->getItem($idv);
1138
- }
1139
-
1140
- if (!is_null($value)) {
1141
- $result[$key] = $value;
1142
- }
1143
- }
1144
- }
1145
- } else {
1146
- // No alias for the AX schema has been found,
1147
- // so there is no AX data in the OP's response.
1148
- }
1149
-
1150
- return $result;
1151
- }
1152
-
1153
- /**
1154
- * @return array
1155
- */
1156
- protected function getSregAttributes()
1157
- {
1158
- $attributes = array();
1159
- $sreg_to_ax = array_flip(self::$ax_to_sreg);
1160
- if ($alias = $this->getNamespaceAlias('http://openid.net/extensions/sreg/1.1', 'sreg')) {
1161
- foreach (explode(',', $this->data['openid_signed']) as $key) {
1162
- $keyMatch = $alias . '.';
1163
- if (strncmp($key, $keyMatch, strlen($keyMatch)) !== 0) {
1164
- continue;
1165
- }
1166
- $key = substr($key, strlen($keyMatch));
1167
- if (!isset($sreg_to_ax[$key])) {
1168
- # The field name isn't part of the SREG spec, so we ignore it.
1169
- continue;
1170
- }
1171
- $attributes[$sreg_to_ax[$key]] = $this->data['openid_' . $alias . '_' . $key];
1172
- }
1173
- }
1174
- return $attributes;
1175
- }
1176
-
1177
- /**
1178
- * Gets AX/SREG attributes provided by OP. should be used only after successful validation.
1179
- * Note that it does not guarantee that any of the required/optional parameters will be present,
1180
- * or that there will be no other attributes besides those specified.
1181
- * In other words. OP may provide whatever information it wants to.
1182
- * * SREG names will be mapped to AX names.
1183
- * *
1184
- * @return array Array of attributes with keys being the AX schema names, e.g. 'contact/email' @see http://www.axschema.org/types/
1185
- */
1186
- public function getAttributes()
1187
- {
1188
- if (isset($this->data['openid_ns'])
1189
- && $this->data['openid_ns'] == 'http://specs.openid.net/auth/2.0'
1190
- ) { # OpenID 2.0
1191
- # We search for both AX and SREG attributes, with AX taking precedence.
1192
- return $this->getAxAttributes() + $this->getSregAttributes();
1193
- }
1194
- return $this->getSregAttributes();
1195
- }
1196
-
1197
- /**
1198
- * Gets an OAuth request token if the OpenID+OAuth hybrid protocol has been used.
1199
- *
1200
- * In order to use the OpenID+OAuth hybrid protocol, you need to add at least one
1201
- * scope to the $openid->oauth array before you get the call to getAuthUrl(), e.g.:
1202
- * $openid->oauth[] = 'https://www.googleapis.com/auth/plus.me';
1203
- *
1204
- * Furthermore the registered consumer name must fit the OpenID realm.
1205
- * To register an OpenID consumer at Google use: https://www.google.com/accounts/ManageDomains
1206
- *
1207
- * @return string|bool OAuth request token on success, FALSE if no token was provided.
1208
- */
1209
- public function getOAuthRequestToken()
1210
- {
1211
- $alias = $this->getNamespaceAlias('http://specs.openid.net/extensions/oauth/1.0');
1212
-
1213
- return !empty($alias) ? $this->data['openid_' . $alias . '_request_token'] : false;
1214
- }
1215
-
1216
- /**
1217
- * Gets the alias for the specified namespace, if it's present.
1218
- *
1219
- * @param string $namespace The namespace for which an alias is needed.
1220
- * @param string $hint Common alias of this namespace, used for optimization.
1221
- * @return string|null The namespace alias if found, otherwise - NULL.
1222
- */
1223
- private function getNamespaceAlias($namespace, $hint = null)
1224
- {
1225
- $result = null;
1226
-
1227
- if (empty($hint) || $this->getItem('openid_ns_' . $hint) != $namespace) {
1228
- // The common alias is either undefined or points to
1229
- // some other extension - search for another alias..
1230
- $prefix = 'openid_ns_';
1231
- $length = strlen($prefix);
1232
-
1233
- foreach ($this->data as $key => $val) {
1234
- if (strncmp($key, $prefix, $length) === 0 && $val === $namespace) {
1235
- $result = trim(substr($key, $length));
1236
- break;
1237
- }
1238
- }
1239
- } else {
1240
- $result = $hint;
1241
- }
1242
-
1243
- return $result;
1244
- }
1245
-
1246
- /**
1247
- * Gets an item from the $data array by the specified id.
1248
- *
1249
- * @param string $id The id of the desired item.
1250
- * @return string|null The item if found, otherwise - NULL.
1251
- */
1252
- private function getItem($id)
1253
- {
1254
- return isset($this->data[$id]) ? $this->data[$id] : null;
1255
- }
1256
- }
1
+ <?php
2
+ /*!
3
+ * This file is part of the LightOpenID PHP Library (https://github.com/iignatov/LightOpenID)
4
+ *
5
+ * LightOpenID is an open source software available under the MIT License.
6
+ *
7
+ * Updated: 52f9910 on 4 Mar 2016.
8
+ */
9
+
10
+ namespace Hybridauth\Thirdparty\OpenID;
11
+
12
+ use Hybridauth\Exception\Exception;
13
+ use Hybridauth\Exception\ExceptionInterface;
14
+
15
+ /**
16
+ * Class ErrorException
17
+ *
18
+ * @package Hybridauth\Thirdparty\OpenID
19
+ */
20
+ class ErrorException extends Exception implements ExceptionInterface
21
+ {
22
+ }
23
+
24
+ /**
25
+ * This class provides a simple interface for OpenID 1.1/2.0 authentication.
26
+ *
27
+ * It requires PHP >= 5.1.2 with cURL or HTTP/HTTPS stream wrappers enabled.
28
+ *
29
+ * @version v1.3.1 (2016-03-04)
30
+ * @link https://code.google.com/p/lightopenid/ Project URL
31
+ * @link https://github.com/iignatov/LightOpenID GitHub Repo
32
+ * @author Mewp <mewp151 at gmail dot com>
33
+ * @copyright Copyright (c) 2013 Mewp
34
+ * @license http://opensource.org/licenses/mit-license.php MIT License
35
+ */
36
+ class LightOpenID
37
+ {
38
+ public $returnUrl
39
+ ;
40
+ public $required = array()
41
+ ;
42
+ public $optional = array()
43
+ ;
44
+ public $verify_peer = null
45
+ ;
46
+ public $capath = null
47
+ ;
48
+ public $cainfo = null
49
+ ;
50
+ public $cnmatch = null
51
+ ;
52
+ public $data
53
+ ;
54
+ public $oauth = array()
55
+ ;
56
+ public $curl_time_out = 30 // in seconds
57
+ ;
58
+ public $curl_connect_time_out = 30; // in seconds
59
+ private $identity;
60
+ private $claimed_id;
61
+ protected $server;
62
+ protected $version;
63
+ protected $trustRoot;
64
+ protected $aliases;
65
+ protected $identifier_select = false
66
+ ;
67
+ protected $ax = false;
68
+ protected $sreg = false;
69
+ protected $setup_url = null;
70
+ protected $headers = array()
71
+ ;
72
+ protected $proxy = null;
73
+ protected $user_agent = 'LightOpenID'
74
+ ;
75
+ protected $xrds_override_pattern = null;
76
+ protected $xrds_override_replacement = null;
77
+ protected static $ax_to_sreg = array(
78
+ 'namePerson/friendly' => 'nickname',
79
+ 'contact/email' => 'email',
80
+ 'namePerson' => 'fullname',
81
+ 'birthDate' => 'dob',
82
+ 'person/gender' => 'gender',
83
+ 'contact/postalCode/home' => 'postcode',
84
+ 'contact/country/home' => 'country',
85
+ 'pref/language' => 'language',
86
+ 'pref/timezone' => 'timezone',
87
+ );
88
+
89
+ /**
90
+ * LightOpenID constructor.
91
+ *
92
+ * @param $host
93
+ * @param null $proxy
94
+ *
95
+ * @throws ErrorException
96
+ */
97
+ public function __construct($host, $proxy = null)
98
+ {
99
+ $this->set_realm($host);
100
+ $this->set_proxy($proxy);
101
+
102
+ $uri = rtrim(preg_replace('#((?<=\?)|&)openid\.[^&]+#', '', $_SERVER['REQUEST_URI']), '?');
103
+ $this->returnUrl = $this->trustRoot . $uri;
104
+
105
+ $this->data = ($_SERVER['REQUEST_METHOD'] === 'POST') ? $_POST : $_GET;
106
+
107
+ if (!function_exists('curl_init') && !in_array('https', stream_get_wrappers())) {
108
+ throw new ErrorException('You must have either https wrappers or curl enabled.');
109
+ }
110
+ }
111
+
112
+ /**
113
+ * @param $name
114
+ *
115
+ * @return bool
116
+ */
117
+ public function __isset($name)
118
+ {
119
+ return in_array($name, array('identity', 'trustRoot', 'realm', 'xrdsOverride', 'mode'));
120
+ }
121
+
122
+ /**
123
+ * @param $name
124
+ * @param $value
125
+ */
126
+ public function __set($name, $value)
127
+ {
128
+ switch ($name) {
129
+ case 'identity':
130
+ if (strlen($value = trim((String) $value))) {
131
+ if (preg_match('#^xri:/*#i', $value, $m)) {
132
+ $value = substr($value, strlen($m[0]));
133
+ } elseif (!preg_match('/^(?:[=@+\$!\(]|https?:)/i', $value)) {
134
+ $value = "http://$value";
135
+ }
136
+ if (preg_match('#^https?://[^/]+$#i', $value, $m)) {
137
+ $value .= '/';
138
+ }
139
+ }
140
+ $this->$name = $this->claimed_id = $value;
141
+ break;
142
+ case 'trustRoot':
143
+ case 'realm':
144
+ $this->trustRoot = trim($value);
145
+ break;
146
+ case 'xrdsOverride':
147
+ if (is_array($value)) {
148
+ list($pattern, $replacement) = $value;
149
+ $this->xrds_override_pattern = $pattern;
150
+ $this->xrds_override_replacement = $replacement;
151
+ } else {
152
+ trigger_error('Invalid value specified for "xrdsOverride".', E_USER_ERROR);
153
+ }
154
+ break;
155
+ }
156
+ }
157
+
158
+ /**
159
+ * @param $name
160
+ *
161
+ * @return |null
162
+ */
163
+ public function __get($name)
164
+ {
165
+ switch ($name) {
166
+ case 'identity':
167
+ # We return claimed_id instead of identity,
168
+ # because the developer should see the claimed identifier,
169
+ # i.e. what he set as identity, not the op-local identifier (which is what we verify)
170
+ return $this->claimed_id;
171
+ case 'trustRoot':
172
+ case 'realm':
173
+ return $this->trustRoot;
174
+ case 'mode':
175
+ return empty($this->data['openid_mode']) ? null : $this->data['openid_mode'];
176
+ }
177
+ }
178
+
179
+ /**
180
+ * @param $proxy
181
+ *
182
+ * @throws ErrorException
183
+ */
184
+ public function set_proxy($proxy)
185
+ {
186
+ if (!empty($proxy)) {
187
+ // When the proxy is a string - try to parse it.
188
+ if (!is_array($proxy)) {
189
+ $proxy = parse_url($proxy);
190
+ }
191
+
192
+ // Check if $proxy is valid after the parsing.
193
+ if ($proxy && !empty($proxy['host'])) {
194
+ // Make sure that a valid port number is specified.
195
+ if (array_key_exists('port', $proxy)) {
196
+ if (!is_int($proxy['port'])) {
197
+ $proxy['port'] = is_numeric($proxy['port']) ? intval($proxy['port']) : 0;
198
+ }
199
+
200
+ if ($proxy['port'] <= 0) {
201
+ throw new ErrorException('The specified proxy port number is invalid.');
202
+ }
203
+ }
204
+
205
+ $this->proxy = $proxy;
206
+ }
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Checks if the server specified in the url exists.
212
+ *
213
+ * @param $url string url to check
214
+ * @return true, if the server exists; false otherwise
215
+ */
216
+ public function hostExists($url)
217
+ {
218
+ if (strpos($url, '/') === false) {
219
+ $server = $url;
220
+ } else {
221
+ $server = @parse_url($url, PHP_URL_HOST);
222
+ }
223
+
224
+ if (!$server) {
225
+ return false;
226
+ }
227
+
228
+ return !!gethostbynamel($server);
229
+ }
230
+
231
+ /**
232
+ * @param $uri
233
+ */
234
+ protected function set_realm($uri)
235
+ {
236
+ $realm = '';
237
+
238
+ # Set a protocol, if not specified.
239
+ $realm .= (($offset = strpos($uri, '://')) === false) ? $this->get_realm_protocol() : '';
240
+
241
+ # Set the offset properly.
242
+ $offset = (($offset !== false) ? $offset + 3 : 0);
243
+
244
+ # Get only the root, without the path.
245
+ $realm .= (($end = strpos($uri, '/', $offset)) === false) ? $uri : substr($uri, 0, $end);
246
+
247
+ $this->trustRoot = $realm;
248
+ }
249
+
250
+ /**
251
+ * @return string
252
+ */
253
+ protected function get_realm_protocol()
254
+ {
255
+ if (!empty($_SERVER['HTTPS'])) {
256
+ $use_secure_protocol = ($_SERVER['HTTPS'] !== 'off');
257
+ } elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
258
+ $use_secure_protocol = ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https');
259
+ } elseif (isset($_SERVER['HTTP__WSSC'])) {
260
+ $use_secure_protocol = ($_SERVER['HTTP__WSSC'] == 'https');
261
+ } else {
262
+ $use_secure_protocol = false;
263
+ }
264
+
265
+ return $use_secure_protocol ? 'https://' : 'http://';
266
+ }
267
+
268
+ /**
269
+ * @param $url
270
+ * @param string $method
271
+ * @param array $params
272
+ * @param $update_claimed_id
273
+ *
274
+ * @return array|bool|string
275
+ * @throws ErrorException
276
+ */
277
+ protected function request_curl($url, $method='GET', $params=array(), $update_claimed_id)
278
+ {
279
+ $params = http_build_query($params, '', '&');
280
+ $curl = curl_init($url . ($method == 'GET' && $params ? '?' . $params : ''));
281
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
282
+ curl_setopt($curl, CURLOPT_HEADER, false);
283
+ curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent);
284
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
285
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
286
+
287
+ if ($method == 'POST') {
288
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
289
+ } else {
290
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/xrds+xml, */*'));
291
+ }
292
+
293
+ curl_setopt($curl, CURLOPT_TIMEOUT, $this->curl_time_out); // defaults to infinite
294
+ curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $this->curl_connect_time_out); // defaults to 300s
295
+
296
+ if (!empty($this->proxy)) {
297
+ curl_setopt($curl, CURLOPT_PROXY, $this->proxy['host']);
298
+
299
+ if (!empty($this->proxy['port'])) {
300
+ curl_setopt($curl, CURLOPT_PROXYPORT, $this->proxy['port']);
301
+ }
302
+
303
+ if (!empty($this->proxy['user'])) {
304
+ curl_setopt($curl, CURLOPT_PROXYUSERPWD, $this->proxy['user'] . ':' . $this->proxy['pass']);
305
+ }
306
+ }
307
+
308
+ if ($this->verify_peer !== null) {
309
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
310
+ if ($this->capath) {
311
+ curl_setopt($curl, CURLOPT_CAPATH, $this->capath);
312
+ }
313
+
314
+ if ($this->cainfo) {
315
+ curl_setopt($curl, CURLOPT_CAINFO, $this->cainfo);
316
+ }
317
+ }
318
+
319
+ if ($method == 'POST') {
320
+ curl_setopt($curl, CURLOPT_POST, true);
321
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
322
+ } elseif ($method == 'HEAD') {
323
+ curl_setopt($curl, CURLOPT_HEADER, true);
324
+ curl_setopt($curl, CURLOPT_NOBODY, true);
325
+ } else {
326
+ curl_setopt($curl, CURLOPT_HEADER, true);
327
+ curl_setopt($curl, CURLOPT_HTTPGET, true);
328
+ }
329
+ $response = curl_exec($curl);
330
+
331
+ if ($method == 'HEAD' && curl_getinfo($curl, CURLINFO_HTTP_CODE) == 405) {
332
+ curl_setopt($curl, CURLOPT_HTTPGET, true);
333
+ $response = curl_exec($curl);
334
+ $response = substr($response, 0, strpos($response, "\r\n\r\n"));
335
+ }
336
+
337
+ if ($method == 'HEAD' || $method == 'GET') {
338
+ $header_response = $response;
339
+
340
+ # If it's a GET request, we want to only parse the header part.
341
+ if ($method == 'GET') {
342
+ $header_response = substr($response, 0, strpos($response, "\r\n\r\n"));
343
+ }
344
+
345
+ $headers = array();
346
+ foreach (explode("\n", $header_response) as $header) {
347
+ $pos = strpos($header, ':');
348
+ if ($pos !== false) {
349
+ $name = strtolower(trim(substr($header, 0, $pos)));
350
+ $headers[$name] = trim(substr($header, $pos+1));
351
+ }
352
+ }
353
+
354
+ if ($update_claimed_id) {
355
+ # Update the claimed_id value in case of redirections.
356
+ $effective_url = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
357
+ # Ignore the fragment (some cURL versions don't handle it well).
358
+ if (strtok($effective_url, '#') != strtok($url, '#')) {
359
+ $this->identity = $this->claimed_id = $effective_url;
360
+ }
361
+ }
362
+
363
+ if ($method == 'HEAD') {
364
+ return $headers;
365
+ } else {
366
+ $this->headers = $headers;
367
+ }
368
+ }
369
+
370
+ if (curl_errno($curl)) {
371
+ throw new ErrorException(curl_error($curl), curl_errno($curl));
372
+ }
373
+
374
+ return $response;
375
+ }
376
+
377
+ /**
378
+ * @param $array
379
+ * @param $update_claimed_id
380
+ *
381
+ * @return array
382
+ */
383
+ protected function parse_header_array($array, $update_claimed_id)
384
+ {
385
+ $headers = array();
386
+ foreach ($array as $header) {
387
+ $pos = strpos($header, ':');
388
+ if ($pos !== false) {
389
+ $name = strtolower(trim(substr($header, 0, $pos)));
390
+ $headers[$name] = trim(substr($header, $pos+1));
391
+
392
+ # Following possible redirections. The point is just to have
393
+ # claimed_id change with them, because the redirections
394
+ # are followed automatically.
395
+ # We ignore redirections with relative paths.
396
+ # If any known provider uses them, file a bug report.
397
+ if ($name == 'location' && $update_claimed_id) {
398
+ if (strpos($headers[$name], 'http') === 0) {
399
+ $this->identity = $this->claimed_id = $headers[$name];
400
+ } elseif ($headers[$name][0] == '/') {
401
+ $parsed_url = parse_url($this->claimed_id);
402
+ $this->identity =
403
+ $this->claimed_id = $parsed_url['scheme'] . '://'
404
+ . $parsed_url['host']
405
+ . $headers[$name];
406
+ }
407
+ }
408
+ }
409
+ }
410
+ return $headers;
411
+ }
412
+
413
+ /**
414
+ * @param $url
415
+ * @param string $method
416
+ * @param array $params
417
+ * @param $update_claimed_id
418
+ *
419
+ * @return array|false|string
420
+ * @throws ErrorException
421
+ */
422
+ protected function request_streams($url, $method='GET', $params=array(), $update_claimed_id)
423
+ {
424
+ if (!$this->hostExists($url)) {
425
+ throw new ErrorException("Could not connect to $url.", 404);
426
+ }
427
+
428
+ if (empty($this->cnmatch)) {
429
+ $this->cnmatch = parse_url($url, PHP_URL_HOST);
430
+ }
431
+
432
+ $params = http_build_query($params, '', '&');
433
+ switch ($method) {
434
+ case 'GET':
435
+ $opts = array(
436
+ 'http' => array(
437
+ 'method' => 'GET',
438
+ 'header' => 'Accept: application/xrds+xml, */*',
439
+ 'user_agent' => $this->user_agent,
440
+ 'ignore_errors' => true,
441
+ ),
442
+ 'ssl' => array(
443
+ 'CN_match' => $this->cnmatch
444
+ )
445
+ );
446
+ $url = $url . ($params ? '?' . $params : '');
447
+ if (!empty($this->proxy)) {
448
+ $opts['http']['proxy'] = $this->proxy_url();
449
+ }
450
+ break;
451
+ case 'POST':
452
+ $opts = array(
453
+ 'http' => array(
454
+ 'method' => 'POST',
455
+ 'header' => 'Content-type: application/x-www-form-urlencoded',
456
+ 'user_agent' => $this->user_agent,
457
+ 'content' => $params,
458
+ 'ignore_errors' => true,
459
+ ),
460
+ 'ssl' => array(
461
+ 'CN_match' => $this->cnmatch
462
+ )
463
+ );
464
+ if (!empty($this->proxy)) {
465
+ $opts['http']['proxy'] = $this->proxy_url();
466
+ }
467
+ break;
468
+ case 'HEAD':
469
+ // We want to send a HEAD request, but since get_headers() doesn't
470
+ // accept $context parameter, we have to change the defaults.
471
+ $default = stream_context_get_options(stream_context_get_default());
472
+
473
+ // PHP does not reset all options. Instead, it just sets the options
474
+ // available in the passed array, therefore set the defaults manually.
475
+ $default += array(
476
+ 'http' => array(),
477
+ 'ssl' => array()
478
+ );
479
+ $default['http'] += array(
480
+ 'method' => 'GET',
481
+ 'header' => '',
482
+ 'user_agent' => '',
483
+ 'ignore_errors' => false
484
+ );
485
+ $default['ssl'] += array(
486
+ 'CN_match' => ''
487
+ );
488
+
489
+ $opts = array(
490
+ 'http' => array(
491
+ 'method' => 'HEAD',
492
+ 'header' => 'Accept: application/xrds+xml, */*',
493
+ 'user_agent' => $this->user_agent,
494
+ 'ignore_errors' => true,
495
+ ),
496
+ 'ssl' => array(
497
+ 'CN_match' => $this->cnmatch
498
+ )
499
+ );
500
+
501
+ // Enable validation of the SSL certificates.
502
+ if ($this->verify_peer) {
503
+ $default['ssl'] += array(
504
+ 'verify_peer' => false,
505
+ 'capath' => '',
506
+ 'cafile' => ''
507
+ );
508
+ $opts['ssl'] += array(
509
+ 'verify_peer' => true,
510
+ 'capath' => $this->capath,
511
+ 'cafile' => $this->cainfo
512
+ );
513
+ }
514
+
515
+ // Change the stream context options.
516
+ stream_context_get_default($opts);
517
+
518
+ $headers = get_headers($url . ($params ? '?' . $params : ''));
519
+
520
+ // Restore the stream context options.
521
+ stream_context_get_default($default);
522
+
523
+ if (!empty($headers)) {
524
+ if (intval(substr($headers[0], strlen('HTTP/1.1 '))) == 405) {
525
+ // The server doesn't support HEAD - emulate it with a GET.
526
+ $args = func_get_args();
527
+ $args[1] = 'GET';
528
+ call_user_func_array(array($this, 'request_streams'), $args);
529
+ $headers = $this->headers;
530
+ } else {
531
+ $headers = $this->parse_header_array($headers, $update_claimed_id);
532
+ }
533
+ } else {
534
+ $headers = array();
535
+ }
536
+
537
+ return $headers;
538
+ }
539
+
540
+ if ($this->verify_peer) {
541
+ $opts['ssl'] += array(
542
+ 'verify_peer' => true,
543
+ 'capath' => $this->capath,
544
+ 'cafile' => $this->cainfo
545
+ );
546
+ }
547
+
548
+ $context = stream_context_create($opts);
549
+ $data = file_get_contents($url, false, $context);
550
+ # This is a hack for providers who don't support HEAD requests.
551
+ # It just creates the headers array for the last request in $this->headers.
552
+ if (isset($http_response_header)) {
553
+ $this->headers = $this->parse_header_array($http_response_header, $update_claimed_id);
554
+ }
555
+
556
+ return $data;
557
+ }
558
+
559
+ /**
560
+ * @param $url
561
+ * @param string $method
562
+ * @param array $params
563
+ * @param bool $update_claimed_id
564
+ *
565
+ * @return array|bool|false|string
566
+ * @throws ErrorException
567
+ */
568
+ protected function request($url, $method='GET', $params=array(), $update_claimed_id=false)
569
+ {
570
+ $use_curl = false;
571
+
572
+ if (function_exists('curl_init')) {
573
+ if (!$use_curl) {
574
+ # When allow_url_fopen is disabled, PHP streams will not work.
575
+ $use_curl = !ini_get('allow_url_fopen');
576
+ }
577
+
578
+ if (!$use_curl) {
579
+ # When there is no HTTPS wrapper, PHP streams cannott be used.
580
+ $use_curl = !in_array('https', stream_get_wrappers());
581
+ }
582
+
583
+ if (!$use_curl) {
584
+ # With open_basedir or safe_mode set, cURL can't follow redirects.
585
+ $use_curl = !(ini_get('safe_mode') || ini_get('open_basedir'));
586
+ }
587
+ }
588
+
589
+ return
590
+ $use_curl
591
+ ? $this->request_curl($url, $method, $params, $update_claimed_id)
592
+ : $this->request_streams($url, $method, $params, $update_claimed_id);
593
+ }
594
+
595
+ /**
596
+ * @return string
597
+ */
598
+ protected function proxy_url()
599
+ {
600
+ $result = '';
601
+
602
+ if (!empty($this->proxy)) {
603
+ $result = $this->proxy['host'];
604
+
605
+ if (!empty($this->proxy['port'])) {
606
+ $result = $result . ':' . $this->proxy['port'];
607
+ }
608
+
609
+ if (!empty($this->proxy['user'])) {
610
+ $result = $this->proxy['user'] . ':' . $this->proxy['pass'] . '@' . $result;
611
+ }
612
+
613
+ $result = 'http://' . $result;
614
+ }
615
+
616
+ return $result;
617
+ }
618
+
619
+ /**
620
+ * @param $url
621
+ * @param $parts
622
+ *
623
+ * @return string
624
+ */
625
+ protected function build_url($url, $parts)
626
+ {
627
+ if (isset($url['query'], $parts['query'])) {
628
+ $parts['query'] = $url['query'] . '&' . $parts['query'];
629
+ }
630
+
631
+ $url = $parts + $url;
632
+ $url = $url['scheme'] . '://'
633
+ . (empty($url['username'])?''
634
+ :(empty($url['password'])? "{$url['username']}@"
635
+ :"{$url['username']}:{$url['password']}@"))
636
+ . $url['host']
637
+ . (empty($url['port'])?'':":{$url['port']}")
638
+ . (empty($url['path'])?'':$url['path'])
639
+ . (empty($url['query'])?'':"?{$url['query']}")
640
+ . (empty($url['fragment'])?'':"#{$url['fragment']}");
641
+ return $url;
642
+ }
643
+
644
+ /**
645
+ * Helper function used to scan for <meta>/<link> tags and extract information
646
+ * from them
647
+ *
648
+ * @param $content
649
+ * @param $tag
650
+ * @param $attrName
651
+ * @param $attrValue
652
+ * @param $valueName
653
+ *
654
+ * @return bool
655
+ */
656
+ protected function htmlTag($content, $tag, $attrName, $attrValue, $valueName)
657
+ {
658
+ preg_match_all("#<{$tag}[^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*$valueName=['\"](.+?)['\"][^>]*/?>#i", $content, $matches1);
659
+ preg_match_all("#<{$tag}[^>]*$valueName=['\"](.+?)['\"][^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*/?>#i", $content, $matches2);
660
+
661
+ $result = array_merge($matches1[1], $matches2[1]);
662
+ return empty($result)?false:$result[0];
663
+ }
664
+
665
+ /**
666
+ * Performs Yadis and HTML discovery. Normally not used.
667
+ * @param $url Identity URL.
668
+ * @return String OP Endpoint (i.e. OpenID provider address).
669
+ * @throws ErrorException
670
+ */
671
+ public function discover($url)
672
+ {
673
+ if (!$url) {
674
+ throw new ErrorException('No identity supplied.');
675
+ }
676
+ # Use xri.net proxy to resolve i-name identities
677
+ if (!preg_match('#^https?:#', $url)) {
678
+ $url = "https://xri.net/$url";
679
+ }
680
+
681
+ # We save the original url in case of Yadis discovery failure.
682
+ # It can happen when we'll be lead to an XRDS document
683
+ # which does not have any OpenID2 services.
684
+ $originalUrl = $url;
685
+
686
+ # A flag to disable yadis discovery in case of failure in headers.
687
+ $yadis = true;
688
+
689
+ # Allows optional regex replacement of the URL, e.g. to use Google Apps
690
+ # as an OpenID provider without setting up XRDS on the domain hosting.
691
+ if (!is_null($this->xrds_override_pattern) && !is_null($this->xrds_override_replacement)) {
692
+ $url = preg_replace($this->xrds_override_pattern, $this->xrds_override_replacement, $url);
693
+ }
694
+
695
+ # We'll jump a maximum of 5 times, to avoid endless redirections.
696
+ for ($i = 0; $i < 5; $i ++) {
697
+ if ($yadis) {
698
+ $headers = $this->request($url, 'HEAD', array(), true);
699
+
700
+ $next = false;
701
+ if (isset($headers['x-xrds-location'])) {
702
+ $url = $this->build_url(parse_url($url), parse_url(trim($headers['x-xrds-location'])));
703
+ $next = true;
704
+ }
705
+
706
+ if (isset($headers['content-type']) && $this->is_allowed_type($headers['content-type'])) {
707
+ # Found an XRDS document, now let's find the server, and optionally delegate.
708
+ $content = $this->request($url, 'GET');
709
+
710
+ preg_match_all('#<Service.*?>(.*?)</Service>#s', $content, $m);
711
+ foreach ($m[1] as $content) {
712
+ $content = ' ' . $content; # The space is added, so that strpos doesn't return 0.
713
+
714
+ # OpenID 2
715
+ $ns = preg_quote('http://specs.openid.net/auth/2.0/', '#');
716
+ if (preg_match('#<Type>\s*'.$ns.'(server|signon)\s*</Type>#s', $content, $type)) {
717
+ if ($type[1] == 'server') {
718
+ $this->identifier_select = true;
719
+ }
720
+
721
+ preg_match('#<URI.*?>(.*)</URI>#', $content, $server);
722
+ preg_match('#<(Local|Canonical)ID>(.*)</\1ID>#', $content, $delegate);
723
+ if (empty($server)) {
724
+ return false;
725
+ }
726
+ # Does the server advertise support for either AX or SREG?
727
+ $this->ax = (bool) strpos($content, '<Type>http://openid.net/srv/ax/1.0</Type>');
728
+ $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>')
729
+ || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>');
730
+
731
+ $server = $server[1];
732
+ if (isset($delegate[2])) {
733
+ $this->identity = trim($delegate[2]);
734
+ }
735
+ $this->version = 2;
736
+
737
+ $this->server = $server;
738
+ return $server;
739
+ }
740
+
741
+ # OpenID 1.1
742
+ $ns = preg_quote('http://openid.net/signon/1.1', '#');
743
+ if (preg_match('#<Type>\s*'.$ns.'\s*</Type>#s', $content)) {
744
+ preg_match('#<URI.*?>(.*)</URI>#', $content, $server);
745
+ preg_match('#<.*?Delegate>(.*)</.*?Delegate>#', $content, $delegate);
746
+ if (empty($server)) {
747
+ return false;
748
+ }
749
+ # AX can be used only with OpenID 2.0, so checking only SREG
750
+ $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>')
751
+ || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>');
752
+
753
+ $server = $server[1];
754
+ if (isset($delegate[1])) {
755
+ $this->identity = $delegate[1];
756
+ }
757
+ $this->version = 1;
758
+
759
+ $this->server = $server;
760
+ return $server;
761
+ }
762
+ }
763
+
764
+ $next = true;
765
+ $yadis = false;
766
+ $url = $originalUrl;
767
+ $content = null;
768
+ break;
769
+ }
770
+ if ($next) {
771
+ continue;
772
+ }
773
+
774
+ # There are no relevant information in headers, so we search the body.
775
+ $content = $this->request($url, 'GET', array(), true);
776
+
777
+ if (isset($this->headers['x-xrds-location'])) {
778
+ $url = $this->build_url(parse_url($url), parse_url(trim($this->headers['x-xrds-location'])));
779
+ continue;
780
+ }
781
+
782
+ $location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'content');
783
+ if ($location) {
784
+ $url = $this->build_url(parse_url($url), parse_url($location));
785
+ continue;
786
+ }
787
+ }
788
+
789
+ if (!$content) {
790
+ $content = $this->request($url, 'GET');
791
+ }
792
+
793
+ # At this point, the YADIS Discovery has failed, so we'll switch
794
+ # to openid2 HTML discovery, then fallback to openid 1.1 discovery.
795
+ $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href');
796
+ $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href');
797
+ $this->version = 2;
798
+
799
+ if (!$server) {
800
+ # The same with openid 1.1
801
+ $server = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href');
802
+ $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href');
803
+ $this->version = 1;
804
+ }
805
+
806
+ if ($server) {
807
+ # We found an OpenID2 OP Endpoint
808
+ if ($delegate) {
809
+ # We have also found an OP-Local ID.
810
+ $this->identity = $delegate;
811
+ }
812
+ $this->server = $server;
813
+ return $server;
814
+ }
815
+
816
+ throw new ErrorException("No OpenID Server found at $url", 404);
817
+ }
818
+ throw new ErrorException('Endless redirection!', 500);
819
+ }
820
+
821
+ /**
822
+ * @param $content_type
823
+ *
824
+ * @return bool
825
+ */
826
+ protected function is_allowed_type($content_type)
827
+ {
828
+ # Apparently, some providers return XRDS documents as text/html.
829
+ # While it is against the spec, allowing this here shouldn't break
830
+ # compatibility with anything.
831
+ $allowed_types = array('application/xrds+xml', 'text/xml');
832
+
833
+ # Only allow text/html content type for the Yahoo logins, since
834
+ # it might cause an endless redirection for the other providers.
835
+ if ($this->get_provider_name($this->claimed_id) == 'yahoo') {
836
+ $allowed_types[] = 'text/html';
837
+ }
838
+
839
+ foreach ($allowed_types as $type) {
840
+ if (strpos($content_type, $type) !== false) {
841
+ return true;
842
+ }
843
+ }
844
+
845
+ return false;
846
+ }
847
+
848
+ /**
849
+ * @param $provider_url
850
+ *
851
+ * @return string
852
+ */
853
+ protected function get_provider_name($provider_url)
854
+ {
855
+ $result = '';
856
+
857
+ if (!empty($provider_url)) {
858
+ $tokens = array_reverse(
859
+ explode('.', parse_url($provider_url, PHP_URL_HOST))
860
+ );
861
+ $result = strtolower(
862
+ (count($tokens) > 1 && strlen($tokens[1]) > 3)
863
+ ? $tokens[1]
864
+ : (count($tokens) > 2 ? $tokens[2] : '')
865
+ );
866
+ }
867
+
868
+ return $result;
869
+ }
870
+
871
+ /**
872
+ * @return array
873
+ */
874
+ protected function sregParams()
875
+ {
876
+ $params = array();
877
+ # We always use SREG 1.1, even if the server is advertising only support for 1.0.
878
+ # That's because it's fully backwards compatible with 1.0, and some providers
879
+ # advertise 1.0 even if they accept only 1.1. One such provider is myopenid.com
880
+ $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1';
881
+ if ($this->required) {
882
+ $params['openid.sreg.required'] = array();
883
+ foreach ($this->required as $required) {
884
+ if (!isset(self::$ax_to_sreg[$required])) {
885
+ continue;
886
+ }
887
+ $params['openid.sreg.required'][] = self::$ax_to_sreg[$required];
888
+ }
889
+ $params['openid.sreg.required'] = implode(',', $params['openid.sreg.required']);
890
+ }
891
+
892
+ if ($this->optional) {
893
+ $params['openid.sreg.optional'] = array();
894
+ foreach ($this->optional as $optional) {
895
+ if (!isset(self::$ax_to_sreg[$optional])) {
896
+ continue;
897
+ }
898
+ $params['openid.sreg.optional'][] = self::$ax_to_sreg[$optional];
899
+ }
900
+ $params['openid.sreg.optional'] = implode(',', $params['openid.sreg.optional']);
901
+ }
902
+ return $params;
903
+ }
904
+
905
+ /**
906
+ * @return array
907
+ */
908
+ protected function axParams()
909
+ {
910
+ $params = array();
911
+ if ($this->required || $this->optional) {
912
+ $params['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0';
913
+ $params['openid.ax.mode'] = 'fetch_request';
914
+ $this->aliases = array();
915
+ $counts = array();
916
+ $required = array();
917
+ $optional = array();
918
+ foreach (array('required','optional') as $type) {
919
+ foreach ($this->$type as $alias => $field) {
920
+ if (is_int($alias)) {
921
+ $alias = strtr($field, '/', '_');
922
+ }
923
+ $this->aliases[$alias] = 'http://axschema.org/' . $field;
924
+ if (empty($counts[$alias])) {
925
+ $counts[$alias] = 0;
926
+ }
927
+ $counts[$alias] += 1;
928
+ ${$type}[] = $alias;
929
+ }
930
+ }
931
+ foreach ($this->aliases as $alias => $ns) {
932
+ $params['openid.ax.type.' . $alias] = $ns;
933
+ }
934
+ foreach ($counts as $alias => $count) {
935
+ if ($count == 1) {
936
+ continue;
937
+ }
938
+ $params['openid.ax.count.' . $alias] = $count;
939
+ }
940
+
941
+ # Don't send empty ax.required and ax.if_available.
942
+ # Google and possibly other providers refuse to support ax when one of these is empty.
943
+ if ($required) {
944
+ $params['openid.ax.required'] = implode(',', $required);
945
+ }
946
+ if ($optional) {
947
+ $params['openid.ax.if_available'] = implode(',', $optional);
948
+ }
949
+ }
950
+ return $params;
951
+ }
952
+
953
+ /**
954
+ * @param $immediate
955
+ *
956
+ * @return string
957
+ */
958
+ protected function authUrl_v1($immediate)
959
+ {
960
+ $returnUrl = $this->returnUrl;
961
+ # If we have an openid.delegate that is different from our claimed id,
962
+ # we need to somehow preserve the claimed id between requests.
963
+ # The simplest way is to just send it along with the return_to url.
964
+ if ($this->identity != $this->claimed_id) {
965
+ $returnUrl .= (strpos($returnUrl, '?') ? '&' : '?') . 'openid.claimed_id=' . $this->claimed_id;
966
+ }
967
+
968
+ $params = array(
969
+ 'openid.return_to' => $returnUrl,
970
+ 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
971
+ 'openid.identity' => $this->identity,
972
+ 'openid.trust_root' => $this->trustRoot,
973
+ ) + $this->sregParams();
974
+
975
+ return $this->build_url(parse_url($this->server), array('query' => http_build_query($params, '', '&')));
976
+ }
977
+
978
+ /**
979
+ * @param $immediate
980
+ *
981
+ * @return string
982
+ */
983
+ protected function authUrl_v2($immediate)
984
+ {
985
+ $params = array(
986
+ 'openid.ns' => 'http://specs.openid.net/auth/2.0',
987
+ 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
988
+ 'openid.return_to' => $this->returnUrl,
989
+ 'openid.realm' => $this->trustRoot,
990
+ );
991
+
992
+ if ($this->ax) {
993
+ $params += $this->axParams();
994
+ }
995
+
996
+ if ($this->sreg) {
997
+ $params += $this->sregParams();
998
+ }
999
+
1000
+ if (!$this->ax && !$this->sreg) {
1001
+ # If OP doesn't advertise either SREG, nor AX, let's send them both
1002
+ # in worst case we don't get anything in return.
1003
+ $params += $this->axParams() + $this->sregParams();
1004
+ }
1005
+
1006
+ if (!empty($this->oauth) && is_array($this->oauth)) {
1007
+ $params['openid.ns.oauth'] = 'http://specs.openid.net/extensions/oauth/1.0';
1008
+ $params['openid.oauth.consumer'] = str_replace(array('http://', 'https://'), '', $this->trustRoot);
1009
+ $params['openid.oauth.scope'] = implode(' ', $this->oauth);
1010
+ }
1011
+
1012
+ if ($this->identifier_select) {
1013
+ $params['openid.identity'] = $params['openid.claimed_id']
1014
+ = 'http://specs.openid.net/auth/2.0/identifier_select';
1015
+ } else {
1016
+ $params['openid.identity'] = $this->identity;
1017
+ $params['openid.claimed_id'] = $this->claimed_id;
1018
+ }
1019
+
1020
+ return $this->build_url(parse_url($this->server), array('query' => http_build_query($params, '', '&')));
1021
+ }
1022
+
1023
+ /**
1024
+ * Returns authentication url. Usually, you want to redirect your user to it.
1025
+ * @param bool $immediate
1026
+ * @return String The authentication url.
1027
+ * @throws ErrorException
1028
+ */
1029
+ public function authUrl($immediate = false)
1030
+ {
1031
+ if ($this->setup_url && !$immediate) {
1032
+ return $this->setup_url;
1033
+ }
1034
+ if (!$this->server) {
1035
+ $this->discover($this->identity);
1036
+ }
1037
+
1038
+ if ($this->version == 2) {
1039
+ return $this->authUrl_v2($immediate);
1040
+ }
1041
+ return $this->authUrl_v1($immediate);
1042
+ }
1043
+
1044
+ /**
1045
+ * Performs OpenID verification with the OP.
1046
+ * @return Bool Whether the verification was successful.
1047
+ * @throws ErrorException
1048
+ */
1049
+ public function validate()
1050
+ {
1051
+ # If the request was using immediate mode, a failure may be reported
1052
+ # by presenting user_setup_url (for 1.1) or reporting
1053
+ # mode 'setup_needed' (for 2.0). Also catching all modes other than
1054
+ # id_res, in order to avoid throwing errors.
1055
+ if (isset($this->data['openid_user_setup_url'])) {
1056
+ $this->setup_url = $this->data['openid_user_setup_url'];
1057
+ return false;
1058
+ }
1059
+ if ($this->mode != 'id_res') {
1060
+ return false;
1061
+ }
1062
+
1063
+ $this->claimed_id = isset($this->data['openid_claimed_id'])?$this->data['openid_claimed_id']:$this->data['openid_identity'];
1064
+ $params = array(
1065
+ 'openid.assoc_handle' => $this->data['openid_assoc_handle'],
1066
+ 'openid.signed' => $this->data['openid_signed'],
1067
+ 'openid.sig' => $this->data['openid_sig'],
1068
+ );
1069
+
1070
+ if (isset($this->data['openid_ns'])) {
1071
+ # We're dealing with an OpenID 2.0 server, so let's set an ns
1072
+ # Even though we should know location of the endpoint,
1073
+ # we still need to verify it by discovery, so $server is not set here
1074
+ $params['openid.ns'] = 'http://specs.openid.net/auth/2.0';
1075
+ } elseif (isset($this->data['openid_claimed_id'])
1076
+ && $this->data['openid_claimed_id'] != $this->data['openid_identity']
1077
+ ) {
1078
+ # If it's an OpenID 1 provider, and we've got claimed_id,
1079
+ # we have to append it to the returnUrl, like authUrl_v1 does.
1080
+ $this->returnUrl .= (strpos($this->returnUrl, '?') ? '&' : '?')
1081
+ . 'openid.claimed_id=' . $this->claimed_id;
1082
+ }
1083
+
1084
+ if ($this->data['openid_return_to'] != $this->returnUrl) {
1085
+ # The return_to url must match the url of current request.
1086
+ # I'm assuming that no one will set the returnUrl to something that doesn't make sense.
1087
+ return false;
1088
+ }
1089
+
1090
+ $server = $this->discover($this->claimed_id);
1091
+
1092
+ foreach (explode(',', $this->data['openid_signed']) as $item) {
1093
+ $value = $this->data['openid_' . str_replace('.', '_', $item)];
1094
+ $params['openid.' . $item] = $value;
1095
+ }
1096
+
1097
+ $params['openid.mode'] = 'check_authentication';
1098
+
1099
+ $response = $this->request($server, 'POST', $params);
1100
+
1101
+ return preg_match('/is_valid\s*:\s*true/i', $response);
1102
+ }
1103
+
1104
+ /**
1105
+ * @return array
1106
+ */
1107
+ protected function getAxAttributes()
1108
+ {
1109
+ $result = array();
1110
+
1111
+ if ($alias = $this->getNamespaceAlias('http://openid.net/srv/ax/1.0', 'ax')) {
1112
+ $prefix = 'openid_' . $alias;
1113
+ $length = strlen('http://axschema.org/');
1114
+
1115
+ foreach (explode(',', $this->data['openid_signed']) as $key) {
1116
+ $keyMatch = $alias . '.type.';
1117
+
1118
+ if (strncmp($key, $keyMatch, strlen($keyMatch)) !== 0) {
1119
+ continue;
1120
+ }
1121
+
1122
+ $key = substr($key, strlen($keyMatch));
1123
+ $idv = $prefix . '_value_' . $key;
1124
+ $idc = $prefix . '_count_' . $key;
1125
+ $key = substr($this->getItem($prefix . '_type_' . $key), $length);
1126
+
1127
+ if (!empty($key)) {
1128
+ if (($count = intval($this->getItem($idc))) > 0) {
1129
+ $value = array();
1130
+
1131
+ for ($i = 1; $i <= $count; $i++) {
1132
+ $value[] = $this->getItem($idv . '_' . $i);
1133
+ }
1134
+
1135
+ $value = ($count == 1) ? reset($value) : $value;
1136
+ } else {
1137
+ $value = $this->getItem($idv);
1138
+ }
1139
+
1140
+ if (!is_null($value)) {
1141
+ $result[$key] = $value;
1142
+ }
1143
+ }
1144
+ }
1145
+ } else {
1146
+ // No alias for the AX schema has been found,
1147
+ // so there is no AX data in the OP's response.
1148
+ }
1149
+
1150
+ return $result;
1151
+ }
1152
+
1153
+ /**
1154
+ * @return array
1155
+ */
1156
+ protected function getSregAttributes()
1157
+ {
1158
+ $attributes = array();
1159
+ $sreg_to_ax = array_flip(self::$ax_to_sreg);
1160
+ if ($alias = $this->getNamespaceAlias('http://openid.net/extensions/sreg/1.1', 'sreg')) {
1161
+ foreach (explode(',', $this->data['openid_signed']) as $key) {
1162
+ $keyMatch = $alias . '.';
1163
+ if (strncmp($key, $keyMatch, strlen($keyMatch)) !== 0) {
1164
+ continue;
1165
+ }
1166
+ $key = substr($key, strlen($keyMatch));
1167
+ if (!isset($sreg_to_ax[$key])) {
1168
+ # The field name isn't part of the SREG spec, so we ignore it.
1169
+ continue;
1170
+ }
1171
+ $attributes[$sreg_to_ax[$key]] = $this->data['openid_' . $alias . '_' . $key];
1172
+ }
1173
+ }
1174
+ return $attributes;
1175
+ }
1176
+
1177
+ /**
1178
+ * Gets AX/SREG attributes provided by OP. should be used only after successful validation.
1179
+ * Note that it does not guarantee that any of the required/optional parameters will be present,
1180
+ * or that there will be no other attributes besides those specified.
1181
+ * In other words. OP may provide whatever information it wants to.
1182
+ * * SREG names will be mapped to AX names.
1183
+ * *
1184
+ * @return array Array of attributes with keys being the AX schema names, e.g. 'contact/email' @see http://www.axschema.org/types/
1185
+ */
1186
+ public function getAttributes()
1187
+ {
1188
+ if (isset($this->data['openid_ns'])
1189
+ && $this->data['openid_ns'] == 'http://specs.openid.net/auth/2.0'
1190
+ ) { # OpenID 2.0
1191
+ # We search for both AX and SREG attributes, with AX taking precedence.
1192
+ return $this->getAxAttributes() + $this->getSregAttributes();
1193
+ }
1194
+ return $this->getSregAttributes();
1195
+ }
1196
+
1197
+ /**
1198
+ * Gets an OAuth request token if the OpenID+OAuth hybrid protocol has been used.
1199
+ *
1200
+ * In order to use the OpenID+OAuth hybrid protocol, you need to add at least one
1201
+ * scope to the $openid->oauth array before you get the call to getAuthUrl(), e.g.:
1202
+ * $openid->oauth[] = 'https://www.googleapis.com/auth/plus.me';
1203
+ *
1204
+ * Furthermore the registered consumer name must fit the OpenID realm.
1205
+ * To register an OpenID consumer at Google use: https://www.google.com/accounts/ManageDomains
1206
+ *
1207
+ * @return string|bool OAuth request token on success, FALSE if no token was provided.
1208
+ */
1209
+ public function getOAuthRequestToken()
1210
+ {
1211
+ $alias = $this->getNamespaceAlias('http://specs.openid.net/extensions/oauth/1.0');
1212
+
1213
+ return !empty($alias) ? $this->data['openid_' . $alias . '_request_token'] : false;
1214
+ }
1215
+
1216
+ /**
1217
+ * Gets the alias for the specified namespace, if it's present.
1218
+ *
1219
+ * @param string $namespace The namespace for which an alias is needed.
1220
+ * @param string $hint Common alias of this namespace, used for optimization.
1221
+ * @return string|null The namespace alias if found, otherwise - NULL.
1222
+ */
1223
+ private function getNamespaceAlias($namespace, $hint = null)
1224
+ {
1225
+ $result = null;
1226
+
1227
+ if (empty($hint) || $this->getItem('openid_ns_' . $hint) != $namespace) {
1228
+ // The common alias is either undefined or points to
1229
+ // some other extension - search for another alias..
1230
+ $prefix = 'openid_ns_';
1231
+ $length = strlen($prefix);
1232
+
1233
+ foreach ($this->data as $key => $val) {
1234
+ if (strncmp($key, $prefix, $length) === 0 && $val === $namespace) {
1235
+ $result = trim(substr($key, $length));
1236
+ break;
1237
+ }
1238
+ }
1239
+ } else {
1240
+ $result = $hint;
1241
+ }
1242
+
1243
+ return $result;
1244
+ }
1245
+
1246
+ /**
1247
+ * Gets an item from the $data array by the specified id.
1248
+ *
1249
+ * @param string $id The id of the desired item.
1250
+ * @return string|null The item if found, otherwise - NULL.
1251
+ */
1252
+ private function getItem($id)
1253
+ {
1254
+ return isset($this->data[$id]) ? $this->data[$id] : null;
1255
+ }
1256
+ }
hybridauth/library/src/Thirdparty/OpenID/README.md CHANGED
@@ -1,7 +1,7 @@
1
- This file is part of the LightOpenID PHP Library
2
-
3
- LightOpenID is an open source software available under the MIT License.
4
-
5
- https://github.com/iignatov/LightOpenID
6
-
7
- http://opensource.org/licenses/mit-license.php
1
+ This file is part of the LightOpenID PHP Library
2
+
3
+ LightOpenID is an open source software available under the MIT License.
4
+
5
+ https://github.com/iignatov/LightOpenID
6
+
7
+ http://opensource.org/licenses/mit-license.php
hybridauth/library/src/Thirdparty/readme.md CHANGED
@@ -1,14 +1,14 @@
1
- ##### Third party libraries
2
-
3
- Here we include a number of third party libraries. Those libraries are used by the various providers supported by Hybridauth.
4
-
5
- Library | Description
6
- -------- | -------------
7
- [LightOpenID](https://gitorious.org/lightopenid) | Contain LightOpenID. Solid OpenID library licensed under the MIT License.
8
- [OAuth Library](https://code.google.com/p/oauth/) | Contain OAuth Library licensed under the MIT License.
9
-
10
- Notes:
11
-
12
- We no longer use the old OAuth clients. Please don't add new libs to this folder, unless strictly necessary.
13
- Both LightOpenID and OAuth are (to be) partially/indirectly tested within the Hybridauth library.
14
- Both LightOpenID and OAuth libraries are excluded from Codeclimate.com Analysis/GPA.
1
+ ##### Third party libraries
2
+
3
+ Here we include a number of third party libraries. Those libraries are used by the various providers supported by Hybridauth.
4
+
5
+ Library | Description
6
+ -------- | -------------
7
+ [LightOpenID](https://gitorious.org/lightopenid) | Contain LightOpenID. Solid OpenID library licensed under the MIT License.
8
+ [OAuth Library](https://code.google.com/p/oauth/) | Contain OAuth Library licensed under the MIT License.
9
+
10
+ Notes:
11
+
12
+ We no longer use the old OAuth clients. Please don't add new libs to this folder, unless strictly necessary.
13
+ Both LightOpenID and OAuth are (to be) partially/indirectly tested within the Hybridauth library.
14
+ Both LightOpenID and OAuth libraries are excluded from Codeclimate.com Analysis/GPA.
hybridauth/library/src/User/Activity.php CHANGED
@@ -1,73 +1,73 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\User;
9
-
10
- use Hybridauth\Exception\UnexpectedValueException;
11
-
12
- /**
13
- * Hybridauth\User\Activity
14
- */
15
- final class Activity
16
- {
17
- /**
18
- * activity id on the provider side, usually given as integer
19
- *
20
- * @var string
21
- */
22
- public $id = null;
23
-
24
- /**
25
- * activity date of creation
26
- *
27
- * @var string
28
- */
29
- public $date = null;
30
-
31
- /**
32
- * activity content as a string
33
- *
34
- * @var string
35
- */
36
- public $text = null;
37
-
38
- /**
39
- * user who created the activity
40
- *
41
- * @var object
42
- */
43
- public $user = null;
44
-
45
- /**
46
- *
47
- */
48
- public function __construct()
49
- {
50
- $this->user = new \stdClass();
51
-
52
- // typically, we should have a few information about the user who created the event from social apis
53
- $this->user->identifier = null;
54
- $this->user->displayName = null;
55
- $this->user->profileURL = null;
56
- $this->user->photoURL = null;
57
- }
58
-
59
- /**
60
- * Prevent the providers adapters from adding new fields.
61
- *
62
- * @var mixed $value
63
- *
64
- * @var string $name
65
- *
66
- * @throws UnexpectedValueException
67
- */
68
- public function __set($name, $value)
69
- {
70
- // phpcs:ignore
71
- throw new UnexpectedValueException(sprintf('Adding new property "%s\' to %s is not allowed.', $name, __CLASS__));
72
- }
73
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\User;
9
+
10
+ use Hybridauth\Exception\UnexpectedValueException;
11
+
12
+ /**
13
+ * Hybridauth\User\Activity
14
+ */
15
+ final class Activity
16
+ {
17
+ /**
18
+ * activity id on the provider side, usually given as integer
19
+ *
20
+ * @var string
21
+ */
22
+ public $id = null;
23
+
24
+ /**
25
+ * activity date of creation
26
+ *
27
+ * @var string
28
+ */
29
+ public $date = null;
30
+
31
+ /**
32
+ * activity content as a string
33
+ *
34
+ * @var string
35
+ */
36
+ public $text = null;
37
+
38
+ /**
39
+ * user who created the activity
40
+ *
41
+ * @var object
42
+ */
43
+ public $user = null;
44
+
45
+ /**
46
+ *
47
+ */
48
+ public function __construct()
49
+ {
50
+ $this->user = new \stdClass();
51
+
52
+ // typically, we should have a few information about the user who created the event from social apis
53
+ $this->user->identifier = null;
54
+ $this->user->displayName = null;
55
+ $this->user->profileURL = null;
56
+ $this->user->photoURL = null;
57
+ }
58
+
59
+ /**
60
+ * Prevent the providers adapters from adding new fields.
61
+ *
62
+ * @var mixed $value
63
+ *
64
+ * @var string $name
65
+ *
66
+ * @throws UnexpectedValueException
67
+ */
68
+ public function __set($name, $value)
69
+ {
70
+ // phpcs:ignore
71
+ throw new UnexpectedValueException(sprintf('Adding new property "%s\' to %s is not allowed.', $name, __CLASS__));
72
+ }
73
+ }
hybridauth/library/src/User/Contact.php CHANGED
@@ -1,78 +1,78 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\User;
9
-
10
- use Hybridauth\Exception\UnexpectedValueException;
11
-
12
- /**
13
- * Hybridauth\User\Contact
14
- */
15
- final class Contact
16
- {
17
- /**
18
- * The Unique contact user ID
19
- *
20
- * @var string
21
- */
22
- public $identifier = null;
23
-
24
- /**
25
- * User website, blog, web page
26
- *
27
- * @var string
28
- */
29
- public $webSiteURL = null;
30
-
31
- /**
32
- * URL link to profile page on the IDp web site
33
- *
34
- * @var string
35
- */
36
- public $profileURL = null;
37
-
38
- /**
39
- * URL link to user photo or avatar
40
- *
41
- * @var string
42
- */
43
- public $photoURL = null;
44
-
45
- /**
46
- * User displayName provided by the IDp or a concatenation of first and last name
47
- *
48
- * @var string
49
- */
50
- public $displayName = null;
51
-
52
- /**
53
- * A short about_me
54
- *
55
- * @var string
56
- */
57
- public $description = null;
58
-
59
- /**
60
- * User email. Not all of IDp grant access to the user email
61
- *
62
- * @var string
63
- */
64
- public $email = null;
65
-
66
- /**
67
- * Prevent the providers adapters from adding new fields.
68
- *
69
- * @param string $name
70
- * @param mixed $value
71
- *
72
- * @throws UnexpectedValueException
73
- */
74
- public function __set($name, $value)
75
- {
76
- throw new UnexpectedValueException(sprintf('Adding new property "%s" to %s is not allowed.', $name, __CLASS__));
77
- }
78
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\User;
9
+
10
+ use Hybridauth\Exception\UnexpectedValueException;
11
+
12
+ /**
13
+ * Hybridauth\User\Contact
14
+ */
15
+ final class Contact
16
+ {
17
+ /**
18
+ * The Unique contact user ID
19
+ *
20
+ * @var string
21
+ */
22
+ public $identifier = null;
23
+
24
+ /**
25
+ * User website, blog, web page
26
+ *
27
+ * @var string
28
+ */
29
+ public $webSiteURL = null;
30
+
31
+ /**
32
+ * URL link to profile page on the IDp web site
33
+ *
34
+ * @var string
35
+ */
36
+ public $profileURL = null;
37
+
38
+ /**
39
+ * URL link to user photo or avatar
40
+ *
41
+ * @var string
42
+ */
43
+ public $photoURL = null;
44
+
45
+ /**
46
+ * User displayName provided by the IDp or a concatenation of first and last name
47
+ *
48
+ * @var string
49
+ */
50
+ public $displayName = null;
51
+
52
+ /**
53
+ * A short about_me
54
+ *
55
+ * @var string
56
+ */
57
+ public $description = null;
58
+
59
+ /**
60
+ * User email. Not all of IDp grant access to the user email
61
+ *
62
+ * @var string
63
+ */
64
+ public $email = null;
65
+
66
+ /**
67
+ * Prevent the providers adapters from adding new fields.
68
+ *
69
+ * @param string $name
70
+ * @param mixed $value
71
+ *
72
+ * @throws UnexpectedValueException
73
+ */
74
+ public function __set($name, $value)
75
+ {
76
+ throw new UnexpectedValueException(sprintf('Adding new property "%s" to %s is not allowed.', $name, __CLASS__));
77
+ }
78
+ }
hybridauth/library/src/User/Profile.php CHANGED
@@ -1,190 +1,190 @@
1
- <?php
2
- /*!
3
- * Hybridauth
4
- * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
- * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
- */
7
-
8
- namespace Hybridauth\User;
9
-
10
- use Hybridauth\Exception\UnexpectedValueException;
11
-
12
- /**
13
- * Hybridauth\Userobject represents the current logged in user profile.
14
- */
15
- final class Profile
16
- {
17
- /**
18
- * The Unique user's ID on the connected provider
19
- *
20
- * @var integer|null
21
- */
22
- public $identifier = null;
23
-
24
- /**
25
- * User website, blog, web page
26
- *
27
- * @var string|null
28
- */
29
- public $webSiteURL = null;
30
-
31
- /**
32
- * URL link to profile page on the IDp web site
33
- *
34
- * @var string|null
35
- */
36
- public $profileURL = null;
37
-
38
- /**
39
- * URL link to user photo or avatar
40
- *
41
- * @var string|null
42
- */
43
- public $photoURL = null;
44
-
45
- /**
46
- * User displayName provided by the IDp or a concatenation of first and last name.
47
- *
48
- * @var string|null
49
- */
50
- public $displayName = null;
51
-
52
- /**
53
- * A short about_me
54
- *
55
- * @var string|null
56
- */
57
- public $description = null;
58
-
59
- /**
60
- * User's first name
61
- *
62
- * @var string|null
63
- */
64
- public $firstName = null;
65
-
66
- /**
67
- * User's last name
68
- *
69
- * @var string|null
70
- */
71
- public $lastName = null;
72
-
73
- /**
74
- * male or female
75
- *
76
- * @var string|null
77
- */
78
- public $gender = null;
79
-
80
- /**
81
- * Language
82
- *
83
- * @var string|null
84
- */
85
- public $language = null;
86
-
87
- /**
88
- * User age, we don't calculate it. we return it as is if the IDp provide it.
89
- *
90
- * @var integer|null
91
- */
92
- public $age = null;
93
-
94
- /**
95
- * User birth Day
96
- *
97
- * @var integer|null
98
- */
99
- public $birthDay = null;
100
-
101
- /**
102
- * User birth Month
103
- *
104
- * @var integer|null
105
- */
106
- public $birthMonth = null;
107
-
108
- /**
109
- * User birth Year
110
- *
111
- * @var integer|null
112
- */
113
- public $birthYear = null;
114
-
115
- /**
116
- * User email. Note: not all of IDp grant access to the user email
117
- *
118
- * @var string|null
119
- */
120
- public $email = null;
121
-
122
- /**
123
- * Verified user email. Note: not all of IDp grant access to verified user email
124
- *
125
- * @var string|null
126
- */
127
- public $emailVerified = null;
128
-
129
- /**
130
- * Phone number
131
- *
132
- * @var string|null
133
- */
134
- public $phone = null;
135
-
136
- /**
137
- * Complete user address
138
- *
139
- * @var string|null
140
- */
141
- public $address = null;
142
-
143
- /**
144
- * User country
145
- *
146
- * @var string|null
147
- */
148
- public $country = null;
149
-
150
- /**
151
- * Region
152
- *
153
- * @var string|null
154
- */
155
- public $region = null;
156
-
157
- /**
158
- * City
159
- *
160
- * @var string|null
161
- */
162
- public $city = null;
163
-
164
- /**
165
- * Postal code
166
- *
167
- * @var string|null
168
- */
169
- public $zip = null;
170
-
171
- /**
172
- * An extra data which is related to the user
173
- *
174
- * @var array
175
- */
176
- public $data = [];
177
-
178
- /**
179
- * Prevent the providers adapters from adding new fields.
180
- *
181
- * @var string $name
182
- * @var mixed $value
183
- *
184
- * @throws UnexpectedValueException
185
- */
186
- public function __set($name, $value)
187
- {
188
- throw new UnexpectedValueException(sprintf('Adding new property "%s" to %s is not allowed.', $name, __CLASS__));
189
- }
190
- }
1
+ <?php
2
+ /*!
3
+ * Hybridauth
4
+ * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
5
+ * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
6
+ */
7
+
8
+ namespace Hybridauth\User;
9
+
10
+ use Hybridauth\Exception\UnexpectedValueException;
11
+
12
+ /**
13
+ * Hybridauth\Userobject represents the current logged in user profile.
14
+ */
15
+ final class Profile
16
+ {
17
+ /**
18
+ * The Unique user's ID on the connected provider
19
+ *
20
+ * @var integer|null
21
+ */
22
+ public $identifier = null;
23
+
24
+ /**
25
+ * User website, blog, web page
26
+ *
27
+ * @var string|null
28
+ */
29
+ public $webSiteURL = null;
30
+
31
+ /**
32
+ * URL link to profile page on the IDp web site
33
+ *
34
+ * @var string|null
35
+ */
36
+ public $profileURL = null;
37
+
38
+ /**
39
+ * URL link to user photo or avatar
40
+ *
41
+ * @var string|null
42
+ */
43
+ public $photoURL = null;
44
+
45
+ /**
46
+ * User displayName provided by the IDp or a concatenation of first and last name.
47
+ *
48
+ * @var string|null
49
+ */
50
+ public $displayName = null;
51
+
52
+ /**
53
+ * A short about_me
54
+ *
55
+ * @var string|null
56
+ */
57
+ public $description = null;
58
+
59
+ /**
60
+ * User's first name
61
+ *
62
+ * @var string|null
63
+ */
64
+ public $firstName = null;
65
+
66
+ /**
67
+ * User's last name
68
+ *
69
+ * @var string|null
70
+ */
71
+ public $lastName = null;
72
+
73
+ /**
74
+ * male or female
75
+ *
76
+ * @var string|null
77
+ */
78
+ public $gender = null;
79
+
80
+ /**
81
+ * Language
82
+ *
83
+ * @var string|null
84
+ */
85
+ public $language = null;
86
+
87
+ /**
88
+ * User age, we don't calculate it. we return it as is if the IDp provide it.
89
+ *
90
+ * @var integer|null
91
+ */
92
+ public $age = null;
93
+
94
+ /**
95
+ * User birth Day
96
+ *
97
+ * @var integer|null
98
+ */
99
+ public $birthDay = null;
100
+
101
+ /**
102
+ * User birth Month
103
+ *
104
+ * @var integer|null
105
+ */
106
+ public $birthMonth = null;
107
+
108
+ /**
109
+ * User birth Year
110
+ *
111
+ * @var integer|null
112
+ */
113
+ public $birthYear = null;
114
+
115
+ /**
116
+ * User email. Note: not all of IDp grant access to the user email
117
+ *
118
+ * @var string|null
119
+ */
120
+ public $email = null;
121
+
122
+ /**
123
+ * Verified user email. Note: not all of IDp grant access to verified user email
124
+ *
125
+ * @var string|null
126
+ */
127
+ public $emailVerified = null;
128
+
129
+ /**
130
+ * Phone number
131
+ *
132
+ * @var string|null
133
+ */
134
+ public $phone = null;
135
+
136
+ /**
137
+ * Complete user address
138
+ *
139
+ * @var string|null
140
+ */
141
+ public $address = null;
142
+
143
+ /**
144
+ * User country
145
+ *
146
+ * @var string|null
147
+ */
148
+ public $country = null;
149
+
150
+ /**
151
+ * Region
152
+ *
153
+ * @var string|null
154
+ */
155
+ public $region = null;
156
+
157
+ /**
158
+ * City
159
+ *
160
+ * @var string|null
161
+ */
162
+ public $city = null;
163
+
164
+ /**
165
+ * Postal code
166
+ *
167
+ * @var string|null
168
+ */
169
+ public $zip = null;
170
+
171
+ /**
172
+ * An extra data which is related to the user
173
+ *
174
+ * @var array
175
+ */
176
+ public $data = [];
177
+
178
+ /**
179
+ * Prevent the providers adapters from adding new fields.
180
+ *
181
+ * @var string $name
182
+ * @var mixed $value
183
+ *
184
+ * @throws UnexpectedValueException
185
+ */
186
+ public function __set($name, $value)
187
+ {
188
+ throw new UnexpectedValueException(sprintf('Adding new property "%s" to %s is not allowed.', $name, __CLASS__));
189
+ }
190
+ }
hybridauth/library/src/autoload.php CHANGED
@@ -1,53 +1,53 @@
1
- <?php
2
- /**
3
- * Basic autoloader for Hybridauth library which you may use as it is or as a template
4
- * to suit your application's environment.
5
- *
6
- * Note that you'd ONLY need this file if you are not using composer.
7
- */
8
-
9
- if (version_compare(PHP_VERSION, '5.4.0', '<')) {
10
- throw new Exception('Hybridauth 3 requires PHP version 5.4 or higher.');
11
- }
12
-
13
- /**
14
- * Register the autoloader for Hybridauth classes.
15
- *
16
- * Based off the official PSR-4 autoloader example found at
17
- * http://www.php-fig.org/psr/psr-4/examples/
18
- *
19
- * @param string $class The fully-qualified class name.
20
- *
21
- * @return void
22
- */
23
- spl_autoload_register(
24
- function ($class) {
25
- // project-specific namespace prefix. Will only kicks in for Hybridauth's namespace.
26
- $prefix = 'Hybridauth\\';
27
-
28
- // base directory for the namespace prefix.
29
- $base_dir = __DIR__; // By default, it points to this same folder.
30
- // You may change this path if having trouble detecting the path to
31
- // the source files.
32
-
33
- // does the class use the namespace prefix?
34
- $len = strlen($prefix);
35
- if (strncmp($prefix, $class, $len) !== 0) {
36
- // no, move to the next registered autoloader.
37
- return;
38
- }
39
-
40
- // get the relative class name.
41
- $relative_class = substr($class, $len);
42
-
43
- // replace the namespace prefix with the base directory, replace namespace
44
- // separators with directory separators in the relative class name, append
45
- // with .php
46
- $file = $base_dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $relative_class).'.php';
47
-
48
- // if the file exists, require it
49
- if (file_exists($file)) {
50
- require $file;
51
- }
52
- }
53
- );
1
+ <?php
2
+ /**
3
+ * Basic autoloader for Hybridauth library which you may use as it is or as a template
4
+ * to suit your application's environment.
5
+ *
6
+ * Note that you'd ONLY need this file if you are not using composer.
7
+ */
8
+
9
+ if (version_compare(PHP_VERSION, '5.4.0', '<')) {
10
+ throw new Exception('Hybridauth 3 requires PHP version 5.4 or higher.');
11
+ }
12
+
13
+ /**
14
+ * Register the autoloader for Hybridauth classes.
15
+ *
16
+ * Based off the official PSR-4 autoloader example found at
17
+ * http://www.php-fig.org/psr/psr-4/examples/
18
+ *
19
+ * @param string $class The fully-qualified class name.
20
+ *
21
+ * @return void
22
+ */
23
+ spl_autoload_register(
24
+ function ($class) {
25
+ // project-specific namespace prefix. Will only kicks in for Hybridauth's namespace.
26
+ $prefix = 'Hybridauth\\';
27
+
28
+ // base directory for the namespace prefix.
29
+ $base_dir = __DIR__; // By default, it points to this same folder.
30
+ // You may change this path if having trouble detecting the path to
31
+ // the source files.
32
+
33
+ // does the class use the namespace prefix?
34
+ $len = strlen($prefix);
35
+ if (strncmp($prefix, $class, $len) !== 0) {
36
+ // no, move to the next registered autoloader.
37
+ return;
38
+ }
39
+
40
+ // get the relative class name.
41
+ $relative_class = substr($class, $len);
42
+
43
+ // replace the namespace prefix with the base directory, replace namespace
44
+ // separators with directory separators in the relative class name, append
45
+ // with .php
46
+ $file = $base_dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $relative_class).'.php';
47
+
48
+ // if the file exists, require it
49
+ if (file_exists($file)) {
50
+ require $file;
51
+ }
52
+ }
53
+ );
includes/admin/wsl.admin.ui.php CHANGED
@@ -1,533 +1,533 @@
1
- <?php
2
- /*!
3
- * WordPress Social Login
4
- *
5
- * https://miled.github.io/wordpress-social-login/ | https://github.com/miled/wordpress-social-login
6
- * (c) 2011-2020 Mohamed Mrassi and contributors | https://wordpress.org/plugins/wordpress-social-login/
7
- */
8
-
9
- /**
10
- * The LOC in charge of displaying WSL Admin GUInterfaces
11
- */
12
-
13
- // Exit if accessed directly
14
- if ( !defined( 'ABSPATH' ) ) exit;
15
-
16
- // --------------------------------------------------------------------
17
-
18
- /**
19
- * Generate wsl admin pages
20
- *
21
- * wp-admin/options-general.php?page=wordpress-social-login&..
22
- */
23
- function wsl_admin_main()
24
- {
25
- // HOOKABLE:
26
- do_action( "wsl_admin_main_start" );
27
-
28
- if ( ! current_user_can('manage_options') )
29
- {
30
- wp_die( _wsl__( 'You do not have sufficient permissions to access this page.' , 'wordpress-social-login' ) );
31
- }
32
-
33
- if( ! wsl_check_requirements() )
34
- {
35
- wsl_admin_ui_fail();
36
-
37
- exit;
38
- }
39
-
40
- GLOBAL $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS;
41
- GLOBAL $WORDPRESS_SOCIAL_LOGIN_COMPONENTS;
42
- GLOBAL $WORDPRESS_SOCIAL_LOGIN_PROVIDERS_CONFIG;
43
- GLOBAL $WORDPRESS_SOCIAL_LOGIN_VERSION;
44
-
45
- if( isset( $_REQUEST["enable"] ) && isset( $WORDPRESS_SOCIAL_LOGIN_COMPONENTS[ $_REQUEST["enable"] ] ) )
46
- {
47
- $component = $_REQUEST["enable"];
48
-
49
- $WORDPRESS_SOCIAL_LOGIN_COMPONENTS[ $component ][ "enabled" ] = true;
50
-
51
- update_option( "wsl_components_" . $component . "_enabled", 1 );
52
-
53
- wsl_register_components();
54
- }
55
-
56
- if( isset( $_REQUEST["disable"] ) && isset( $WORDPRESS_SOCIAL_LOGIN_COMPONENTS[ $_REQUEST["disable"] ] ) )
57
- {
58
- $component = $_REQUEST["disable"];
59
-
60
- $WORDPRESS_SOCIAL_LOGIN_COMPONENTS[ $component ][ "enabled" ] = false;
61
-
62
- update_option( "wsl_components_" . $component . "_enabled", 2 );
63
-
64
- wsl_register_components();
65
- }
66
-
67
- $wslp = "networks";
68
- $assets_base_url = WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . 'assets/img/16x16/';
69
-
70
- if( isset( $_REQUEST["wslp"] ) )
71
- {
72
- $wslp = trim( strtolower( strip_tags( $_REQUEST["wslp"] ) ) );
73
- }
74
-
75
- wsl_admin_ui_header( $wslp );
76
-
77
- if( isset( $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS[$wslp] ) && $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS[$wslp]["enabled"] )
78
- {
79
- if( isset( $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS[$wslp]["action"] ) && $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS[$wslp]["action"] )
80
- {
81
- do_action( $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS[$wslp]["action"] );
82
- }
83
- else
84
- {
85
- include "components/$wslp/index.php";
86
- }
87
- }
88
- else
89
- {
90
- wsl_admin_ui_error();
91
- }
92
-
93
- wsl_admin_ui_footer();
94
-
95
- // HOOKABLE:
96
- do_action( "wsl_admin_main_end" );
97
- }
98
-
99
- // --------------------------------------------------------------------
100
-
101
- /**
102
- * Render wsl admin pages header (label and tabs)
103
- */
104
- function wsl_admin_ui_header( $wslp = null )
105
- {
106
- // HOOKABLE:
107
- do_action( "wsl_admin_ui_header_start" );
108
-
109
- GLOBAL $WORDPRESS_SOCIAL_LOGIN_VERSION;
110
- GLOBAL $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS;
111
-
112
- // Dismiss WSL migration notice
113
- if( isset( $_REQUEST["wsldmn"] ) && (int) $_REQUEST["wsldmn"] === 1 )
114
- {
115
- update_option( "wsl_settings_migration_notice_is_read", true );
116
- }
117
- ?>
118
- <a name="wsltop"></a>
119
- <div class="wsl-container">
120
-
121
- <?php
122
- // nag
123
-
124
- if( in_array( $wslp, array( 'networks', 'login-widget' ) ) and ( isset( $_REQUEST['settings-updated'] ) or isset( $_REQUEST['enable'] ) ) )
125
- {
126
- $active_plugins = implode('', (array) get_option('active_plugins') );
127
- $cache_enabled =
128
- strpos( $active_plugins, "w3-total-cache" ) !== false |
129
- strpos( $active_plugins, "wp-super-cache" ) !== false |
130
- strpos( $active_plugins, "quick-cache" ) !== false |
131
- strpos( $active_plugins, "wp-fastest-cache" ) !== false |
132
- strpos( $active_plugins, "wp-widget-cache" ) !== false |
133
- strpos( $active_plugins, "hyper-cache" ) !== false;
134
-
135
- if( $cache_enabled )
136
- {
137
- ?>
138
- <div class="fade updated" style="margin: 4px 0 20px;">
139
- <p>
140
- <?php _wsl_e("<b>Note:</b> WSL has detected that you are using a caching plugin. If the saved changes didn't take effect immediately then you might need to empty the cache", 'wordpress-social-login') ?>.
141
- </p>
142
- </div>
143
- <?php
144
- }
145
- }
146
-
147
- if( get_option( 'wsl_settings_development_mode_enabled' ) )
148
- {
149
- ?>
150
- <div class="fade error wsl-error-dev-mode-on" style="margin: 4px 0 20px;">
151
- <p>
152
- <?php _wsl_e('<b>Warning:</b> You are now running WordPress Social Login with DEVELOPMENT MODE enabled. This mode is not intended for live websites as it might raise serious security risks', 'wordpress-social-login') ?>.
153
- </p>
154
- <p>
155
- <a class="button-secondary" href="options-general.php?page=wordpress-social-login&wslp=tools#dev-mode"><?php _wsl_e('Change this mode', 'wordpress-social-login') ?></a>
156
- <a class="button-secondary" href="http://miled.github.io/wordpress-social-login/troubleshooting-advanced.html" target="_blank"><?php _wsl_e('Read about the development mode', 'wordpress-social-login') ?></a>
157
- </p>
158
- </div>
159
- <?php
160
- }
161
-
162
- if( get_option( 'wsl_settings_debug_mode_enabled' ) )
163
- {
164
- ?>
165
- <div class="fade updated wsl-error-debug-mode-on" style="margin: 4px 0 20px;">
166
- <p>
167
- <?php _wsl_e('<b>Note:</b> You are now running WordPress Social Login with DEBUG MODE enabled. This mode is not intended for live websites as it might add to loading time and store unnecessary data on your server', 'wordpress-social-login') ?>.
168
- </p>
169
- <p>
170
- <a class="button-secondary" href="options-general.php?page=wordpress-social-login&wslp=tools#debug-mode"><?php _wsl_e('Change this mode', 'wordpress-social-login') ?></a>
171
- <a class="button-secondary" href="options-general.php?page=wordpress-social-login&wslp=watchdog"><?php _wsl_e('View WSL logs', 'wordpress-social-login') ?></a>
172
- <a class="button-secondary" href="http://miled.github.io/wordpress-social-login/troubleshooting-advanced.html" target="_blank"><?php _wsl_e('Read about the debug mode', 'wordpress-social-login') ?></a>
173
- </p>
174
- </div>
175
- <?php
176
- }
177
-
178
- if( ! get_option( 'wsl_settings_migration_notice_is_read' ) )
179
- {
180
- ?>
181
- <div class="fade updated" style="margin: 4px 0 20px; border-left-color: #ffc107;">
182
- <p><b><?php _wsl_e("Breaking changes notice", 'wordpress-social-login') ?>:</b></p>
183
-
184
- <p><?php _wsl_e("In WordPress Social Login 3.0 we have reworked the identity provider's <b>Callback URLs</b>. To make sure the plugin will keep working correctly, you can either create a new application for each enabled provider, or simply update the already created application with the newly generated callback urls:", 'wordpress-social-login') ?></p>
185
-
186
- <ol>
187
- <li><?php _wsl_e("First, navigate to <b>WSL Settting > Networks</b> tab", 'wordpress-social-login') ?>,</li>
188
- <li><?php _wsl_e("Next, refer to <b>Where do I get this info?</b> section for each enabled provider and copy its new auto generated callback url", 'wordpress-social-login') ?>,</li>
189
- <li><?php _wsl_e("Finally, update that link on the provider developer website", 'wordpress-social-login') ?>.</li>
190
- </ol>
191
-
192
- <p><?php _wsl_e("It's also important to note that a number of providers are now made obsolete in WSL 3.0, while a few other were added, and cetain providers has changed their requirements", 'wordpress-social-login') ?>.</p>
193
-
194
- <p>
195
- <a class="button-secondary" style="background-color: #ffc107; border-color: #e3ab02; color: #fff;min-width: 95px;text-align: center;" href="options-general.php?page=wordpress-social-login&wslp=networks&wsldmn=1"><?php _wsl_e('Okey, dismiss this notice', 'wordpress-social-login') ?></a>
196
- </p>
197
- </div>
198
- <?php
199
- }
200
- ?>
201
-
202
- <div class="alignright">
203
- <a style="font-size: 0.9em; text-decoration: none;" target="_blank" href="http://miled.github.io/wordpress-social-login/documentation.html"><?php _wsl_e('Docs', 'wordpress-social-login') ?></a> -
204
- <a style="font-size: 0.9em; text-decoration: none;" target="_blank" href="http://miled.github.io/wordpress-social-login/support.html"><?php _wsl_e('Support', 'wordpress-social-login') ?></a> -
205
- <a style="font-size: 0.9em; text-decoration: none;" target="_blank" href="https://github.com/miled/wordpress-social-login"><?php _wsl_e('Github', 'wordpress-social-login') ?></a>
206
- </div>
207
-
208
- <h1 <?php if( is_rtl() ) echo 'style="margin: 20px 0;"'; ?>>
209
- <?php _wsl_e( 'WordPress Social Login', 'wordpress-social-login' ) ?>
210
-
211
- <small><?php echo $WORDPRESS_SOCIAL_LOGIN_VERSION ?></small>
212
- </h1>
213
-
214
- <h2 class="nav-tab-wrapper">
215
- &nbsp;
216
- <?php
217
- $css_pull_right = "";
218
-
219
- foreach( $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS as $name => $settings )
220
- {
221
- if( $settings["enabled"] && ( $settings["visible"] || $wslp == $name ) )
222
- {
223
- if( isset( $settings["pull-right"] ) && $settings["pull-right"] )
224
- {
225
- $css_pull_right = "float:right";
226
-
227
- if( is_rtl() )
228
- {
229
- $css_pull_right = "float:left";
230
- }
231
- }
232
-
233
- ?><a class="nav-tab <?php if( $wslp == $name ) echo "nav-tab-active"; ?>" style="<?php echo $css_pull_right; ?>" href="options-general.php?page=wordpress-social-login&wslp=<?php echo $name ?>"><?php if( isset( $settings["ico"] ) ) echo '<img style="margin: 0px; padding: 0px; border: 0px none;width: 16px; height: 16px;" src="' . WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . '/assets/img/' . $settings["ico"] . '" />'; else _wsl_e( $settings["label"], 'wordpress-social-login' ); ?></a><?php
234
- }
235
- }
236
- ?>
237
- </h2>
238
-
239
- <div id="wsl_admin_tab_content">
240
- <?php
241
- // HOOKABLE:
242
- do_action( "wsl_admin_ui_header_end" );
243
- }
244
-
245
- // --------------------------------------------------------------------
246
-
247
- /**
248
- * Renders wsl admin pages footer
249
- */
250
- function wsl_admin_ui_footer()
251
- {
252
- // HOOKABLE:
253
- do_action( "wsl_admin_ui_footer_start" );
254
-
255
- GLOBAL $WORDPRESS_SOCIAL_LOGIN_VERSION;
256
- ?>
257
- </div> <!-- ./wsl_admin_tab_content -->
258
-
259
- <div class="clear"></div>
260
-
261
- <?php
262
- wsl_admin_help_us_localize_note();
263
-
264
- // HOOKABLE:
265
- do_action( "wsl_admin_ui_footer_end" );
266
-
267
- if( get_option( 'wsl_settings_development_mode_enabled' ) )
268
- {
269
- wsl_display_dev_mode_debugging_area();
270
- }
271
- }
272
-
273
- // --------------------------------------------------------------------
274
-
275
- /**
276
- * Renders wsl admin error page
277
- */
278
- function wsl_admin_ui_error()
279
- {
280
- // HOOKABLE:
281
- do_action( "wsl_admin_ui_error_start" );
282
- ?>
283
- <div id="wsl_div_warn">
284
- <h3 style="margin:0px;"><?php _wsl_e('Oops! We ran into an issue.', 'wordpress-social-login') ?></h3>
285
-
286
- <hr />
287
-
288
- <p>
289
- <?php _wsl_e('Unknown or Disabled <b>Component</b>! Check the list of enabled components or the typed URL', 'wordpress-social-login') ?> .
290
- </p>
291
-
292
- <p>
293
- <?php _wsl_e("If you believe you've found a problem with <b>WordPress Social Login</b>, be sure to let us know so we can fix it", 'wordpress-social-login') ?>.
294
- </p>
295
-
296
- <hr />
297
-
298
- <div>
299
- <a class="button-secondary" href="http://miled.github.io/wordpress-social-login/support.html" target="_blank"><?php _wsl_e( "Report as bug", 'wordpress-social-login' ) ?></a>
300
- <a class="button-primary" href="options-general.php?page=wordpress-social-login&wslp=components" style="float:<?php if( is_rtl() ) echo 'left'; else echo 'right'; ?>"><?php _wsl_e( "Check enabled components", 'wordpress-social-login' ) ?></a>
301
- </div>
302
- </div>
303
- <?php
304
- // HOOKABLE:
305
- do_action( "wsl_admin_ui_error_end" );
306
- }
307
-
308
- // --------------------------------------------------------------------
309
-
310
- /**
311
- * Renders WSL #FAIL page
312
- */
313
- function wsl_admin_ui_fail()
314
- {
315
- // HOOKABLE:
316
- do_action( "wsl_admin_ui_fail_start" );
317
- ?>
318
- <div class="wsl-container">
319
- <div style="background: none repeat scroll 0 0 #fff;border: 1px solid #e5e5e5;box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);padding:20px;">
320
- <h1><?php _e("WordPress Social Login - FAIL!", 'wordpress-social-login') ?></h1>
321
-
322
- <hr />
323
-
324
- <p>
325
- <?php _e('Despite the efforts, put into <b>WordPress Social Login</b> in terms of reliability, portability, and maintenance by the plugin <a href="http://profiles.wordpress.org/miled/" target="_blank">author</a> and <a href="https://github.com/hybridauth/WordPress-Social-Login/graphs/contributors" target="_blank">contributors</a>', 'wordpress-social-login') ?>.
326
- <b style="color:red;"><?php _e('Your server failed the requirements check for this plugin', 'wordpress-social-login') ?>:</b>
327
- </p>
328
-
329
- <p>
330
- <?php _e('These requirements are usually met by default by most "modern" web hosting providers, however some complications may occur with <b>shared hosting</b> and, or <b>custom wordpress installations</b>', 'wordpress-social-login') ?>.
331
- </p>
332
-
333
- <p>
334
- <?php _wsl_e("The minimum server requirements are", 'wordpress-social-login') ?>:
335
- </p>
336
-
337
- <ul style="margin-left:60px;">
338
- <li><?php _wsl_e("PHP >= 5.2.0 installed", 'wordpress-social-login') ?></li>
339
- <li><?php _wsl_e("WSL Endpoint URLs reachable", 'wordpress-social-login') ?></li>
340
- <li><?php _wsl_e("PHP's default SESSION handling", 'wordpress-social-login') ?></li>
341
- <li><?php _wsl_e("PHP/CURL/SSL Extension enabled", 'wordpress-social-login') ?></li>
342
- <li><?php _wsl_e("PHP/JSON Extension enabled", 'wordpress-social-login') ?></li>
343
- <li><?php _wsl_e("PHP/REGISTER_GLOBALS Off", 'wordpress-social-login') ?></li>
344
- <li><?php _wsl_e("jQuery installed on WordPress backoffice", 'wordpress-social-login') ?></li>
345
- </ul>
346
- </div>
347
-
348
- <?php
349
- include_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/admin/components/tools/wsl.components.tools.actions.job.php' );
350
-
351
- wsl_component_tools_do_diagnostics();
352
- ?>
353
- </div>
354
- <style>.wsl-container .button-secondary { display:none; }</style>
355
- <?php
356
- // HOOKABLE:
357
- do_action( "wsl_admin_ui_fail_end" );
358
- }
359
-
360
- // --------------------------------------------------------------------
361
-
362
- /**
363
- * Renders wsl admin welcome panel
364
- */
365
- function wsl_admin_welcome_panel()
366
- {
367
- // Dissmiss WSL Welcome pannel
368
- if( isset( $_REQUEST["wsldwp"] ) && (int) $_REQUEST["wsldwp"] === 1 )
369
- {
370
- update_option( "wsl_settings_welcome_panel_enabled", wsl_get_version() );
371
-
372
- return;
373
- }
374
-
375
- // if new user or wsl updated, then we display wsl welcome panel
376
- if( get_option( 'wsl_settings_welcome_panel_enabled' ) == wsl_get_version() )
377
- {
378
- return;
379
- }
380
-
381
- $wslp = "networks";
382
-
383
- if( isset( $_REQUEST["wslp"] ) )
384
- {
385
- $wslp = $_REQUEST["wslp"];
386
- }
387
- ?>
388
- <!--
389
- if you want to know if a UI was made by developer, then here is a tip: he will always use tables
390
-
391
- //> wsl-w-panel is shamelessly borrowed and modified from wordpress welcome-panel
392
- -->
393
- <div id="wsl-w-panel">
394
- <a href="options-general.php?page=wordpress-social-login&wslp=<?php echo $wslp ?>&wsldwp=1" id="wsl-w-panel-dismiss" <?php if( is_rtl() ) echo 'style="left: 10px;right: auto;"'; ?>><?php _wsl_e("Dismiss", 'wordpress-social-login') ?></a>
395
-
396
- <table width="100%" border="0" style="margin:0;padding:0;">
397
- <tr>
398
- <td width="10" valign="top"></td>
399
- <td width="300" valign="top">
400
- <b style="font-size: 16px;"><?php _wsl_e("Welcome!", 'wordpress-social-login') ?></b>
401
- <p>
402
- <?php _wsl_e("If you are still new to WordPress Social Login, we have provided a few walkthroughs to get you started", 'wordpress-social-login') ?>.
403
- </p>
404
- </td>
405
- <td width="40" valign="top"></td>
406
- <td width="260" valign="top">
407
- <br />
408
- <p>
409
- <b><?php _wsl_e("Get Started", 'wordpress-social-login') ?></b>
410
- </p>
411
- <ul style="margin-left:25px;">
412
- <li><a href="http://miled.github.io/wordpress-social-login/overview.html" target="_blank"><?php _wsl_e('Plugin Overview', 'wordpress-social-login') ?></a></li>
413
- <li><a href="http://miled.github.io/wordpress-social-login/networks.html" target="_blank"><?php _wsl_e('Setup and Configuration', 'wordpress-social-login') ?></a></li>
414
- <li><a href="http://miled.github.io/wordpress-social-login/widget.html" target="_blank"><?php _wsl_e('Customize WSL Widgets', 'wordpress-social-login') ?></a></li>
415
- <li><a href="http://miled.github.io/wordpress-social-login/userdata.html" target="_blank"><?php _wsl_e('Manage users and contacts', 'wordpress-social-login') ?></a></li>
416
- <li><a href="http://miled.github.io/wordpress-social-login/documentation.html" target="_blank"><?php _wsl_e('WSL Developer API', 'wordpress-social-login') ?></a></li>
417
- </ul>
418
- </td>
419
- <td width="" valign="top">
420
- <br />
421
- <p>
422
- <b><?php echo sprintf( _wsl__( "What's new on WSL %s", 'wordpress-social-login'), wsl_get_version() ) ?></b>
423
- </p>
424
-
425
- <ul style="margin-left:25px;">
426
- <li><?php _wsl_e('WSL is now fully migrated to Hybridauth 3.4', 'wordpress-social-login') ?></li>
427
- <li><?php _wsl_e("Reworked providers Callback URLs and it's a breaking change! See up top notice", 'wordpress-social-login') ?></li>
428
- <li><?php _wsl_e('Added serval new providers: Amazon, Discord and Spotify to name a few', 'wordpress-social-login') ?></li>
429
- <li><?php _wsl_e('Removal of a number of currently defunct identity providers ', 'wordpress-social-login') ?></li>
430
- <li><?php _wsl_e('Authentication widgets and forms design overhall', 'wordpress-social-login') ?></li>
431
- <li><?php _wsl_e('Various fixes and improvements', 'wordpress-social-login') ?></li>
432
- </ul>
433
- </td>
434
- </tr>
435
- <tr id="wsl-w-panel-updates-tr">
436
- <td colspan="5" style="border-top:1px solid #ccc;" id="wsl-w-panel-updates-td">
437
- &nbsp;
438
- </td>
439
- </tr>
440
- </table>
441
- </div>
442
- <?php
443
- }
444
-
445
- // --------------------------------------------------------------------
446
-
447
- /**
448
- * Renders wsl localization note
449
- */
450
- function wsl_admin_help_us_localize_note()
451
- {
452
- return; // nothing, until I decide otherwise..
453
-
454
- $assets_url = WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . 'assets/img/';
455
-
456
- ?>
457
- <div id="l10n-footer">
458
- <br /><br />
459
- <img src="<?php echo $assets_url ?>flags.png">
460
- <a href="https://www.transifex.com/projects/p/wordpress-social-login/" target="_blank"><?php _wsl_e( "Help us translate WordPress Social Login into your language", 'wordpress-social-login' ) ?></a>
461
- </div>
462
- <?php
463
- }
464
-
465
- // --------------------------------------------------------------------
466
-
467
- /**
468
- * Renders an editor in a page in the typical fashion used in Posts and Pages.
469
- * wp_editor was implemented in wp 3.3. if not found we fallback to a regular textarea
470
- *
471
- * Utility.
472
- */
473
- function wsl_render_wp_editor( $name, $content )
474
- {
475
- if( ! function_exists( 'wp_editor' ) )
476
- {
477
- ?>
478
- <textarea style="width:100%;height:100px;margin-top:6px;" name="<?php echo $name ?>"><?php echo htmlentities( $content ); ?></textarea>
479
- <?php
480
- return;
481
- }
482
- ?>
483
- <div class="postbox">
484
- <div class="wp-editor-textarea" style="background-color: #FFFFFF;">
485
- <?php
486
- wp_editor(
487
- $content, $name,
488
- array( 'textarea_name' => $name, 'media_buttons' => true, 'tinymce' => array( 'theme_advanced_buttons1' => 'formatselect,forecolor,|,bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,link,unlink' ) )
489
- );
490
- ?>
491
- </div>
492
- </div>
493
- <?php
494
- }
495
-
496
- // --------------------------------------------------------------------
497
-
498
- /**
499
- * Display WordPress Social Login on settings as submenu
500
- */
501
- function wsl_admin_menu()
502
- {
503
- add_options_page(
504
- _wsl__( 'WP Social Login', 'wordpress-social-login' ),
505
- _wsl__( 'WP Social Login', 'wordpress-social-login' ),
506
- 'manage_options',
507
- 'wordpress-social-login',
508
- 'wsl_admin_main'
509
- );
510
-
511
- add_action( 'admin_init', 'wsl_register_setting' );
512
- }
513
-
514
- add_action('admin_menu', 'wsl_admin_menu' );
515
-
516
- // --------------------------------------------------------------------
517
-
518
- /**
519
- * Enqueue WSL admin CSS file
520
- */
521
- function wsl_add_admin_stylesheets()
522
- {
523
- if( ! wp_style_is( 'wsl-admin', 'registered' ) )
524
- {
525
- wp_register_style( "wsl-admin", WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . "assets/css/admin.css" );
526
- }
527
-
528
- wp_enqueue_style( "wsl-admin" );
529
- }
530
-
531
- add_action( 'admin_enqueue_scripts', 'wsl_add_admin_stylesheets' );
532
-
533
- // --------------------------------------------------------------------
1
+ <?php
2
+ /*!
3
+ * WordPress Social Login
4
+ *
5
+ * https://miled.github.io/wordpress-social-login/ | https://github.com/miled/wordpress-social-login
6
+ * (c) 2011-2020 Mohamed Mrassi and contributors | https://wordpress.org/plugins/wordpress-social-login/
7
+ */
8
+
9
+ /**
10
+ * The LOC in charge of displaying WSL Admin GUInterfaces
11
+ */
12
+
13
+ // Exit if accessed directly
14
+ if ( !defined( 'ABSPATH' ) ) exit;
15
+
16
+ // --------------------------------------------------------------------
17
+
18
+ /**
19
+ * Generate wsl admin pages
20
+ *
21
+ * wp-admin/options-general.php?page=wordpress-social-login&..
22
+ */
23
+ function wsl_admin_main()
24
+ {
25
+ // HOOKABLE:
26
+ do_action( "wsl_admin_main_start" );
27
+
28
+ if ( ! current_user_can('manage_options') )
29
+ {
30
+ wp_die( _wsl__( 'You do not have sufficient permissions to access this page.' , 'wordpress-social-login' ) );
31
+ }
32
+
33
+ if( ! wsl_check_requirements() )
34
+ {
35
+ wsl_admin_ui_fail();
36
+
37
+ exit;
38
+ }
39
+
40
+ GLOBAL $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS;
41
+ GLOBAL $WORDPRESS_SOCIAL_LOGIN_COMPONENTS;
42
+ GLOBAL $WORDPRESS_SOCIAL_LOGIN_PROVIDERS_CONFIG;
43
+ GLOBAL $WORDPRESS_SOCIAL_LOGIN_VERSION;
44
+
45
+ if( isset( $_REQUEST["enable"] ) && isset( $WORDPRESS_SOCIAL_LOGIN_COMPONENTS[ $_REQUEST["enable"] ] ) )
46
+ {
47
+ $component = $_REQUEST["enable"];
48
+
49
+ $WORDPRESS_SOCIAL_LOGIN_COMPONENTS[ $component ][ "enabled" ] = true;
50
+
51
+ update_option( "wsl_components_" . $component . "_enabled", 1 );
52
+
53
+ wsl_register_components();
54
+ }
55
+
56
+ if( isset( $_REQUEST["disable"] ) && isset( $WORDPRESS_SOCIAL_LOGIN_COMPONENTS[ $_REQUEST["disable"] ] ) )
57
+ {
58
+ $component = $_REQUEST["disable"];
59
+
60
+ $WORDPRESS_SOCIAL_LOGIN_COMPONENTS[ $component ][ "enabled" ] = false;
61
+
62
+ update_option( "wsl_components_" . $component . "_enabled", 2 );
63
+
64
+ wsl_register_components();
65
+ }
66
+
67
+ $wslp = "networks";
68
+ $assets_base_url = WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . 'assets/img/16x16/';
69
+
70
+ if( isset( $_REQUEST["wslp"] ) )
71
+ {
72
+ $wslp = trim( strtolower( strip_tags( $_REQUEST["wslp"] ) ) );
73
+ }
74
+
75
+ wsl_admin_ui_header( $wslp );
76
+
77
+ if( isset( $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS[$wslp] ) && $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS[$wslp]["enabled"] )
78
+ {
79
+ if( isset( $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS[$wslp]["action"] ) && $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS[$wslp]["action"] )
80
+ {
81
+ do_action( $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS[$wslp]["action"] );
82
+ }
83
+ else
84
+ {
85
+ include "components/$wslp/index.php";
86
+ }
87
+ }
88
+ else
89
+ {
90
+ wsl_admin_ui_error();
91
+ }
92
+
93
+ wsl_admin_ui_footer();
94
+
95
+ // HOOKABLE:
96
+ do_action( "wsl_admin_main_end" );
97
+ }
98
+
99
+ // --------------------------------------------------------------------
100
+
101
+ /**
102
+ * Render wsl admin pages header (label and tabs)
103
+ */
104
+ function wsl_admin_ui_header( $wslp = null )
105
+ {
106
+ // HOOKABLE:
107
+ do_action( "wsl_admin_ui_header_start" );
108
+
109
+ GLOBAL $WORDPRESS_SOCIAL_LOGIN_VERSION;
110
+ GLOBAL $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS;
111
+
112
+ // Dismiss WSL migration notice
113
+ if( isset( $_REQUEST["wsldmn"] ) && (int) $_REQUEST["wsldmn"] === 1 )
114
+ {
115
+ update_option( "wsl_settings_migration_notice_is_read", true );
116
+ }
117
+ ?>
118
+ <a name="wsltop"></a>
119
+ <div class="wsl-container">
120
+
121
+ <?php
122
+ // nag
123
+
124
+ if( in_array( $wslp, array( 'networks', 'login-widget' ) ) and ( isset( $_REQUEST['settings-updated'] ) or isset( $_REQUEST['enable'] ) ) )
125
+ {
126
+ $active_plugins = implode('', (array) get_option('active_plugins') );
127
+ $cache_enabled =
128
+ strpos( $active_plugins, "w3-total-cache" ) !== false |
129
+ strpos( $active_plugins, "wp-super-cache" ) !== false |
130
+ strpos( $active_plugins, "quick-cache" ) !== false |
131
+ strpos( $active_plugins, "wp-fastest-cache" ) !== false |
132
+ strpos( $active_plugins, "wp-widget-cache" ) !== false |
133
+ strpos( $active_plugins, "hyper-cache" ) !== false;
134
+
135
+ if( $cache_enabled )
136
+ {
137
+ ?>
138
+ <div class="fade updated" style="margin: 4px 0 20px;">
139
+ <p>
140
+ <?php _wsl_e("<b>Note:</b> WSL has detected that you are using a caching plugin. If the saved changes didn't take effect immediately then you might need to empty the cache", 'wordpress-social-login') ?>.
141
+ </p>
142
+ </div>
143
+ <?php
144
+ }
145
+ }
146
+
147
+ if( get_option( 'wsl_settings_development_mode_enabled' ) )
148
+ {
149
+ ?>
150
+ <div class="fade error wsl-error-dev-mode-on" style="margin: 4px 0 20px;">
151
+ <p>
152
+ <?php _wsl_e('<b>Warning:</b> You are now running WordPress Social Login with DEVELOPMENT MODE enabled. This mode is not intended for live websites as it might raise serious security risks', 'wordpress-social-login') ?>.
153
+ </p>
154
+ <p>
155
+ <a class="button-secondary" href="options-general.php?page=wordpress-social-login&wslp=tools#dev-mode"><?php _wsl_e('Change this mode', 'wordpress-social-login') ?></a>
156
+ <a class="button-secondary" href="http://miled.github.io/wordpress-social-login/troubleshooting-advanced.html" target="_blank"><?php _wsl_e('Read about the development mode', 'wordpress-social-login') ?></a>
157
+ </p>
158
+ </div>
159
+ <?php
160
+ }
161
+
162
+ if( get_option( 'wsl_settings_debug_mode_enabled' ) )
163
+ {
164
+ ?>
165
+ <div class="fade updated wsl-error-debug-mode-on" style="margin: 4px 0 20px;">
166
+ <p>
167
+ <?php _wsl_e('<b>Note:</b> You are now running WordPress Social Login with DEBUG MODE enabled. This mode is not intended for live websites as it might add to loading time and store unnecessary data on your server', 'wordpress-social-login') ?>.
168
+ </p>
169
+ <p>
170
+ <a class="button-secondary" href="options-general.php?page=wordpress-social-login&wslp=tools#debug-mode"><?php _wsl_e('Change this mode', 'wordpress-social-login') ?></a>
171
+ <a class="button-secondary" href="options-general.php?page=wordpress-social-login&wslp=watchdog"><?php _wsl_e('View WSL logs', 'wordpress-social-login') ?></a>
172
+ <a class="button-secondary" href="http://miled.github.io/wordpress-social-login/troubleshooting-advanced.html" target="_blank"><?php _wsl_e('Read about the debug mode', 'wordpress-social-login') ?></a>
173
+ </p>
174
+ </div>
175
+ <?php
176
+ }
177
+
178
+ if( ! get_option( 'wsl_settings_migration_notice_is_read' ) )
179
+ {
180
+ ?>
181
+ <div class="fade updated" style="margin: 4px 0 20px; border-left-color: #ffc107;">
182
+ <p><b><?php _wsl_e("Breaking changes notice", 'wordpress-social-login') ?>:</b></p>
183
+
184
+ <p><?php _wsl_e("In WordPress Social Login 3.0 we have reworked the identity provider's <b>Callback URLs</b>. To make sure the plugin will keep working correctly, you can either create a new application for each enabled provider, or simply update the already created application with the newly generated callback urls:", 'wordpress-social-login') ?></p>
185
+
186
+ <ol>
187
+ <li><?php _wsl_e("First, navigate to <b>WSL Settting > Networks</b> tab", 'wordpress-social-login') ?>,</li>
188
+ <li><?php _wsl_e("Next, refer to <b>Where do I get this info?</b> section for each enabled provider and copy its new auto generated callback url", 'wordpress-social-login') ?>,</li>
189
+ <li><?php _wsl_e("Finally, update that link on the provider developer website", 'wordpress-social-login') ?>.</li>
190
+ </ol>
191
+
192
+ <p><?php _wsl_e("It's also important to note that a number of providers are now made obsolete in WSL 3.0, while a few other were added, and cetain providers has changed their requirements", 'wordpress-social-login') ?>.</p>
193
+
194
+ <p>
195
+ <a class="button-secondary" style="background-color: #ffc107; border-color: #e3ab02; color: #fff;min-width: 95px;text-align: center;" href="options-general.php?page=wordpress-social-login&wslp=networks&wsldmn=1"><?php _wsl_e('Okey, dismiss this notice', 'wordpress-social-login') ?></a>
196
+ </p>
197
+ </div>
198
+ <?php
199
+ }
200
+ ?>
201
+
202
+ <div class="alignright">
203
+ <a style="font-size: 0.9em; text-decoration: none;" target="_blank" href="http://miled.github.io/wordpress-social-login/documentation.html"><?php _wsl_e('Docs', 'wordpress-social-login') ?></a> -
204
+ <a style="font-size: 0.9em; text-decoration: none;" target="_blank" href="http://miled.github.io/wordpress-social-login/support.html"><?php _wsl_e('Support', 'wordpress-social-login') ?></a> -
205
+ <a style="font-size: 0.9em; text-decoration: none;" target="_blank" href="https://github.com/miled/wordpress-social-login"><?php _wsl_e('Github', 'wordpress-social-login') ?></a>
206
+ </div>
207
+
208
+ <h1 <?php if( is_rtl() ) echo 'style="margin: 20px 0;"'; ?>>
209
+ <?php _wsl_e( 'WordPress Social Login', 'wordpress-social-login' ) ?>
210
+
211
+ <small><?php echo $WORDPRESS_SOCIAL_LOGIN_VERSION ?></small>
212
+ </h1>
213
+
214
+ <h2 class="nav-tab-wrapper">
215
+ &nbsp;
216
+ <?php
217
+ $css_pull_right = "";
218
+
219
+ foreach( $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS as $name => $settings )
220
+ {
221
+ if( $settings["enabled"] && ( $settings["visible"] || $wslp == $name ) )
222
+ {
223
+ if( isset( $settings["pull-right"] ) && $settings["pull-right"] )
224
+ {
225
+ $css_pull_right = "float:right";
226
+
227
+ if( is_rtl() )
228
+ {
229
+ $css_pull_right = "float:left";
230
+ }
231
+ }
232
+
233
+ ?><a class="nav-tab <?php if( $wslp == $name ) echo "nav-tab-active"; ?>" style="<?php echo $css_pull_right; ?>" href="options-general.php?page=wordpress-social-login&wslp=<?php echo $name ?>"><?php if( isset( $settings["ico"] ) ) echo '<img style="margin: 0px; padding: 0px; border: 0px none;width: 16px; height: 16px;" src="' . WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . '/assets/img/' . $settings["ico"] . '" />'; else _wsl_e( $settings["label"], 'wordpress-social-login' ); ?></a><?php
234
+ }
235
+ }
236
+ ?>
237
+ </h2>
238
+
239
+ <div id="wsl_admin_tab_content">
240
+ <?php
241
+ // HOOKABLE:
242
+ do_action( "wsl_admin_ui_header_end" );
243
+ }
244
+
245
+ // --------------------------------------------------------------------
246
+
247
+ /**
248
+ * Renders wsl admin pages footer
249
+ */
250
+ function wsl_admin_ui_footer()
251
+ {
252
+ // HOOKABLE:
253
+ do_action( "wsl_admin_ui_footer_start" );
254
+
255
+ GLOBAL $WORDPRESS_SOCIAL_LOGIN_VERSION;
256
+ ?>
257
+ </div> <!-- ./wsl_admin_tab_content -->
258
+
259
+ <div class="clear"></div>
260
+
261
+ <?php
262
+ wsl_admin_help_us_localize_note();
263
+
264
+ // HOOKABLE:
265
+ do_action( "wsl_admin_ui_footer_end" );
266
+
267
+ if( get_option( 'wsl_settings_development_mode_enabled' ) )
268
+ {
269
+ wsl_display_dev_mode_debugging_area();
270
+ }
271
+ }
272
+
273
+ // --------------------------------------------------------------------
274
+
275
+ /**
276
+ * Renders wsl admin error page
277
+ */
278
+ function wsl_admin_ui_error()
279
+ {
280
+ // HOOKABLE:
281
+ do_action( "wsl_admin_ui_error_start" );
282
+ ?>
283
+ <div id="wsl_div_warn">
284
+ <h3 style="margin:0px;"><?php _wsl_e('Oops! We ran into an issue.', 'wordpress-social-login') ?></h3>
285
+
286
+ <hr />
287
+
288
+ <p>
289
+ <?php _wsl_e('Unknown or Disabled <b>Component</b>! Check the list of enabled components or the typed URL', 'wordpress-social-login') ?> .
290
+ </p>
291
+
292
+ <p>
293
+ <?php _wsl_e("If you believe you've found a problem with <b>WordPress Social Login</b>, be sure to let us know so we can fix it", 'wordpress-social-login') ?>.
294
+ </p>
295
+
296
+ <hr />
297
+
298
+ <div>
299
+ <a class="button-secondary" href="http://miled.github.io/wordpress-social-login/support.html" target="_blank"><?php _wsl_e( "Report as bug", 'wordpress-social-login' ) ?></a>
300
+ <a class="button-primary" href="options-general.php?page=wordpress-social-login&wslp=components" style="float:<?php if( is_rtl() ) echo 'left'; else echo 'right'; ?>"><?php _wsl_e( "Check enabled components", 'wordpress-social-login' ) ?></a>
301
+ </div>
302
+ </div>
303
+ <?php
304
+ // HOOKABLE:
305
+ do_action( "wsl_admin_ui_error_end" );
306
+ }
307
+
308
+ // --------------------------------------------------------------------
309
+
310
+ /**
311
+ * Renders WSL #FAIL page
312
+ */
313
+ function wsl_admin_ui_fail()
314
+ {
315
+ // HOOKABLE:
316
+ do_action( "wsl_admin_ui_fail_start" );
317
+ ?>
318
+ <div class="wsl-container">
319
+ <div style="background: none repeat scroll 0 0 #fff;border: 1px solid #e5e5e5;box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);padding:20px;">
320
+ <h1><?php _e("WordPress Social Login - FAIL!", 'wordpress-social-login') ?></h1>
321
+
322
+ <hr />
323
+
324
+ <p>
325
+ <?php _e('Despite the efforts, put into <b>WordPress Social Login</b> in terms of reliability, portability, and maintenance by the plugin <a href="http://profiles.wordpress.org/miled/" target="_blank">author</a> and <a href="https://github.com/hybridauth/WordPress-Social-Login/graphs/contributors" target="_blank">contributors</a>', 'wordpress-social-login') ?>.
326
+ <b style="color:red;"><?php _e('Your server failed the requirements check for this plugin', 'wordpress-social-login') ?>:</b>
327
+ </p>
328
+
329
+ <p>
330
+ <?php _e('These requirements are usually met by default by most "modern" web hosting providers, however some complications may occur with <b>shared hosting</b> and, or <b>custom wordpress installations</b>', 'wordpress-social-login') ?>.
331
+ </p>
332
+
333
+ <p>
334
+ <?php _wsl_e("The minimum server requirements are", 'wordpress-social-login') ?>:
335
+ </p>
336
+
337
+ <ul style="margin-left:60px;">
338
+ <li><?php _wsl_e("PHP >= 5.2.0 installed", 'wordpress-social-login') ?></li>
339
+ <li><?php _wsl_e("WSL Endpoint URLs reachable", 'wordpress-social-login') ?></li>
340
+ <li><?php _wsl_e("PHP's default SESSION handling", 'wordpress-social-login') ?></li>
341
+ <li><?php _wsl_e("PHP/CURL/SSL Extension enabled", 'wordpress-social-login') ?></li>
342
+ <li><?php _wsl_e("PHP/JSON Extension enabled", 'wordpress-social-login') ?></li>
343
+ <li><?php _wsl_e("PHP/REGISTER_GLOBALS Off", 'wordpress-social-login') ?></li>
344
+ <li><?php _wsl_e("jQuery installed on WordPress backoffice", 'wordpress-social-login') ?></li>
345
+ </ul>
346
+ </div>
347
+
348
+ <?php
349
+ include_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/admin/components/tools/wsl.components.tools.actions.job.php' );
350
+
351
+ wsl_component_tools_do_diagnostics();
352
+ ?>
353
+ </div>
354
+ <style>.wsl-container .button-secondary { display:none; }</style>
355
+ <?php
356
+ // HOOKABLE:
357
+ do_action( "wsl_admin_ui_fail_end" );
358
+ }
359
+
360
+ // --------------------------------------------------------------------
361
+
362
+ /**
363
+ * Renders wsl admin welcome panel
364
+ */
365
+ function wsl_admin_welcome_panel()
366
+ {
367
+ // Dissmiss WSL Welcome pannel
368
+ if( isset( $_REQUEST["wsldwp"] ) && (int) $_REQUEST["wsldwp"] === 1 )
369
+ {
370
+ update_option( "wsl_settings_welcome_panel_enabled", wsl_get_version() );
371
+
372
+ return;
373
+ }
374
+
375
+ // if new user or wsl updated, then we display wsl welcome panel
376
+ if( get_option( 'wsl_settings_welcome_panel_enabled' ) == wsl_get_version() )
377
+ {
378
+ return;
379
+ }
380
+
381
+ $wslp = "networks";
382
+
383
+ if( isset( $_REQUEST["wslp"] ) )
384
+ {
385
+ $wslp = $_REQUEST["wslp"];
386
+ }
387
+ ?>
388
+ <!--
389
+ if you want to know if a UI was made by developer, then here is a tip: he will always use tables
390
+
391
+ //> wsl-w-panel is shamelessly borrowed and modified from wordpress welcome-panel
392
+ -->
393
+ <div id="wsl-w-panel">
394
+ <a href="options-general.php?page=wordpress-social-login&wslp=<?php echo $wslp ?>&wsldwp=1" id="wsl-w-panel-dismiss" <?php if( is_rtl() ) echo 'style="left: 10px;right: auto;"'; ?>><?php _wsl_e("Dismiss", 'wordpress-social-login') ?></a>
395
+
396
+ <table width="100%" border="0" style="margin:0;padding:0;">
397
+ <tr>
398
+ <td width="10" valign="top"></td>
399
+ <td width="300" valign="top">
400
+ <b style="font-size: 16px;"><?php _wsl_e("Welcome!", 'wordpress-social-login') ?></b>
401
+ <p>
402
+ <?php _wsl_e("If you are still new to WordPress Social Login, we have provided a few walkthroughs to get you started", 'wordpress-social-login') ?>.
403
+ </p>
404
+ </td>
405
+ <td width="40" valign="top"></td>
406
+ <td width="260" valign="top">
407
+ <br />
408
+ <p>
409
+ <b><?php _wsl_e("Get Started", 'wordpress-social-login') ?></b>
410
+ </p>
411
+ <ul style="margin-left:25px;">
412
+ <li><a href="http://miled.github.io/wordpress-social-login/overview.html" target="_blank"><?php _wsl_e('Plugin Overview', 'wordpress-social-login') ?></a></li>
413
+ <li><a href="http://miled.github.io/wordpress-social-login/networks.html" target="_blank"><?php _wsl_e('Setup and Configuration', 'wordpress-social-login') ?></a></li>
414
+ <li><a href="http://miled.github.io/wordpress-social-login/widget.html" target="_blank"><?php _wsl_e('Customize WSL Widgets', 'wordpress-social-login') ?></a></li>
415
+ <li><a href="http://miled.github.io/wordpress-social-login/userdata.html" target="_blank"><?php _wsl_e('Manage users and contacts', 'wordpress-social-login') ?></a></li>
416
+ <li><a href="http://miled.github.io/wordpress-social-login/documentation.html" target="_blank"><?php _wsl_e('WSL Developer API', 'wordpress-social-login') ?></a></li>
417
+ </ul>
418
+ </td>
419
+ <td width="" valign="top">
420
+ <br />
421
+ <p>
422
+ <b><?php echo sprintf( _wsl__( "What's new on WSL %s", 'wordpress-social-login'), wsl_get_version() ) ?></b>
423
+ </p>
424
+
425
+ <ul style="margin-left:25px;">
426
+ <li><?php _wsl_e('WSL is now fully migrated to Hybridauth 3.5', 'wordpress-social-login') ?></li>
427
+ <li><?php _wsl_e("Reworked providers Callback URLs and it's a breaking change! See up top notice", 'wordpress-social-login') ?></li>
428
+ <li><?php _wsl_e('Added serval new providers: Amazon, Discord and Spotify to name a few', 'wordpress-social-login') ?></li>
429
+ <li><?php _wsl_e('Removal of a number of currently defunct identity providers ', 'wordpress-social-login') ?></li>
430
+ <li><?php _wsl_e('Authentication widgets and forms design overhall', 'wordpress-social-login') ?></li>
431
+ <li><?php _wsl_e('Various fixes and improvements', 'wordpress-social-login') ?></li>
432
+ </ul>
433
+ </td>
434
+ </tr>
435
+ <tr id="wsl-w-panel-updates-tr">
436
+ <td colspan="5" style="border-top:1px solid #ccc;" id="wsl-w-panel-updates-td">
437
+ &nbsp;
438
+ </td>
439
+ </tr>
440
+ </table>
441
+ </div>
442
+ <?php
443
+ }
444
+
445
+ // --------------------------------------------------------------------
446
+
447
+ /**
448
+ * Renders wsl localization note
449
+ */
450
+ function wsl_admin_help_us_localize_note()
451
+ {
452
+ return; // nothing, until I decide otherwise..
453
+
454
+ $assets_url = WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . 'assets/img/';
455
+
456
+ ?>
457
+ <div id="l10n-footer">
458
+ <br /><br />
459
+ <img src="<?php echo $assets_url ?>flags.png">
460
+ <a href="https://www.transifex.com/projects/p/wordpress-social-login/" target="_blank"><?php _wsl_e( "Help us translate WordPress Social Login into your language", 'wordpress-social-login' ) ?></a>
461
+ </div>
462
+ <?php
463
+ }
464
+
465
+ // --------------------------------------------------------------------
466
+
467
+ /**
468
+ * Renders an editor in a page in the typical fashion used in Posts and Pages.
469
+ * wp_editor was implemented in wp 3.3. if not found we fallback to a regular textarea
470
+ *
471
+ * Utility.
472
+ */
473
+ function wsl_render_wp_editor( $name, $content )
474
+ {
475
+ if( ! function_exists( 'wp_editor' ) )
476
+ {
477
+ ?>
478
+ <textarea style="width:100%;height:100px;margin-top:6px;" name="<?php echo $name ?>"><?php echo htmlentities( $content ); ?></textarea>
479
+ <?php
480
+ return;
481
+ }
482
+ ?>
483
+ <div class="postbox">
484
+ <div class="wp-editor-textarea" style="background-color: #FFFFFF;">
485
+ <?php
486
+ wp_editor(
487
+ $content, $name,
488
+ array( 'textarea_name' => $name, 'media_buttons' => true, 'tinymce' => array( 'theme_advanced_buttons1' => 'formatselect,forecolor,|,bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,link,unlink' ) )
489
+ );
490
+ ?>
491
+ </div>
492
+ </div>
493
+ <?php
494
+ }
495
+
496
+ // --------------------------------------------------------------------
497
+
498
+ /**
499
+ * Display WordPress Social Login on settings as submenu
500
+ */
501
+ function wsl_admin_menu()
502
+ {
503
+ add_options_page(
504
+ _wsl__( 'WP Social Login', 'wordpress-social-login' ),
505
+ _wsl__( 'WP Social Login', 'wordpress-social-login' ),
506
+ 'manage_options',
507
+ 'wordpress-social-login',
508
+ 'wsl_admin_main'
509
+ );
510
+
511
+ add_action( 'admin_init', 'wsl_register_setting' );
512
+ }
513
+
514
+ add_action('admin_menu', 'wsl_admin_menu' );
515
+
516
+ // --------------------------------------------------------------------
517
+
518
+ /**
519
+ * Enqueue WSL admin CSS file
520
+ */
521
+ function wsl_add_admin_stylesheets()
522
+ {
523
+ if( ! wp_style_is( 'wsl-admin', 'registered' ) )
524
+ {
525
+ wp_register_style( "wsl-admin", WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . "assets/css/admin.css" );
526
+ }
527
+
528
+ wp_enqueue_style( "wsl-admin" );
529
+ }
530
+
531
+ add_action( 'admin_enqueue_scripts', 'wsl_add_admin_stylesheets' );
532
+
533
+ // --------------------------------------------------------------------
includes/services/wsl.authentication.php CHANGED
@@ -1,1190 +1,1195 @@
1
- <?php
2
- /*!
3
- * WordPress Social Login
4
- *
5
- * https://miled.github.io/wordpress-social-login/ | https://github.com/miled/wordpress-social-login
6
- * (c) 2011-2020 Mohamed Mrassi and contributors | https://wordpress.org/plugins/wordpress-social-login/
7
- */
8
-
9
- /**
10
- * Authenticate users via social networks.
11
- *
12
- * Ref: http://miled.github.io/wordpress-social-login/developer-api-authentication.html
13
- **
14
- * Side note: I don't usually over-comment codes, but this is the main WSL script and I had to since
15
- * many users with diffrent "skill levels" may want to understand how this piece of code works.
16
- **
17
- * To sum things up, here is how WSL works (bit hard to explain, so bare with me):
18
- *
19
- * Let assume a user come to page at our website and he click on of the providers icons in order connect.
20
- *
21
- * - If &action=wordpress_social_authenticate is found in the current url, then WSL will display a loading screen,
22
- * - That loading screen will refresh it self adding &redirect_to_provider=ture to the url, which will trigger the next step,
23
- * - Next, WSL will instantiate Hybridauth main class, build the required provider config then initiate the auth protocol /hybridauth/?hauth.start=PROVIDER_ID,
24
- * - Hybridauth will redirect the user to the selected provider site to ask for his consent (authorisation to access his profile),
25
- * - If the user gives his authorisation for your application, the provider will redirect the user back to Hybridauth entry point /hybridauth/?hauth.done=PROVIDER_ID,
26
- * - Hybridauth will redirect the user to the given callback url.
27
- * - In that callback url, WSL will display a second loading screen This loading screen will generate and submit a form with a hidden input &action= wordpress_social_authenticated to the current url which will trigger the second part of the auth process,
28
- * - WSL will grab the user profile from the provider, attempt to identify him and create a new WordPress user if he doesn't exist. In this step, and when enabled, WSL will also import the user contacts and map his profile data to Buddypress xporfiles tables,
29
- * - Finally, WSL will authenticate the user within WordPress (give him a sweet cookie) and redirect him back to Redirect URL
30
- **
31
- * Functions execution order is the following:
32
- *
33
- * do_action('init')
34
- * . wsl_process_login()
35
- * . . wsl_process_login_begin()
36
- * . . . wsl_render_redirect_to_provider_loading_screen()
37
- * . . . Hybridauth\Hybridauth::authenticate()
38
- * . . . wsl_render_return_from_provider_loading_screen()
39
- * . .
40
- * . . wsl_process_login_end()
41
- * . . . wsl_process_login_get_user_data()
42
- * . . . . wsl_process_login_request_user_social_profile()
43
- * . . . . . Hybridauth\Hybridauth::getUserProfile()
44
- * . . . .
45
- * . . . . wsl_process_login_complete_registration()
46
- * . . .
47
- * . . . wsl_process_login_create_wp_user()
48
- * . . .
49
- * . . . wsl_process_login_update_wsl_user_data()
50
- * . . . . wsl_store_hybridauth_user_profile()
51
- * . . . . wsl_buddypress_xprofile_mapping()
52
- * . . . . wsl_store_hybridauth_user_contacts()
53
- * . . .
54
- * . . . wsl_process_login_authenticate_wp_user()
55
- */
56
-
57
- // Exit if accessed directly
58
- if( !defined( 'ABSPATH' ) ) exit;
59
-
60
- // --------------------------------------------------------------------
61
-
62
- /**
63
- * Entry point to the authentication process
64
- *
65
- * This function runs after WordPress has finished loading but before any headers are sent.
66
- * This function will analyse the current URL parameters and start the login process whenever an
67
- * WSL action is found: $_REQUEST['action'] eq wordpress_social_*
68
- *
69
- * Example of valid origin url:
70
- * wp-login.php
71
- * ?action=wordpress_social_authenticate // current step
72
- * &mode=login // auth mode
73
- * &provider=Twitter // selected provider
74
- * &redirect_to=http%3A%2F%2Fexample.com%2Fwordpress%2F%3Fp%3D1 // where the user come from
75
- *
76
- * Ref: http://codex.wordpress.org/Plugin_API/Action_Reference/init
77
- */
78
- function wsl_process_login()
79
- {
80
- // > check for wsl actions
81
- $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : null;
82
-
83
- if( ! in_array( $action, array( "wordpress_social_authenticate", "wordpress_social_profile_completion", "wordpress_social_account_linking", "wordpress_social_authenticated" ) ) )
84
- {
85
- return false;
86
- }
87
-
88
- require_once WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'hybridauth/library/src/autoload.php';
89
-
90
- // authentication mode
91
- $auth_mode = wsl_process_login_get_auth_mode();
92
-
93
- // start loggin the auth process, if debug mode is enabled
94
- wsl_watchdog_init();
95
-
96
- // halt, if mode login and user already logged in
97
- if( 'login' == $auth_mode && is_user_logged_in() )
98
- {
99
- $current_user = wp_get_current_user();
100
-
101
- return wsl_process_login_render_notice_page( sprintf( _wsl__( "You are already logged in as %s. Do you want to <a href='%s'>log out</a>?", 'wordpress-social-login' ), $current_user->display_name, wp_logout_url( home_url() ) ) );
102
- }
103
-
104
- // halt, if mode link and user not logged in
105
- if( 'link' == $auth_mode && ! is_user_logged_in() )
106
- {
107
- return wsl_process_login_render_notice_page( sprintf( _wsl__( "You have to be logged in to be able to link your existing account. Do you want to <a href='%s'>login</a>?", 'wordpress-social-login' ), wp_login_url( home_url() ) ) );
108
- }
109
-
110
- // halt, if mode test and not admin
111
- if( 'test' == $auth_mode && ! current_user_can('manage_options') )
112
- {
113
- return wsl_process_login_render_notice_page( _wsl__( 'You do not have sufficient permissions to access this page.', 'wordpress-social-login' ) );
114
- }
115
-
116
- // Bouncer :: Allow authentication?
117
- if( get_option( 'wsl_settings_bouncer_authentication_enabled' ) == 2 )
118
- {
119
- return wsl_process_login_render_notice_page( _wsl__( "Authentication through social networks is currently disabled.", 'wordpress-social-login' ) );
120
- }
121
-
122
- add_action( 'wsl_clear_user_php_session', 'wsl_process_login_clear_user_php_session' );
123
-
124
- // HOOKABLE:
125
- do_action( "wsl_process_login_start" );
126
-
127
- // if action=wordpress_social_authenticate
128
- // > start the first part of authentication (redirect the user to the selected provider)
129
- if( $action == "wordpress_social_authenticate" )
130
- {
131
- return wsl_process_login_begin();
132
- }
133
-
134
- // if action=wordpress_social_authenticated or action=wordpress_social_profile_completion
135
- // > finish the authentication process (create new user if doesn't exist in database, then log him in within wordpress)
136
- wsl_process_login_end();
137
- }
138
-
139
- add_action( 'init', 'wsl_process_login' );
140
-
141
- // --------------------------------------------------------------------
142
-
143
- /**
144
- * Start the first part of authentication
145
- *
146
- * Steps:
147
- * 1. Display a loading screen while hybridauth is redirecting the user to the selected provider
148
- * 2. Build the hybridauth config for the selected provider (keys, scope, etc)
149
- * 3. Instantiate the class Hybridauth\Hybridauth and redirect the user to provider to ask for authorisation for this website
150
- * 4. Display a loading screen after user come back from provider as we redirect the user back to Widget::Redirect URL
151
- */
152
- function wsl_process_login_begin()
153
- {
154
- // HOOKABLE:
155
- do_action( "wsl_process_login_begin_start" );
156
-
157
- $config = null;
158
- $hybridauth = null;
159
- $provider = null;
160
- $adapter = null;
161
-
162
- // check if php session are working as expected by wsl
163
- if( ! wsl_process_login_check_php_session() )
164
- {
165
- return wsl_process_login_render_notice_page( sprintf( _wsl__( 'The session identifier is missing.<br />For more information refer to WSL <a href="http://miled.github.io/wordpress-social-login/troubleshooting.html#session-error" target="_blank">Troubleshooting</a>.', 'wordpress-social-login' ), home_url() ) );
166
- }
167
-
168
- // HOOKABLE: selected provider name
169
- $provider = wsl_process_login_get_selected_provider();
170
-
171
- if( ! $provider )
172
- {
173
- return wsl_process_login_render_notice_page( _wsl__( 'Bouncer says this makes no sense.', 'wordpress-social-login' ) );
174
- }
175
-
176
- /* 1. Display a loading screen while hybridauth is redirecting the user to the selected provider */
177
-
178
- // the loading screen should refresh it self with a new arg in url: &redirect_to_provider=true
179
- if( ! isset( $_REQUEST["redirect_to_provider"] ) )
180
- {
181
- do_action( 'wsl_clear_user_php_session' );
182
-
183
- return wsl_render_redirect_to_provider_loading_screen( $provider );
184
- }
185
-
186
- /* 2. Build the hybridauth config for the selected provider (keys, scope, etc) */
187
-
188
- // provider enabled?
189
- if( ! get_option( 'wsl_settings_' . $provider . '_enabled' ) )
190
- {
191
- return wsl_process_login_render_notice_page( _wsl__( "Unknown or disabled provider.", 'wordpress-social-login' ) );
192
- }
193
-
194
- $config = wsl_process_login_build_provider_config( $provider );
195
-
196
- /* 3. Instantiate the class Hybridauth and redirect the user to provider to ask for authorisation for this website */
197
-
198
- // HOOKABLE:
199
- do_action( "wsl_hook_process_login_before_hybridauth_authenticate", $provider, $config );
200
-
201
- try
202
- {
203
- // create an instance oh hybridauth with the generated config
204
- $hybridauth = new Hybridauth\Hybridauth( $config );
205
-
206
- // start the authentication process via hybridauth
207
- // > if not already connected hybridauth::authenticate() will redirect the user to the provider
208
- // > where he will be asked for his consent (most providers ask for consent only once).
209
- // > after that, the provider will redirect the user back to this same page (and this same line).
210
- // > if the user is successfully connected to provider, then this time hybridauth::authenticate()
211
- // > will just return the provider adapter
212
- wsl_set_provider_config_in_session_storage( $provider, $config );
213
-
214
- $adapter = $hybridauth->authenticate( $provider );
215
- }
216
-
217
- // if hybridauth fails to authenticate the user, then we display an error message
218
- catch( Exception $e )
219
- {
220
- return wsl_process_login_render_error_page( $e, $config, $provider );
221
- }
222
-
223
- // HOOKABLE:
224
- do_action( "wsl_hook_process_login_after_hybridauth_authenticate", $provider, $config, $hybridauth, $adapter );
225
-
226
- /* 4. Display a loading screen after user come back from provider as we redirect the user back to Widget::Redirect URL */
227
-
228
- // get Widget::Authentication display
229
- $wsl_settings_use_popup = get_option( 'wsl_settings_use_popup' );
230
-
231
- // authentication mode
232
- $auth_mode = wsl_process_login_get_auth_mode();
233
-
234
- $redirect_to = isset( $_REQUEST[ 'redirect_to' ] ) ? $_REQUEST[ 'redirect_to' ] : home_url();
235
-
236
- // build the authenticateD, which will make wsl_process_login() fire the next step wsl_process_login_end()
237
- $authenticated_url = site_url( 'wp-login.php', 'login_post' ) . ( strpos( site_url( 'wp-login.php', 'login_post' ), '?' ) ? '&' : '?' ) . "action=wordpress_social_authenticated&provider=" . $provider . '&mode=' . $auth_mode;
238
-
239
- // display a loading screen
240
- return wsl_render_return_from_provider_loading_screen( $provider, $authenticated_url, $redirect_to, $wsl_settings_use_popup );
241
- }
242
-
243
- // --------------------------------------------------------------------
244
-
245
- /**
246
- * Finish the authentication process
247
- *
248
- * Steps:
249
- * 1. Get the user profile from provider
250
- * 2. Create new wordpress user if he didn't exist in database
251
- * 3. Store his Hybridauth profile, contacts and BP mapping
252
- * 4. Authenticate the user within wordpress
253
- */
254
- function wsl_process_login_end()
255
- {
256
- // HOOKABLE:
257
- do_action( "wsl_process_login_end_start" );
258
-
259
- // HOOKABLE: set a custom Redirect URL
260
- $redirect_to = wsl_process_login_get_redirect_to();
261
-
262
- // HOOKABLE: selected provider name
263
- $provider = wsl_process_login_get_selected_provider();
264
-
265
- // authentication mode
266
- $auth_mode = wsl_process_login_get_auth_mode();
267
-
268
- $is_new_user = false; // is it a new or returning user
269
- $user_id = '' ; // wp user id
270
- $adapter = '' ; // hybriauth adapter for the selected provider
271
- $hybridauth_user_profile = '' ; // hybriauth user profile
272
- $requested_user_login = '' ; // username typed by users in Profile Completion
273
- $requested_user_email = '' ; // email typed by users in Profile Completion
274
-
275
- // provider is enabled?
276
- if( ! get_option( 'wsl_settings_' . $provider . '_enabled' ) )
277
- {
278
- return wsl_process_login_render_notice_page( _wsl__( "Unknown or disabled provider.", 'wordpress-social-login' ) );
279
- }
280
-
281
- if( 'test' == $auth_mode )
282
- {
283
- $redirect_to = admin_url( 'options-general.php?page=wordpress-social-login&wslp=auth-paly&provider=' . $provider );
284
-
285
- return wp_safe_redirect( $redirect_to );
286
- }
287
-
288
- if( 'link' == $auth_mode )
289
- {
290
- // a social account cant be associated with more than one wordpress account.
291
-
292
- $hybridauth_user_profile = wsl_process_login_request_user_social_profile( $provider );
293
-
294
- $adapter = wsl_process_login_get_provider_adapter( $provider );
295
-
296
- $user_id = (int) wsl_get_stored_hybridauth_user_id_by_provider_and_provider_uid( $provider, $hybridauth_user_profile->identifier );
297
-
298
- if( $user_id && $user_id != get_current_user_id() )
299
- {
300
- return wsl_process_login_render_notice_page( sprintf( _wsl__( "Your <b>%s ID</b> is already linked to another account on this website.", 'wordpress-social-login'), $provider ) );
301
- }
302
-
303
- $user_id = get_current_user_id();
304
-
305
- // doesn't hurt to double check
306
- if( ! $user_id )
307
- {
308
- return wsl_process_login_render_notice_page( _wsl__( "Sorry, we couldn't link your account.", 'wordpress-social-login' ) );
309
- }
310
- }
311
- elseif( 'login' != $auth_mode )
312
- {
313
- return wsl_process_login_render_notice_page( _wsl__( 'Bouncer says no.', 'wordpress-social-login' ) );
314
- }
315
-
316
- if( 'login' == $auth_mode )
317
- {
318
- // returns user data after he authenticate via hybridauth
319
- list
320
- (
321
- $user_id ,
322
- $adapter ,
323
- $hybridauth_user_profile,
324
- $requested_user_login ,
325
- $requested_user_email ,
326
- $wordpress_user_id
327
- )
328
- = wsl_process_login_get_user_data( $provider, $redirect_to );
329
-
330
- // if no associated user were found in wslusersprofiles, create new WordPress user
331
- if( ! $wordpress_user_id )
332
- {
333
- $user_id = wsl_process_login_create_wp_user( $provider, $hybridauth_user_profile, $requested_user_login, $requested_user_email );
334
-
335
- $is_new_user = true;
336
- $redirect_to = apply_filters('wsl_redirect_after_registration', $redirect_to);
337
- }else{
338
- $user_id = $wordpress_user_id;
339
- $is_new_user = false;
340
- }
341
- }
342
-
343
- // if user is found in wslusersprofiles but the associated WP user account no longer exist
344
- // > this should never happen! but just in case: we delete the user wslusersprofiles/wsluserscontacts entries and we reset the process
345
- $wp_user = get_userdata( $user_id );
346
-
347
- if( ! $wp_user )
348
- {
349
- wsl_delete_stored_hybridauth_user_data( $user_id );
350
-
351
- return wsl_process_login_render_notice_page( sprintf( _wsl__( "Sorry, we couldn't connect you. <a href=\"%s\">Please try again</a>.", 'wordpress-social-login' ), site_url( 'wp-login.php', 'login_post' ) ) );
352
- }
353
-
354
- // store user hybridauth profile (wslusersprofiles), contacts (wsluserscontacts) and buddypress mapping
355
- wsl_process_login_update_wsl_user_data( $is_new_user, $user_id, $provider, $adapter, $hybridauth_user_profile, $wp_user );
356
-
357
- // finally create a wordpress session for the user
358
- wsl_process_login_authenticate_wp_user( $user_id, $provider, $redirect_to, $adapter, $hybridauth_user_profile, $wp_user );
359
- }
360
-
361
- // --------------------------------------------------------------------
362
-
363
- /**
364
- * Returns user data after he authenticate via hybridauth
365
- *
366
- * Steps:
367
- * 1. Grab the user profile from hybridauth
368
- * 2. Run Bouncer::Filters if enabled (domains, emails, profiles urls)
369
- * 3. Check if user exist in database by looking for the couple (Provider name, Provider user ID) or verified email
370
- * 4. Deletegate detection of user id to custom functions / hooks
371
- * 5. If Bouncer::Profile Completion is enabled and user didn't exist, we require the user to complete the registration (user name & email)
372
- */
373
- function wsl_process_login_get_user_data( $provider, $redirect_to )
374
- {
375
- // HOOKABLE:
376
- do_action( "wsl_process_login_get_user_data_start", $provider, $redirect_to );
377
-
378
- $user_id = null;
379
- $config = null;
380
- $hybridauth = null;
381
- $adapter = null;
382
- $hybridauth_user_profile = null;
383
- $requested_user_login = '';
384
- $requested_user_email = '';
385
- $wordpress_user_id = 0;
386
-
387
- /* 1. Grab the user profile from social network */
388
-
389
- if( ! ( isset( $_SESSION['wsl::userprofile'] ) && $_SESSION['wsl::userprofile'] && $hybridauth_user_profile = json_decode( $_SESSION['wsl::userprofile'] ) ) )
390
- {
391
- $hybridauth_user_profile = wsl_process_login_request_user_social_profile( $provider );
392
-
393
- $_SESSION['wsl::userprofile'] = json_encode( $hybridauth_user_profile );
394
- }
395
-
396
- $adapter = wsl_process_login_get_provider_adapter( $provider );
397
-
398
- $hybridauth_user_email = sanitize_email( $hybridauth_user_profile->email );
399
- $hybridauth_user_email_verified = sanitize_email( $hybridauth_user_profile->emailVerified );
400
-
401
- /* 2. Run Bouncer::Filters if enabled (domains, emails, profiles urls) */
402
-
403
- // Bouncer::Filters by emails domains name
404
- if( get_option( 'wsl_settings_bouncer_new_users_restrict_domain_enabled' ) == 1 )
405
- {
406
- if( empty( $hybridauth_user_email ) )
407
- {
408
- return wsl_process_login_render_notice_page( _wsl__( get_option( 'wsl_settings_bouncer_new_users_restrict_domain_text_bounce' ), 'wordpress-social-login') );
409
- }
410
-
411
- $list = get_option( 'wsl_settings_bouncer_new_users_restrict_domain_list' );
412
- $list = preg_split( '/$\R?^/m', $list );
413
-
414
- $current = strstr( $hybridauth_user_email, '@' );
415
-
416
- $shall_pass = false;
417
-
418
- foreach( $list as $item )
419
- {
420
- if( trim( strtolower( "@$item" ) ) == strtolower( $current ) )
421
- {
422
- $shall_pass = true;
423
- }
424
- }
425
-
426
- if( ! $shall_pass )
427
- {
428
- return wsl_process_login_render_notice_page( _wsl__( get_option( 'wsl_settings_bouncer_new_users_restrict_domain_text_bounce' ), 'wordpress-social-login') );
429
- }
430
- }
431
-
432
- // Bouncer::Filters by e-mails addresses
433
- if( get_option( 'wsl_settings_bouncer_new_users_restrict_email_enabled' ) == 1 )
434
- {
435
- error_log(__METHOD__ . ' start wsl_settings_bouncer_new_users_restrict_email_enabled.');
436
- error_log(__METHOD__ . ' hybridauth_user_email is ' . $hybridauth_user_email );
437
- if( empty( $hybridauth_user_email ) )
438
- {
439
- return wsl_process_login_render_notice_page( _wsl__( get_option( 'wsl_settings_bouncer_new_users_restrict_email_text_bounce' ), 'wordpress-social-login') );
440
- }
441
-
442
- $list = get_option( 'wsl_settings_bouncer_new_users_restrict_email_list' );
443
- $list = preg_split( '/$\R?^/m', $list );
444
-
445
- $shall_pass = false;
446
-
447
- foreach( $list as $item )
448
- {
449
- if( trim( strtolower( $item ) ) == strtolower( $hybridauth_user_email ) )
450
- {
451
- $shall_pass = true;
452
- }
453
- }
454
-
455
- if( ! $shall_pass )
456
- {
457
- return wsl_process_login_render_notice_page( _wsl__( get_option( 'wsl_settings_bouncer_new_users_restrict_email_text_bounce' ), 'wordpress-social-login') );
458
- }
459
- }
460
-
461
- // Bouncer::Filters by profile urls
462
- if( get_option( 'wsl_settings_bouncer_new_users_restrict_profile_enabled' ) == 1 )
463
- {
464
- error_log(__METHOD__ . ' start restrict_profile_enabled.');
465
- $list = get_option( 'wsl_settings_bouncer_new_users_restrict_profile_list' );
466
- $list = preg_split( '/$\R?^/m', $list );
467
- error_log(__METHOD__ . ' $list is ' . print_r($list, true));
468
-
469
- $shall_pass = false;
470
-
471
- foreach( $list as $item )
472
- {
473
- error_log(__METHOD__ . ' $item is ' . $item );
474
- error_log(__METHOD__ . ' $hybridauth_user_profile->profileURL is ' . $hybridauth_user_profile->profileURL);
475
- if( trim( strtolower( $item ) ) == strtolower( $hybridauth_user_profile->profileURL ) )
476
- {
477
- $shall_pass = true;
478
- }
479
- }
480
-
481
- if( ! $shall_pass )
482
- {
483
- return wsl_process_login_render_notice_page( _wsl__( get_option( 'wsl_settings_bouncer_new_users_restrict_profile_text_bounce' ), 'wordpress-social-login') );
484
- }
485
- }
486
-
487
- /* 3. Check if user exist in database by looking for the couple (Provider name, Provider user ID) or verified email */
488
-
489
- // check if user already exist in wslusersprofiles
490
- $user_id = (int) wsl_get_stored_hybridauth_user_id_by_provider_and_provider_uid( $provider, $hybridauth_user_profile->identifier );
491
-
492
- // if not found in wslusersprofiles, then check his verified email
493
- if( ! $user_id && ! empty( $hybridauth_user_email_verified ) )
494
- {
495
- // check if the verified email exist in wp_users
496
- $user_id = (int) wsl_wp_email_exists( $hybridauth_user_email_verified );
497
-
498
- // check if the verified email exist in wslusersprofiles
499
- if( ! $user_id )
500
- {
501
- $user_id = (int) wsl_get_stored_hybridauth_user_id_by_email_verified( $hybridauth_user_email_verified );
502
- }
503
-
504
- // if the user exists in Wordpress
505
- if( $user_id )
506
- {
507
- $wordpress_user_id = $user_id;
508
- }
509
- }
510
-
511
- /* 4 Deletegate detection of user id to custom filters hooks */
512
-
513
- // HOOKABLE:
514
- $user_id = apply_filters( 'wsl_hook_process_login_alter_user_id', $user_id, $provider, $hybridauth_user_profile );
515
-
516
- /* 5. If Bouncer::Profile Completion is enabled and user didn't exist, we require the user to complete the registration (user name & email) */
517
- if( ! $user_id )
518
- {
519
- // Bouncer :: Accept new registrations?
520
- if( get_option( 'wsl_settings_bouncer_registration_enabled' ) == 2
521
- && ( get_option( 'wsl_settings_bouncer_authentication_enabled' ) == 2 || get_option( 'wsl_settings_bouncer_accounts_linking_enabled' ) == 2 ) )
522
- {
523
- return wsl_process_login_render_notice_page( _wsl__( "Registration is now closed.", 'wordpress-social-login' ) );
524
- }
525
-
526
- // Bouncer::Accounts linking/mapping
527
- // > > not implemented yet! Planned for WSL 2.3
528
- if( get_option( 'wsl_settings_bouncer_accounts_linking_enabled' ) == 1 )
529
- {
530
- do
531
- {
532
- list
533
- (
534
- $shall_pass,
535
- $user_id,
536
- $requested_user_login,
537
- $requested_user_email
538
- )
539
- = wsl_process_login_new_users_gateway( $provider, $redirect_to, $hybridauth_user_profile );
540
- }
541
- while( ! $shall_pass );
542
- $wordpress_user_id = $user_id;
543
- }
544
-
545
- // Bouncer::Profile Completion
546
- // > > in WSL 2.3 Profile Completion will be reworked and merged with Accounts linking
547
- elseif( ( get_option( 'wsl_settings_bouncer_profile_completion_require_email' ) == 1 && empty( $hybridauth_user_email ) )
548
- || get_option( 'wsl_settings_bouncer_profile_completion_change_username' ) == 1 )
549
- {
550
- do
551
- {
552
- list
553
- (
554
- $shall_pass,
555
- $user_id,
556
- $requested_user_login,
557
- $requested_user_email
558
- )
559
- = wsl_process_login_new_users_gateway( $provider, $redirect_to, $hybridauth_user_profile );
560
- }
561
- while( ! $shall_pass );
562
- }
563
-
564
- }else{
565
- $wordpress_user_id = $user_id;
566
- }
567
-
568
- /* 6. returns user data */
569
-
570
- return array(
571
- $user_id,
572
- $adapter,
573
- $hybridauth_user_profile,
574
- $requested_user_login,
575
- $requested_user_email,
576
- $wordpress_user_id
577
- );
578
- }
579
-
580
- // --------------------------------------------------------------------
581
-
582
- /**
583
- * Create a new wordpress user
584
- *
585
- * Ref: http://codex.wordpress.org/Function_Reference/wp_insert_user
586
- */
587
- function wsl_process_login_create_wp_user( $provider, $hybridauth_user_profile, $requested_user_login, $requested_user_email )
588
- {
589
- // HOOKABLE:
590
- do_action( "wsl_process_login_create_wp_user_start", $provider, $hybridauth_user_profile, $requested_user_login, $requested_user_email );
591
-
592
- $user_login = '';
593
- $user_email = '';
594
-
595
- // if coming from "complete registration form"
596
- if( $requested_user_login )
597
- {
598
- $user_login = $requested_user_login;
599
- }
600
-
601
- if( $requested_user_email )
602
- {
603
- $user_email = $requested_user_email;
604
- }
605
-
606
- if( ! $user_login )
607
- {
608
- // attempt to generate user_login from hybridauth user profile display name
609
- $user_login = $hybridauth_user_profile->displayName;
610
-
611
- // sanitize user login
612
- $user_login = sanitize_user( $user_login, true );
613
-
614
- // remove spaces and dots
615
- $user_login = trim( str_replace( array( ' ', '.' ), '_', $user_login ) );
616
- $user_login = trim( str_replace( '__', '_', $user_login ) );
617
-
618
- // if user profile display name is not provided
619
- if( empty( $user_login ) )
620
- {
621
- // may be that $user_email is empty then we got wp error login can't be empty, so check it now
622
- if ( $user_email ) {
623
- $user_login = sanitize_user( current( explode( '@', $user_email ) ), true );
624
- } else {
625
- $user_login = sanitize_user( current( explode( '@', $hybridauth_user_profile->email ) ), true );
626
- }
627
- }
628
- }
629
-
630
- // user name should be unique
631
- if( username_exists( $user_login ) )
632
- {
633
- $i = 1;
634
- $user_login_tmp = $user_login;
635
-
636
- do
637
- {
638
- $user_login_tmp = $user_login . "_" . ($i++);
639
- }
640
- while( username_exists ($user_login_tmp));
641
-
642
- $user_login = $user_login_tmp;
643
- }
644
-
645
- if( ! $user_email )
646
- {
647
- $user_email = $hybridauth_user_profile->email;
648
-
649
- // generate an email if none
650
- if( ! isset ( $user_email ) OR ! is_email( $user_email ) )
651
- {
652
- $user_email = strtolower( $provider . "_user_" . $user_login ) . '@example.com';
653
- }
654
-
655
- // email should be unique
656
- if( wsl_wp_email_exists ( $user_email ) )
657
- {
658
- do
659
- {
660
- $user_email = md5( uniqid( wp_rand( 10000, 99000 ) ) ) . '@example.com';
661
- }
662
- while( wsl_wp_email_exists( $user_email ) );
663
- }
664
- }
665
-
666
- $display_name = $hybridauth_user_profile->displayName;
667
-
668
- if( empty( $display_name ) )
669
- {
670
- $display_name = $hybridauth_user_profile->firstName;
671
- }
672
-
673
- if( empty( $display_name ) )
674
- {
675
- $display_name = strtolower( $provider ) . "_user";
676
- }
677
-
678
- $userdata = array(
679
- 'user_login' => $user_login,
680
- 'user_email' => $user_email,
681
-
682
- 'display_name' => $display_name,
683
-
684
- 'first_name' => $hybridauth_user_profile->firstName,
685
- 'last_name' => $hybridauth_user_profile->lastName,
686
- 'user_url' => $hybridauth_user_profile->profileURL,
687
- 'description' => $hybridauth_user_profile->description,
688
-
689
- 'user_pass' => wp_generate_password()
690
- );
691
-
692
- // Bouncer::Membership level
693
- $wsl_settings_bouncer_new_users_membership_default_role = get_option( 'wsl_settings_bouncer_new_users_membership_default_role' );
694
-
695
- // if level eq "default", we set role to wp default user role
696
- if( $wsl_settings_bouncer_new_users_membership_default_role == "default" )
697
- {
698
- $userdata['role'] = get_option('default_role');
699
- }
700
-
701
- // if level not eq "default" or 'wslnorole' nor empty, we set role to the selected role in bouncer settings
702
- elseif( $wsl_settings_bouncer_new_users_membership_default_role && $wsl_settings_bouncer_new_users_membership_default_role != 'wslnorole' )
703
- {
704
- $userdata['role'] = $wsl_settings_bouncer_new_users_membership_default_role;
705
- }
706
-
707
- // Bouncer::User Moderation
708
- // > if Bouncer::User Moderation is enabled (Yield to Theme My Login), then we overwrite the user role to 'pending'
709
- # http://www.jfarthing.com/development/theme-my-login/user-moderation/
710
- if( get_option( 'wsl_settings_bouncer_new_users_moderation_level' ) > 100 )
711
- {
712
- $userdata['role'] = "pending";
713
- }
714
-
715
- // HOOKABLE: change the user data
716
- $userdata = apply_filters( 'wsl_hook_process_login_alter_wp_insert_user_data', $userdata, $provider, $hybridauth_user_profile );
717
-
718
- // DEPRECIATED: as of 2.2.3
719
- // $userdata = apply_filters( 'wsl_hook_process_login_alter_userdata', $userdata, $provider, $hybridauth_user_profile );
720
-
721
- // HOOKABLE: This action runs just before creating a new wordpress user.
722
- do_action( 'wsl_hook_process_login_before_wp_insert_user', $userdata, $provider, $hybridauth_user_profile );
723
-
724
- // DEPRECIATED: as of 2.2.3
725
- // do_action( 'wsl_hook_process_login_before_insert_user', $userdata, $provider, $hybridauth_user_profile );
726
-
727
- // HOOKABLE: This action runs just before creating a new wordpress user, it delegate user insert to a custom function.
728
- $user_id = apply_filters( 'wsl_hook_process_login_delegate_wp_insert_user', $userdata, $provider, $hybridauth_user_profile );
729
-
730
- // Create a new WordPress user
731
- if( ! $user_id || ! is_integer( $user_id ) )
732
- {
733
- $user_id = wp_insert_user( $userdata );
734
- }
735
-
736
- // do not continue without user_id
737
- if( ! $user_id || ! is_integer( $user_id ) )
738
- {
739
- if( is_wp_error( $user_id ) )
740
- {
741
- return wsl_process_login_render_notice_page( _wsl__( "An error occurred while creating a new user: ", 'wordpress-social-login' ) . $user_id->get_error_message() );
742
- }
743
-
744
- return wsl_process_login_render_notice_page( _wsl__( "An error occurred while creating a new user!", 'wordpress-social-login' ) );
745
- }
746
-
747
- // wp_insert_user may fail on first and last name meta, expliciting setting to correct.
748
- update_user_meta($user_id, 'first_name', apply_filters( 'pre_user_first_name',$userdata['first_name']));
749
- update_user_meta($user_id, 'last_name', apply_filters( 'pre_user_last_name', $userdata['last_name']));
750
-
751
- // Send notifications
752
- if( get_option( 'wsl_settings_users_notification' ) == 1 )
753
- {
754
- wsl_admin_notification( $user_id, $provider );
755
- }
756
-
757
- // HOOKABLE: This action runs just after a wordpress user has been created
758
- // > Note: At this point, the user has been added to wordpress database, but NOT CONNECTED.
759
- do_action( 'wsl_hook_process_login_after_wp_insert_user', $user_id, $provider, $hybridauth_user_profile );
760
-
761
- // DEPRECIATED: as of 2.2.3
762
- // do_action( 'wsl_hook_process_login_after_create_wp_user', $user_id, $provider, $hybridauth_user_profile );
763
-
764
- // returns the user created user id
765
- return $user_id;
766
- }
767
-
768
- // --------------------------------------------------------------------
769
-
770
- /**
771
- * Store WSL user data
772
- *
773
- * Steps:
774
- * 1. Store Hybridauth user profile
775
- * 2. Import user contacts
776
- * 3. Launch BuddyPress Profile mapping
777
- */
778
- function wsl_process_login_update_wsl_user_data( $is_new_user, $user_id, $provider, $adapter, $hybridauth_user_profile, $wp_user )
779
- {
780
- // HOOKABLE:
781
- do_action( "wsl_process_login_update_wsl_user_data_start", $is_new_user, $user_id, $provider, $adapter, $hybridauth_user_profile, $wp_user );
782
-
783
- // store user hybridauth user profile in table wslusersprofiles
784
- // > wsl will only sotre the user profile if it has changed since last login.
785
- wsl_store_hybridauth_user_profile( $user_id, $provider, $hybridauth_user_profile );
786
-
787
- // map hybridauth user profile to buddypress xprofile table, if enabled
788
- // > Profile mapping will only work with new users. Profile mapping for returning users will implemented in future version of WSL.
789
- if( $is_new_user )
790
- {
791
- wsl_buddypress_xprofile_mapping( $user_id, $provider, $hybridauth_user_profile );
792
- }
793
-
794
- // import user contacts into wslusersprofiles, if enabled
795
- // > wsl will only import the contacts list once per user per provider.
796
- wsl_store_hybridauth_user_contacts( $user_id, $provider, $adapter );
797
- }
798
-
799
- // --------------------------------------------------------------------
800
-
801
- /**
802
- * Authenticate a user within wordpress
803
- *
804
- * Ref: http://codex.wordpress.org/Function_Reference/wp_set_auth_cookie
805
- * Ref: http://codex.wordpress.org/Function_Reference/wp_safe_redirect
806
- */
807
- function wsl_process_login_authenticate_wp_user( $user_id, $provider, $redirect_to, $adapter, $hybridauth_user_profile, $wp_user )
808
- {
809
- // HOOKABLE:
810
- do_action( "wsl_process_login_authenticate_wp_user_start", $user_id, $provider, $redirect_to, $adapter, $hybridauth_user_profile, $wp_user );
811
-
812
- // update some fields in usermeta for the current user
813
- update_user_meta( $user_id, 'wsl_current_provider', $provider );
814
-
815
- if( $hybridauth_user_profile->photoURL )
816
- {
817
- update_user_meta( $user_id, 'wsl_current_user_image', $hybridauth_user_profile->photoURL );
818
- }
819
-
820
- // Bouncer::User Moderation
821
- // > When Bouncer::User Moderation is enabled, WSL will check for the current user role. If equal to 'pending', then Bouncer will do the following :
822
- // 1. Halt the authentication process,
823
- // 2. Skip setting the authentication cookies for the user,
824
- // 3. Reset the Redirect URL to the appropriate Theme My Login page.
825
- $wsl_settings_bouncer_new_users_moderation_level = get_option( 'wsl_settings_bouncer_new_users_moderation_level' );
826
-
827
- // current user role
828
- $role = current( $wp_user->roles );
829
-
830
- // if role eq 'pending', we halt the authentication and we redirect the user to the appropriate url (pending=activation or pending=approval)
831
- if( $role == 'pending' )
832
- {
833
- // E-mail Confirmation
834
- if( $wsl_settings_bouncer_new_users_moderation_level == 101 )
835
- {
836
- $redirect_to = site_url( 'wp-login.php', 'login_post' ) . ( strpos( site_url( 'wp-login.php', 'login_post' ), '?' ) ? '&' : '?' ) . "pending=activation";
837
-
838
- // send a new e-mail/activation notification - if TML not enabled, we ensure WSL to keep it quiet
839
- $errors = new WP_Error();
840
- do_action( 'register_post', $wp_user->user_nicename, $wp_user->user_email, $errors );
841
- @ Theme_My_Login_User_Moderation::new_user_activation_notification( $user_id );
842
- }
843
-
844
- // Admin Approval
845
- elseif( $wsl_settings_bouncer_new_users_moderation_level == 102 )
846
- {
847
- $redirect_to = site_url( 'wp-login.php', 'login_post' ) . ( strpos( site_url( 'wp-login.php', 'login_post' ), '?' ) ? '&' : '?' ) . "pending=approval";
848
- }
849
- }
850
-
851
- // otherwise, we connect the user with in wordpress (we give him a cookie)
852
- else
853
- {
854
- // HOOKABLE: This action runs just before logging the user in (before creating a WP cookie)
855
- do_action( "wsl_hook_process_login_before_wp_set_auth_cookie", $user_id, $provider, $hybridauth_user_profile );
856
-
857
- // DEPRECIATED: as of 2.2.3
858
- // do_action( 'wsl_hook_process_login_before_set_auth_cookie', $user_id, $provider, $hybridauth_user_profile );
859
-
860
- // Set WP auth cookie
861
- wp_set_auth_cookie( $user_id, true );
862
-
863
- // let keep it std
864
- do_action( 'wp_login', $wp_user->user_login, $wp_user );
865
- }
866
-
867
- // HOOKABLE: This action runs just before redirecting the user back to $redirect_to
868
- // > Note: If you have enabled User Moderation, then the user is NOT NECESSARILY CONNECTED
869
- // > within wordpress at this point (in case the user $role == 'pending').
870
- // > To be sure the user is connected, use wsl_hook_process_login_before_wp_set_auth_cookie instead.
871
- do_action( "wsl_hook_process_login_before_wp_safe_redirect", $user_id, $provider, $hybridauth_user_profile, $redirect_to );
872
-
873
- // DEPRECIATED: as of 2.2.3
874
- // do_action( 'wsl_hook_process_login_before_set_auth_cookie', $user_id, $provider, $hybridauth_user_profile );
875
-
876
- do_action( 'wsl_clear_user_php_session' );
877
-
878
- // Display WSL debugging instead of redirecting the user
879
- // > this will give a complete report on what wsl did : database queries and fired hooks
880
- // wsl_display_dev_mode_debugging_area(); die(); // ! keep this line commented unless you know what you are doing :)
881
-
882
- // That's it. We done.
883
- wp_safe_redirect( $redirect_to );
884
-
885
- // for good measures
886
- die();
887
- }
888
-
889
- // --------------------------------------------------------------------
890
-
891
- /**
892
- * Build required hybridauth configuration for the given provider
893
- */
894
- function wsl_process_login_build_provider_config( $provider )
895
- {
896
- require_once WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'hybridauth/library/src/autoload.php';
897
-
898
- $config = array();
899
- $config["current_page"] = Hybridauth\HttpClient\Util::getCurrentUrl(true);
900
- $config["callback"] = WORDPRESS_SOCIAL_LOGIN_HYBRIDAUTH_ENDPOINT_URL . 'callbacks/' . strtolower( $provider ) . '.php';
901
- $config["providers"] = array();
902
- $config["providers"][$provider] = array();
903
- $config["providers"][$provider]["enabled"] = true;
904
- $config["providers"][$provider]["keys"] = array( 'id' => null, 'key' => null, 'secret' => null );
905
-
906
- // provider application id ?
907
- if( get_option( 'wsl_settings_' . $provider . '_app_id' ) )
908
- {
909
- $config["providers"][$provider]["keys"]["id"] = get_option( 'wsl_settings_' . $provider . '_app_id' );
910
- }
911
-
912
- // provider application key ?
913
- if( get_option( 'wsl_settings_' . $provider . '_app_key' ) )
914
- {
915
- $config["providers"][$provider]["keys"]["key"] = get_option( 'wsl_settings_' . $provider . '_app_key' );
916
- }
917
-
918
- // provider application secret ?
919
- if( get_option( 'wsl_settings_' . $provider . '_app_secret' ) )
920
- {
921
- $config["providers"][$provider]["keys"]["secret"] = get_option( 'wsl_settings_' . $provider . '_app_secret' );
922
- }
923
-
924
- // set custom config for facebook
925
- if( strtolower( $provider ) == "facebook" )
926
- {
927
- $config["providers"][$provider]["display"] = "popup";
928
- $config["providers"][$provider]["trustForwarded"] = true;
929
-
930
- // switch to fb::display 'page' if wsl auth in page
931
- if( get_option( 'wsl_settings_use_popup') == 2 )
932
- {
933
- $config["providers"][$provider]["display"] = "page";
934
- }
935
-
936
- $config["providers"][$provider]["scope"] = "email, public_profile";
937
- }
938
-
939
- // set custom config for google
940
- if( strtolower( $provider ) == "google" )
941
- {
942
- $config["providers"][$provider]["scope"] = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email";
943
- }
944
-
945
- // set custom config for linkedin
946
- if( strtolower( $provider ) == "linkedin" )
947
- {
948
- $config["providers"][$provider]["scope"] = "r_liteprofile r_emailaddress";
949
- }
950
-
951
- $provider_scope = isset( $config["providers"][$provider]["scope"] ) ? $config["providers"][$provider]["scope"] : '' ;
952
-
953
- // HOOKABLE: allow to overwrite scopes
954
- $config["providers"][$provider]["scope"] = apply_filters( 'wsl_hook_alter_provider_scope', $provider_scope, $provider );
955
-
956
- // HOOKABLE: allow to overwrite hybridauth config for the selected provider
957
- $config["providers"][$provider] = apply_filters( 'wsl_hook_alter_provider_config', $config["providers"][$provider], $provider );
958
-
959
- return $config;
960
- }
961
-
962
- // --------------------------------------------------------------------
963
-
964
- /**
965
- * Grab the user profile from social network
966
- */
967
- function wsl_process_login_request_user_social_profile( $provider )
968
- {
969
- $adapter = null;
970
- $config = null;
971
- $hybridauth_user_profile = null;
972
-
973
- try
974
- {
975
- // get idp adapter
976
- $adapter = wsl_process_login_get_provider_adapter( $provider );
977
-
978
- $config = wsl_get_provider_config_from_session_storage( $provider );
979
-
980
- // if user authenticated successfully with social network
981
- if( $adapter->isConnected() )
982
- {
983
- // grab user profile via hybridauth api
984
- $hybridauth_user_profile = $adapter->getUserProfile();
985
- }
986
-
987
- // if user not connected to provider (ie: session lost, url forged)
988
- else
989
- {
990
- return wsl_process_login_render_notice_page( sprintf( _wsl__( "Sorry, we couldn't connect you with <b>%s</b>. <a href=\"%s\">Please try again</a>.", 'wordpress-social-login' ), $provider, site_url( 'wp-login.php', 'login_post' ) ) );
991
- }
992
- }
993
-
994
- // if things didn't go as expected, we dispay the appropriate error message
995
- catch( Exception $e )
996
- {
997
- return wsl_process_login_render_error_page( $e, $config, $provider, $adapter );
998
- }
999
-
1000
- return $hybridauth_user_profile;
1001
- }
1002
-
1003
- // --------------------------------------------------------------------
1004
-
1005
- /**
1006
- * Returns hybriauth idp adapter.
1007
- */
1008
- function wsl_process_login_get_provider_adapter( $provider )
1009
- {
1010
- require_once WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'hybridauth/library/src/autoload.php';
1011
-
1012
- $config = wsl_get_provider_config_from_session_storage( $provider );
1013
-
1014
- $hybridauth = new Hybridauth\Hybridauth( $config );
1015
-
1016
- return $hybridauth->getAdapter( $provider );
1017
- }
1018
-
1019
- // --------------------------------------------------------------------
1020
-
1021
- /**
1022
- * Returns redirect_to (callback url)
1023
- *
1024
- * By default, once a user authenticate, he will be automatically redirected to the page where he come from (referer).
1025
- * If WSL wasn't able to identify the referer url (or if the user come wp-login.php), then they will be redirected to
1026
- * Widget::Redirect URL instead.
1027
- *
1028
- * When Widget::Force redirection is set to Yes, users will be always redirected to Widget::Redirect URL.
1029
- *
1030
- * Note: Widget::Redirect URL can be customised using the filter 'wsl_hook_process_login_alter_redirect_to'
1031
- */
1032
- function wsl_process_login_get_redirect_to()
1033
- {
1034
- // force redirection?
1035
- $wsl_settings_redirect_url = get_option( 'wsl_settings_redirect_url' );
1036
-
1037
- if( get_option( 'wsl_settings_force_redirect_url' ) == 1 )
1038
- {
1039
- $redirect_to = apply_filters( 'wsl_hook_process_login_alter_redirect_to', $wsl_settings_redirect_url );
1040
-
1041
- return $redirect_to;
1042
- }
1043
-
1044
- // get a valid $redirect_to
1045
- if( isset( $_REQUEST[ 'redirect_to' ] ) && $_REQUEST[ 'redirect_to' ] != '' )
1046
- {
1047
- $redirect_to = $_REQUEST[ 'redirect_to' ];
1048
-
1049
- // we don't go there..
1050
- if( strpos( $redirect_to, 'wp-admin') )
1051
- {
1052
- $redirect_to = $wsl_settings_redirect_url;
1053
- }
1054
-
1055
- // nor there..
1056
- if( strpos( $redirect_to, 'wp-login.php') )
1057
- {
1058
- $redirect_to = $wsl_settings_redirect_url;
1059
- }
1060
- }
1061
-
1062
- if( empty( $redirect_to ) )
1063
- {
1064
- $redirect_to = $wsl_settings_redirect_url;
1065
- }
1066
-
1067
- if( empty( $redirect_to ) )
1068
- {
1069
- $redirect_to = home_url();
1070
- }
1071
-
1072
- $redirect_to = apply_filters( 'wsl_hook_process_login_alter_redirect_to', $redirect_to );
1073
-
1074
- return $redirect_to;
1075
- }
1076
-
1077
- // --------------------------------------------------------------------
1078
-
1079
- /**
1080
- * Display an error message in case user authentication fails
1081
- */
1082
- function wsl_process_login_render_error_page( $e, $config = null, $provider = null, $adapter = null )
1083
- {
1084
- // HOOKABLE:
1085
- do_action( "wsl_process_login_render_error_page", $e, $config, $provider, $adapter );
1086
-
1087
- $assets_base_url = WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . 'assets/img/';
1088
-
1089
- $message = "";
1090
- $notes = "";
1091
- $apierror = substr( $e->getMessage(), 0, 256 );
1092
-
1093
- if( is_object( $adapter ) )
1094
- {
1095
- $adapter->disconnect();
1096
- }
1097
-
1098
- return wsl_render_error_page( $message, $notes, $provider, $apierror, $e );
1099
- }
1100
-
1101
- // --------------------------------------------------------------------
1102
-
1103
- /**
1104
- * Display an notice message
1105
- */
1106
- function wsl_process_login_render_notice_page( $message )
1107
- {
1108
- // HOOKABLE:
1109
- do_action( "wsl_process_login_render_notice_page", $message );
1110
-
1111
- return wsl_render_notice_page( $message );
1112
- }
1113
-
1114
- // --------------------------------------------------------------------
1115
-
1116
- /**
1117
- * Returns the selected provider from _REQUEST, default to null
1118
- */
1119
- function wsl_process_login_get_selected_provider()
1120
- {
1121
- $provider = isset( $_REQUEST["provider"] ) ? sanitize_text_field( $_REQUEST["provider"] ) : null;
1122
-
1123
- return apply_filters( 'wsl_hook_process_login_alter_provider', $provider ) ;
1124
- }
1125
-
1126
- // --------------------------------------------------------------------
1127
-
1128
- /**
1129
- * Returns the selected auth mode from _REQUEST, default to login
1130
- */
1131
- function wsl_process_login_get_auth_mode()
1132
- {
1133
- $auth_mode = isset( $_REQUEST["mode"] ) ? sanitize_text_field( $_REQUEST["mode"] ) : 'login';
1134
-
1135
- return apply_filters( 'wsl_hook_process_login_alter_auth_mode', $auth_mode ) ;
1136
- }
1137
-
1138
- // --------------------------------------------------------------------
1139
-
1140
- /**
1141
- * Clear the stored data by hybridauth and wsl in php session
1142
- */
1143
- function wsl_process_login_clear_user_php_session()
1144
- {
1145
- $_SESSION["HYBRIDAUTH::STORAGE"] = array(); // used by hybridauth library. to clear as soon as the auth process ends.
1146
- $_SESSION["wsl::userprofile"] = array(); // used by wsl to temporarily store the user profile so we don't make unnecessary calls to social apis.
1147
- }
1148
-
1149
- // --------------------------------------------------------------------
1150
-
1151
- /**
1152
- * Returns IDP actual name
1153
- */
1154
- function wsl_get_provider_name_by_id( $provider_id)
1155
- {
1156
- global $WORDPRESS_SOCIAL_LOGIN_PROVIDERS_CONFIG;
1157
-
1158
- foreach( $WORDPRESS_SOCIAL_LOGIN_PROVIDERS_CONFIG as $provider_settings ) {
1159
- if ( $provider_settings['provider_id'] == $provider_id ) {
1160
- return $provider_name = $provider_settings['provider_name'];
1161
- }
1162
- }
1163
-
1164
- return $provider_id;
1165
- }
1166
-
1167
- // --------------------------------------------------------------------
1168
-
1169
- /**
1170
- * Check Php session
1171
- */
1172
- function wsl_process_login_check_php_session()
1173
- {
1174
- if( isset( $_SESSION["wsl::plugin"] ) && $_SESSION["wsl::plugin"] )
1175
- {
1176
- return true;
1177
- }
1178
- }
1179
-
1180
- // --------------------------------------------------------------------
1181
-
1182
- /**
1183
- * Returns redirect url for when a new account was created
1184
- */
1185
- function wsl_new_register_redirect_url($redirect_to) {
1186
- return $redirect_to;
1187
- }
1188
- add_filter("wsl_redirect_after_registration", "wsl_new_register_redirect_url", 10, 1);
1189
-
1190
- // --------------------------------------------------------------------
 
 
 
 
 
1
+ <?php
2
+ /*!
3
+ * WordPress Social Login
4
+ *
5
+ * https://miled.github.io/wordpress-social-login/ | https://github.com/miled/wordpress-social-login
6
+ * (c) 2011-2020 Mohamed Mrassi and contributors | https://wordpress.org/plugins/wordpress-social-login/
7
+ */
8
+
9
+ /**
10
+ * Authenticate users via social networks.
11
+ *
12
+ * Ref: http://miled.github.io/wordpress-social-login/developer-api-authentication.html
13
+ **
14
+ * Side note: I don't usually over-comment codes, but this is the main WSL script and I had to since
15
+ * many users with diffrent "skill levels" may want to understand how this piece of code works.
16
+ **
17
+ * To sum things up, here is how WSL works (bit hard to explain, so bare with me):
18
+ *
19
+ * Let assume a user come to page at our website and he click on of the providers icons in order connect.
20
+ *
21
+ * - If &action=wordpress_social_authenticate is found in the current url, then WSL will display a loading screen,
22
+ * - That loading screen will refresh it self adding &redirect_to_provider=ture to the url, which will trigger the next step,
23
+ * - Next, WSL will instantiate Hybridauth main class, build the required provider config then initiate the auth protocol /hybridauth/?hauth.start=PROVIDER_ID,
24
+ * - Hybridauth will redirect the user to the selected provider site to ask for his consent (authorisation to access his profile),
25
+ * - If the user gives his authorisation for your application, the provider will redirect the user back to Hybridauth entry point /hybridauth/?hauth.done=PROVIDER_ID,
26
+ * - Hybridauth will redirect the user to the given callback url.
27
+ * - In that callback url, WSL will display a second loading screen This loading screen will generate and submit a form with a hidden input &action= wordpress_social_authenticated to the current url which will trigger the second part of the auth process,
28
+ * - WSL will grab the user profile from the provider, attempt to identify him and create a new WordPress user if he doesn't exist. In this step, and when enabled, WSL will also import the user contacts and map his profile data to Buddypress xporfiles tables,
29
+ * - Finally, WSL will authenticate the user within WordPress (give him a sweet cookie) and redirect him back to Redirect URL
30
+ **
31
+ * Functions execution order is the following:
32
+ *
33
+ * do_action('init')
34
+ * . wsl_process_login()
35
+ * . . wsl_process_login_begin()
36
+ * . . . wsl_render_redirect_to_provider_loading_screen()
37
+ * . . . Hybridauth\Hybridauth::authenticate()
38
+ * . . . wsl_render_return_from_provider_loading_screen()
39
+ * . .
40
+ * . . wsl_process_login_end()
41
+ * . . . wsl_process_login_get_user_data()
42
+ * . . . . wsl_process_login_request_user_social_profile()
43
+ * . . . . . Hybridauth\Hybridauth::getUserProfile()
44
+ * . . . .
45
+ * . . . . wsl_process_login_complete_registration()
46
+ * . . .
47
+ * . . . wsl_process_login_create_wp_user()
48
+ * . . .
49
+ * . . . wsl_process_login_update_wsl_user_data()
50
+ * . . . . wsl_store_hybridauth_user_profile()
51
+ * . . . . wsl_buddypress_xprofile_mapping()
52
+ * . . . . wsl_store_hybridauth_user_contacts()
53
+ * . . .
54
+ * . . . wsl_process_login_authenticate_wp_user()
55
+ */
56
+
57
+ // Exit if accessed directly
58
+ if( !defined( 'ABSPATH' ) ) exit;
59
+
60
+ // --------------------------------------------------------------------
61
+
62
+ /**
63
+ * Entry point to the authentication process
64
+ *
65
+ * This function runs after WordPress has finished loading but before any headers are sent.
66
+ * This function will analyse the current URL parameters and start the login process whenever an
67
+ * WSL action is found: $_REQUEST['action'] eq wordpress_social_*
68
+ *
69
+ * Example of valid origin url:
70
+ * wp-login.php
71
+ * ?action=wordpress_social_authenticate // current step
72
+ * &mode=login // auth mode
73
+ * &provider=Twitter // selected provider
74
+ * &redirect_to=http%3A%2F%2Fexample.com%2Fwordpress%2F%3Fp%3D1 // where the user come from
75
+ *
76
+ * Ref: http://codex.wordpress.org/Plugin_API/Action_Reference/init
77
+ */
78
+ function wsl_process_login()
79
+ {
80
+ // > check for wsl actions
81
+ $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : null;
82
+
83
+ if( ! in_array( $action, array( "wordpress_social_authenticate", "wordpress_social_profile_completion", "wordpress_social_account_linking", "wordpress_social_authenticated" ) ) )
84
+ {
85
+ return false;
86
+ }
87
+
88
+ require_once WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'hybridauth/library/src/autoload.php';
89
+
90
+ // authentication mode
91
+ $auth_mode = wsl_process_login_get_auth_mode();
92
+
93
+ // start loggin the auth process, if debug mode is enabled
94
+ wsl_watchdog_init();
95
+
96
+ // halt, if mode login and user already logged in
97
+ if( 'login' == $auth_mode && is_user_logged_in() )
98
+ {
99
+ $current_user = wp_get_current_user();
100
+
101
+ return wsl_process_login_render_notice_page( sprintf( _wsl__( "You are already logged in as %s. Do you want to <a href='%s'>log out</a>?", 'wordpress-social-login' ), $current_user->display_name, wp_logout_url( home_url() ) ) );
102
+ }
103
+
104
+ // halt, if mode link and user not logged in
105
+ if( 'link' == $auth_mode && ! is_user_logged_in() )
106
+ {
107
+ return wsl_process_login_render_notice_page( sprintf( _wsl__( "You have to be logged in to be able to link your existing account. Do you want to <a href='%s'>login</a>?", 'wordpress-social-login' ), wp_login_url( home_url() ) ) );
108
+ }
109
+
110
+ // halt, if mode test and not admin
111
+ if( 'test' == $auth_mode && ! current_user_can('manage_options') )
112
+ {
113
+ return wsl_process_login_render_notice_page( _wsl__( 'You do not have sufficient permissions to access this page.', 'wordpress-social-login' ) );
114
+ }
115
+
116
+ // Bouncer :: Allow authentication?
117
+ if( get_option( 'wsl_settings_bouncer_authentication_enabled' ) == 2 )
118
+ {
119
+ return wsl_process_login_render_notice_page( _wsl__( "Authentication through social networks is currently disabled.", 'wordpress-social-login' ) );
120
+ }
121
+
122
+ add_action( 'wsl_clear_user_php_session', 'wsl_process_login_clear_user_php_session' );
123
+
124
+ // HOOKABLE:
125
+ do_action( "wsl_process_login_start" );
126
+
127
+ // if action=wordpress_social_authenticate
128
+ // > start the first part of authentication (redirect the user to the selected provider)
129
+ if( $action == "wordpress_social_authenticate" )
130
+ {
131
+ return wsl_process_login_begin();
132
+ }
133
+
134
+ // if action=wordpress_social_authenticated or action=wordpress_social_profile_completion
135
+ // > finish the authentication process (create new user if doesn't exist in database, then log him in within wordpress)
136
+ wsl_process_login_end();
137
+ }
138
+
139
+ add_action( 'init', 'wsl_process_login' );
140
+
141
+ // --------------------------------------------------------------------
142
+
143
+ /**
144
+ * Start the first part of authentication
145
+ *
146
+ * Steps:
147
+ * 1. Display a loading screen while hybridauth is redirecting the user to the selected provider
148
+ * 2. Build the hybridauth config for the selected provider (keys, scope, etc)
149
+ * 3. Instantiate the class Hybridauth\Hybridauth and redirect the user to provider to ask for authorisation for this website
150
+ * 4. Display a loading screen after user come back from provider as we redirect the user back to Widget::Redirect URL
151
+ */
152
+ function wsl_process_login_begin()
153
+ {
154
+ // HOOKABLE:
155
+ do_action( "wsl_process_login_begin_start" );
156
+
157
+ $config = null;
158
+ $hybridauth = null;
159
+ $provider = null;
160
+ $adapter = null;
161
+
162
+ // check if php session are working as expected by wsl
163
+ if( ! wsl_process_login_check_php_session() )
164
+ {
165
+ return wsl_process_login_render_notice_page( sprintf( _wsl__( 'The session identifier is missing.<br />For more information refer to WSL <a href="http://miled.github.io/wordpress-social-login/troubleshooting.html#session-error" target="_blank">Troubleshooting</a>.', 'wordpress-social-login' ), home_url() ) );
166
+ }
167
+
168
+ // HOOKABLE: selected provider name
169
+ $provider = wsl_process_login_get_selected_provider();
170
+
171
+ if( ! $provider )
172
+ {
173
+ return wsl_process_login_render_notice_page( _wsl__( 'Bouncer says this makes no sense.', 'wordpress-social-login' ) );
174
+ }
175
+
176
+ /* 1. Display a loading screen while hybridauth is redirecting the user to the selected provider */
177
+
178
+ // the loading screen should refresh it self with a new arg in url: &redirect_to_provider=true
179
+ if( ! isset( $_REQUEST["redirect_to_provider"] ) )
180
+ {
181
+ do_action( 'wsl_clear_user_php_session' );
182
+
183
+ return wsl_render_redirect_to_provider_loading_screen( $provider );
184
+ }
185
+
186
+ /* 2. Build the hybridauth config for the selected provider (keys, scope, etc) */
187
+
188
+ // provider enabled?
189
+ if( ! get_option( 'wsl_settings_' . $provider . '_enabled' ) )
190
+ {
191
+ return wsl_process_login_render_notice_page( _wsl__( "Unknown or disabled provider.", 'wordpress-social-login' ) );
192
+ }
193
+
194
+ $config = wsl_process_login_build_provider_config( $provider );
195
+
196
+ /* 3. Instantiate the class Hybridauth and redirect the user to provider to ask for authorisation for this website */
197
+
198
+ // HOOKABLE:
199
+ do_action( "wsl_hook_process_login_before_hybridauth_authenticate", $provider, $config );
200
+
201
+ try
202
+ {
203
+ // create an instance oh hybridauth with the generated config
204
+ $hybridauth = new Hybridauth\Hybridauth( $config );
205
+
206
+ // start the authentication process via hybridauth
207
+ // > if not already connected hybridauth::authenticate() will redirect the user to the provider
208
+ // > where he will be asked for his consent (most providers ask for consent only once).
209
+ // > after that, the provider will redirect the user back to this same page (and this same line).
210
+ // > if the user is successfully connected to provider, then this time hybridauth::authenticate()
211
+ // > will just return the provider adapter
212
+ wsl_set_provider_config_in_session_storage( $provider, $config );
213
+
214
+ $adapter = $hybridauth->authenticate( $provider );
215
+ }
216
+
217
+ // if hybridauth fails to authenticate the user, then we display an error message
218
+ catch( Exception $e )
219
+ {
220
+ return wsl_process_login_render_error_page( $e, $config, $provider );
221
+ }
222
+
223
+ // HOOKABLE:
224
+ do_action( "wsl_hook_process_login_after_hybridauth_authenticate", $provider, $config, $hybridauth, $adapter );
225
+
226
+ /* 4. Display a loading screen after user come back from provider as we redirect the user back to Widget::Redirect URL */
227
+
228
+ // get Widget::Authentication display
229
+ $wsl_settings_use_popup = get_option( 'wsl_settings_use_popup' );
230
+
231
+ // authentication mode
232
+ $auth_mode = wsl_process_login_get_auth_mode();
233
+
234
+ $redirect_to = isset( $_REQUEST[ 'redirect_to' ] ) ? $_REQUEST[ 'redirect_to' ] : home_url();
235
+
236
+ // build the authenticateD, which will make wsl_process_login() fire the next step wsl_process_login_end()
237
+ $authenticated_url = site_url( 'wp-login.php', 'login_post' ) . ( strpos( site_url( 'wp-login.php', 'login_post' ), '?' ) ? '&' : '?' ) . "action=wordpress_social_authenticated&provider=" . $provider . '&mode=' . $auth_mode;
238
+
239
+ // display a loading screen
240
+ return wsl_render_return_from_provider_loading_screen( $provider, $authenticated_url, $redirect_to, $wsl_settings_use_popup );
241
+ }
242
+
243
+ // --------------------------------------------------------------------
244
+
245
+ /**
246
+ * Finish the authentication process
247
+ *
248
+ * Steps:
249
+ * 1. Get the user profile from provider
250
+ * 2. Create new wordpress user if he didn't exist in database
251
+ * 3. Store his Hybridauth profile, contacts and BP mapping
252
+ * 4. Authenticate the user within wordpress
253
+ */
254
+ function wsl_process_login_end()
255
+ {
256
+ // HOOKABLE:
257
+ do_action( "wsl_process_login_end_start" );
258
+
259
+ // HOOKABLE: set a custom Redirect URL
260
+ $redirect_to = wsl_process_login_get_redirect_to();
261
+
262
+ // HOOKABLE: selected provider name
263
+ $provider = wsl_process_login_get_selected_provider();
264
+
265
+ // authentication mode
266
+ $auth_mode = wsl_process_login_get_auth_mode();
267
+
268
+ $is_new_user = false; // is it a new or returning user
269
+ $user_id = '' ; // wp user id
270
+ $adapter = '' ; // hybriauth adapter for the selected provider
271
+ $hybridauth_user_profile = '' ; // hybriauth user profile
272
+ $requested_user_login = '' ; // username typed by users in Profile Completion
273
+ $requested_user_email = '' ; // email typed by users in Profile Completion
274
+
275
+ // provider is enabled?
276
+ if( ! get_option( 'wsl_settings_' . $provider . '_enabled' ) )
277
+ {
278
+ return wsl_process_login_render_notice_page( _wsl__( "Unknown or disabled provider.", 'wordpress-social-login' ) );
279
+ }
280
+
281
+ if( 'test' == $auth_mode )
282
+ {
283
+ $redirect_to = admin_url( 'options-general.php?page=wordpress-social-login&wslp=auth-paly&provider=' . $provider );
284
+
285
+ return wp_safe_redirect( $redirect_to );
286
+ }
287
+
288
+ if( 'link' == $auth_mode )
289
+ {
290
+ // a social account cant be associated with more than one wordpress account.
291
+
292
+ $hybridauth_user_profile = wsl_process_login_request_user_social_profile( $provider );
293
+
294
+ $adapter = wsl_process_login_get_provider_adapter( $provider );
295
+
296
+ $user_id = (int) wsl_get_stored_hybridauth_user_id_by_provider_and_provider_uid( $provider, $hybridauth_user_profile->identifier );
297
+
298
+ if( $user_id && $user_id != get_current_user_id() )
299
+ {
300
+ return wsl_process_login_render_notice_page( sprintf( _wsl__( "Your <b>%s ID</b> is already linked to another account on this website.", 'wordpress-social-login'), $provider ) );
301
+ }
302
+
303
+ $user_id = get_current_user_id();
304
+
305
+ // doesn't hurt to double check
306
+ if( ! $user_id )
307
+ {
308
+ return wsl_process_login_render_notice_page( _wsl__( "Sorry, we couldn't link your account.", 'wordpress-social-login' ) );
309
+ }
310
+ }
311
+ elseif( 'login' != $auth_mode )
312
+ {
313
+ return wsl_process_login_render_notice_page( _wsl__( 'Bouncer says no.', 'wordpress-social-login' ) );
314
+ }
315
+
316
+ if( 'login' == $auth_mode )
317
+ {
318
+ // returns user data after he authenticate via hybridauth
319
+ list
320
+ (
321
+ $user_id ,
322
+ $adapter ,
323
+ $hybridauth_user_profile,
324
+ $requested_user_login ,
325
+ $requested_user_email ,
326
+ $wordpress_user_id
327
+ )
328
+ = wsl_process_login_get_user_data( $provider, $redirect_to );
329
+
330
+ // if no associated user were found in wslusersprofiles, create new WordPress user
331
+ if( ! $wordpress_user_id )
332
+ {
333
+ $user_id = wsl_process_login_create_wp_user( $provider, $hybridauth_user_profile, $requested_user_login, $requested_user_email );
334
+
335
+ $is_new_user = true;
336
+ $redirect_to = apply_filters('wsl_redirect_after_registration', $redirect_to);
337
+ }else{
338
+ $user_id = $wordpress_user_id;
339
+ $is_new_user = false;
340
+ }
341
+ }
342
+
343
+ // if user is found in wslusersprofiles but the associated WP user account no longer exist
344
+ // > this should never happen! but just in case: we delete the user wslusersprofiles/wsluserscontacts entries and we reset the process
345
+ $wp_user = get_userdata( $user_id );
346
+
347
+ if( ! $wp_user )
348
+ {
349
+ wsl_delete_stored_hybridauth_user_data( $user_id );
350
+
351
+ return wsl_process_login_render_notice_page( sprintf( _wsl__( "Sorry, we couldn't connect you. <a href=\"%s\">Please try again</a>.", 'wordpress-social-login' ), site_url( 'wp-login.php', 'login_post' ) ) );
352
+ }
353
+
354
+ // store user hybridauth profile (wslusersprofiles), contacts (wsluserscontacts) and buddypress mapping
355
+ wsl_process_login_update_wsl_user_data( $is_new_user, $user_id, $provider, $adapter, $hybridauth_user_profile, $wp_user );
356
+
357
+ // finally create a wordpress session for the user
358
+ wsl_process_login_authenticate_wp_user( $user_id, $provider, $redirect_to, $adapter, $hybridauth_user_profile, $wp_user );
359
+ }
360
+
361
+ // --------------------------------------------------------------------
362
+
363
+ /**
364
+ * Returns user data after he authenticate via hybridauth
365
+ *
366
+ * Steps:
367
+ * 1. Grab the user profile from hybridauth
368
+ * 2. Run Bouncer::Filters if enabled (domains, emails, profiles urls)
369
+ * 3. Check if user exist in database by looking for the couple (Provider name, Provider user ID) or verified email
370
+ * 4. Deletegate detection of user id to custom functions / hooks
371
+ * 5. If Bouncer::Profile Completion is enabled and user didn't exist, we require the user to complete the registration (user name & email)
372
+ */
373
+ function wsl_process_login_get_user_data( $provider, $redirect_to )
374
+ {
375
+ // HOOKABLE:
376
+ do_action( "wsl_process_login_get_user_data_start", $provider, $redirect_to );
377
+
378
+ $user_id = null;
379
+ $config = null;
380
+ $hybridauth = null;
381
+ $adapter = null;
382
+ $hybridauth_user_profile = null;
383
+ $requested_user_login = '';
384
+ $requested_user_email = '';
385
+ $wordpress_user_id = 0;
386
+
387
+ /* 1. Grab the user profile from social network */
388
+
389
+ if( ! ( isset( $_SESSION['wsl::userprofile'] ) && $_SESSION['wsl::userprofile'] && $hybridauth_user_profile = json_decode( $_SESSION['wsl::userprofile'] ) ) )
390
+ {
391
+ $hybridauth_user_profile = wsl_process_login_request_user_social_profile( $provider );
392
+
393
+ $_SESSION['wsl::userprofile'] = json_encode( $hybridauth_user_profile );
394
+ }
395
+
396
+ $adapter = wsl_process_login_get_provider_adapter( $provider );
397
+
398
+ $hybridauth_user_email = sanitize_email( $hybridauth_user_profile->email );
399
+ $hybridauth_user_email_verified = sanitize_email( $hybridauth_user_profile->emailVerified );
400
+
401
+ /* 2. Run Bouncer::Filters if enabled (domains, emails, profiles urls) */
402
+
403
+ // Bouncer::Filters by emails domains name
404
+ if( get_option( 'wsl_settings_bouncer_new_users_restrict_domain_enabled' ) == 1 )
405
+ {
406
+ if( empty( $hybridauth_user_email ) )
407
+ {
408
+ return wsl_process_login_render_notice_page( _wsl__( get_option( 'wsl_settings_bouncer_new_users_restrict_domain_text_bounce' ), 'wordpress-social-login') );
409
+ }
410
+
411
+ $list = get_option( 'wsl_settings_bouncer_new_users_restrict_domain_list' );
412
+ $list = preg_split( '/$\R?^/m', $list );
413
+
414
+ $current = strstr( $hybridauth_user_email, '@' );
415
+
416
+ $shall_pass = false;
417
+
418
+ foreach( $list as $item )
419
+ {
420
+ if( trim( strtolower( "@$item" ) ) == strtolower( $current ) )
421
+ {
422
+ $shall_pass = true;
423
+ }
424
+ }
425
+
426
+ if( ! $shall_pass )
427
+ {
428
+ return wsl_process_login_render_notice_page( _wsl__( get_option( 'wsl_settings_bouncer_new_users_restrict_domain_text_bounce' ), 'wordpress-social-login') );
429
+ }
430
+ }
431
+
432
+ // Bouncer::Filters by e-mails addresses
433
+ if( get_option( 'wsl_settings_bouncer_new_users_restrict_email_enabled' ) == 1 )
434
+ {
435
+ error_log(__METHOD__ . ' start wsl_settings_bouncer_new_users_restrict_email_enabled.');
436
+ error_log(__METHOD__ . ' hybridauth_user_email is ' . $hybridauth_user_email );
437
+ if( empty( $hybridauth_user_email ) )
438
+ {
439
+ return wsl_process_login_render_notice_page( _wsl__( get_option( 'wsl_settings_bouncer_new_users_restrict_email_text_bounce' ), 'wordpress-social-login') );
440
+ }
441
+
442
+ $list = get_option( 'wsl_settings_bouncer_new_users_restrict_email_list' );
443
+ $list = preg_split( '/$\R?^/m', $list );
444
+
445
+ $shall_pass = false;
446
+
447
+ foreach( $list as $item )
448
+ {
449
+ if( trim( strtolower( $item ) ) == strtolower( $hybridauth_user_email ) )
450
+ {
451
+ $shall_pass = true;
452
+ }
453
+ }
454
+
455
+ if( ! $shall_pass )
456
+ {
457
+ return wsl_process_login_render_notice_page( _wsl__( get_option( 'wsl_settings_bouncer_new_users_restrict_email_text_bounce' ), 'wordpress-social-login') );
458
+ }
459
+ }
460
+
461
+ // Bouncer::Filters by profile urls
462
+ if( get_option( 'wsl_settings_bouncer_new_users_restrict_profile_enabled' ) == 1 )
463
+ {
464
+ error_log(__METHOD__ . ' start restrict_profile_enabled.');
465
+ $list = get_option( 'wsl_settings_bouncer_new_users_restrict_profile_list' );
466
+ $list = preg_split( '/$\R?^/m', $list );
467
+ error_log(__METHOD__ . ' $list is ' . print_r($list, true));
468
+
469
+ $shall_pass = false;
470
+
471
+ foreach( $list as $item )
472
+ {
473
+ error_log(__METHOD__ . ' $item is ' . $item );
474
+ error_log(__METHOD__ . ' $hybridauth_user_profile->profileURL is ' . $hybridauth_user_profile->profileURL);
475
+ if( trim( strtolower( $item ) ) == strtolower( $hybridauth_user_profile->profileURL ) )
476
+ {
477
+ $shall_pass = true;
478
+ }
479
+ }
480
+
481
+ if( ! $shall_pass )
482
+ {
483
+ return wsl_process_login_render_notice_page( _wsl__( get_option( 'wsl_settings_bouncer_new_users_restrict_profile_text_bounce' ), 'wordpress-social-login') );
484
+ }
485
+ }
486
+
487
+ /* 3. Check if user exist in database by looking for the couple (Provider name, Provider user ID) or verified email */
488
+
489
+ // check if user already exist in wslusersprofiles
490
+ $user_id = (int) wsl_get_stored_hybridauth_user_id_by_provider_and_provider_uid( $provider, $hybridauth_user_profile->identifier );
491
+
492
+ // if not found in wslusersprofiles, then check his verified email
493
+ if( ! $user_id && ! empty( $hybridauth_user_email_verified ) )
494
+ {
495
+ // check if the verified email exist in wp_users
496
+ $user_id = (int) wsl_wp_email_exists( $hybridauth_user_email_verified );
497
+
498
+ // check if the verified email exist in wslusersprofiles
499
+ if( ! $user_id )
500
+ {
501
+ $user_id = (int) wsl_get_stored_hybridauth_user_id_by_email_verified( $hybridauth_user_email_verified );
502
+ }
503
+
504
+ // if the user exists in Wordpress
505
+ if( $user_id )
506
+ {
507
+ $wordpress_user_id = $user_id;
508
+ }
509
+ }
510
+
511
+ /* 4 Deletegate detection of user id to custom filters hooks */
512
+
513
+ // HOOKABLE:
514
+ $user_id = apply_filters( 'wsl_hook_process_login_alter_user_id', $user_id, $provider, $hybridauth_user_profile );
515
+
516
+ /* 5. If Bouncer::Profile Completion is enabled and user didn't exist, we require the user to complete the registration (user name & email) */
517
+ if( ! $user_id )
518
+ {
519
+ // Bouncer :: Accept new registrations?
520
+ if( get_option( 'wsl_settings_bouncer_registration_enabled' ) == 2
521
+ && ( get_option( 'wsl_settings_bouncer_authentication_enabled' ) == 2 || get_option( 'wsl_settings_bouncer_accounts_linking_enabled' ) == 2 ) )
522
+ {
523
+ return wsl_process_login_render_notice_page( _wsl__( "Registration is now closed.", 'wordpress-social-login' ) );
524
+ }
525
+
526
+ // Bouncer::Accounts linking/mapping
527
+ // > > not implemented yet! Planned for WSL 2.3
528
+ if( get_option( 'wsl_settings_bouncer_accounts_linking_enabled' ) == 1 )
529
+ {
530
+ do
531
+ {
532
+ list
533
+ (
534
+ $shall_pass,
535
+ $user_id,
536
+ $requested_user_login,
537
+ $requested_user_email
538
+ )
539
+ = wsl_process_login_new_users_gateway( $provider, $redirect_to, $hybridauth_user_profile );
540
+ }
541
+ while( ! $shall_pass );
542
+ $wordpress_user_id = $user_id;
543
+ }
544
+
545
+ // Bouncer::Profile Completion
546
+ // > > in WSL 2.3 Profile Completion will be reworked and merged with Accounts linking
547
+ elseif( ( get_option( 'wsl_settings_bouncer_profile_completion_require_email' ) == 1 && empty( $hybridauth_user_email ) )
548
+ || get_option( 'wsl_settings_bouncer_profile_completion_change_username' ) == 1 )
549
+ {
550
+ do
551
+ {
552
+ list
553
+ (
554
+ $shall_pass,
555
+ $user_id,
556
+ $requested_user_login,
557
+ $requested_user_email
558
+ )
559
+ = wsl_process_login_new_users_gateway( $provider, $redirect_to, $hybridauth_user_profile );
560
+ }
561
+ while( ! $shall_pass );
562
+ }
563
+
564
+ }else{
565
+ $wordpress_user_id = $user_id;
566
+ }
567
+
568
+ /* 6. returns user data */
569
+
570
+ return array(
571
+ $user_id,
572
+ $adapter,
573
+ $hybridauth_user_profile,
574
+ $requested_user_login,
575
+ $requested_user_email,
576
+ $wordpress_user_id
577
+ );
578
+ }
579
+
580
+ // --------------------------------------------------------------------
581
+
582
+ /**
583
+ * Create a new wordpress user
584
+ *
585
+ * Ref: http://codex.wordpress.org/Function_Reference/wp_insert_user
586
+ */
587
+ function wsl_process_login_create_wp_user( $provider, $hybridauth_user_profile, $requested_user_login, $requested_user_email )
588
+ {
589
+ // HOOKABLE:
590
+ do_action( "wsl_process_login_create_wp_user_start", $provider, $hybridauth_user_profile, $requested_user_login, $requested_user_email );
591
+
592
+ $user_login = '';
593
+ $user_email = '';
594
+
595
+ // if coming from "complete registration form"
596
+ if( $requested_user_login )
597
+ {
598
+ $user_login = $requested_user_login;
599
+ }
600
+
601
+ if( $requested_user_email )
602
+ {
603
+ $user_email = $requested_user_email;
604
+ }
605
+
606
+ if( ! $user_login )
607
+ {
608
+ // attempt to generate user_login from hybridauth user profile display name
609
+ $user_login = $hybridauth_user_profile->displayName;
610
+
611
+ // sanitize user login
612
+ $user_login = sanitize_user( $user_login, true );
613
+
614
+ // remove spaces and dots
615
+ $user_login = trim( str_replace( array( ' ', '.' ), '_', $user_login ) );
616
+ $user_login = trim( str_replace( '__', '_', $user_login ) );
617
+
618
+ // if user profile display name is not provided
619
+ if( empty( $user_login ) )
620
+ {
621
+ // may be that $user_email is empty then we got wp error login can't be empty, so check it now
622
+ if ( $user_email ) {
623
+ $user_login = sanitize_user( current( explode( '@', $user_email ) ), true );
624
+ } else {
625
+ $user_login = sanitize_user( current( explode( '@', $hybridauth_user_profile->email ) ), true );
626
+ }
627
+ }
628
+ }
629
+
630
+ // user name should be unique
631
+ if( username_exists( $user_login ) )
632
+ {
633
+ $i = 1;
634
+ $user_login_tmp = $user_login;
635
+
636
+ do
637
+ {
638
+ $user_login_tmp = $user_login . "_" . ($i++);
639
+ }
640
+ while( username_exists ($user_login_tmp));
641
+
642
+ $user_login = $user_login_tmp;
643
+ }
644
+
645
+ if( ! $user_email )
646
+ {
647
+ $user_email = $hybridauth_user_profile->email;
648
+
649
+ // generate an email if none
650
+ if( ! isset ( $user_email ) OR ! is_email( $user_email ) )
651
+ {
652
+ $user_email = strtolower( $provider . "_user_" . $user_login ) . '@example.com';
653
+ }
654
+
655
+ // email should be unique
656
+ if( wsl_wp_email_exists ( $user_email ) )
657
+ {
658
+ do
659
+ {
660
+ $user_email = md5( uniqid( wp_rand( 10000, 99000 ) ) ) . '@example.com';
661
+ }
662
+ while( wsl_wp_email_exists( $user_email ) );
663
+ }
664
+ }
665
+
666
+ $display_name = $hybridauth_user_profile->displayName;
667
+
668
+ if( empty( $display_name ) )
669
+ {
670
+ $display_name = $hybridauth_user_profile->firstName;
671
+ }
672
+
673
+ if( empty( $display_name ) )
674
+ {
675
+ $display_name = strtolower( $provider ) . "_user";
676
+ }
677
+
678
+ $userdata = array(
679
+ 'user_login' => $user_login,
680
+ 'user_email' => $user_email,
681
+
682
+ 'display_name' => $display_name,
683
+
684
+ 'first_name' => $hybridauth_user_profile->firstName,
685
+ 'last_name' => $hybridauth_user_profile->lastName,
686
+ 'user_url' => $hybridauth_user_profile->profileURL,
687
+ 'description' => $hybridauth_user_profile->description,
688
+
689
+ 'user_pass' => wp_generate_password()
690
+ );
691
+
692
+ // Bouncer::Membership level
693
+ $wsl_settings_bouncer_new_users_membership_default_role = get_option( 'wsl_settings_bouncer_new_users_membership_default_role' );
694
+
695
+ // if level eq "default", we set role to wp default user role
696
+ if( $wsl_settings_bouncer_new_users_membership_default_role == "default" )
697
+ {
698
+ $userdata['role'] = get_option('default_role');
699
+ }
700
+
701
+ // if level not eq "default" or 'wslnorole' nor empty, we set role to the selected role in bouncer settings
702
+ elseif( $wsl_settings_bouncer_new_users_membership_default_role && $wsl_settings_bouncer_new_users_membership_default_role != 'wslnorole' )
703
+ {
704
+ $userdata['role'] = $wsl_settings_bouncer_new_users_membership_default_role;
705
+ }
706
+
707
+ // Bouncer::User Moderation
708
+ // > if Bouncer::User Moderation is enabled (Yield to Theme My Login), then we overwrite the user role to 'pending'
709
+ # http://www.jfarthing.com/development/theme-my-login/user-moderation/
710
+ if( get_option( 'wsl_settings_bouncer_new_users_moderation_level' ) > 100 )
711
+ {
712
+ $userdata['role'] = "pending";
713
+ }
714
+
715
+ // HOOKABLE: change the user data
716
+ $userdata = apply_filters( 'wsl_hook_process_login_alter_wp_insert_user_data', $userdata, $provider, $hybridauth_user_profile );
717
+
718
+ // DEPRECIATED: as of 2.2.3
719
+ // $userdata = apply_filters( 'wsl_hook_process_login_alter_userdata', $userdata, $provider, $hybridauth_user_profile );
720
+
721
+ // HOOKABLE: This action runs just before creating a new wordpress user.
722
+ do_action( 'wsl_hook_process_login_before_wp_insert_user', $userdata, $provider, $hybridauth_user_profile );
723
+
724
+ // DEPRECIATED: as of 2.2.3
725
+ // do_action( 'wsl_hook_process_login_before_insert_user', $userdata, $provider, $hybridauth_user_profile );
726
+
727
+ // HOOKABLE: This action runs just before creating a new wordpress user, it delegate user insert to a custom function.
728
+ $user_id = apply_filters( 'wsl_hook_process_login_delegate_wp_insert_user', $userdata, $provider, $hybridauth_user_profile );
729
+
730
+ // Create a new WordPress user
731
+ if( ! $user_id || ! is_integer( $user_id ) )
732
+ {
733
+ $user_id = wp_insert_user( $userdata );
734
+ }
735
+
736
+ // do not continue without user_id
737
+ if( ! $user_id || ! is_integer( $user_id ) )
738
+ {
739
+ if( is_wp_error( $user_id ) )
740
+ {
741
+ return wsl_process_login_render_notice_page( _wsl__( "An error occurred while creating a new user: ", 'wordpress-social-login' ) . $user_id->get_error_message() );
742
+ }
743
+
744
+ return wsl_process_login_render_notice_page( _wsl__( "An error occurred while creating a new user!", 'wordpress-social-login' ) );
745
+ }
746
+
747
+ // wp_insert_user may fail on first and last name meta, expliciting setting to correct.
748
+ update_user_meta($user_id, 'first_name', apply_filters( 'pre_user_first_name',$userdata['first_name']));
749
+ update_user_meta($user_id, 'last_name', apply_filters( 'pre_user_last_name', $userdata['last_name']));
750
+
751
+ // Send notifications
752
+ if( get_option( 'wsl_settings_users_notification' ) == 1 )
753
+ {
754
+ wsl_admin_notification( $user_id, $provider );
755
+ }
756
+
757
+ // HOOKABLE: This action runs just after a wordpress user has been created
758
+ // > Note: At this point, the user has been added to wordpress database, but NOT CONNECTED.
759
+ do_action( 'wsl_hook_process_login_after_wp_insert_user', $user_id, $provider, $hybridauth_user_profile );
760
+
761
+ // DEPRECIATED: as of 2.2.3
762
+ // do_action( 'wsl_hook_process_login_after_create_wp_user', $user_id, $provider, $hybridauth_user_profile );
763
+
764
+ // returns the user created user id
765
+ return $user_id;
766
+ }
767
+
768
+ // --------------------------------------------------------------------
769
+
770
+ /**
771
+ * Store WSL user data
772
+ *
773
+ * Steps:
774
+ * 1. Store Hybridauth user profile
775
+ * 2. Import user contacts
776
+ * 3. Launch BuddyPress Profile mapping
777
+ */
778
+ function wsl_process_login_update_wsl_user_data( $is_new_user, $user_id, $provider, $adapter, $hybridauth_user_profile, $wp_user )
779
+ {
780
+ // HOOKABLE:
781
+ do_action( "wsl_process_login_update_wsl_user_data_start", $is_new_user, $user_id, $provider, $adapter, $hybridauth_user_profile, $wp_user );
782
+
783
+ // store user hybridauth user profile in table wslusersprofiles
784
+ // > wsl will only sotre the user profile if it has changed since last login.
785
+ wsl_store_hybridauth_user_profile( $user_id, $provider, $hybridauth_user_profile );
786
+
787
+ // map hybridauth user profile to buddypress xprofile table, if enabled
788
+ // > Profile mapping will only work with new users. Profile mapping for returning users will implemented in future version of WSL.
789
+ if( $is_new_user )
790
+ {
791
+ wsl_buddypress_xprofile_mapping( $user_id, $provider, $hybridauth_user_profile );
792
+ }
793
+
794
+ // import user contacts into wslusersprofiles, if enabled
795
+ // > wsl will only import the contacts list once per user per provider.
796
+ wsl_store_hybridauth_user_contacts( $user_id, $provider, $adapter );
797
+ }
798
+
799
+ // --------------------------------------------------------------------
800
+
801
+ /**
802
+ * Authenticate a user within wordpress
803
+ *
804
+ * Ref: http://codex.wordpress.org/Function_Reference/wp_set_auth_cookie
805
+ * Ref: http://codex.wordpress.org/Function_Reference/wp_safe_redirect
806
+ */
807
+ function wsl_process_login_authenticate_wp_user( $user_id, $provider, $redirect_to, $adapter, $hybridauth_user_profile, $wp_user )
808
+ {
809
+ // HOOKABLE:
810
+ do_action( "wsl_process_login_authenticate_wp_user_start", $user_id, $provider, $redirect_to, $adapter, $hybridauth_user_profile, $wp_user );
811
+
812
+ // update some fields in usermeta for the current user
813
+ update_user_meta( $user_id, 'wsl_current_provider', $provider );
814
+
815
+ if( $hybridauth_user_profile->photoURL )
816
+ {
817
+ update_user_meta( $user_id, 'wsl_current_user_image', $hybridauth_user_profile->photoURL );
818
+ }
819
+
820
+ // Bouncer::User Moderation
821
+ // > When Bouncer::User Moderation is enabled, WSL will check for the current user role. If equal to 'pending', then Bouncer will do the following :
822
+ // 1. Halt the authentication process,
823
+ // 2. Skip setting the authentication cookies for the user,
824
+ // 3. Reset the Redirect URL to the appropriate Theme My Login page.
825
+ $wsl_settings_bouncer_new_users_moderation_level = get_option( 'wsl_settings_bouncer_new_users_moderation_level' );
826
+
827
+ // current user role
828
+ $role = current( $wp_user->roles );
829
+
830
+ // if role eq 'pending', we halt the authentication and we redirect the user to the appropriate url (pending=activation or pending=approval)
831
+ if( $role == 'pending' )
832
+ {
833
+ // E-mail Confirmation
834
+ if( $wsl_settings_bouncer_new_users_moderation_level == 101 )
835
+ {
836
+ $redirect_to = site_url( 'wp-login.php', 'login_post' ) . ( strpos( site_url( 'wp-login.php', 'login_post' ), '?' ) ? '&' : '?' ) . "pending=activation";
837
+
838
+ // send a new e-mail/activation notification - if TML not enabled, we ensure WSL to keep it quiet
839
+ $errors = new WP_Error();
840
+ do_action( 'register_post', $wp_user->user_nicename, $wp_user->user_email, $errors );
841
+ @ Theme_My_Login_User_Moderation::new_user_activation_notification( $user_id );
842
+ }
843
+
844
+ // Admin Approval
845
+ elseif( $wsl_settings_bouncer_new_users_moderation_level == 102 )
846
+ {
847
+ $redirect_to = site_url( 'wp-login.php', 'login_post' ) . ( strpos( site_url( 'wp-login.php', 'login_post' ), '?' ) ? '&' : '?' ) . "pending=approval";
848
+ }
849
+ }
850
+
851
+ // otherwise, we connect the user with in wordpress (we give him a cookie)
852
+ else
853
+ {
854
+ // HOOKABLE: This action runs just before logging the user in (before creating a WP cookie)
855
+ do_action( "wsl_hook_process_login_before_wp_set_auth_cookie", $user_id, $provider, $hybridauth_user_profile );
856
+
857
+ // DEPRECIATED: as of 2.2.3
858
+ // do_action( 'wsl_hook_process_login_before_set_auth_cookie', $user_id, $provider, $hybridauth_user_profile );
859
+
860
+ // Set WP auth cookie
861
+ wp_set_auth_cookie( $user_id, true );
862
+
863
+ // let keep it std
864
+ do_action( 'wp_login', $wp_user->user_login, $wp_user );
865
+ }
866
+
867
+ // HOOKABLE: This action runs just before redirecting the user back to $redirect_to
868
+ // > Note: If you have enabled User Moderation, then the user is NOT NECESSARILY CONNECTED
869
+ // > within wordpress at this point (in case the user $role == 'pending').
870
+ // > To be sure the user is connected, use wsl_hook_process_login_before_wp_set_auth_cookie instead.
871
+ do_action( "wsl_hook_process_login_before_wp_safe_redirect", $user_id, $provider, $hybridauth_user_profile, $redirect_to );
872
+
873
+ // DEPRECIATED: as of 2.2.3
874
+ // do_action( 'wsl_hook_process_login_before_set_auth_cookie', $user_id, $provider, $hybridauth_user_profile );
875
+
876
+ do_action( 'wsl_clear_user_php_session' );
877
+
878
+ // Display WSL debugging instead of redirecting the user
879
+ // > this will give a complete report on what wsl did : database queries and fired hooks
880
+ // wsl_display_dev_mode_debugging_area(); die(); // ! keep this line commented unless you know what you are doing :)
881
+
882
+ // That's it. We done.
883
+ wp_safe_redirect( $redirect_to );
884
+
885
+ // for good measures
886
+ die();
887
+ }
888
+
889
+ // --------------------------------------------------------------------
890
+
891
+ /**
892
+ * Build required hybridauth configuration for the given provider
893
+ */
894
+ function wsl_process_login_build_provider_config( $provider )
895
+ {
896
+ require_once WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'hybridauth/library/src/autoload.php';
897
+
898
+ $config = array();
899
+ $config["current_page"] = Hybridauth\HttpClient\Util::getCurrentUrl(true);
900
+ $config["callback"] = WORDPRESS_SOCIAL_LOGIN_HYBRIDAUTH_ENDPOINT_URL . 'callbacks/' . strtolower( $provider ) . '.php';
901
+ $config["providers"] = array();
902
+ $config["providers"][$provider] = array();
903
+ $config["providers"][$provider]["enabled"] = true;
904
+ $config["providers"][$provider]["keys"] = array( 'id' => null, 'key' => null, 'secret' => null );
905
+
906
+ // provider application id ?
907
+ if( get_option( 'wsl_settings_' . $provider . '_app_id' ) )
908
+ {
909
+ $config["providers"][$provider]["keys"]["id"] = get_option( 'wsl_settings_' . $provider . '_app_id' );
910
+ }
911
+
912
+ // provider application key ?
913
+ if( get_option( 'wsl_settings_' . $provider . '_app_key' ) )
914
+ {
915
+ $config["providers"][$provider]["keys"]["key"] = get_option( 'wsl_settings_' . $provider . '_app_key' );
916
+ }
917
+
918
+ // provider application secret ?
919
+ if( get_option( 'wsl_settings_' . $provider . '_app_secret' ) )
920
+ {
921
+ $config["providers"][$provider]["keys"]["secret"] = get_option( 'wsl_settings_' . $provider . '_app_secret' );
922
+ }
923
+
924
+ // set custom config for facebook
925
+ if( strtolower( $provider ) == "facebook" )
926
+ {
927
+ $config["providers"][$provider]["display"] = "popup";
928
+ $config["providers"][$provider]["trustForwarded"] = true;
929
+
930
+ // switch to fb::display 'page' if wsl auth in page
931
+ if( get_option( 'wsl_settings_use_popup') == 2 )
932
+ {
933
+ $config["providers"][$provider]["display"] = "page";
934
+ }
935
+
936
+ $config["providers"][$provider]["scope"] = "email, public_profile";
937
+ }
938
+
939
+ // set custom config for google
940
+ if( strtolower( $provider ) == "google" )
941
+ {
942
+ $config["providers"][$provider]["scope"] = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email";
943
+ }
944
+
945
+ // set custom config for linkedin
946
+ if( strtolower( $provider ) == "linkedin" )
947
+ {
948
+ $config["providers"][$provider]["scope"] = "r_liteprofile r_emailaddress";
949
+ }
950
+
951
+ $provider_scope = isset( $config["providers"][$provider]["scope"] ) ? $config["providers"][$provider]["scope"] : null ;
952
+
953
+ // HOOKABLE: allow to overwrite scopes
954
+ $provider_scope = apply_filters( 'wsl_hook_alter_provider_scope', $provider_scope, $provider );
955
+
956
+ // XXX: Scope needs to be diffrent than null.
957
+ if($provider_scope !== null){
958
+ $config["providers"][$provider]["scope"] = $provider_scope;
959
+ }
960
+
961
+ // HOOKABLE: allow to overwrite hybridauth config for the selected provider
962
+ $config["providers"][$provider] = apply_filters( 'wsl_hook_alter_provider_config', $config["providers"][$provider], $provider );
963
+
964
+ return $config;
965
+ }
966
+
967
+ // --------------------------------------------------------------------
968
+
969
+ /**
970
+ * Grab the user profile from social network
971
+ */
972
+ function wsl_process_login_request_user_social_profile( $provider )
973
+ {
974
+ $adapter = null;
975
+ $config = null;
976
+ $hybridauth_user_profile = null;
977
+
978
+ try
979
+ {
980
+ // get idp adapter
981
+ $adapter = wsl_process_login_get_provider_adapter( $provider );
982
+
983
+ $config = wsl_get_provider_config_from_session_storage( $provider );
984
+
985
+ // if user authenticated successfully with social network
986
+ if( $adapter->isConnected() )
987
+ {
988
+ // grab user profile via hybridauth api
989
+ $hybridauth_user_profile = $adapter->getUserProfile();
990
+ }
991
+
992
+ // if user not connected to provider (ie: session lost, url forged)
993
+ else
994
+ {
995
+ return wsl_process_login_render_notice_page( sprintf( _wsl__( "Sorry, we couldn't connect you with <b>%s</b>. <a href=\"%s\">Please try again</a>.", 'wordpress-social-login' ), $provider, site_url( 'wp-login.php', 'login_post' ) ) );
996
+ }
997
+ }
998
+
999
+ // if things didn't go as expected, we dispay the appropriate error message
1000
+ catch( Exception $e )
1001
+ {
1002
+ return wsl_process_login_render_error_page( $e, $config, $provider, $adapter );
1003
+ }
1004
+
1005
+ return $hybridauth_user_profile;
1006
+ }
1007
+
1008
+ // --------------------------------------------------------------------
1009
+
1010
+ /**
1011
+ * Returns hybriauth idp adapter.
1012
+ */
1013
+ function wsl_process_login_get_provider_adapter( $provider )
1014
+ {
1015
+ require_once WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'hybridauth/library/src/autoload.php';
1016
+
1017
+ $config = wsl_get_provider_config_from_session_storage( $provider );
1018
+
1019
+ $hybridauth = new Hybridauth\Hybridauth( $config );
1020
+
1021
+ return $hybridauth->getAdapter( $provider );
1022
+ }
1023
+
1024
+ // --------------------------------------------------------------------
1025
+
1026
+ /**
1027
+ * Returns redirect_to (callback url)
1028
+ *
1029
+ * By default, once a user authenticate, he will be automatically redirected to the page where he come from (referer).
1030
+ * If WSL wasn't able to identify the referer url (or if the user come wp-login.php), then they will be redirected to
1031
+ * Widget::Redirect URL instead.
1032
+ *
1033
+ * When Widget::Force redirection is set to Yes, users will be always redirected to Widget::Redirect URL.
1034
+ *
1035
+ * Note: Widget::Redirect URL can be customised using the filter 'wsl_hook_process_login_alter_redirect_to'
1036
+ */
1037
+ function wsl_process_login_get_redirect_to()
1038
+ {
1039
+ // force redirection?
1040
+ $wsl_settings_redirect_url = get_option( 'wsl_settings_redirect_url' );
1041
+
1042
+ if( get_option( 'wsl_settings_force_redirect_url' ) == 1 )
1043
+ {
1044
+ $redirect_to = apply_filters( 'wsl_hook_process_login_alter_redirect_to', $wsl_settings_redirect_url );
1045
+
1046
+ return $redirect_to;
1047
+ }
1048
+
1049
+ // get a valid $redirect_to
1050
+ if( isset( $_REQUEST[ 'redirect_to' ] ) && $_REQUEST[ 'redirect_to' ] != '' )
1051
+ {
1052
+ $redirect_to = $_REQUEST[ 'redirect_to' ];
1053
+
1054
+ // we don't go there..
1055
+ if( strpos( $redirect_to, 'wp-admin') )
1056
+ {
1057
+ $redirect_to = $wsl_settings_redirect_url;
1058
+ }
1059
+
1060
+ // nor there..
1061
+ if( strpos( $redirect_to, 'wp-login.php') )
1062
+ {
1063
+ $redirect_to = $wsl_settings_redirect_url;
1064
+ }
1065
+ }
1066
+
1067
+ if( empty( $redirect_to ) )
1068
+ {
1069
+ $redirect_to = $wsl_settings_redirect_url;
1070
+ }
1071
+
1072
+ if( empty( $redirect_to ) )
1073
+ {
1074
+ $redirect_to = home_url();
1075
+ }
1076
+
1077
+ $redirect_to = apply_filters( 'wsl_hook_process_login_alter_redirect_to', $redirect_to );
1078
+
1079
+ return $redirect_to;
1080
+ }
1081
+
1082
+ // --------------------------------------------------------------------
1083
+
1084
+ /**
1085
+ * Display an error message in case user authentication fails
1086
+ */
1087
+ function wsl_process_login_render_error_page( $e, $config = null, $provider = null, $adapter = null )
1088
+ {
1089
+ // HOOKABLE:
1090
+ do_action( "wsl_process_login_render_error_page", $e, $config, $provider, $adapter );
1091
+
1092
+ $assets_base_url = WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . 'assets/img/';
1093
+
1094
+ $message = "";
1095
+ $notes = "";
1096
+ $apierror = substr( $e->getMessage(), 0, 256 );
1097
+
1098
+ if( is_object( $adapter ) )
1099
+ {
1100
+ $adapter->disconnect();
1101
+ }
1102
+
1103
+ return wsl_render_error_page( $message, $notes, $provider, $apierror, $e );
1104
+ }
1105
+
1106
+ // --------------------------------------------------------------------
1107
+
1108
+ /**
1109
+ * Display an notice message
1110
+ */
1111
+ function wsl_process_login_render_notice_page( $message )
1112
+ {
1113
+ // HOOKABLE:
1114
+ do_action( "wsl_process_login_render_notice_page", $message );
1115
+
1116
+ return wsl_render_notice_page( $message );
1117
+ }
1118
+
1119
+ // --------------------------------------------------------------------
1120
+
1121
+ /**
1122
+ * Returns the selected provider from _REQUEST, default to null
1123
+ */
1124
+ function wsl_process_login_get_selected_provider()
1125
+ {
1126
+ $provider = isset( $_REQUEST["provider"] ) ? sanitize_text_field( $_REQUEST["provider"] ) : null;
1127
+
1128
+ return apply_filters( 'wsl_hook_process_login_alter_provider', $provider ) ;
1129
+ }
1130
+
1131
+ // --------------------------------------------------------------------
1132
+
1133
+ /**
1134
+ * Returns the selected auth mode from _REQUEST, default to login
1135
+ */
1136
+ function wsl_process_login_get_auth_mode()
1137
+ {
1138
+ $auth_mode = isset( $_REQUEST["mode"] ) ? sanitize_text_field( $_REQUEST["mode"] ) : 'login';
1139
+
1140
+ return apply_filters( 'wsl_hook_process_login_alter_auth_mode', $auth_mode ) ;
1141
+ }
1142
+
1143
+ // --------------------------------------------------------------------
1144
+
1145
+ /**
1146
+ * Clear the stored data by hybridauth and wsl in php session
1147
+ */
1148
+ function wsl_process_login_clear_user_php_session()
1149
+ {
1150
+ $_SESSION["HYBRIDAUTH::STORAGE"] = array(); // used by hybridauth library. to clear as soon as the auth process ends.
1151
+ $_SESSION["wsl::userprofile"] = array(); // used by wsl to temporarily store the user profile so we don't make unnecessary calls to social apis.
1152
+ }
1153
+
1154
+ // --------------------------------------------------------------------
1155
+
1156
+ /**
1157
+ * Returns IDP actual name
1158
+ */
1159
+ function wsl_get_provider_name_by_id( $provider_id)
1160
+ {
1161
+ global $WORDPRESS_SOCIAL_LOGIN_PROVIDERS_CONFIG;
1162
+
1163
+ foreach( $WORDPRESS_SOCIAL_LOGIN_PROVIDERS_CONFIG as $provider_settings ) {
1164
+ if ( $provider_settings['provider_id'] == $provider_id ) {
1165
+ return $provider_name = $provider_settings['provider_name'];
1166
+ }
1167
+ }
1168
+
1169
+ return $provider_id;
1170
+ }
1171
+
1172
+ // --------------------------------------------------------------------
1173
+
1174
+ /**
1175
+ * Check Php session
1176
+ */
1177
+ function wsl_process_login_check_php_session()
1178
+ {
1179
+ if( isset( $_SESSION["wsl::plugin"] ) && $_SESSION["wsl::plugin"] )
1180
+ {
1181
+ return true;
1182
+ }
1183
+ }
1184
+
1185
+ // --------------------------------------------------------------------
1186
+
1187
+ /**
1188
+ * Returns redirect url for when a new account was created
1189
+ */
1190
+ function wsl_new_register_redirect_url($redirect_to) {
1191
+ return $redirect_to;
1192
+ }
1193
+ add_filter("wsl_redirect_after_registration", "wsl_new_register_redirect_url", 10, 1);
1194
+
1195
+ // --------------------------------------------------------------------
readme.md CHANGED
@@ -1,52 +1,52 @@
1
- ## [WordPress Social Login](https://wordpress.org/plugins/wordpress-social-login/) 3.0.3-dev
2
-
3
- **WordPress Social Login** is a free and open source plugin made by the community, for the community.
4
-
5
- Basically, WordPress Social Login allow your website visitors and customers to register and login via social networks such as twitter, facebook and google but it has much more to offer.
6
-
7
- For more information about WordPress Social Login, refer to our [online user guide](http://miled.github.io/wordpress-social-login/).
8
-
9
- ![WSL Authentication Widget](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-1.png)
10
-
11
- ### Key Features
12
-
13
- - No premium features.
14
- - One-click social login.
15
- - Absolute privacy of your website users data.
16
- - Wide variety of identities providers.
17
- - A highly customizable and fully extensible widgets.
18
- - Easy-to-use and clean user interfaces.
19
- - Contacts import from google, facebook, live, linkedin and vkontakte.
20
- - User profiles and contacts management.
21
- - Compatible with WordPress 3.0+, BuddyPress and bbPress.
22
- - ACL-based security model.
23
- - Provides a direct access to social networks apis.
24
- - Modular design easily extended.
25
- - Comprehensive documentation.
26
-
27
- #### License
28
-
29
- MIT — That's short for do whatever you want.
30
-
31
- #### Thanks
32
-
33
- Big thanks to everyone who have contributed to WordPress Social Login by submitting Patches, Ideas, Reviews and by Helping in the support forum.
34
-
35
- #### Screenshots
36
- ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-2.png)
37
- ===
38
- ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-3.png)
39
- ===
40
- ![screenshot](http://miled.github.io/wordpress-social-login/assets/img/theme_fontawesome.png)
41
- ===
42
- ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-4.png)
43
- =
44
- ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-5.png)
45
- ===
46
- ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-6.png)
47
- ===
48
- ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-7.png)
49
- ===
50
- ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-8.png)
51
- ===
52
- ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-9.png)
1
+ ## [WordPress Social Login](https://wordpress.org/plugins/wordpress-social-login/) 3.0.4-dev
2
+
3
+ **WordPress Social Login** is a free and open source plugin made by the community, for the community.
4
+
5
+ Basically, WordPress Social Login allow your website visitors and customers to register and login via social networks such as twitter, facebook and google but it has much more to offer.
6
+
7
+ For more information about WordPress Social Login, refer to our [online user guide](http://miled.github.io/wordpress-social-login/).
8
+
9
+ ![WSL Authentication Widget](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-1.png)
10
+
11
+ ### Key Features
12
+
13
+ - No premium features.
14
+ - One-click social login.
15
+ - Absolute privacy of your website users data.
16
+ - Wide variety of identities providers.
17
+ - A highly customizable and fully extensible widgets.
18
+ - Easy-to-use and clean user interfaces.
19
+ - Contacts import from google, facebook, live, linkedin and vkontakte.
20
+ - User profiles and contacts management.
21
+ - Compatible with WordPress 3.0+, BuddyPress and bbPress.
22
+ - ACL-based security model.
23
+ - Provides a direct access to social networks apis.
24
+ - Modular design easily extended.
25
+ - Comprehensive documentation.
26
+
27
+ #### License
28
+
29
+ MIT — That's short for do whatever you want.
30
+
31
+ #### Thanks
32
+
33
+ Big thanks to everyone who have contributed to WordPress Social Login by submitting Patches, Ideas, Reviews and by Helping in the support forum.
34
+
35
+ #### Screenshots
36
+ ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-2.png)
37
+ ===
38
+ ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-3.png)
39
+ ===
40
+ ![screenshot](http://miled.github.io/wordpress-social-login/assets/img/theme_fontawesome.png)
41
+ ===
42
+ ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-4.png)
43
+ =
44
+ ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-5.png)
45
+ ===
46
+ ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-6.png)
47
+ ===
48
+ ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-7.png)
49
+ ===
50
+ ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-8.png)
51
+ ===
52
+ ![screenshot](https://raw.githubusercontent.com/miled/wordpress-social-login/master/assets/screenshot-9.png)
readme.txt CHANGED
@@ -1,224 +1,220 @@
1
- === WordPress Social Login ===
2
- Contributors: miled
3
- Tags: login, register, comment, social login, social networks, facebook, google, twitter, reddit, linkedin, instagram, vkontakte, github, steam, dribbble, twitch.tv
4
- Requires at least: 3.0
5
- Tested up to: 5.5
6
- Stable tag: 2.2.3
7
- License: MIT License
8
- License URI: http://opensource.org/licenses/MIT
9
- Donate link: https://www.redcross.org/quickdonate/index.jsp
10
-
11
- WordPress Social Login allow your visitors to comment and login with social networks such as Twitter, Facebook, Google, Yahoo and more.
12
-
13
- == Description ==
14
-
15
- <strong>Wordpress Social Login</strong> allow your website readers and customers to register on using their existing social accounts IDs, eliminating the need to fill out registration forms and remember usernames and passwords.
16
-
17
- Wordpress Social Login also allow you to import users contact list from Google Gmail, Facebook, Windows Live and LinkedIn.
18
-
19
- Wordpress Social Login gives you absolute control over users access to your website and comes a list of rules and restrictions for you to setup.
20
-
21
- <strong>Easy to customize and integrate</strong> <br>
22
- Wordpress Social Login come with a simple but flexible and fully customizable authentication widget. And if you are a developer or designer then you can customize it to your heart's content.
23
-
24
- <strong>Wide variety of providers</strong> <br>
25
- Depending on the audience you're targeting, you can choose from a wide variety of providers and services including: Social networks, Microblogging platforms, Professional networks, Media, Photo sharing, Programmers and Gamers networks.
26
-
27
- <strong>Currently supported providers</strong><br>
28
- Facebook, Google, Twitter, Windows Live, Yahoo!, LinkedIn, Reddit, Disqus, Tumblr, Stackoverflow, GitHub, Dribbble, Instagram, 500px, Foursquare, Steam, Twitch.tv, Mixi, Vkontakte, Mail.ru, Yandex, Odnoklassniki, Goodreads, Skyrock, Last.fm, AOL and PixelPin.
29
-
30
- <strong>Free, unlimited and white-label</strong> <br>
31
- Wordpress Social Login is open-source and completely free. The source code is publicly available on [GitHub](https://github.com/hybridauth/WordPress-Social-Login) for anyone to help and contribute. You are free to use a Wordpress Social Login in commercial projects as long as the copyright header is left intact.
32
-
33
- <strong>Special thanks to:</strong>
34
-
35
- * [Thenbrent](http://profiles.wordpress.org/users/thenbrent/) the talented developer behind the Social Connect plugin.
36
- * [Pat Anvil](http://patanvil.com) for adding Goodreads.
37
- * [Ayrat Belyaev](https://github.com/xbreaker) for adding Mail.ru, Yandex and Odnoklassniki.
38
- * [Social Login plugin](https://wordpress.org/plugins/oa-social-login/) for many borrowed functions.
39
- * [Query Monitor plugin](https://wordpress.org/plugins/query-monitor/) - A must have for Wordpress plugins developers.
40
-
41
- Big thanks to everyone who have contributed to WordPress Social Login by submitting Patches, Ideas, Reviews and by Helping in the support forum.
42
-
43
- == Installation ==
44
-
45
- = The hard way =
46
-
47
- 1. Download, Unzip and drop the extension on /wp-content/plugins/ directory,
48
- 1. As administrator, activate the plugin through the 'Plugins' menu in WordPress,
49
- 1. Goto the Settings > WP Social Login to get started.
50
-
51
- = The easy way =
52
-
53
- 1. As administrator, goto 'Plugins' then Click on 'Add New',
54
- 2. Search for 'WordPress Social Login' then Click on 'Install Now',
55
- 3. Wait for it to download, Unpack and to install,
56
- 4. Activate the plugin by Clicking on 'Activate Plugin'
57
- 5. Goto the Settings > WP Social Login to get started.
58
-
59
-
60
- == Frequently Asked Questions ==
61
-
62
- The user guide and frequently asked questions can be found at http://miled.github.io/wordpress-social-login/
63
-
64
- == Screenshots ==
65
-
66
- 1. WSL attempts to work with the default WordPress comment, login and registration forms.
67
- 2. WSL come with a simple but flexible and fully customizable authentication widget.
68
- 3. WSL widget can be easily integrated into most WordPress themes and many popular plugins using hooks and shortcodes.
69
- 4. Accounts linking/mapping.
70
- 5. WSL social networks setup.
71
- 6. WSL widget customization.
72
- 7. WSL advanced configuration.
73
- 8. WSL Buddypress Integration.
74
- 9. WSL components and add-ons manager.
75
-
76
- == Changelog ==
77
-
78
- = 3.0.3 =
79
-
80
- * WSL is now fully migrated to Hybridauth 3.5.
81
- * Reworked providers Callback URLs and it's a breaking change! More at http://miled.github.io/wordpress-social-login/migrating-to-3.0.html
82
- * Added serval new providers: Amazon, Discord and Spotify to name a few.
83
- * Removal of a number of currently defunct identity providers.
84
- * Authentication widgets and forms design overhall.
85
- * Various fixes and minor improvements.
86
-
87
- = 2.3.0 =
88
-
89
- * Accounts linking/mapping.
90
- * Improved Profile Completion.
91
- * Widget shortcode arguments.
92
- * Added new translations.
93
- * Fix an issue with Facebook users profiles.
94
- * Fix email confirmation in WSL.
95
- * Small fix for error when merging wsl users with wp users.
96
- * Remove hardcoded plugin directories.
97
- * Reduce Twitch TV requested permissions.
98
-
99
- = 2.2.3 =
100
-
101
- WSL 2.2.3 fixes a critical issue found on WSL 2.2.2 that could potentially allow multiple accounts and prevent contacts import. We recommend that users upgrade to this latest version.
102
-
103
- WSL 2.2.3 also include a number of new features, and fixes several stability issues. See below for details.
104
-
105
- <strong>Developers Release Notes</strong>
106
-
107
- > These release notes are aimed at developers.
108
-
109
- This release did focus on code health and flexibility and it was necessary to move some code around, and to remove few functions and hooks. We know, it sucks to break WSL API at such short notice, but it was indispensable and unavoidable as we're trying to move the project forward.
110
-
111
- As announced on WSL Support Forum, this is by no means a drastic change to the API. In fact, we tried our best to keep the said changes to a strict minimum, and the vast majority of WSL users will not be affected.
112
-
113
- Those breaking changes are:
114
-
115
- * Deprecated hooks, prior to 2.2.2, have been removed.
116
- * Deprecated css selectors, prior to 2.2.2, have been removed.
117
- * Deprecated internal functions have been removed.
118
- * Few internal functions have been either removed, renamed or slightly changed.
119
- * Few pluggable functions has slightly changed.
120
- * Steam's users identifiers are converted to a new format.
121
-
122
- Please update the WSL hooks you were using accordingly to the new developer API:
123
-
124
- http://miled.github.io/wordpress-social-login/developer-api-migrating-2.2.html
125
- http://miled.github.io/wordpress-social-login/developer-api-authentication.html
126
- http://miled.github.io/wordpress-social-login/developer-api-widget.html
127
- http://miled.github.io/wordpress-social-login/developer-api-functions.html
128
-
129
- On this release we have reworked Steam provider to fully support their new Web API, and we decided to change Steam's users identifiers to SteamID64. When updated, WSL 2.2.3 will automatically convert all the existing steam users identifiers in wslusersprofiles to the new format.
130
-
131
- It's worth mentioning that in upcoming releases and before we hit WSL 3.0, we're planning to rework other parts of the codebase; for instance user database functions will be re-factored using an ORM, and profile completion will be replaced by new module.
132
-
133
- We explicitly discourage you from using, or hacking, any internal function (i.e., Not publicly documented on WSL dev API), as they are now subject to change in subsequent releases. If it wasn't possible to achieve some required functionality in a proper way through the already available and documented WSL hooks, please ask for support before resorting to hacks.
134
-
135
- Upon reaching WSL 3.0 as a major milestone, our priorities will flip to maintenance and stability (i.e, repair code health, enhance code coverage) rather than developing new features. This massive rewrite aims to make WSL more modular easily extended through plugins and add-ons (e.g., http://miled.github.io/wsl-users-converter/).
136
-
137
- <strong>List of changes</strong>
138
-
139
- * WSL is now compatible with PHP 5.2 again.
140
- * WSL is now compatible with WordPress 3.0+ again.
141
- * WSL now display social apis errors when authentication fails.
142
- * WSL now support authentications through Dribbble.com.
143
- * Steam provider has been entirely reworked and now fully support the new Web API.
144
- * Steam users IDs is now converted to SteamID64 rather than http://steamcommunity.com/openid/id/{USER_STEAMID64}.
145
- * LinkedIn provider has been enhanced. WSL can now get the full LinkedIn's members avatars and headline (fix).
146
- * Changed facebook api endpoints to graph api v2.0
147
- * WSL can now import users contacts from vkontakte.
148
- * Profile completion form has received a visual update.
149
- * WSL now provide an easier access to social networks apis.
150
- * WSL now trigger WordPress do_login action hooks whenever a user connect.
151
- * Authentication display now fall back to In Page when WSL is used on a mobile device.
152
- * WSL admin interfaces have been reworked and can be now extended with hooks.
153
- * Bouncer Membership level can be now set to any user role.
154
- * WSL Diagnostics has been reworked and can check the minimum system requirements and for few common issues.
155
- * Added "Repair WSL tables" under Tools tab.
156
- * Added "Debug mode" under Tools tab (namely whatchdog).
157
- * Added "Authentication Playground" under Tools tab (namely auth-paly).
158
- * Added "Uninstall" under Tools tab.
159
- * Added new hooks in the authentication widget and auth process.
160
- * Made WSL more RTL friendly.
161
- * Added 403 pages under wsl folders (silence is.. highly overrated).
162
- * PHP file wsl.auth.widget.php renamed to wsl.auth.widgets.php
163
- * Function wsl_render_login_form() renamed to wsl_render_auth_widget()
164
- * wsl_user_custom_avatar and wsl_bp_user_custom_avatar are now pluggable and can be redefined.
165
- * wsl_render_notice_page and wsl_render_error_page has slightly changed.
166
- * Fix a critical issue found on WSL 2.2.2 with wslusersprofiles.
167
- * Fix an issue where redirect_to get overwritten in some cases.
168
- * Fix an issue with redirect_to where the callback url was encoded twice.
169
- * Fix several stability issues.
170
- * Added testunit to the project (early version).
171
- * Deprecated hooks, prior to 2.2.2, have been removed.
172
- * Deprecated internal functions have been removed.
173
- * Deprecated css selectors, in wsl widget, have been removed.
174
- * Updated the API documentation for WSL authentication process
175
- * Updated the API documentation for WSL widget generator
176
- * Updated the API documentation for pluggable WSL functions
177
- * Added a list of code snippets to WSL documentation
178
- * Added documentation for social apis access (through php code)
179
- * Added documentation for basic troubleshooting (common issues)
180
- * Added documentation for advanced troubleshooting (internal tools)
181
-
182
- = 2.2.2 =
183
-
184
- * Fix an issue where wsl did not display the right user avatar.
185
- * Fix an issue where providers icons wasn't showing in sites using https.
186
- * Fix an issue with basic insights, where users counts by age wasn't showing.
187
- * Add WordPress to list of supported provider.
188
-
189
- = 2.2.1 =
190
-
191
- * WSL can be fully integrated with your BuddyPress installation: display of users avatars and xprofiles mapping.
192
- * WSL is now updated to work with the latest apis changes of the supported social networks.
193
- * WSL Widget is now more flexible than before and can be fully customized to fit you website theme.
194
- * Introducing new providers : Reddit, Disqus and PixelPin.
195
- * WSL Hooks has been reworked and few hooks have been depreciated in favour of new ones. For more information, see: http://hybridauth.sourceforge.net/wsl/developer.html
196
- * A number of bugfixes, small enhancements and visual updates.
197
-
198
- = 2.1.3 =
199
-
200
- * In a similar way to WordPress plugins, WSL uses Components,
201
- * Email Validation is replaced with Profile Completion,
202
- * User Moderation made compatible with Theme My Login plugin,
203
- * A number of enhancements and new options now available but who care
204
-
205
- = 2.0.3 =
206
-
207
- * Managing WSL users,
208
- * Import WSL users contact list from Google Gmail, Facebook, Live and LinkedIn,
209
- * An entirely reworked user interface,
210
- * Improving the documentation and guides,
211
- * Introducing a new module, and the long awaited, The bouncer,
212
- * Added Twitch.tv and Steam.
213
-
214
- = 1.2.4 =
215
-
216
- * WSL admin ui Relooking
217
- * Code re-factoring
218
- * add Widget display on advanced settings
219
- * RIP Gowalla
220
- * WordPress Social Login is now licensed under The MIT License only (should be GPL compatible)
221
-
222
- = 0.0.0 =
223
-
224
- * I'm too old to remember
1
+ === WordPress Social Login ===
2
+ Contributors: miled
3
+ Tags: login, register, comment, social login, social networks, facebook, google, twitter, reddit, linkedin, instagram, vkontakte, github, steam, dribbble, twitch.tv
4
+ Requires at least: 3.0
5
+ Tested up to: 5.5
6
+ Stable tag: 3.0.4
7
+ License: MIT License
8
+ License URI: http://opensource.org/licenses/MIT
9
+ Donate link: https://www.redcross.org/quickdonate/index.jsp
10
+
11
+ WordPress Social Login allow your visitors to comment and login with social networks such as Twitter, Facebook, Google, Yahoo and more.
12
+
13
+ == Description ==
14
+
15
+ <strong>Wordpress Social Login</strong> allow your website readers and customers to register on using their existing social accounts IDs, eliminating the need to fill out registration forms and remember usernames and passwords.
16
+
17
+ Wordpress Social Login also allow you to import users contact list from Google Gmail, Facebook, Windows Live and LinkedIn.
18
+
19
+ Wordpress Social Login gives you absolute control over users access to your website and comes a list of rules and restrictions for you to setup.
20
+
21
+ <strong>Easy to customize and integrate</strong> <br>
22
+ Wordpress Social Login come with a simple but flexible and fully customizable authentication widget. And if you are a developer or designer then you can customize it to your heart's content.
23
+
24
+ <strong>Wide variety of providers</strong> <br>
25
+ Depending on the audience you're targeting, you can choose from a wide variety of providers and services including: Social networks, Microblogging platforms, Professional networks, Media, Photo sharing, Programmers and Gamers networks.
26
+
27
+ <strong>Currently supported providers</strong><br>
28
+ Facebook, Google, Twitter, Windows Live, Yahoo!, LinkedIn, Reddit, Disqus, Tumblr, Stackoverflow, GitHub, Dribbble, Instagram, 500px, Foursquare, Steam, Twitch.tv, Mixi, Vkontakte, Mail.ru, Yandex, Odnoklassniki, Goodreads, Skyrock, Last.fm, AOL and PixelPin.
29
+
30
+ <strong>Free, unlimited and white-label</strong> <br>
31
+ Wordpress Social Login is open-source and completely free. The source code is publicly available on [GitHub](https://github.com/hybridauth/WordPress-Social-Login) for anyone to help and contribute. You are free to use a Wordpress Social Login in commercial projects as long as the copyright header is left intact.
32
+
33
+ Big thanks to everyone who have contributed to WordPress Social Login by submitting Patches, Ideas, Reviews and by Helping in the support forum.
34
+
35
+ == Installation ==
36
+
37
+ = The hard way =
38
+
39
+ 1. Download, Unzip and drop the extension on /wp-content/plugins/ directory,
40
+ 1. As administrator, activate the plugin through the 'Plugins' menu in WordPress,
41
+ 1. Goto the Settings > WP Social Login to get started.
42
+
43
+ = The easy way =
44
+
45
+ 1. As administrator, goto 'Plugins' then Click on 'Add New',
46
+ 2. Search for 'WordPress Social Login' then Click on 'Install Now',
47
+ 3. Wait for it to download, Unpack and to install,
48
+ 4. Activate the plugin by Clicking on 'Activate Plugin'
49
+ 5. Goto the Settings > WP Social Login to get started.
50
+
51
+
52
+ == Frequently Asked Questions ==
53
+
54
+ The user guide and frequently asked questions can be found at http://miled.github.io/wordpress-social-login/
55
+
56
+ == Screenshots ==
57
+
58
+ 1. WSL attempts to work with the default WordPress comment, login and registration forms.
59
+ 2. WSL come with a simple but flexible and fully customizable authentication widget.
60
+ 3. WSL widget can be easily integrated into most WordPress themes and many popular plugins using hooks and shortcodes.
61
+ 4. Accounts linking/mapping.
62
+ 5. WSL social networks setup.
63
+ 6. WSL widget customization.
64
+ 7. WSL advanced configuration.
65
+ 8. WSL Buddypress Integration.
66
+ 9. WSL components and add-ons manager.
67
+
68
+ == Changelog ==
69
+
70
+ = 3.0.4 =
71
+
72
+ * Hotfix an issue with default scopes of a certain identity providers.
73
+
74
+ = 3.0.3 =
75
+
76
+ * WSL is now fully migrated to Hybridauth 3.5.
77
+ * Reworked providers Callback URLs and it's a breaking change! More at http://miled.github.io/wordpress-social-login/migrating-to-3.0.html
78
+ * Added serval new providers: Amazon, Discord and Spotify to name a few.
79
+ * Removal of a number of currently defunct identity providers.
80
+ * Authentication widgets and forms design overhall.
81
+ * Various fixes and minor improvements.
82
+
83
+ = 2.3.0 =
84
+
85
+ * Accounts linking/mapping.
86
+ * Improved Profile Completion.
87
+ * Widget shortcode arguments.
88
+ * Added new translations.
89
+ * Fix an issue with Facebook users profiles.
90
+ * Fix email confirmation in WSL.
91
+ * Small fix for error when merging wsl users with wp users.
92
+ * Remove hardcoded plugin directories.
93
+ * Reduce Twitch TV requested permissions.
94
+
95
+ = 2.2.3 =
96
+
97
+ WSL 2.2.3 fixes a critical issue found on WSL 2.2.2 that could potentially allow multiple accounts and prevent contacts import. We recommend that users upgrade to this latest version.
98
+
99
+ WSL 2.2.3 also include a number of new features, and fixes several stability issues. See below for details.
100
+
101
+ <strong>Developers Release Notes</strong>
102
+
103
+ > These release notes are aimed at developers.
104
+
105
+ This release did focus on code health and flexibility and it was necessary to move some code around, and to remove few functions and hooks. We know, it sucks to break WSL API at such short notice, but it was indispensable and unavoidable as we're trying to move the project forward.
106
+
107
+ As announced on WSL Support Forum, this is by no means a drastic change to the API. In fact, we tried our best to keep the said changes to a strict minimum, and the vast majority of WSL users will not be affected.
108
+
109
+ Those breaking changes are:
110
+
111
+ * Deprecated hooks, prior to 2.2.2, have been removed.
112
+ * Deprecated css selectors, prior to 2.2.2, have been removed.
113
+ * Deprecated internal functions have been removed.
114
+ * Few internal functions have been either removed, renamed or slightly changed.
115
+ * Few pluggable functions has slightly changed.
116
+ * Steam's users identifiers are converted to a new format.
117
+
118
+ Please update the WSL hooks you were using accordingly to the new developer API:
119
+
120
+ http://miled.github.io/wordpress-social-login/developer-api-migrating-2.2.html
121
+ http://miled.github.io/wordpress-social-login/developer-api-authentication.html
122
+ http://miled.github.io/wordpress-social-login/developer-api-widget.html
123
+ http://miled.github.io/wordpress-social-login/developer-api-functions.html
124
+
125
+ On this release we have reworked Steam provider to fully support their new Web API, and we decided to change Steam's users identifiers to SteamID64. When updated, WSL 2.2.3 will automatically convert all the existing steam users identifiers in wslusersprofiles to the new format.
126
+
127
+ It's worth mentioning that in upcoming releases and before we hit WSL 3.0, we're planning to rework other parts of the codebase; for instance user database functions will be re-factored using an ORM, and profile completion will be replaced by new module.
128
+
129
+ We explicitly discourage you from using, or hacking, any internal function (i.e., Not publicly documented on WSL dev API), as they are now subject to change in subsequent releases. If it wasn't possible to achieve some required functionality in a proper way through the already available and documented WSL hooks, please ask for support before resorting to hacks.
130
+
131
+ Upon reaching WSL 3.0 as a major milestone, our priorities will flip to maintenance and stability (i.e, repair code health, enhance code coverage) rather than developing new features. This massive rewrite aims to make WSL more modular easily extended through plugins and add-ons (e.g., http://miled.github.io/wsl-users-converter/).
132
+
133
+ <strong>List of changes</strong>
134
+
135
+ * WSL is now compatible with PHP 5.2 again.
136
+ * WSL is now compatible with WordPress 3.0+ again.
137
+ * WSL now display social apis errors when authentication fails.
138
+ * WSL now support authentications through Dribbble.com.
139
+ * Steam provider has been entirely reworked and now fully support the new Web API.
140
+ * Steam users IDs is now converted to SteamID64 rather than http://steamcommunity.com/openid/id/{USER_STEAMID64}.
141
+ * LinkedIn provider has been enhanced. WSL can now get the full LinkedIn's members avatars and headline (fix).
142
+ * Changed facebook api endpoints to graph api v2.0
143
+ * WSL can now import users contacts from vkontakte.
144
+ * Profile completion form has received a visual update.
145
+ * WSL now provide an easier access to social networks apis.
146
+ * WSL now trigger WordPress do_login action hooks whenever a user connect.
147
+ * Authentication display now fall back to In Page when WSL is used on a mobile device.
148
+ * WSL admin interfaces have been reworked and can be now extended with hooks.
149
+ * Bouncer Membership level can be now set to any user role.
150
+ * WSL Diagnostics has been reworked and can check the minimum system requirements and for few common issues.
151
+ * Added "Repair WSL tables" under Tools tab.
152
+ * Added "Debug mode" under Tools tab (namely whatchdog).
153
+ * Added "Authentication Playground" under Tools tab (namely auth-paly).
154
+ * Added "Uninstall" under Tools tab.
155
+ * Added new hooks in the authentication widget and auth process.
156
+ * Made WSL more RTL friendly.
157
+ * Added 403 pages under wsl folders (silence is.. highly overrated).
158
+ * PHP file wsl.auth.widget.php renamed to wsl.auth.widgets.php
159
+ * Function wsl_render_login_form() renamed to wsl_render_auth_widget()
160
+ * wsl_user_custom_avatar and wsl_bp_user_custom_avatar are now pluggable and can be redefined.
161
+ * wsl_render_notice_page and wsl_render_error_page has slightly changed.
162
+ * Fix a critical issue found on WSL 2.2.2 with wslusersprofiles.
163
+ * Fix an issue where redirect_to get overwritten in some cases.
164
+ * Fix an issue with redirect_to where the callback url was encoded twice.
165
+ * Fix several stability issues.
166
+ * Added testunit to the project (early version).
167
+ * Deprecated hooks, prior to 2.2.2, have been removed.
168
+ * Deprecated internal functions have been removed.
169
+ * Deprecated css selectors, in wsl widget, have been removed.
170
+ * Updated the API documentation for WSL authentication process
171
+ * Updated the API documentation for WSL widget generator
172
+ * Updated the API documentation for pluggable WSL functions
173
+ * Added a list of code snippets to WSL documentation
174
+ * Added documentation for social apis access (through php code)
175
+ * Added documentation for basic troubleshooting (common issues)
176
+ * Added documentation for advanced troubleshooting (internal tools)
177
+
178
+ = 2.2.2 =
179
+
180
+ * Fix an issue where wsl did not display the right user avatar.
181
+ * Fix an issue where providers icons wasn't showing in sites using https.
182
+ * Fix an issue with basic insights, where users counts by age wasn't showing.
183
+ * Add WordPress to list of supported provider.
184
+
185
+ = 2.2.1 =
186
+
187
+ * WSL can be fully integrated with your BuddyPress installation: display of users avatars and xprofiles mapping.
188
+ * WSL is now updated to work with the latest apis changes of the supported social networks.
189
+ * WSL Widget is now more flexible than before and can be fully customized to fit you website theme.
190
+ * Introducing new providers : Reddit, Disqus and PixelPin.
191
+ * WSL Hooks has been reworked and few hooks have been depreciated in favour of new ones. For more information, see: http://hybridauth.sourceforge.net/wsl/developer.html
192
+ * A number of bugfixes, small enhancements and visual updates.
193
+
194
+ = 2.1.3 =
195
+
196
+ * In a similar way to WordPress plugins, WSL uses Components,
197
+ * Email Validation is replaced with Profile Completion,
198
+ * User Moderation made compatible with Theme My Login plugin,
199
+ * A number of enhancements and new options now available but who care
200
+
201
+ = 2.0.3 =
202
+
203
+ * Managing WSL users,
204
+ * Import WSL users contact list from Google Gmail, Facebook, Live and LinkedIn,
205
+ * An entirely reworked user interface,
206
+ * Improving the documentation and guides,
207
+ * Introducing a new module, and the long awaited, The bouncer,
208
+ * Added Twitch.tv and Steam.
209
+
210
+ = 1.2.4 =
211
+
212
+ * WSL admin ui Relooking
213
+ * Code re-factoring
214
+ * add Widget display on advanced settings
215
+ * RIP Gowalla
216
+ * WordPress Social Login is now licensed under The MIT License only (should be GPL compatible)
217
+
218
+ = 0.0.0 =
219
+
220
+ * I'm too old to remember
 
 
 
 
wp-social-login.php CHANGED
@@ -1,267 +1,267 @@
1
- <?php
2
- /*
3
- Plugin Name: WordPress Social Login
4
- Plugin URI: http://miled.github.io/wordpress-social-login/
5
- Description: Allow your visitors to comment and login with social networks such as Twitter, Facebook, Google, Yahoo and more.
6
- Version: 3.0.3
7
- Author: Miled
8
- Author URI: https://github.com/miled
9
- License: MIT License
10
- Text Domain: wordpress-social-login
11
- Domain Path: /languages
12
- */
13
-
14
- /*
15
- *
16
- * Hi and thanks for taking the time to check out WSL code.
17
- *
18
- * Please, don't hesitate to:
19
- *
20
- * - Report bugs and issues.
21
- * - Contribute: code, reviews, ideas and design.
22
- * - Point out stupidity, smells and inconsistencies in the code.
23
- * - Criticize.
24
- *
25
- * If you want to contribute, please consider these general "guide lines":
26
- *
27
- * - Small patches will be always welcome. Large changes should be discussed ahead of time.
28
- * - That said, don't hesitate to delete code that doesn't make sense or looks redundant.
29
- * - Feel free to create new functions and files when needed.
30
- * - Avoid over-commenting, unless you find it necessary.
31
- * - Avoid using 'switch' and 'for'. I hate those.
32
- *
33
- * Coding Style :
34
- *
35
- * - Readable code.
36
- * - Clear indentations (tabs: 8-char indents).
37
- * - Same name convention of WordPress: those long long and self-explanatory functions and variables.
38
- *
39
- * To keep the code accessible to everyone and easy to maintain, WordPress Social Login is programmed in
40
- * procedural PHP and will be kept that way.
41
- *
42
- * If you have fixed, improved or translated something in WSL, Please consider contributing back to the project
43
- * by submitting a Pull Request at https://github.com/miled/wordpress-social-login
44
- *
45
- * Grep's user, read below. Keywords stuffing:<add_action|do_action|add_filter|apply_filters>
46
- *
47
- * If you are here just looking for the hooks, then refer to the online Developer API. If it wasn't possible to
48
- * achieve some required functionality in a proper way through the already available and documented WSL hooks,
49
- * please ask for support before resorting to hacks. WSL internals are not to be used.
50
- * http://miled.github.io/wordpress-social-login/documentation.html
51
- *
52
- * If you want to translate this plugin into your language (or to improve the current translations), you can
53
- * join in the ongoing effort at https://www.transifex.com/projects/p/wordpress-social-login/
54
- *
55
- * Peace.
56
- *
57
- */
58
-
59
- // Exit if accessed directly
60
- if( !defined( 'ABSPATH' ) ) exit;
61
-
62
- // --------------------------------------------------------------------
63
-
64
- global $WORDPRESS_SOCIAL_LOGIN_VERSION;
65
- global $WORDPRESS_SOCIAL_LOGIN_PROVIDERS_CONFIG;
66
- global $WORDPRESS_SOCIAL_LOGIN_COMPONENTS;
67
- global $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS;
68
-
69
- $WORDPRESS_SOCIAL_LOGIN_VERSION = "3.0.3";
70
-
71
- // --------------------------------------------------------------------
72
-
73
- /**
74
- * Initialize PHP sessions
75
- * see implementation in includes/services/wsl.session.php
76
- */
77
- add_action('init', 'wsl_init_php_session');
78
-
79
- // --------------------------------------------------------------------
80
-
81
- /**
82
- * This file might be used to :
83
- * 1. Redefine WSL constants, so you can move WSL folder around.
84
- * 2. Define WSL Pluggable PHP Functions. See http://miled.github.io/wordpress-social-login/developer-api-functions.html
85
- * 5. Implement your WSL hooks.
86
- */
87
- if( file_exists( WP_PLUGIN_DIR . '/wp-social-login-custom.php' ) )
88
- {
89
- include_once( WP_PLUGIN_DIR . '/wp-social-login-custom.php' );
90
- }
91
-
92
- // --------------------------------------------------------------------
93
-
94
- /**
95
- * Define WSL constants, if not already defined
96
- */
97
- defined( 'WORDPRESS_SOCIAL_LOGIN_ABS_PATH' )
98
- || define( 'WORDPRESS_SOCIAL_LOGIN_ABS_PATH', plugin_dir_path( __FILE__ ) );
99
-
100
- defined( 'WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL' )
101
- || define( 'WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
102
-
103
- defined( 'WORDPRESS_SOCIAL_LOGIN_HYBRIDAUTH_ENDPOINT_URL' )
104
- || define( 'WORDPRESS_SOCIAL_LOGIN_HYBRIDAUTH_ENDPOINT_URL', WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . 'hybridauth/' );
105
-
106
- // --------------------------------------------------------------------
107
-
108
- /**
109
- * Check for Wordpress 3.0
110
- */
111
- function wsl_activate()
112
- {
113
- if( ! function_exists( 'register_post_status' ) )
114
- {
115
- deactivate_plugins( basename( dirname( __FILE__ ) ) . '/' . basename (__FILE__) );
116
-
117
- wp_die( __( "This plugin requires WordPress 3.0 or newer. Please update your WordPress installation to activate this plugin.", 'wordpress-social-login' ) );
118
- }
119
- }
120
-
121
- register_activation_hook( __FILE__, 'wsl_activate' );
122
-
123
- // --------------------------------------------------------------------
124
-
125
- /**
126
- * Attempt to install/migrate/repair WSL upon activation
127
- *
128
- * Create wsl tables
129
- * Migrate old versions
130
- * Register default components
131
- */
132
- function wsl_install()
133
- {
134
- wsl_database_install();
135
-
136
- wsl_update_compatibilities();
137
-
138
- wsl_register_components();
139
- }
140
-
141
- register_activation_hook( __FILE__, 'wsl_install' );
142
-
143
- // --------------------------------------------------------------------
144
-
145
- /**
146
- * Add a settings to plugin_action_links
147
- */
148
- function wsl_add_plugin_action_links( $links, $file )
149
- {
150
- static $this_plugin;
151
-
152
- if( ! $this_plugin )
153
- {
154
- $this_plugin = plugin_basename( __FILE__ );
155
- }
156
-
157
- if( $file == $this_plugin )
158
- {
159
- $wsl_links = '<a href="options-general.php?page=wordpress-social-login">' . __( "Settings" ) . '</a>';
160
-
161
- array_unshift( $links, $wsl_links );
162
- }
163
-
164
- return $links;
165
- }
166
-
167
- add_filter( 'plugin_action_links', 'wsl_add_plugin_action_links', 10, 2 );
168
-
169
- // --------------------------------------------------------------------
170
-
171
- /**
172
- * Add faq and user guide links to plugin_row_meta
173
- */
174
- function wsl_add_plugin_row_meta( $links, $file )
175
- {
176
- static $this_plugin;
177
-
178
- if( ! $this_plugin )
179
- {
180
- $this_plugin = plugin_basename( __FILE__ );
181
- }
182
-
183
- if( $file == $this_plugin )
184
- {
185
- $wsl_links = array(
186
- '<a href="http://miled.github.io/wordpress-social-login/">' . _wsl__( "Docs" , 'wordpress-social-login' ) . '</a>',
187
- '<a href="http://miled.github.io/wordpress-social-login/support.html">' . _wsl__( "Support" , 'wordpress-social-login' ) . '</a>',
188
- '<a href="https://github.com/miled/wordpress-social-login">' . _wsl__( "Fork me on Github", 'wordpress-social-login' ) . '</a>',
189
- );
190
-
191
- return array_merge( $links, $wsl_links );
192
- }
193
-
194
- return $links;
195
- }
196
-
197
- add_filter( 'plugin_row_meta', 'wsl_add_plugin_row_meta', 10, 2 );
198
-
199
- // --------------------------------------------------------------------
200
-
201
- /**
202
- * Loads the plugin's translated strings.
203
- *
204
- * http://codex.wordpress.org/Function_Reference/load_plugin_textdomain
205
- */
206
- if( ! function_exists( 'wsl_load_plugin_textdomain' ) )
207
- {
208
- function wsl_load_plugin_textdomain()
209
- {
210
- load_plugin_textdomain( 'wordpress-social-login', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
211
- }
212
- }
213
-
214
- add_action( 'plugins_loaded', 'wsl_load_plugin_textdomain' );
215
-
216
- // --------------------------------------------------------------------
217
-
218
- /**
219
- * _e() wrapper
220
- */
221
- function _wsl_e( $text, $domain )
222
- {
223
- echo __( $text, $domain );
224
- }
225
-
226
- // --------------------------------------------------------------------
227
-
228
- /**
229
- * __() wrapper
230
- */
231
- function _wsl__( $text, $domain )
232
- {
233
- return __( $text, $domain );
234
- }
235
-
236
- // --------------------------------------------------------------------
237
-
238
- /* includes */
239
-
240
- # WSL Setup & Settings
241
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/settings/wsl.providers.php' ); // List of supported providers (mostly provided by hybridauth library)
242
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/settings/wsl.database.php' ); // Install/Uninstall WSL database tables
243
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/settings/wsl.initialization.php' ); // Check WSL requirements and register WSL settings
244
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/settings/wsl.compatibilities.php' ); // Check and upgrade WSL database/settings (for older versions)
245
-
246
- # Services & Utilities
247
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.authentication.php' ); // Authenticate users via social networks. <- that's the most important script
248
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.mail.notification.php' ); // Emails and notifications
249
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.user.avatar.php' ); // Display users avatar
250
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.user.data.php' ); // User data functions (database related)
251
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.session.php' ); // Manage PHP session
252
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.utilities.php' ); // Unclassified functions & utilities
253
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.watchdog.php' ); // WSL logging agent
254
-
255
- # WSL Widgets & Front-end interfaces
256
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/widgets/wsl.auth.widgets.php' ); // Authentication widget generators (where WSL widget/icons are displayed)
257
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/widgets/wsl.users.gateway.php' ); // Accounts linking + Profile Completion
258
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/widgets/wsl.error.pages.php' ); // Generate WSL notices end errors pages
259
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/widgets/wsl.loading.screens.php' ); // Generate WSL loading screens
260
-
261
- # WSL Admin interfaces
262
- if( is_admin() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) )
263
- {
264
- require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/admin/wsl.admin.ui.php' ); // The entry point to WSL Admin interfaces
265
- }
266
-
267
- // --------------------------------------------------------------------
1
+ <?php
2
+ /*
3
+ Plugin Name: WordPress Social Login
4
+ Plugin URI: http://miled.github.io/wordpress-social-login/
5
+ Description: Allow your visitors to comment and login with social networks such as Twitter, Facebook, Google, Yahoo and more.
6
+ Version: 3.0.4
7
+ Author: Miled
8
+ Author URI: https://github.com/miled
9
+ License: MIT License
10
+ Text Domain: wordpress-social-login
11
+ Domain Path: /languages
12
+ */
13
+
14
+ /*
15
+ *
16
+ * Hi and thanks for taking the time to check out WSL code.
17
+ *
18
+ * Please, don't hesitate to:
19
+ *
20
+ * - Report bugs and issues.
21
+ * - Contribute: code, reviews, ideas and design.
22
+ * - Point out stupidity, smells and inconsistencies in the code.
23
+ * - Criticize.
24
+ *
25
+ * If you want to contribute, please consider these general "guide lines":
26
+ *
27
+ * - Small patches will be always welcome. Large changes should be discussed ahead of time.
28
+ * - That said, don't hesitate to delete code that doesn't make sense or looks redundant.
29
+ * - Feel free to create new functions and files when needed.
30
+ * - Avoid over-commenting, unless you find it necessary.
31
+ * - Avoid using 'switch' and 'for'. I hate those.
32
+ *
33
+ * Coding Style :
34
+ *
35
+ * - Readable code.
36
+ * - Clear indentations (tabs: 8-char indents).
37
+ * - Same name convention of WordPress: those long long and self-explanatory functions and variables.
38
+ *
39
+ * To keep the code accessible to everyone and easy to maintain, WordPress Social Login is programmed in
40
+ * procedural PHP and will be kept that way.
41
+ *
42
+ * If you have fixed, improved or translated something in WSL, Please consider contributing back to the project
43
+ * by submitting a Pull Request at https://github.com/miled/wordpress-social-login
44
+ *
45
+ * Grep's user, read below. Keywords stuffing:<add_action|do_action|add_filter|apply_filters>
46
+ *
47
+ * If you are here just looking for the hooks, then refer to the online Developer API. If it wasn't possible to
48
+ * achieve some required functionality in a proper way through the already available and documented WSL hooks,
49
+ * please ask for support before resorting to hacks. WSL internals are not to be used.
50
+ * http://miled.github.io/wordpress-social-login/documentation.html
51
+ *
52
+ * If you want to translate this plugin into your language (or to improve the current translations), you can
53
+ * join in the ongoing effort at https://www.transifex.com/projects/p/wordpress-social-login/
54
+ *
55
+ * Peace.
56
+ *
57
+ */
58
+
59
+ // Exit if accessed directly
60
+ if( !defined( 'ABSPATH' ) ) exit;
61
+
62
+ // --------------------------------------------------------------------
63
+
64
+ global $WORDPRESS_SOCIAL_LOGIN_VERSION;
65
+ global $WORDPRESS_SOCIAL_LOGIN_PROVIDERS_CONFIG;
66
+ global $WORDPRESS_SOCIAL_LOGIN_COMPONENTS;
67
+ global $WORDPRESS_SOCIAL_LOGIN_ADMIN_TABS;
68
+
69
+ $WORDPRESS_SOCIAL_LOGIN_VERSION = "3.0.3";
70
+
71
+ // --------------------------------------------------------------------
72
+
73
+ /**
74
+ * Initialize PHP sessions
75
+ * see implementation in includes/services/wsl.session.php
76
+ */
77
+ add_action('init', 'wsl_init_php_session');
78
+
79
+ // --------------------------------------------------------------------
80
+
81
+ /**
82
+ * This file might be used to :
83
+ * 1. Redefine WSL constants, so you can move WSL folder around.
84
+ * 2. Define WSL Pluggable PHP Functions. See http://miled.github.io/wordpress-social-login/developer-api-functions.html
85
+ * 5. Implement your WSL hooks.
86
+ */
87
+ if( file_exists( WP_PLUGIN_DIR . '/wp-social-login-custom.php' ) )
88
+ {
89
+ include_once( WP_PLUGIN_DIR . '/wp-social-login-custom.php' );
90
+ }
91
+
92
+ // --------------------------------------------------------------------
93
+
94
+ /**
95
+ * Define WSL constants, if not already defined
96
+ */
97
+ defined( 'WORDPRESS_SOCIAL_LOGIN_ABS_PATH' )
98
+ || define( 'WORDPRESS_SOCIAL_LOGIN_ABS_PATH', plugin_dir_path( __FILE__ ) );
99
+
100
+ defined( 'WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL' )
101
+ || define( 'WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
102
+
103
+ defined( 'WORDPRESS_SOCIAL_LOGIN_HYBRIDAUTH_ENDPOINT_URL' )
104
+ || define( 'WORDPRESS_SOCIAL_LOGIN_HYBRIDAUTH_ENDPOINT_URL', WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . 'hybridauth/' );
105
+
106
+ // --------------------------------------------------------------------
107
+
108
+ /**
109
+ * Check for Wordpress 3.0
110
+ */
111
+ function wsl_activate()
112
+ {
113
+ if( ! function_exists( 'register_post_status' ) )
114
+ {
115
+ deactivate_plugins( basename( dirname( __FILE__ ) ) . '/' . basename (__FILE__) );
116
+
117
+ wp_die( __( "This plugin requires WordPress 3.0 or newer. Please update your WordPress installation to activate this plugin.", 'wordpress-social-login' ) );
118
+ }
119
+ }
120
+
121
+ register_activation_hook( __FILE__, 'wsl_activate' );
122
+
123
+ // --------------------------------------------------------------------
124
+
125
+ /**
126
+ * Attempt to install/migrate/repair WSL upon activation
127
+ *
128
+ * Create wsl tables
129
+ * Migrate old versions
130
+ * Register default components
131
+ */
132
+ function wsl_install()
133
+ {
134
+ wsl_database_install();
135
+
136
+ wsl_update_compatibilities();
137
+
138
+ wsl_register_components();
139
+ }
140
+
141
+ register_activation_hook( __FILE__, 'wsl_install' );
142
+
143
+ // --------------------------------------------------------------------
144
+
145
+ /**
146
+ * Add a settings to plugin_action_links
147
+ */
148
+ function wsl_add_plugin_action_links( $links, $file )
149
+ {
150
+ static $this_plugin;
151
+
152
+ if( ! $this_plugin )
153
+ {
154
+ $this_plugin = plugin_basename( __FILE__ );
155
+ }
156
+
157
+ if( $file == $this_plugin )
158
+ {
159
+ $wsl_links = '<a href="options-general.php?page=wordpress-social-login">' . __( "Settings" ) . '</a>';
160
+
161
+ array_unshift( $links, $wsl_links );
162
+ }
163
+
164
+ return $links;
165
+ }
166
+
167
+ add_filter( 'plugin_action_links', 'wsl_add_plugin_action_links', 10, 2 );
168
+
169
+ // --------------------------------------------------------------------
170
+
171
+ /**
172
+ * Add faq and user guide links to plugin_row_meta
173
+ */
174
+ function wsl_add_plugin_row_meta( $links, $file )
175
+ {
176
+ static $this_plugin;
177
+
178
+ if( ! $this_plugin )
179
+ {
180
+ $this_plugin = plugin_basename( __FILE__ );
181
+ }
182
+
183
+ if( $file == $this_plugin )
184
+ {
185
+ $wsl_links = array(
186
+ '<a href="http://miled.github.io/wordpress-social-login/">' . _wsl__( "Docs" , 'wordpress-social-login' ) . '</a>',
187
+ '<a href="http://miled.github.io/wordpress-social-login/support.html">' . _wsl__( "Support" , 'wordpress-social-login' ) . '</a>',
188
+ '<a href="https://github.com/miled/wordpress-social-login">' . _wsl__( "Fork me on Github", 'wordpress-social-login' ) . '</a>',
189
+ );
190
+
191
+ return array_merge( $links, $wsl_links );
192
+ }
193
+
194
+ return $links;
195
+ }
196
+
197
+ add_filter( 'plugin_row_meta', 'wsl_add_plugin_row_meta', 10, 2 );
198
+
199
+ // --------------------------------------------------------------------
200
+
201
+ /**
202
+ * Loads the plugin's translated strings.
203
+ *
204
+ * http://codex.wordpress.org/Function_Reference/load_plugin_textdomain
205
+ */
206
+ if( ! function_exists( 'wsl_load_plugin_textdomain' ) )
207
+ {
208
+ function wsl_load_plugin_textdomain()
209
+ {
210
+ load_plugin_textdomain( 'wordpress-social-login', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
211
+ }
212
+ }
213
+
214
+ add_action( 'plugins_loaded', 'wsl_load_plugin_textdomain' );
215
+
216
+ // --------------------------------------------------------------------
217
+
218
+ /**
219
+ * _e() wrapper
220
+ */
221
+ function _wsl_e( $text, $domain )
222
+ {
223
+ echo __( $text, $domain );
224
+ }
225
+
226
+ // --------------------------------------------------------------------
227
+
228
+ /**
229
+ * __() wrapper
230
+ */
231
+ function _wsl__( $text, $domain )
232
+ {
233
+ return __( $text, $domain );
234
+ }
235
+
236
+ // --------------------------------------------------------------------
237
+
238
+ /* includes */
239
+
240
+ # WSL Setup & Settings
241
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/settings/wsl.providers.php' ); // List of supported providers (mostly provided by hybridauth library)
242
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/settings/wsl.database.php' ); // Install/Uninstall WSL database tables
243
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/settings/wsl.initialization.php' ); // Check WSL requirements and register WSL settings
244
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/settings/wsl.compatibilities.php' ); // Check and upgrade WSL database/settings (for older versions)
245
+
246
+ # Services & Utilities
247
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.authentication.php' ); // Authenticate users via social networks. <- that's the most important script
248
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.mail.notification.php' ); // Emails and notifications
249
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.user.avatar.php' ); // Display users avatar
250
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.user.data.php' ); // User data functions (database related)
251
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.session.php' ); // Manage PHP session
252
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.utilities.php' ); // Unclassified functions & utilities
253
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/services/wsl.watchdog.php' ); // WSL logging agent
254
+
255
+ # WSL Widgets & Front-end interfaces
256
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/widgets/wsl.auth.widgets.php' ); // Authentication widget generators (where WSL widget/icons are displayed)
257
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/widgets/wsl.users.gateway.php' ); // Accounts linking + Profile Completion
258
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/widgets/wsl.error.pages.php' ); // Generate WSL notices end errors pages
259
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/widgets/wsl.loading.screens.php' ); // Generate WSL loading screens
260
+
261
+ # WSL Admin interfaces
262
+ if( is_admin() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) )
263
+ {
264
+ require_once( WORDPRESS_SOCIAL_LOGIN_ABS_PATH . 'includes/admin/wsl.admin.ui.php' ); // The entry point to WSL Admin interfaces
265
+ }
266
+
267
+ // --------------------------------------------------------------------