From afd7465a223eda6c3a362e4a5ecb62e0b2fe874c Mon Sep 17 00:00:00 2001
From: Bruno Skvorc <bruno@skvorc.me>
Date: Thu, 12 Nov 2015 19:07:00 +0000
Subject: [PATCH] Added basic Account API support

---
 dash.html                                  |   0
 src/Abstracts/Entity.php                   |   7 +
 src/Diffbot.php                            |  33 +++
 src/Entity/Account.php                     | 121 +++++++++
 src/Traits/StandardEntity.php              |   6 -
 tests/Entity/AccountTest.php               | 274 +++++++++++++++++++++
 tests/Mocks/Account/demo/15-11-08-31d.json |   1 +
 7 files changed, 436 insertions(+), 6 deletions(-)
 create mode 100644 dash.html
 create mode 100644 src/Entity/Account.php
 create mode 100644 tests/Entity/AccountTest.php
 create mode 100644 tests/Mocks/Account/demo/15-11-08-31d.json

diff --git a/dash.html b/dash.html
new file mode 100644
index 0000000..e69de29
diff --git a/src/Abstracts/Entity.php b/src/Abstracts/Entity.php
index d39fa8b..6c0baa5 100644
--- a/src/Abstracts/Entity.php
+++ b/src/Abstracts/Entity.php
@@ -36,4 +36,11 @@ public function __call($name, $arguments)
 
         throw new \BadMethodCallException('No such method: '.$name);
     }
+
+    protected function getOrDefault($key, $default = null, $data = null)
+    {
+        $data = ($data !== null) ?: $this->data;
+        return (isset($data[$key]) ? $data[$key] : $default);
+    }
+
 }
\ No newline at end of file
diff --git a/src/Diffbot.php b/src/Diffbot.php
index 3d001d8..d224a63 100644
--- a/src/Diffbot.php
+++ b/src/Diffbot.php
@@ -7,6 +7,7 @@
 use Swader\Diffbot\Api\Crawl;
 use Swader\Diffbot\Api\Custom;
 use Swader\Diffbot\Api\Search;
+use Swader\Diffbot\Entity\Account;
 use Swader\Diffbot\Exceptions\DiffbotException;
 use Swader\Diffbot\Api\Product;
 use Swader\Diffbot\Api\Image;
@@ -76,6 +77,7 @@ private static function validateToken($token)
         if (strlen($token) < 4) {
             throw new \InvalidArgumentException('Token "' . $token . '" is too short, and thus invalid.');
         }
+
         return true;
     }
 
@@ -104,6 +106,7 @@ public function setHttpClient(Client $client = null)
             );
         }
         $this->client = $client;
+
         return $this;
     }
 
@@ -127,6 +130,7 @@ public function setEntityFactory(EntityFactory $factory = null)
             $factory = new Entity();
         }
         $this->factory = $factory;
+
         return $this;
     }
 
@@ -155,6 +159,7 @@ public function createProductAPI($url)
         if (!$this->getEntityFactory()) {
             $this->setEntityFactory();
         }
+
         return $api->registerDiffbot($this);
     }
 
@@ -173,6 +178,7 @@ public function createArticleAPI($url)
         if (!$this->getEntityFactory()) {
             $this->setEntityFactory();
         }
+
         return $api->registerDiffbot($this);
     }
 
@@ -191,6 +197,7 @@ public function createImageAPI($url)
         if (!$this->getEntityFactory()) {
             $this->setEntityFactory();
         }
+
         return $api->registerDiffbot($this);
     }
 
@@ -209,6 +216,7 @@ public function createAnalyzeAPI($url)
         if (!$this->getEntityFactory()) {
             $this->setEntityFactory();
         }
+
         return $api->registerDiffbot($this);
     }
 
@@ -227,6 +235,7 @@ public function createDiscussionAPI($url)
         if (!$this->getEntityFactory()) {
             $this->setEntityFactory();
         }
+
         return $api->registerDiffbot($this);
     }
 
@@ -248,6 +257,7 @@ public function createCustomAPI($url, $name)
         if (!$this->getEntityFactory()) {
             $this->setEntityFactory();
         }
+
         return $api->registerDiffbot($this);
     }
 
@@ -270,6 +280,7 @@ public function crawl($name = null, Api $api = null)
         if (!$this->getEntityFactory()) {
             $this->setEntityFactory();
         }
+
         return $api->registerDiffbot($this);
     }
 
@@ -288,6 +299,28 @@ public function search($q)
         if (!$this->getEntityFactory()) {
             $this->setEntityFactory();
         }
+
         return $api->registerDiffbot($this);
     }
+
+    public function getAccountInfo($days = 31)
+    {
+        if (!$this->getHttpClient()) {
+            $this->setHttpClient();
+        }
+
+        $url = 'https://api.diffbot.com/v3/account?token='
+            . $this->getToken()
+            . '&invoices=true&days=' . $days;
+
+        $response = $this->getHttpClient()->get($url);
+
+        $info = json_decode($response->getBody()->getContents(), true);
+
+        if (!$info) {
+            throw new DiffbotException('Could not retrieve account information!');
+        }
+
+        return new Account($info);
+    }
 }
\ No newline at end of file
diff --git a/src/Entity/Account.php b/src/Entity/Account.php
new file mode 100644
index 0000000..49e5670
--- /dev/null
+++ b/src/Entity/Account.php
@@ -0,0 +1,121 @@
+<?php
+
+namespace Swader\Diffbot\Entity;
+
+use Swader\Diffbot\Abstracts\Entity;
+
+class Account extends Entity
+{
+    /** @var bool */
+    protected $carbonated = false;
+
+    public function __construct(array $data)
+    {
+        parent::__construct($data);
+        if (class_exists('\Carbon\Carbon')) {
+            $this->carbonated = true;
+            $format = 'o-m-d';
+            \Carbon\Carbon::setToStringFormat($format);
+
+        }
+        $this->getInvoices();
+    }
+
+    /**
+     * Returns false if token is "inactive", true otherwise
+     * @return bool
+     */
+    public function isActive()
+    {
+        return !($this->data['status'] === 'inactive');
+    }
+
+    /**
+     * Returns an array of arrays where each child array has two elements:
+     * a date (Carbon instance if Carbon is installed), and an integer
+     * indicating the number of API calls made.
+     *
+     * @return array
+     */
+    public function getApiCalls()
+    {
+        return $this->getOrDefault('apiCalls', []);
+    }
+
+    /**
+     * Returns all invoices issued to the token holder, ever.
+     *
+     * Every invoice will be an array with "status", a date (Carbon instance if
+     * Carbon is installed), totalCalls (int), totalAmount (int), plan,
+     * and overageAmount (int).
+     *
+     * @return null | array
+     */
+    public function getInvoices()
+    {
+        $invoices = $this->getOrDefault('invoices');
+        if ($invoices && $this->carbonated && !isset($this->data['invoices-carbonated'])) {
+            foreach ($invoices as &$inv) {
+                $inv['date'] = new \Carbon\Carbon($inv['date'], 'GMT');
+            }
+            $this->data['invoices'] = $invoices;
+            $this->data['invoices-carbonated'] = true;
+        }
+
+        return $this->data['invoices'];
+    }
+
+    /**
+     * Date of last billing.
+     * Null if not available, instance of Carbon if Carbon is installed.
+     * YYYY-MM-DD string otherwise.
+     *
+     * @return \Carbon\Carbon | string | null
+     */
+    public function getLastBilling()
+    {
+        $lastBilling = $this->getOrDefault('lastBilling');
+
+        return ($lastBilling && $this->carbonated) ?
+            new \Carbon\Carbon($lastBilling, 'GMT') :
+            $lastBilling;
+    }
+
+    /**
+     * @return string Name of the token owner
+     */
+    public function getName()
+    {
+        return $this->getOrDefault('name');
+    }
+
+    /**
+     * Type of plan, i.e., custom, diffbot, starter...
+     *
+     * @return string
+     */
+    public function getPlan()
+    {
+        return $this->getOrDefault('plan');
+    }
+
+    /**
+     * Email registered to token
+     *
+     * @return string
+     */
+    public function getEmail()
+    {
+        return $this->getOrDefault('email');
+    }
+
+    /**
+     * Returns the current status of the token (i.e. inactive, active...)
+     *
+     * @return string
+     */
+    public function getStatus()
+    {
+        return $this->getOrDefault('status');
+    }
+}
\ No newline at end of file
diff --git a/src/Traits/StandardEntity.php b/src/Traits/StandardEntity.php
index 10ca851..d3f24c4 100644
--- a/src/Traits/StandardEntity.php
+++ b/src/Traits/StandardEntity.php
@@ -113,10 +113,4 @@ public function getDiffbotUri()
         return $this->data['diffbotUri'];
     }
 
-    protected function getOrDefault($key, $default = null, $data = null)
-    {
-        $data = ($data !== null) ?: $this->data;
-        return (isset($data[$key]) ? $data[$key] : $default);
-    }
-
 }
\ No newline at end of file
diff --git a/tests/Entity/AccountTest.php b/tests/Entity/AccountTest.php
new file mode 100644
index 0000000..e280438
--- /dev/null
+++ b/tests/Entity/AccountTest.php
@@ -0,0 +1,274 @@
+<?php
+
+namespace Swader\Diffbot\Test\Entity;
+
+use Swader\Diffbot\Entity\Account;
+use Swader\Diffbot\Entity\EntityIterator;
+use Swader\Diffbot\Test\ResponseProvider;
+
+class AccountTest extends ResponseProvider
+{
+    protected static $staticFiles = [
+        'Account/demo/15-11-08-31d.json',
+    ];
+
+    protected function ei($file)
+    {
+        $acc = new Account(
+            json_decode(
+                parent::prepareResponsesStatic()[$file]->getBody(), true
+            )
+        );
+
+        return new EntityIterator([$acc],
+            parent::prepareResponsesStatic()[$file]);
+    }
+
+
+    public function statusProvider()
+    {
+        return [
+            ['Account/demo/15-11-08-31d.json', 'inactive'],
+        ];
+    }
+
+    /**
+     * @param $file
+     * @param $value1
+     * @dataProvider statusProvider
+     */
+    public function testStatus($file, $value1)
+    {
+        /**
+         * @var int $i
+         * @var Account $entity
+         */
+        foreach ($this->ei($file) as $i => $entity) {
+            $this->assertEquals($value1, $entity->getStatus());
+            if ($value1 === 'inactive') {
+                $this->assertFalse($entity->isActive());
+            }
+        }
+    }
+
+    public function invoicesProvider()
+    {
+        return [
+            [
+                'Account/demo/15-11-08-31d.json',
+                array(
+                    0 => array(
+                        'date' => '2012-05-01',
+                        'totalCalls' => 0,
+                        'totalAmount' => 20,
+                        'plan' => 'starter',
+                        'overageAmount' => 0,
+                        'status' => 'paid',
+                    ),
+                    1 => array(
+                        'date' => '2012-04-01',
+                        'totalCalls' => 0,
+                        'totalAmount' => 20,
+                        'plan' => 'starter',
+                        'overageAmount' => 0,
+                        'status' => 'paid',
+                    ),
+                    2 => array(
+                        'date' => '2012-03-01',
+                        'totalCalls' => 0,
+                        'totalAmount' => 20,
+                        'plan' => 'starter',
+                        'overageAmount' => 0,
+                        'status' => 'paid',
+                    ),
+                    3 => array(
+                        'date' => '2012-02-01',
+                        'totalCalls' => 0,
+                        'totalAmount' => 20,
+                        'plan' => 'starter',
+                        'overageAmount' => 0,
+                        'status' => 'unpaid',
+                    ),
+                ),
+                [5, 4, 3, 2]
+            ],
+        ];
+    }
+
+    /**
+     * @param $file
+     * @param $value1
+     * @param $value2
+     * @dataProvider invoicesProvider
+     */
+    public function testInvoices($file, $value1, $value2)
+    {
+        /**
+         * @var int $i
+         * @var Account $entity
+         */
+        foreach ($this->ei($file) as $i => $entity) {
+            $this->assertEquals($value1, $entity->getInvoices());
+            //dump($entity->getInvoices());
+            if (class_exists('\Carbon\Carbon')) {
+                $value1 = $entity->getInvoices();
+                foreach ($value1 as $j => $invoiceArray) {
+                    $this->assertEquals($value2[$j], $invoiceArray['date']->month);
+                }
+            }
+        }
+    }
+
+    public function apiCallsProvider()
+    {
+        return [
+            [
+                'Account/demo/15-11-08-31d.json',
+                array(
+                    0 => array('date' => '2015-11-08', 'calls' => 0,),
+                    1 => array('date' => '2015-11-07', 'calls' => 0,),
+                    2 => array('date' => '2015-11-06', 'calls' => 0,),
+                    3 => array('date' => '2015-11-05', 'calls' => 100,),
+                    4 => array('date' => '2015-11-04', 'calls' => 0,),
+                    5 => array('date' => '2015-11-03', 'calls' => 0,),
+                    6 => array('date' => '2015-11-02', 'calls' => 0,),
+                    7 => array('date' => '2015-11-01', 'calls' => 0,),
+                    8 => array('date' => '2015-10-31', 'calls' => 0,),
+                    9 => array('date' => '2015-10-30', 'calls' => 0,),
+                    10 => array('date' => '2015-10-29', 'calls' => 5,),
+                    11 => array('date' => '2015-10-28', 'calls' => 0,),
+                    12 => array('date' => '2015-10-27', 'calls' => 10,),
+                    13 => array('date' => '2015-10-26', 'calls' => 0,),
+                    14 => array('date' => '2015-10-25', 'calls' => 0,),
+                    15 => array('date' => '2015-10-24', 'calls' => 0,),
+                    16 => array('date' => '2015-10-23', 'calls' => 0,),
+                    17 => array('date' => '2015-10-22', 'calls' => 0,),
+                    18 => array('date' => '2015-10-21', 'calls' => 0,),
+                    19 => array('date' => '2015-10-20', 'calls' => 0,),
+                    20 => array('date' => '2015-10-19', 'calls' => 0,),
+                    21 => array('date' => '2015-10-18', 'calls' => 0,),
+                    22 => array('date' => '2015-10-17', 'calls' => 0,),
+                    23 => array('date' => '2015-10-16', 'calls' => 0,),
+                    24 => array('date' => '2015-10-15', 'calls' => 0,),
+                    25 => array('date' => '2015-10-14', 'calls' => 0,),
+                    26 => array('date' => '2015-10-13', 'calls' => 0,),
+                    27 => array('date' => '2015-10-12', 'calls' => 0,),
+                    28 => array('date' => '2015-10-11', 'calls' => 0,),
+                    29 => array('date' => '2015-10-10', 'calls' => 0,),
+                    30 => array('date' => '2015-10-09', 'calls' => 0,),
+                )
+            ],
+        ];
+    }
+
+    /**
+     * @param $file
+     * @param $value1
+     * @dataProvider apiCallsProvider
+     */
+    public function testApiCalls($file, $value1)
+    {
+        /**
+         * @var int $i
+         * @var Account $entity
+         */
+        foreach ($this->ei($file) as $i => $entity) {
+            $this->assertEquals($value1, $entity->getApiCalls());
+        }
+    }
+
+    public function lastBillingProvider()
+    {
+        return [
+            ['Account/demo/15-11-08-31d.json', '2012-05-01', 2012],
+        ];
+    }
+
+    /**
+     * @param $file
+     * @param $value1
+     * @param $value2
+     * @dataProvider lastBillingProvider
+     */
+    public function testLastBilling($file, $value1, $value2)
+    {
+        /**
+         * @var int $i
+         * @var Account $entity
+         */
+        foreach ($this->ei($file) as $i => $entity) {
+            $this->assertEquals($value1, (string)$entity->getLastBilling());
+            if (class_exists('\Carbon\Carbon')) {
+                $this->assertEquals($value2, $entity->getLastBilling()->year);
+            }
+        }
+
+    }
+
+    public function basicsProvider()
+    {
+        return [
+            [
+                'Account/demo/15-11-08-31d.json',
+                'Demo',
+                'diffbot',
+                'comments@diffbot.com'
+            ],
+        ];
+    }
+
+    /**
+     * @param $file
+     * @param $value1
+     * @param $value2
+     * @param $value3
+     * @dataProvider basicsProvider
+     */
+    public function testName($file, $value1, $value2, $value3)
+    {
+        /**
+         * @var int $i
+         * @var Account $entity
+         */
+        foreach ($this->ei($file) as $i => $entity) {
+            $this->assertEquals($value1, $entity->getName());
+        }
+    }
+
+    /**
+     * @param $file
+     * @param $value1
+     * @param $value2
+     * @param $value3
+     * @dataProvider basicsProvider
+     */
+    public function testPlan($file, $value1, $value2, $value3)
+    {
+        /**
+         * @var int $i
+         * @var Account $entity
+         */
+        foreach ($this->ei($file) as $i => $entity) {
+            $this->assertEquals($value2, $entity->getPlan());
+        }
+    }
+
+    /**
+     * @param $file
+     * @param $value1
+     * @param $value2
+     * @param $value3
+     * @dataProvider basicsProvider
+     */
+    public function testEmail($file, $value1, $value2, $value3)
+    {
+        /**
+         * @var int $i
+         * @var Account $entity
+         */
+        foreach ($this->ei($file) as $i => $entity) {
+            $this->assertEquals($value3, $entity->getEmail());
+        }
+    }
+
+}
diff --git a/tests/Mocks/Account/demo/15-11-08-31d.json b/tests/Mocks/Account/demo/15-11-08-31d.json
new file mode 100644
index 0000000..1a70673
--- /dev/null
+++ b/tests/Mocks/Account/demo/15-11-08-31d.json
@@ -0,0 +1 @@
+{"invoices":[{"date":"2012-05-01","totalCalls":0,"totalAmount":20,"plan":"starter","overageAmount":0,"status":"paid"},{"date":"2012-04-01","totalCalls":0,"totalAmount":20,"plan":"starter","overageAmount":0,"status":"paid"},{"date":"2012-03-01","totalCalls":0,"totalAmount":20,"plan":"starter","overageAmount":0,"status":"paid"},{"date":"2012-02-01","totalCalls":0,"totalAmount":20,"plan":"starter","overageAmount":0,"status":"unpaid"}],"lastBilling":"2012-05-01","name":"Demo","plan":"diffbot","apiCalls":[{"date":"2015-11-08","calls":0},{"date":"2015-11-07","calls":0},{"date":"2015-11-06","calls":0},{"date":"2015-11-05","calls":100},{"date":"2015-11-04","calls":0},{"date":"2015-11-03","calls":0},{"date":"2015-11-02","calls":0},{"date":"2015-11-01","calls":0},{"date":"2015-10-31","calls":0},{"date":"2015-10-30","calls":0},{"date":"2015-10-29","calls":5},{"date":"2015-10-28","calls":0},{"date":"2015-10-27","calls":10},{"date":"2015-10-26","calls":0},{"date":"2015-10-25","calls":0},{"date":"2015-10-24","calls":0},{"date":"2015-10-23","calls":0},{"date":"2015-10-22","calls":0},{"date":"2015-10-21","calls":0},{"date":"2015-10-20","calls":0},{"date":"2015-10-19","calls":0},{"date":"2015-10-18","calls":0},{"date":"2015-10-17","calls":0},{"date":"2015-10-16","calls":0},{"date":"2015-10-15","calls":0},{"date":"2015-10-14","calls":0},{"date":"2015-10-13","calls":0},{"date":"2015-10-12","calls":0},{"date":"2015-10-11","calls":0},{"date":"2015-10-10","calls":0},{"date":"2015-10-09","calls":0}],"email":"comments@diffbot.com","token":"demo","status":"inactive"}
\ No newline at end of file
