From 6547b91ca3fc20e20089fd16465352ff7ae5af2d Mon Sep 17 00:00:00 2001 From: Nick Matthews Date: Sun, 17 Apr 2016 17:17:57 +0000 Subject: [PATCH 1/4] Implementing new Birthday class to handle Graph API response variations --- docs/Birthday.fbmd | 63 ++++++++++++++++++ docs/GraphNode.fbmd | 4 +- docs/sdk_reference.fbmd | 4 ++ src/Facebook/GraphNodes/Birthday.php | 92 +++++++++++++++++++++++++++ src/Facebook/GraphNodes/GraphNode.php | 16 ++++- tests/GraphNodes/GraphUserTest.php | 66 ++++++++++++++++++- 6 files changed, 240 insertions(+), 5 deletions(-) create mode 100644 docs/Birthday.fbmd create mode 100644 src/Facebook/GraphNodes/Birthday.php diff --git a/docs/Birthday.fbmd b/docs/Birthday.fbmd new file mode 100644 index 000000000..3be5fcf0f --- /dev/null +++ b/docs/Birthday.fbmd @@ -0,0 +1,63 @@ + +# Birthday for the Facebook SDK for PHP + +Extends `\DateTime` and represents a user's birthday returned from the Graph API which can be returned omitting certain information. + +Users may opt not to share birth day or month, or may not share birth year. Possible returns: + +* MM/DD/YYYY +* MM/DD +* YYYY + + + +## Facebook\GraphNodes\Birthday {#overview} + +After retrieving a GraphUser from the Graph API, the `getBirthday()` method will return the birthday in the form of a `Facebook\GraphNodes\Birthday` entity which indicates which aspects of the birthday the user opted to share. + +The `Facebook\GraphNodes\Birthday` entity extends `DateTime` so `format` may be used to present the information appropriately depending on what information it contains. + +Usage: + +~~~~ +$fb = new Facebook\Facebook(\* *\); +// Returns a `Facebook\FacebookResponse` object +$response = $fb->get('/something'); + +// Get the response typed as a GraphUser +$user = $response->getGraphUser(); + +// Gets birthday value, assume graph return was format MM/DD +$birthday = $user->getBirthday(); + +var_dump($birthday); +// class Facebook\GraphNodes\Birthday ... + +var_dump($birthday->hasDate()); +// true + +var_dump($birthday->hasYear()); +// false + +var_dump($birthday->format('m/d')); +// 03/21 +~~~~ + + + +## Instance Methods {#instance-methods} + +### hasDate() {#has-date} +~~~~ +public boolean hasDate() +~~~~ +Returns whether or not the birthday object contains the day and month of birth. + + + +### hasYear() {#has-year} +~~~~ +public boolean hasYear() +~~~~ +Returns whether or not the birthday object contains the year of birth. + diff --git a/docs/GraphNode.fbmd b/docs/GraphNode.fbmd index 66ca76aae..c7cc30ea9 100644 --- a/docs/GraphNode.fbmd +++ b/docs/GraphNode.fbmd @@ -166,9 +166,9 @@ Returns the `link` property for the user as a string if present. ### getBirthday() {#user-getbirthday} ~~~~ -public \DateTime|null getBirthday() +public \Facebook\GraphNodes\Birthday|null getBirthday() ~~~~ -Returns the `birthday` property for the user as a `\DateTime` if present. +Returns the `birthday` property for the user as a `\Facebook\GraphNodes\Birthday` if present. ### getLocation() {#user-getlocation} ~~~~ diff --git a/docs/sdk_reference.fbmd b/docs/sdk_reference.fbmd index 2ab60bb16..8832d0844 100644 --- a/docs/sdk_reference.fbmd +++ b/docs/sdk_reference.fbmd @@ -172,6 +172,10 @@ Graph nodes are collections that represent nodes returned by the Graph API. And '[`Facebook\\GraphNodes\\GraphUser`](/docs/php/GraphNode#user-instance-methods)', 'A collection that represents a User node.', ], + [ + '[`Facebook\\GraphNodes\\Birthday`](/docs/php/Birthday#instance-methods)', + 'A class that represents a GraphUser\'s birthday.', + ], ], }) diff --git a/src/Facebook/GraphNodes/Birthday.php b/src/Facebook/GraphNodes/Birthday.php new file mode 100644 index 000000000..05c78a9ae --- /dev/null +++ b/src/Facebook/GraphNodes/Birthday.php @@ -0,0 +1,92 @@ +hasYear = true; + } + + if (count($parts) === 3 || count($parts) === 2) { + $this->hasDate = true; + } + + parent::__construct($date, $timezone); + } + + /** + * Returns whether date object contains birth day and month + * + * @return bool + */ + public function hasDate() + { + return $this->hasDate; + } + + /** + * Returns whether date object contains birth year + * + * @return bool + */ + public function hasYear() + { + return $this->hasYear; + } +} diff --git a/src/Facebook/GraphNodes/GraphNode.php b/src/Facebook/GraphNodes/GraphNode.php index c9f58c348..f838b3062 100644 --- a/src/Facebook/GraphNodes/GraphNode.php +++ b/src/Facebook/GraphNodes/GraphNode.php @@ -62,10 +62,11 @@ public function castItems(array $data) foreach ($data as $k => $v) { if ($this->shouldCastAsDateTime($k) && (is_numeric($v) - || $k === 'birthday' || $this->isIso8601DateString($v)) ) { $items[$k] = $this->castToDateTime($v); + } else if ($k === 'birthday') { + $items[$k] = $this->castToBirthday($v); } else { $items[$k] = $v; } @@ -149,7 +150,6 @@ public function shouldCastAsDateTime($key) 'backdated_time', 'issued_at', 'expires_at', - 'birthday', 'publish_time' ], true); } @@ -173,6 +173,18 @@ public function castToDateTime($value) return $dt; } + /** + * Casts a birthday value from Graph to Birthday + * + * @param string $value + * + * @return \Facebook\GraphNodes\Birthday + */ + public function castToBirthday($value) + { + return new Birthday($value); + } + /** * Getter for $graphObjectMap. * diff --git a/tests/GraphNodes/GraphUserTest.php b/tests/GraphNodes/GraphUserTest.php index 25a7cc5a4..e545065d5 100644 --- a/tests/GraphNodes/GraphUserTest.php +++ b/tests/GraphNodes/GraphUserTest.php @@ -42,7 +42,25 @@ public function setUp() public function testDatesGetCastToDateTime() { $dataFromGraph = [ - 'birthday' => '1984-01-01', + 'updated_time' => '2016-04-26 13:22:05' + ]; + + $this->responseMock + ->shouldReceive('getDecodedBody') + ->once() + ->andReturn($dataFromGraph); + $factory = new GraphNodeFactory($this->responseMock); + $graphNode = $factory->makeGraphUser(); + + $updatedTime = $graphNode->getField('updated_time'); + + $this->assertInstanceOf('DateTime', $updatedTime); + } + + public function testBirthdaysGetCastToBirthday() + { + $dataFromGraph = [ + 'birthday' => '1984/01/01', ]; $this->responseMock @@ -54,7 +72,53 @@ public function testDatesGetCastToDateTime() $birthday = $graphNode->getBirthday(); + // Test to ensure BC $this->assertInstanceOf('DateTime', $birthday); + + $this->assertInstanceOf('\\Facebook\\GraphNodes\\Birthday', $birthday); + $this->assertTrue($birthday->hasDate()); + $this->assertTrue($birthday->hasYear()); + $this->assertEquals('1984/01/01', $birthday->format('Y/m/d')); + } + + public function testBirthdayCastHandlesDateWithoutYear() + { + $dataFromGraph = [ + 'birthday' => '03/21', + ]; + + $this->responseMock + ->shouldReceive('getDecodedBody') + ->once() + ->andReturn($dataFromGraph); + $factory = new GraphNodeFactory($this->responseMock); + $graphNode = $factory->makeGraphUser(); + + $birthday = $graphNode->getBirthday(); + + $this->assertTrue($birthday->hasDate()); + $this->assertFalse($birthday->hasYear()); + $this->assertEquals('03/21', $birthday->format('m/d')); + } + + public function testBirthdayCastHandlesYearWithoutDate() + { + $dataFromGraph = [ + 'birthday' => '1984', + ]; + + $this->responseMock + ->shouldReceive('getDecodedBody') + ->once() + ->andReturn($dataFromGraph); + $factory = new GraphNodeFactory($this->responseMock); + $graphNode = $factory->makeGraphUser(); + + $birthday = $graphNode->getBirthday(); + + $this->assertTrue($birthday->hasYear()); + $this->assertFalse($birthday->hasDate()); + $this->assertEquals('1984', $birthday->format('Y')); } public function testPagePropertiesWillGetCastAsGraphPageObjects() From 3ee3ac068544b1c268becc4a18cc3075f1393e3c Mon Sep 17 00:00:00 2001 From: Nick Matthews Date: Sun, 17 Apr 2016 17:55:06 +0000 Subject: [PATCH 2/4] Correcting typos in Birthday docs --- docs/Birthday.fbmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Birthday.fbmd b/docs/Birthday.fbmd index 3be5fcf0f..303a29da3 100644 --- a/docs/Birthday.fbmd +++ b/docs/Birthday.fbmd @@ -22,12 +22,12 @@ Usage: ~~~~ $fb = new Facebook\Facebook(\* *\); // Returns a `Facebook\FacebookResponse` object -$response = $fb->get('/something'); +$response = $fb->get('/me'); // Get the response typed as a GraphUser $user = $response->getGraphUser(); -// Gets birthday value, assume graph return was format MM/DD +// Gets birthday value, assume Graph return was format MM/DD $birthday = $user->getBirthday(); var_dump($birthday); From 6b596986000108bc928faf5bb2386e301c505e74 Mon Sep 17 00:00:00 2001 From: Nick Matthews Date: Sun, 17 Apr 2016 19:01:58 +0000 Subject: [PATCH 3/4] Coding style violations, removing timezone --- src/Facebook/GraphNodes/Birthday.php | 17 +++++------------ src/Facebook/GraphNodes/GraphNode.php | 4 ++-- tests/GraphNodes/GraphUserTest.php | 2 +- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/Facebook/GraphNodes/Birthday.php b/src/Facebook/GraphNodes/Birthday.php index 05c78a9ae..35ca57d23 100644 --- a/src/Facebook/GraphNodes/Birthday.php +++ b/src/Facebook/GraphNodes/Birthday.php @@ -24,7 +24,6 @@ namespace Facebook\GraphNodes; use DateTime; -use DateTimeZone; /** * Birthday object to handle various Graph return formats @@ -52,22 +51,16 @@ class Birthday extends DateTime * * @link https://developers.facebook.com/docs/graph-api/reference/user * - * @param string $date - * @param DateTimeZone $timezone + * @param string $date */ - public function __construct($date, DateTimeZone $timezone = null) + public function __construct($date) { $parts = explode('/', $date); - if (count($parts) === 3 || count($parts) === 1) { - $this->hasYear = true; - } + $this->hasYear = count($parts) === 3 || count($parts) === 1; + $this->hasDate = count($parts) === 3 || count($parts) === 2; - if (count($parts) === 3 || count($parts) === 2) { - $this->hasDate = true; - } - - parent::__construct($date, $timezone); + parent::__construct($date); } /** diff --git a/src/Facebook/GraphNodes/GraphNode.php b/src/Facebook/GraphNodes/GraphNode.php index f838b3062..bd79bf0ea 100644 --- a/src/Facebook/GraphNodes/GraphNode.php +++ b/src/Facebook/GraphNodes/GraphNode.php @@ -65,7 +65,7 @@ public function castItems(array $data) || $this->isIso8601DateString($v)) ) { $items[$k] = $this->castToDateTime($v); - } else if ($k === 'birthday') { + } elseif ($k === 'birthday') { $items[$k] = $this->castToBirthday($v); } else { $items[$k] = $v; @@ -178,7 +178,7 @@ public function castToDateTime($value) * * @param string $value * - * @return \Facebook\GraphNodes\Birthday + * @return Birthday */ public function castToBirthday($value) { diff --git a/tests/GraphNodes/GraphUserTest.php b/tests/GraphNodes/GraphUserTest.php index e545065d5..415116a4e 100644 --- a/tests/GraphNodes/GraphUserTest.php +++ b/tests/GraphNodes/GraphUserTest.php @@ -42,7 +42,7 @@ public function setUp() public function testDatesGetCastToDateTime() { $dataFromGraph = [ - 'updated_time' => '2016-04-26 13:22:05' + 'updated_time' => '2016-04-26 13:22:05', ]; $this->responseMock From e4e6df7a0f131bf8e8eb7240ccb1b02cf173ed21 Mon Sep 17 00:00:00 2001 From: Nick Matthews Date: Tue, 19 Apr 2016 21:01:40 +0000 Subject: [PATCH 4/4] Setting Birthday variables to private, moving Birthday docs link to more appropriate location --- docs/GraphNode.fbmd | 2 +- docs/sdk_reference.fbmd | 4 ---- src/Facebook/GraphNodes/Birthday.php | 4 ++-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/docs/GraphNode.fbmd b/docs/GraphNode.fbmd index c7cc30ea9..0263fa4f2 100644 --- a/docs/GraphNode.fbmd +++ b/docs/GraphNode.fbmd @@ -168,7 +168,7 @@ Returns the `link` property for the user as a string if present. ~~~~ public \Facebook\GraphNodes\Birthday|null getBirthday() ~~~~ -Returns the `birthday` property for the user as a `\Facebook\GraphNodes\Birthday` if present. +Returns the `birthday` property for the user as a [`Facebook\GraphNodes\Birthday`](/docs/php/Birthday) if present. ### getLocation() {#user-getlocation} ~~~~ diff --git a/docs/sdk_reference.fbmd b/docs/sdk_reference.fbmd index 8832d0844..2ab60bb16 100644 --- a/docs/sdk_reference.fbmd +++ b/docs/sdk_reference.fbmd @@ -172,10 +172,6 @@ Graph nodes are collections that represent nodes returned by the Graph API. And '[`Facebook\\GraphNodes\\GraphUser`](/docs/php/GraphNode#user-instance-methods)', 'A collection that represents a User node.', ], - [ - '[`Facebook\\GraphNodes\\Birthday`](/docs/php/Birthday#instance-methods)', - 'A class that represents a GraphUser\'s birthday.', - ], ], }) diff --git a/src/Facebook/GraphNodes/Birthday.php b/src/Facebook/GraphNodes/Birthday.php index 35ca57d23..e45dcf4b1 100644 --- a/src/Facebook/GraphNodes/Birthday.php +++ b/src/Facebook/GraphNodes/Birthday.php @@ -35,12 +35,12 @@ class Birthday extends DateTime /** * @var bool */ - protected $hasDate = false; + private $hasDate = false; /** * @var bool */ - protected $hasYear = false; + private $hasYear = false; /** * Parses Graph birthday format to set indication flags, possible values: