Commit 165e9ede by Klimov Paul

Added ability to operate nested and complex attributes via…

Added ability to operate nested and complex attributes via `yii\authclient\BaseClient::normalizeUserAttributeMap`
parent 239d48c3
......@@ -9,6 +9,7 @@ namespace yii\authclient;
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
use yii\base\NotSupportedException;
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
......@@ -50,7 +51,23 @@ abstract class BaseClient extends Component implements ClientInterface
private $_userAttributes;
/**
* @var array map used to normalize user attributes fetched from external auth service
* in format: rawAttributeName => normalizedAttributeName
* in format: normalizedAttributeName => sourceSpecification
* 'sourceSpecification' can be:
* - string, raw attribute name
* - array, pass to raw attribute value
* - callable, PHP callback, which should accept array of raw attributes and return normalized value.
*
* For example:
*
* ```php
* 'normalizeUserAttributeMap' => [
* 'about' => 'bio',
* 'language' => ['languages', 0, 'name'],
* 'fullName' => function ($attributes) {
* return $attributes['firstName'] . ' ' . $attributes['lastName'];
* },
* ],
* ```
*/
private $_normalizeUserAttributeMap;
/**
......@@ -229,14 +246,38 @@ abstract class BaseClient extends Component implements ClientInterface
/**
* Normalize given user attributes according to [[normalizeUserAttributeMap]].
* @param array $attributes raw attributes.
* @throws InvalidConfigException on incorrect normalize attribute map.
* @return array normalized attributes.
*/
protected function normalizeUserAttributes($attributes)
{
foreach ($this->getNormalizeUserAttributeMap() as $normalizedName => $actualName) {
if (is_scalar($actualName)) {
if (array_key_exists($actualName, $attributes)) {
$attributes[$normalizedName] = $attributes[$actualName];
}
} else {
if (is_callable($actualName)) {
$attributes[$normalizedName] = call_user_func($actualName, $attributes);
} elseif (is_array($actualName)) {
$haystack = $attributes;
$searchKeys = $actualName;
$isFound = true;
while (($key = array_shift($searchKeys)) !== null) {
if (is_array($haystack) && array_key_exists($key, $haystack)) {
$haystack = $haystack[$key];
} else {
$isFound = false;
break;
}
}
if ($isFound) {
$attributes[$normalizedName] = $haystack;
}
} else {
throw new InvalidConfigException('Invalid actual name "' . gettype($actualName) . '" specified at "' . get_class($this) . '::normalizeUserAttributeMap"');
}
}
}
return $attributes;
......
......@@ -4,7 +4,7 @@ Yii Framework 2 authclient extension Change Log
2.0.0 under development
-----------------------
- no changes in this release.
- Enh #5135: Added ability to operate nested and complex attributes via `yii\authclient\BaseClient::normalizeUserAttributeMap` (zinzinday, klimov-paul)
2.0.0-rc September 27, 2014
......
......@@ -155,7 +155,6 @@ Following predefined auth clients are available:
- [[yii\authclient\clients\GoogleOAuth]] - [Google](https://www.google.com/) OAuth2 client
- [[yii\authclient\clients\GoogleOpenId]] - [Google](https://www.google.com/) OpenID client
- [[yii\authclient\clients\LinkedIn]] - [LinkedIn](http://www.linkedin.com/) OAuth2 client
- [[yii\authclient\clients\LinkedIn]] - [LinkedIn](http://www.linkedin.com/) OAuth2 client
- [[yii\authclient\clients\Live]] - [Microsoft Live](http://live.com/) OAuth2 client
- [[yii\authclient\clients\Twitter]] - [Twitter](https://twitter.com/) OAuth1 client
- [[yii\authclient\clients\VKontakte]] - [VKontakte](http://vk.com/) OAuth2 client
......
......@@ -55,25 +55,88 @@ class BaseClientTest extends TestCase
}
/**
* @depends testSetGet
* Data provider for [[testNormalizeUserAttributes()]]
* @return array test data
*/
public function testNormalizeUserAttributes()
public function dataProviderNormalizeUserAttributes()
{
$client = new Client();
$normalizeUserAttributeMap = [
'raw/name' => 'name',
'raw/email' => 'email',
];
$client->setNormalizeUserAttributeMap($normalizeUserAttributeMap);
$rawUserAttributes = [
return [
[
[
'name' => 'raw/name',
'email' => 'raw/email',
],
[
'raw/name' => 'name value',
'raw/email' => 'email value',
],
[
'name' => 'name value',
'email' => 'email value',
],
],
[
[
'name' => function ($attributes) {
return $attributes['firstName'] . ' ' . $attributes['lastName'];
},
],
[
'firstName' => 'John',
'lastName' => 'Smith',
],
[
'name' => 'John Smith',
],
],
[
[
'email' => ['emails', 'prime'],
],
[
'emails' => [
'prime' => 'some@email.com'
],
],
[
'email' => 'some@email.com',
],
],
[
[
'email' => ['emails', 0],
'secondaryEmail' => ['emails', 1],
],
[
'emails' => [
'some@email.com',
],
],
[
'email' => 'some@email.com',
],
],
];
}
/**
* @dataProvider dataProviderNormalizeUserAttributes
*
* @depends testSetGet
*
* @param array $normalizeUserAttributeMap
* @param array $rawUserAttributes
* @param array $expectedNormalizedUserAttributes
*/
public function testNormalizeUserAttributes($normalizeUserAttributeMap, $rawUserAttributes, $expectedNormalizedUserAttributes)
{
$client = new Client();
$client->setNormalizeUserAttributeMap($normalizeUserAttributeMap);
$client->setUserAttributes($rawUserAttributes);
$normalizedUserAttributes = $client->getUserAttributes();
$expectedNormalizedUserAttributes = array_combine(array_keys($normalizeUserAttributeMap), array_values($rawUserAttributes));
$this->assertEquals($expectedNormalizedUserAttributes, $normalizedUserAttributes);
$this->assertEquals(array_merge($rawUserAttributes, $expectedNormalizedUserAttributes), $normalizedUserAttributes);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment