diff --git a/Bpi/Sdk/Bpi.php b/Bpi/Sdk/Bpi.php index fddb751..44ebd56 100644 --- a/Bpi/Sdk/Bpi.php +++ b/Bpi/Sdk/Bpi.php @@ -1,12 +1,18 @@ authorization = new Authorization($agencyId, $publicKey, $secret); } - private function request($method, $url, array $data = []) + protected function request($method, $url, array $data = []) { try { $this->client = new GuzzleHttpClient([ @@ -55,9 +60,7 @@ private function request($method, $url, array $data = []) 'Auth' => $this->authorization->toHTTPHeader(), ], ]); - $result = $this->client->request($method, $url, $data); - return $result; } catch (GuzzleClientException $e) { throw new SDKException($e->getMessage(), $e->getCode(), $e); @@ -73,7 +76,7 @@ private function request($method, $url, array $data = []) */ public function searchNodes(array $query = array()) { - $result = $this->request('GET', '/node/collection', [ + $result = $this->request('GET', 'node/collection', [ 'query' => $query, ]); $element = new \SimpleXMLElement((string)$result->getBody()); @@ -90,7 +93,7 @@ public function searchNodes(array $query = array()) */ public function push(array $data) { - $result = $this->request('POST', '/node', ['form_params' => $data]); + $result = $this->request('POST', 'node', ['form_params' => $data]); $element = new \SimpleXMLElement((string)$result->getBody()); return new Node($element->item[0]); @@ -104,7 +107,7 @@ public function push(array $data) */ public function syndicateNode($id) { - $result = $this->request('GET', '/node/syndicated', ['query' => ['id' => $id]]); + $result = $this->request('GET', 'node/syndicated', ['query' => ['id' => $id]]); return $result->getStatusCode() === 200; } @@ -117,7 +120,7 @@ public function syndicateNode($id) */ public function deleteNode($id) { - $result = $this->request('GET', '/node/delete', ['query' => ['id' => $id]]); + $result = $this->request('GET', 'node/delete', ['query' => ['id' => $id]]); return $result->getStatusCode() === 200; } @@ -134,7 +137,7 @@ public function deleteNode($id) */ public function getStatistics($dateFrom, $dateTo) { - $result = $this->request('GET', '/statistics', ['query' => ['dateFrom' => $dateFrom, 'dateTo' => $dateTo]]); + $result = $this->request('GET', 'statistics', ['query' => ['dateFrom' => $dateFrom, 'dateTo' => $dateTo]]); $element = new \SimpleXMLElement((string)$result->getBody()); return new BaseItem($element->item[0]); @@ -148,7 +151,7 @@ public function getStatistics($dateFrom, $dateTo) */ public function getNode($id) { - $result = $this->request('GET', '/node/item/' . $id); + $result = $this->request('GET', 'node/item/' . $id); $element = new \SimpleXMLElement((string)$result->getBody()); return new Node($element->item[0]); @@ -161,7 +164,7 @@ public function getNode($id) */ public function getDictionaries() { - $result = $this->request('GET', '/profile/dictionary'); + $result = $this->request('GET', 'profile/dictionary'); $element = new \SimpleXMLElement((string)$result->getBody()); $dictionary = []; @@ -176,4 +179,334 @@ public function getDictionaries() return $dictionary; } + + // ----------------------------------------------------------------------------- + + /** + * Get list of channels. + * + * @param array $query available keys are: amount, offset, filter, sort + * filter and sort requires nested arrays + * @return \Bpi\Sdk\NodeList + */ + public function searchChannels($query = []) + { + $result = $this->request('GET', 'channel/', [ + 'query' => $query, + ]); + $element = new \SimpleXMLElement((string)$result->getBody()); + + return new ChannelList($element); + } + + /** + * Create a new channel. + * + * @param string $name + * @param string $description + * @param string $adminId + */ + public function createChannel(array $data) + { + $this->checkRequired($data, ['name', 'description', 'adminId']); + $values = $this->apiRename($data, [ + 'name' => 'name', + 'description' => 'channelDescription', + 'adminId' => 'editorId', + ]); + + $result = $this->request('POST', 'channel/', ['form_params' => $values]); + $element = new \SimpleXMLElement((string)$result->getBody()); + + return new Channel($element->channel[0]); + } + + /** + * Get a channel by Id. + * + * @param string $id + * The channel id. + * + * @return Channel + * The channel if found. + */ + public function getChannel($id) + { + $result = $this->request('GET', 'channel/' . $id); + $element = new \SimpleXMLElement((string)$result->getBody()); + + return new Channel($element->channel[0]); + } + + /** + * @param string $name + * @param string $description + * @param string $adminId + */ + public function updateChannel($channelId, array $data) + { + $this->checkRequired($data, [ 'name', 'description' ]); + + $values = $this->apiRename($data, [ + 'name' => 'channelName', + 'description' => 'channelDescription', + ]); + + $result = $this->request('POST', 'channel/edit/' . $channelId, ['form_params' => $values]); + $element = new \SimpleXMLElement((string)$result->getBody()); + + return new Channel($element->channel[0]); + } + + /** + * @param string $name + * @param string $description + * @param string $adminId + */ + public function deleteChannel($channelId) + { + $result = $this->request('DELETE', 'channel/remove/' . $channelId); + + return $result->getStatusCode() === 200; + } + + public function addEditorToChannel($channelId, $adminId, $editorIds) + { + if (!is_array($editorIds)) { + $editorIds = [ $editorIds ]; + } + $values = [ + 'channelId' => $channelId, + 'adminId' => $adminId, + 'users' => array_map(function ($editorId) { + return [ 'editorId' => $editorId ]; + }, $editorIds), + ]; + + $result = $this->request('POST', 'channel/add/editor', ['form_params' => $values]); + + if ($result->getStatusCode() !== 200) { + return false; + } + + $element = new \SimpleXMLElement((string)$result->getBody()); + $result = new GroupOperationResult($element); + + return count($result->getSuccessIds()) === count($editorIds); + } + + public function removeEditorFromChannel($channelId, $adminId, $editorIds) + { + if (!is_array($editorIds)) { + $editorIds = [ $editorIds ]; + } + $values = [ + 'channelId' => $channelId, + 'adminId' => $adminId, + 'users' => array_map(function ($editorId) { + return [ 'editorId' => $editorId ]; + }, $editorIds), + ]; + + $result = $this->request('POST', 'channel/remove/editor', ['form_params' => $values]); + + if ($result->getStatusCode() !== 200) { + return false; + } + + $element = new \SimpleXMLElement((string)$result->getBody()); + $result = new GroupOperationResult($element); + + return count($result->getSuccessIds()) === count($editorIds); + } + + public function getChannelsByUser($userId) + { + $result = $this->request('GET', 'channel/user/' . $userId); + $element = new \SimpleXMLElement((string)$result->getBody()); + + return new ChannelList($element); + } + + public function addNodeToChannel($channelId, $editorId, $nodeIds) + { + if (!is_array($nodeIds)) { + $nodeIds = [ $nodeIds ]; + } + $values = [ + 'channelId' => $channelId, + 'editorId' => $editorId, + 'nodes' => array_map(function ($nodeId) { + return [ 'nodeId' => $nodeId ]; + }, $nodeIds), + ]; + + $result = $this->request('POST', 'channel/add/node', ['form_params' => $values]); + + if ($result->getStatusCode() !== 200) { + return false; + } + + $element = new \SimpleXMLElement((string)$result->getBody()); + $result = new GroupOperationResult($element); + + return count($result->getSuccessIds()) === count($nodeIds); + } + + public function removeNodeFromChannel($channelId, $editorId, $nodeIds) + { + if (!is_array($nodeIds)) { + $nodeIds = [ $nodeIds ]; + } + $values = [ + 'channelId' => $channelId, + 'editorId' => $editorId, + 'nodes' => array_map(function ($nodeId) { + return [ 'nodeId' => $nodeId ]; + }, $nodeIds), + ]; + + $result = $this->request('POST', 'channel/remove/node', ['form_params' => $values]); + + if ($result->getStatusCode() !== 200) { + return false; + } + + $element = new \SimpleXMLElement((string)$result->getBody()); + $result = new GroupOperationResult($element); + + return count($result->getSuccessIds()) === count($nodeIds); + } + + // ----------------------------------------------------------------------------- + + /** + * Get list of users based on conditions + * + * @param array $queries available keys are: search, amount, offset, filter, sort + * filter and sort requires nested arrays + * @return \Bpi\Sdk\UserList + */ + public function searchUsers($query = []) + { + $result = $this->request('GET', 'user/', [ + 'query' => $query, + ]); + $element = new \SimpleXMLElement((string)$result->getBody()); + + return new UserList($element); + } + + public function createUser(array $data) + { + $this->checkRequired($data, [ 'externalId', 'email' ]); + + $values = $this->apiRename($data, [ + 'externalId' => 'externalId', + 'email' => 'email', + 'firstName' => 'userFirstName', + 'lastName' => 'userLastName', + ]); + + $result = $this->request('POST', 'user/', ['form_params' => $values]); + $element = new \SimpleXMLElement((string)$result->getBody()); + + return new User($element->user[0]); + } + + public function getUser($id) + { + $result = $this->request('GET', 'user/' . $id); + $element = new \SimpleXMLElement((string)$result->getBody()); + + return new User($element->user[0]); + } + + /** + * @param string $userId + * @param array $data + */ + public function updateUser($userId, array $data) + { + $this->checkRequired($data, []); + + $values = $this->apiRename($data, [ + 'externalId' => 'externalId', + 'email' => 'email', + 'firstName' => 'userFirstName', + 'lastName' => 'userLastName', + ]); + + $result = $this->request('POST', 'user/edit/' . $userId, ['form_params' => $values]); + $element = new \SimpleXMLElement((string)$result->getBody()); + + return new User($element->user[0]); + } + + /** + * @param string $name + * @param string $description + * @param string $adminId + */ + public function deleteUser($userId) + { + throw new \Exception(__METHOD__ . ' not supported'); + } + + /** + * @param string $userId + * @param array $data + * + * @return Subscription + */ + public function createSubscription($userId, array $data) + { + $this->checkRequired($data, [ 'title', 'filter' ]); + + $values = $data; + $values['filter'] = json_encode($values['filter']); + $values['userId'] = $userId; + + $result = $this->request('POST', 'user/subscription', ['form_params' => $values]); + $element = new \SimpleXMLElement((string)$result->getBody()); + + return new User($element->user[0]); + } + + /** + * @param string $userId + * @param string $title + */ + public function deleteSubscription($userId, $title) + { + $values = [ + 'userId' => $userId, + 'subscriptionTitle' => $title, + ]; + + $result = $this->request('POST', 'user/subscription/remove', ['form_params' => $values]); + $element = new \SimpleXMLElement((string)$result->getBody()); + + return new User($element); + } + + protected function checkRequired(array $data, array $required) + { + foreach ($required as $name) { + if (!isset($data[$name])) { + throw new \InvalidArgumentException(sprintf('Field [%s] is required', (string)$name)); + } + } + } + + protected function apiRename(array $data, array $apiNames) + { + $values = []; + foreach ($data as $name => $value) { + if (isset($apiNames[$name])) { + $values[$apiNames[$name]] = $value; + } + } + return $values; + } } diff --git a/Bpi/Sdk/ChannelList.php b/Bpi/Sdk/ChannelList.php new file mode 100644 index 0000000..cbad78b --- /dev/null +++ b/Bpi/Sdk/ChannelList.php @@ -0,0 +1,23 @@ +element->xpath('/channels/channel') as $el) { + $items[] = new Channel($el); + } + + return $items; + } +} diff --git a/Bpi/Sdk/GroupOperationResult.php b/Bpi/Sdk/GroupOperationResult.php new file mode 100644 index 0000000..c967d0f --- /dev/null +++ b/Bpi/Sdk/GroupOperationResult.php @@ -0,0 +1,70 @@ +element = $element; + + if (isset($element)) { + $this->code = (int)$element->code; + $this->skipped = (int)$element->skipped; + $this->success = (int)$element->success; + if (isset($element->success_list)) { + $this->successIds = []; + foreach ($element->success_list->item as $item) { + $this->successIds[] = (string)$item; + } + } + } + } + + public function getCode() + { + return $this->code; + } + + public function getSkipped() + { + return $this->skipped; + } + + public function getSuccess() + { + return $this->success; + } + + public function getSuccessIds() + { + return $this->successIds; + } +} diff --git a/Bpi/Sdk/Item/Agency.php b/Bpi/Sdk/Item/Agency.php new file mode 100644 index 0000000..5959324 --- /dev/null +++ b/Bpi/Sdk/Item/Agency.php @@ -0,0 +1,58 @@ +id; + } + + /** + * @return string + */ + private function setId($id) + { + $this->id = $id; + return $this; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string $name + * @return Channel + */ + public function setName($name) + { + $this->name = $name; + return $this; + } + + public function __construct(\SimpleXMLElement $el) + { + $this->setId((string)$el->id); + $this->setName((string)$el->name); + } +} diff --git a/Bpi/Sdk/Item/Channel.php b/Bpi/Sdk/Item/Channel.php new file mode 100644 index 0000000..44e1b76 --- /dev/null +++ b/Bpi/Sdk/Item/Channel.php @@ -0,0 +1,187 @@ +id; + } + + /** + * @return string + */ + private function setId($id) + { + $this->id = $id; + return $this; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string $name + * @return Channel + */ + public function setName($name) + { + $this->name = $name; + return $this; + } + + /** + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param string $description + * @return Channel + */ + public function setDescription($description) + { + $this->description = $description; + return $this; + } + + /** + * @return string + */ + public function getAdminId() + { + return $this->adminId; + } + + /** + * @param string $adminId + * @return Channel + */ + public function setAdminId($adminId) + { + $this->adminId = $adminId; + return $this; + } + + /** + * @return User + */ + public function getAdmin() + { + return $this->admin; + } + + /** + * @param User $admin + * @return Channel + */ + public function setAdmin($admin) + { + $this->admin = $admin; + return $this; + } + + /** + * @return array + */ + public function getEditors() + { + return $this->editors; + } + + /** + * @return array + */ + public function getNodes() + { + return $this->nodes; + } + + /** + * @return DateTime + */ + public function getNodeLastAddedAt() + { + return $this->nodeLastAddedAt; + } + + public function __construct(\SimpleXMLElement $el) + { + $this->setId((string)$el->id); + $this->setName((string)$el->channel_name); + $this->setDescription((string)$el->channel_description); + + $admin = new User($el->channel_admin); + $this->setAdminId($admin->getId()); + $this->setAdmin($admin); + + if (isset($el->users)) { + $users = []; + foreach ($el->users->user as $user) { + $users[] = new User($user); + } + $this->editors = $users; + } + + if (isset($el->nodes)) { + $nodes = []; + foreach ($el->nodes->node as $node) { + $nodes[] = (string)$node; + } + $this->nodes = $nodes; + } + + $this->nodeLastAddedAt = (string)$el->node_last_added_at ? new \DateTime((string)$el->node_last_added_at) : null; + } +} diff --git a/Bpi/Sdk/Item/Node.php b/Bpi/Sdk/Item/Node.php index c7e12f1..682aed1 100644 --- a/Bpi/Sdk/Item/Node.php +++ b/Bpi/Sdk/Item/Node.php @@ -35,7 +35,6 @@ public function getAssets() } $assets[$type][] = $properties; } - $this->assets = $assets; } diff --git a/Bpi/Sdk/Item/Subscription.php b/Bpi/Sdk/Item/Subscription.php new file mode 100644 index 0000000..02e5f8c --- /dev/null +++ b/Bpi/Sdk/Item/Subscription.php @@ -0,0 +1,65 @@ +title; + } + + /** + * @param string $title + * @return Title + */ + public function setTitle($title) + { + $this->title = $title; + return $this; + } + + /** + * @return array + */ + public function getFilter() + { + return $this->filter; + } + + /** + * @param mixed $filter + * @return User + */ + public function setFilter($filter) + { + if (is_string($filter)) { + $this->filter = json_decode($filter, true); + } else { + $this->filter = $filter; + } + return $this; + } + + public function __construct(\SimpleXMLElement $el) + { + $title = (string)$el->title; + $filter = (string)$el->filter; + $this->setTitle(htmlspecialchars_decode($title, ENT_QUOTES)); + $this->setFilter(htmlspecialchars_decode($filter, ENT_QUOTES)); + } +} diff --git a/Bpi/Sdk/Item/User.php b/Bpi/Sdk/Item/User.php new file mode 100644 index 0000000..654ed08 --- /dev/null +++ b/Bpi/Sdk/Item/User.php @@ -0,0 +1,167 @@ +id; + } + + /** + * @param string $id + * @return User + */ + protected function setId($id) + { + $this->id = $id; + return $this; + } + + /** + * @return string + */ + public function getAgency() + { + return $this->agency; + } + + /** + * @param string $agency + * @return User + */ + public function setAgency($agency) + { + $this->agency = $agency; + return $this; + } + + /** + * @return string + */ + public function getEmail() + { + return $this->email; + } + + /** + * @param string $email + * @return User + */ + public function setEmail($email) + { + $this->email = $email; + return $this; + } + + /** + * @return string + */ + public function getFirstName() + { + return $this->firstName; + } + + /** + * @param string $firstName + * @return User + */ + public function setFirstName($firstName) + { + $this->firstName = $firstName; + return $this; + } + + /** + * @return string + */ + public function getSubscriptions() + { + return $this->subscriptions; + } + + /** + * @param string $subscriptions + * @return User + */ + public function setSubscriptions($subscriptions) + { + $this->subscriptions = $subscriptions; + return $this; + } + + /** + * @return string + */ + public function getLastName() + { + return $this->lastName; + } + + /** + * @param string $lastName + * @return User + */ + public function setLastName($lastName) + { + $this->lastName = $lastName; + return $this; + } + + /** + * @return string + */ + public function getName() + { + return trim($this->getFirstName() . ' ' . $this->getLastName()); + } + + public function __construct(\SimpleXMLElement $el) + { + $this->setId((string)$el->id); + $this->setEmail((string)$el->email); + $this->setFirstName((string)$el->user_first_name); + $this->setLastName((string)$el->user_last_name); + $this->setAgency(new Agency($el->agency)); + if (isset($el->subscriptions->entry)) { + $subscriptions = []; + foreach ($el->subscriptions->entry as $subscription) { + $subscriptions[] = new Subscription($subscription); + } + $this->setSubscriptions($subscriptions); + } + } +} diff --git a/Bpi/Sdk/ItemList.php b/Bpi/Sdk/ItemList.php new file mode 100644 index 0000000..2e178ba --- /dev/null +++ b/Bpi/Sdk/ItemList.php @@ -0,0 +1,163 @@ +element = $element; + $this->total = $this->buildTotal(); + $this->items = $this->buildItems(); + } + + /** + * Iterator interface implementation + * + * @group Iterator + */ + public function rewind() + { + $this->position = 0; + } + + /** + * Returns same instance but with internal pointer to current item in collection + * + * @group Iterator + */ + public function current() + { + return $this->items[$this->position]; + } + + /** + * Key of current iteration position + * + * @group Iterator + */ + public function key() + { + return $this->position; + } + + /** + * Iterate to next item + * + * @group Iterator + */ + public function next() + { + $this->position++; + } + + /** + * Checks if is ready for iteration + * + * @group Iterator + * @return boolean + */ + public function valid() + { + return isset($this->items[$this->position]); + } + + /** + * + * @return integer + */ + public function count() + { + return count($this->items); + } + + /** + * Get facets. + * + * @return Facets + */ + public function getFacets() + { + if (!$this->facets) { + $this->facets = $this->buildFacets(); + } + + return $this->facets; + } + + /** + * Build list of items. + * + * @return array + * An array of items. + */ + abstract protected function buildItems(); + + /** + * Get total number of items. + * + * @return int + * The total number of items. + */ + protected function buildTotal() + { + return (int)$this->element['total']; + } + + /** + * Build item facets. + * + * @return Facets + */ + protected function buildFacets() + { + $facets = new Facets(); + foreach ($this->element->xpath('/*/facet') as $el) { + $facet = new Facet(); + $facet->setFacetName((string)$el['name']); + foreach ($el->xpath('term') as $term) { + $facet->addFacetTerm((string)$term['name'], (string)$term['title'], (int)$term); + } + $facets->addFacet($facet); + } + + return $facets; + } +} diff --git a/Bpi/Sdk/NodeList.php b/Bpi/Sdk/NodeList.php index 0647954..a721b48 100644 --- a/Bpi/Sdk/NodeList.php +++ b/Bpi/Sdk/NodeList.php @@ -44,14 +44,15 @@ class NodeList implements \Iterator, \Countable public function __construct(\SimpleXMLElement $element) { $this->element = $element; - try { - $collection = $this->element->xpath('/bpi/item[@type = "collection"]')[0]; - $this->total = (int)($collection->xpath('properties/property[@name = "total"]')[0]); + + $collections = $this->element->xpath('/bpi/item[@type = "collection"]'); + if ($collections) { + $collection = $collections[0]; + $this->total = (int) ($collection->xpath('properties/property[@name = "total"]')[0]); foreach ($this->element->xpath('/bpi/item[@type = "entity"]') as $node) { $this->nodes[] = new Node($node); } - } catch (Exception\EmptyList $e) { } } @@ -69,6 +70,8 @@ public function rewind() * Returns same instance but with internal pointer to current item in collection * * @group Iterator + * + * @return Node */ public function current() { @@ -79,6 +82,8 @@ public function current() * Key of current iteration position * * @group Iterator + * + * @return int */ public function key() { @@ -99,6 +104,7 @@ public function next() * Checks if is ready for iteration * * @group Iterator + * * @return boolean */ public function valid() @@ -107,7 +113,6 @@ public function valid() } /** - * * @return integer */ public function count() diff --git a/Bpi/Sdk/UserList.php b/Bpi/Sdk/UserList.php new file mode 100644 index 0000000..dd0c6e8 --- /dev/null +++ b/Bpi/Sdk/UserList.php @@ -0,0 +1,24 @@ +element->xpath('/users/user') as $el) { + $items[] = new User($el); + } + + return $items; + } +} diff --git a/README.md b/README.md index 415e1d0..39a1ab2 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,27 @@ Install dev dependencies: composer install ``` -Run all unit tests: +## Unit tests + +Run unit tests: + +``` +./vendor/bin/phpunit Tests/Unit/ +``` + +## Web service tests + +These tests must be run against an actual BPI web service (see https://github.com/inleadmedia/rest-api) on the [`develop`](https://github.com/inleadmedia/rest-api/tree/develop) branch. + +First, load fixtures in the BPI web service and create the schema (!): ``` -./vendor/bin/phpunit +app/console doctrine:mongodb:fixtures:load +app/console doctrine:mongodb:schema:create ``` +When running the web service tests, the web service endpoint and user credentials (api key and secret) must be specified using environment variables. Adapt the example to match your actual setup. + Run web service tests: ``` diff --git a/Tests/Unit/BpiClient.php b/Tests/Unit/BpiClient.php new file mode 100644 index 0000000..12d40a1 --- /dev/null +++ b/Tests/Unit/BpiClient.php @@ -0,0 +1,34 @@ +injectedClient = $endpoint; + } else { + parent::__construct($endpoint, $agencyId, $publicKey, $secret); + } + } + + protected function request($method, $url, array $data = []) + { + if ($this->injectedClient !== null) { + return $this->injectedClient->request($method, $url, $data); + } + + return parent::request($method, $url, $data); // TODO: Change the autogenerated stub + } +} diff --git a/Tests/Unit/ChannelTest.php b/Tests/Unit/ChannelTest.php new file mode 100644 index 0000000..03be541 --- /dev/null +++ b/Tests/Unit/ChannelTest.php @@ -0,0 +1,54 @@ +getClient(__DIR__ . '/Fixtures/GetChannels.response'); + + $bpi = new BpiClient($client); + $channels = $bpi->searchChannels([]); + $this->assertEquals(11, $channels->total); + $this->assertEquals(3, count($channels)); + + $channels->rewind(); + $channel = $channels->current(); + $this->assertNotNull($channel); + $this->assertEquals('Mikkels kanal', $channel->getName()); + + $channels->next(); + $channel = $channels->current(); + $this->assertNotNull($channel); + $this->assertEquals('Test kanal', $channel->getName()); + } + + public function testGetChannelsFacets() + { + $client = $this->getClient(__DIR__ . '/Fixtures/GetChannels.response'); + + $bpi = new BpiClient($client); + $channels = $bpi->searchChannels([]); + $facets = $channels->getFacets()->getFacets(); + $this->assertEquals(1, count($facets)); + /** @var \Bpi\Sdk\Item\Facet $facet */ + $facet = $facets[0]; + $this->assertEquals('agency_id', $facet->getFacetName()); + + $terms = $facet->getFacetTerms(); + $this->assertEquals(2, count($terms)); + + $this->assertArrayHasKey('999999', $terms); + $term = $terms['999999']; + $this->assertEquals(2, $term->getAmount()); + $this->assertEquals('999999', $term->getName()); + $this->assertEquals('Test bibliotek', $term->getTitle()); + + $this->assertArrayHasKey('775100', $terms); + $term = $terms['775100']; + $this->assertEquals(1, $term->getAmount()); + $this->assertEquals('775100', $term->getName()); + $this->assertEquals('Aarhus Kommunes Biblioteker', $term->getTitle()); + } +} diff --git a/Tests/Unit/Fixtures/GetChannels.response b/Tests/Unit/Fixtures/GetChannels.response new file mode 100644 index 0000000..a5109e7 --- /dev/null +++ b/Tests/Unit/Fixtures/GetChannels.response @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + + <![CDATA[Mit abonnement]]> + + + + + <![CDATA[### 5720915ba4f2f1e1048b45bb - 57209201a4f2f1e2048b45a6 ###]]> + + + + + <![CDATA[Search for "test"]]> + + + + + <![CDATA[eReolen]]> + + + + + <![CDATA[### 5720915ba4f2f1e1048b45bb - 57ee4006a4f2f1b4048b456f ###]]> + + + + + <![CDATA[### 5720915ba4f2f1e1048b45bb - 57877e59a4f2f1be048b4593 ###]]> + + + + + + + + + + + + + + + + + + + + + + + + <![CDATA[### 5720919da4f2f124048b45ce - 57877e59a4f2f1be048b4593 ###]]> + + + + + <![CDATA[eReolen]]> + + + + + <![CDATA[### 5720919da4f2f124048b45ce - 576b95e3a4f2f1d10b8b4794 ###]]> + + + + + + + + + + + + + + + + + + + + + + + <![CDATA[### 5730915da4f2f124048b45cf - 573194cea4f2f18f048b45a8 ###]]> + + + + + <![CDATA[eReolen]]> + + + + + + + + + + + + + + + + + + + + + + + <![CDATA[Mit abonnement]]> + + + + + <![CDATA[### 5720915ba4f2f1e1048b45bb - 57209201a4f2f1e2048b45a6 ###]]> + + + + + <![CDATA[Search for "test"]]> + + + + + <![CDATA[eReolen]]> + + + + + <![CDATA[### 5720915ba4f2f1e1048b45bb - 57ee4006a4f2f1b4048b456f ###]]> + + + + + <![CDATA[### 5720915ba4f2f1e1048b45bb - 57877e59a4f2f1be048b4593 ###]]> + + + + + + + + + + + + + + + + + + + + + + + <![CDATA[ACS]]> + + + + + <![CDATA[### 57309051a4f2f125048b4592 - 57209201a4f2f1e2048b45a6 ###]]> + + + + + <![CDATA[### 57309051a4f2f125048b4592 - 573194cea4f2f18f048b45a8 ###]]> + + + + + <![CDATA[### 57309051a4f2f125048b4592 - 5731833aa4f2f124048b45d0 ###]]> + + + + + + + + + + + + + + + + + + + + + + + <![CDATA[### 5720919da4f2f124048b45ce - 57877e59a4f2f1be048b4593 ###]]> + + + + + <![CDATA[eReolen]]> + + + + + <![CDATA[### 5720919da4f2f124048b45ce - 576b95e3a4f2f1d10b8b4794 ###]]> + + + + + + + + + + + + + + + + + <![CDATA[### 5730915da4f2f124048b45cf - 573194cea4f2f18f048b45a8 ###]]> + + + + + <![CDATA[eReolen]]> + + + + + + + + + + + + diff --git a/Tests/Unit/Fixtures/GetNodes.response b/Tests/Unit/Fixtures/GetNodes.response new file mode 100644 index 0000000..605b53a --- /dev/null +++ b/Tests/Unit/Fixtures/GetNodes.response @@ -0,0 +1,645 @@ +HTTP/1.1 200 OK +Server: nginx/1.10.2 +Content-Type: application/xml +Transfer-Encoding: chunked +Connection: keep-alive +Keep-Alive: timeout=120 +X-Powered-By: PHP/5.3.19 +cache-control: max-age=315360000 +date: Thu, 12 Jan 2017 19:27:08 GMT +Expires: Thu, 31 Dec 2037 23:55:55 GMT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Det er ikke særlig fedt at være udenfor i disse dage. Det er mørkt, koldt og egentlig temmelig trist. Med andre ord – her er en rigtig god undskyldning for at blive indenfor og læse en masse gode bøger. Frem med plaid og varm kakao og find en god krog, hvor I kan sidde sammen og læse. +
Her er nogle forslag til humoristiske læseoplevelser, I kan dele sammen voksne og børn. Bøgerne er rigtig gode til at blive læst højt. 
+
 
+
Skurkistan
+
I et land hvor loven siger, at alle skal være skurke, er man måske den største skurk, hvis man nægter at overholde loven og altid opfører sig pænt? En sjov og skør historie for børn og voksne der holder af eventyr og ballade
+
 
+
Frygt og Bæven og en mand på strømpesokker
+
En historie om en følsom og temperamentsfuld dreng. Han er knyttet meget tæt til sin adoptivmor Kis og vil have hende for sig selv. Han har det meget svært, når nogen ringer for at tale med Kis. Da Ole Madsen en dag ringer på døren, har drengen svært ved at overgive sig og dele Kis med ham. 
+
 
+
Megasnyd og mælkesnot
+
Brødrene Olfert og Olfert, Karl og Max, er 11 og 9 år og hinandens bedste venner. De har deres eget regelsæt og filosofiske tilgang til verden, og så er de fulde af gode ideer til skæg og ballade
+
 
+
Hvad fætter gør er altid det rigtige
+
Osama hjælper til i sin fars kiosk. Bedstemoren sidder på en kasse cola i baglokalet, ser tv og storbander. Osama skal ud og sælge en tyggegummiautomat for at skaffe penge til kioskens strøm. Osama forhandler sig igennem Vesterbros mange tilbud med en charme og en naturlighed, for at vende tilbage til kiosken, hvor Dennis Diller er sikker på, at den står på skideballe.
+
 
+
Vilde Wilma
+
Den 6-årige Wilma er en egenrådig og frygtløs pige, som ikke finder sig i hvad som helst. Hun bor sammen med sin far, som er tålmodig, venlig og en anelse ubeslutsom. Man kommer helt automatisk til at tænke på Alfons Åbergs far. Læseren hører bl.a. om en telttur med faren, en tur på biblioteket og om en tur i svømmehallen, hvor det er ved at gå galt.
+
 
+
Dennis' dramatiske dage : flødeskumsedderkoppen og andre røverhistorier
+
Dennis er den gennemgående hovedperson, og det er hans mere eller mindre heldige uge, der er omdrejningspunktet for løjerne. Han møder en flødeskumsedderkop, bliver kidnappet som cirkusartist, får briller efter utallige baldrede ruder og bliver en helt efter en tur i svømmehallen. Bogen slutter, hvor den begynder med mandag morgen, og en ny skoleuge starter
+
 
+
Moren som hersede sig ihjel
+
Fridas og Ellens mor herser rundt med dem og faderen især om morgenen, indtil hun en dag falder død om i en snedrive. Så følger en tid med totalt kaos, for moderen var jo den, der holdt snor i alting. Til sidst griber skolen ind, og så får faderen hanket op i hverdagen. Men samtidig har moderen problemer i himlen, hvor englene er ved at gå i strejke over hendes herseri. Så hun bliver returneret med beskeden om, at der kun må herses 5 gange om dagen
+
 
+
Alle bøgerne kan lånes på biblioteket. Vi ses/Bettina
+
 
+
 
+

Oprindeligt skrevet af bbo, Randers Bibliotek.

]]>
+ + + +
+ + + + +
+ + + + + + + + + + + + + + Adam Lerner er 27 og har et godt arbejde, en smukke kæreste og gode venner. Alt det vendes der op og ned på, da han bliver diagnosticeret med en alvorlig kræftsygdom (på internettet gives en overlevelsesrate på 50%). Forholdet til hans familie, kæreste og bedste ven sættes alle under pres, og ikke alle forhold kan klare presset fra en mulig dødsdom.
Manuskriptforfatteren Will Reiser byggede 50/50 på hans egen kamp mod kræft, som 25 årig. Filmen er instrueret af Jonathan Levine og Adam spilles af Joseph Gordon-Levitt. Seth Rogen, Anna Kendrick og Anjelica Huston medvirker også.

+

+

+
+ +

Se filmen på filmstriben.

+

 

+

D. 10. januar ​åbnede Filmstribens nye hjemmeside officielt fjernleje.filmstriben.dk.

+

Der er også en ny  iOS app "Filmstriben Next". De gamle apps "Filmstriben I lænestolen" og "Filmstriben På biblioteket" virke ikke efter den 10. januar (en infotekst i de gamle apps vil henvise til den nye app).

+

Filmstriben understøttes på nuværende tidspunkt ikke på Android-platforme, men DBC forventer i første kvartal 2017 at lancere en Android-app med bl.a. Chromecast-funktionalitet, samtidig med at Airplay tilføjes i iOS-appen.

+

Samtidig forventes en ny HTML5-baseret web-player lanceret til erstatning af Silverlight-playeren, hvilket vil gøre det muligt at benytte Filmstriben i alle browsere.

+

 

+

 

+

 

+

Oprindeligt skrevet af Aarhus Kommunes Biblioteker.

]]>
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + Forfatteren har brug for hjælp. Oven på succesen med en selvbiografisk bestseller er hun udkørt og ramt af skriveblokade. I denne tilstand møder hun den mystiske kvinde L, som hurtigt indtager en eksklusiv plads i hendes liv og hverdag. Men hvem er L, og har hun udelukkende gode intentioner på forfatterens vegne?

+

Delphine de Vigan fik sit store gennembrud med den selvbiografiske "Alt må vige for natten", som udkom på dansk i 2013. Vigans mor begik selvmord i 2008, og i romanen forsøgte hun gennem interviews og erindringer at begribe morens liv og død. Efter denne meget personlige familiekrønike kom det derfor som en overraskelse for de fleste, da Vigan sidste år udkom med "Baseret på en sand historie", som er en nervepirrende psykologisk thriller - med litterære ambitioner. Bogen er et vellykket studie i paranoia og følelsesmæssig afhængighed, og samtidig leverer den et væsentligt bidrag til debatten om selvbiografisk fiktion.

+

Her finder du "Baseret på en sand historie" i selskab med en række andre gode lydbøger, der eksemplificerer og udfordrer den selvbiografiske genre.

+

Oprindeligt skrevet af eReolen.

]]>
+ + + + + + + + + + + +
+ + + + +
+
diff --git a/Tests/Unit/Fixtures/GetUsers.response b/Tests/Unit/Fixtures/GetUsers.response new file mode 100644 index 0000000..e08d799 --- /dev/null +++ b/Tests/Unit/Fixtures/GetUsers.response @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + <![CDATA[Mit abonnement]]> + + + + + <![CDATA[### 5720915ba4f2f1e1048b45bb - 57209201a4f2f1e2048b45a6 ###]]> + + + + + <![CDATA[Search for "test"]]> + + + + + <![CDATA[eReolen]]> + + + + + <![CDATA[### 5720915ba4f2f1e1048b45bb - 57ee4006a4f2f1b4048b456f ###]]> + + + + + <![CDATA[### 5720915ba4f2f1e1048b45bb - 57877e59a4f2f1be048b4593 ###]]> + + + + + + + + + + + + + + + + + <![CDATA[### 5720919da4f2f124048b45ce - 57877e59a4f2f1be048b4593 ###]]> + + + + + <![CDATA[eReolen]]> + + + + + <![CDATA[### 5720919da4f2f124048b45ce - 576b95e3a4f2f1d10b8b4794 ###]]> + + + + + + + + + + + + + + + + + <![CDATA[ACS]]> + + + + + <![CDATA[### 57309051a4f2f125048b4592 - 57209201a4f2f1e2048b45a6 ###]]> + + + + + <![CDATA[### 57309051a4f2f125048b4592 - 573194cea4f2f18f048b45a8 ###]]> + + + + + <![CDATA[### 57309051a4f2f125048b4592 - 5731833aa4f2f124048b45d0 ###]]> + + + + + + + + + + diff --git a/Tests/Unit/NodeTest.php b/Tests/Unit/NodeTest.php new file mode 100644 index 0000000..fe0aa06 --- /dev/null +++ b/Tests/Unit/NodeTest.php @@ -0,0 +1,44 @@ +getClient(__DIR__ . '/Fixtures/GetNodes.response'); + + $bpi = new BpiClient($client); + $nodelist = $bpi->searchNodes([]); + $this->assertEquals(3, count($nodelist)); + $this->assertEquals(2948, $nodelist->total); + + $nodelist->rewind(); + $node = $nodelist->current(); + $properties = $node->getProperties(); + $this->assertEquals('Vintertid er læsetid', $properties['title']); + } + + public function testGetNodesFacets() + { + $client = $this->getClient(__DIR__ . '/Fixtures/GetNodes.response'); + + $bpi = new BpiClient($client); + $nodelist = $bpi->searchNodes([]); + $facets = $nodelist->getFacets()->getFacets(); + $this->assertEquals(5, count($facets)); + /** @var \Bpi\Sdk\Item\Facet $facet */ + $facet = $facets[0]; + $this->assertEquals('category', $facet->getFacetName()); + + $terms = $facet->getFacetTerms(); + $this->assertEquals(20, count($terms)); + $this->assertArrayHasKey('Film', $terms); + + /** @var \Bpi\Sdk\Item\FacetTerm $term */ + $term = $terms['Film']; + $this->assertEquals(122, $term->getAmount()); + $this->assertEquals('Film', $term->getName()); + $this->assertEquals('Film', $term->getTitle()); + } +} diff --git a/Tests/Unit/UnitTestCase.php b/Tests/Unit/UnitTestCase.php new file mode 100644 index 0000000..3bb4328 --- /dev/null +++ b/Tests/Unit/UnitTestCase.php @@ -0,0 +1,44 @@ + $line) { + if (preg_match('@HTTP/[0-9.]* (?[0-9]+) .+@', $line, $matches)) { + $status = (int)$matches['code']; + } elseif (preg_match('/(?[^:]+):\s*(?.+)/', $line, $matches)) { + $headers[$matches['name']] = $matches['value']; + } elseif (!trim($line)) { + // Skip blank lines. + } else { + $body = implode(PHP_EOL, array_slice($lines, $index)); + break; + } + } + + $mock = new MockHandler([ + new Response($status, $headers, $body), + ]); + $handler = HandlerStack::create($mock); + + return new Client(['handler' => $handler]); + } +} diff --git a/Tests/Unit/UserTest.php b/Tests/Unit/UserTest.php new file mode 100644 index 0000000..58510e1 --- /dev/null +++ b/Tests/Unit/UserTest.php @@ -0,0 +1,59 @@ +getClient(__DIR__ . '/Fixtures/GetUsers.response'); + + $bpi = new BpiClient($client); + $users = $bpi->searchUsers([]); + $this->assertEquals(87, $users->total); + $this->assertEquals(3, count($users)); + + $users->rewind(); + $user = $users->current(); + $this->assertNotNull($user); + $this->assertEquals('user@999999.example.com', $user->getEmail()); + + $users->next(); + $user = $users->current(); + $this->assertNotNull($user); + $this->assertEquals('another.user@999999.example.com', $user->getEmail()); + + $users->next(); + $user = $users->current(); + $this->assertNotNull($user); + $this->assertEquals('user@775100.example.com', $user->getEmail()); + } + + public function testGetUsersFacets() + { + $client = $this->getClient(__DIR__ . '/Fixtures/GetUsers.response'); + + $bpi = new BpiClient($client); + $users = $bpi->searchUsers([]); + $facets = $users->getFacets()->getFacets(); + $this->assertEquals(1, count($facets)); + /** @var \Bpi\Sdk\Item\Facet $facet */ + $facet = $facets[0]; + $this->assertEquals('agency_id', $facet->getFacetName()); + + $terms = $facet->getFacetTerms(); + $this->assertEquals(2, count($terms)); + + $this->assertArrayHasKey('999999', $terms); + $term = $terms['999999']; + $this->assertEquals(2, $term->getAmount()); + $this->assertEquals('999999', $term->getName()); + $this->assertEquals('Test bibliotek', $term->getTitle()); + + $this->assertArrayHasKey('775100', $terms); + $term = $terms['775100']; + $this->assertEquals(1, $term->getAmount()); + $this->assertEquals('775100', $term->getName()); + $this->assertEquals('Aarhus Kommunes Biblioteker', $term->getTitle()); + } +} diff --git a/Tests/WebService/ChannelTest.php b/Tests/WebService/ChannelTest.php new file mode 100644 index 0000000..484bdc9 --- /dev/null +++ b/Tests/WebService/ChannelTest.php @@ -0,0 +1,325 @@ +admin = $this->client->createUser([ 'externalId' => mt_rand(), 'email' => mt_rand() . '-admin@example.com' ]); + } + + public function testCanCreateChannel() + { + $channels = $this->searchChannels(); + $numberOfChannels = count($channels); + + $channel = $this->client->createChannel([ 'name' => $this->getChannelName(), 'description' => 'test', 'adminId' => $this->admin->getId() ]); + + $channels = $this->searchChannels(); + $newNumberOfChannels = count($channels); + + $this->assertEquals($numberOfChannels + 1, $newNumberOfChannels); + } + + public function testCanLimitChannels() + { + $this->client->createChannel([ 'name' => $this->getChannelName(), 'description' => 'test', 'adminId' => $this->admin->getId() ]); + $this->client->createChannel([ 'name' => $this->getChannelName(), 'description' => 'test', 'adminId' => $this->admin->getId() ]); + + $channels = $this->searchChannels([ + 'amount' => 1, + ]); + + $this->assertEquals(1, count($channels)); + } + + public function testCanGetChannel() + { + $newChannel = $this->client->createChannel([ 'name' => $this->getChannelName(), 'description' => 'test', 'adminId' => $this->admin->getId() ]); + + $channel = $this->client->getChannel($newChannel->getId()); + + // $this->assertEquals($newChannel->getAdminId(), $this->admin->getId()); + // @FIXME + $newChannel->setAdmin($channel->getAdmin()); + $channel->setAdminId($newChannel->getAdminId()); + + $this->assertEquals($newChannel->getName(), $channel->getName()); + } + + public function testCanUpdateChannel() + { + $channel = $this->client->createChannel([ 'name' => $this->getChannelName(), 'description' => 'test', 'adminId' => $this->admin->getId() ]); + + $name = $channel->getName() . mt_rand(); + $description = $channel->getDescription() . mt_rand(); + $updatedChannel = $this->client->updateChannel($channel->getId(), [ 'name' => $name, 'description' => $description ]); + + $this->assertEquals($name, $updatedChannel->getName()); + $this->assertEquals($description, $updatedChannel->getDescription()); + } + + public function testCanDeleteChannel() + { + $channel = $this->client->createChannel([ 'name' => $this->getChannelName(), 'description' => 'test', 'adminId' => $this->admin->getId() ]); + + $channels = $this->searchChannels(); + $numberOfChannels = count($channels); + + $result = $this->client->deleteChannel($channel->getId()); + + $this->assertEquals(true, $result); + + $channels = $this->searchChannels(); + $this->assertEquals($numberOfChannels - 1, count($channels)); + } + + public function testCanAddEditorToChannel() + { + $channel = $this->client->createChannel([ 'name' => $this->getChannelName(), 'description' => 'test', 'adminId' => $this->admin->getId() ]); + $channel = $this->client->getChannel($channel->getId()); + + $numberOfEditors = count($channel->getEditors()); + $editor = $this->client->createUser([ 'externalId' => mt_rand(), 'email' => mt_rand() . '-editor@example.com' ]); + + $result = $this->client->addEditorToChannel($channel->getId(), $channel->getAdmin()->getId(), $editor->getId()); + + $this->assertEquals(true, $result); + + $channel = $this->client->getChannel($channel->getId()); + + $this->assertEquals($numberOfEditors + 1, count($channel->getEditors())); + } + + public function testCanRemoveEditorFromChannel() + { + $channel = $this->client->createChannel([ 'name' => $this->getChannelName(), 'description' => 'test', 'adminId' => $this->admin->getId() ]); + $editor = $this->client->createUser([ 'externalId' => mt_rand(), 'email' => mt_rand() . '-editor@example.com' ]); + + $result = $this->client->addEditorToChannel($channel->getId(), $this->admin->getId(), $editor->getId()); + + $this->assertEquals(true, $result, 'Can add editor to channel'); + + $channel = $this->client->getChannel($channel->getId()); + $numberOfEditors = count($channel->getEditors()); + + $this->assertEquals(1, $numberOfEditors, 'Number of editors are 1'); + + $result = $this->client->removeEditorFromChannel($channel->getId(), $this->admin->getId(), $editor->getId()); + + $this->assertEquals(true, $result, 'Can remove editor from channel'); + + $channel = $this->client->getChannel($channel->getId()); + + $this->assertEquals($numberOfEditors - 1, count($channel->getEditors()), 'Number of editors are decreased by 1'); + } + + public function testCanGetUsersChannels() + { + $user = $this->client->createUser([ 'externalId' => mt_rand(), 'email' => mt_rand() . '-user@example.com' ]); + + $channels = $this->client->getChannelsByUser($user->getId()); + $this->assertEquals(0, count($channels)); + + $channel = $this->client->createChannel([ 'name' => $this->getChannelName(), 'description' => 'test', 'adminId' => $this->admin->getId() ]); + $channel = $this->client->getChannel($channel->getId()); + + $result = $this->client->addEditorToChannel($channel->getId(), $channel->getAdmin()->getId(), $user->getId()); + + $this->assertEquals(true, $result); + + $channels = $this->client->getChannelsByUser($user->getId()); + $this->assertEquals(1, count($channels)); + } + + public function testCanAddNodeToChannel() + { + $channel = $this->client->createChannel([ 'name' => $this->getChannelName(), 'description' => 'test', 'adminId' => $this->admin->getId() ]); + $channel = $this->client->getChannel($channel->getId()); + + $numberOfNodes = count($channel->getNodes()); + + $this->assertEquals(0, $numberOfNodes); + + $nodeId = $this->createNode(); + + $result = $this->client->addNodeToChannel($channel->getId(), $this->admin->getId(), $nodeId); + + $this->assertEquals(true, $result); + + $channel = $this->client->getChannel($channel->getId()); + + $this->assertEquals($numberOfNodes + 1, count($channel->getNodes())); + $this->assertNotNull($channel->getNodeLastAddedAt()); + } + + private function createNode(array $data = []) + { + $data = array_merge([ + 'title' => $this->getRandomName(), + 'body' => '', + 'teaser' => '', + 'type' => 'test', + 'creation' => date('c'), + 'category' => 'Other', + 'audience' => 'All', + 'editable' => 1, + 'authorship' => '', + 'agency_id' => $this->agencyId, + 'local_id' => 87, + 'firstname' => 'test', + 'lastname' => '', + 'assets' => [], + 'related_materials' => [], + 'tags' => 'test', + 'url' => '', + 'data' => '', + ], $data); + $node = $this->client->push($data); + + if (!$node) { + throw new \Exception('Cannot create node'); + } + + $properties = $node->getProperties(); + return $properties['id']; + } + + public function testCanRemoveNodeFromChannel() + { + $channel = $this->client->createChannel([ 'name' => $this->getChannelName(), 'description' => 'test', 'adminId' => $this->admin->getId() ]); + + $nodeId = $this->createNode(); + + $result = $this->client->addNodeToChannel($channel->getId(), $this->admin->getId(), $nodeId); + + $this->assertEquals(true, $result); + + $channel = $this->client->getChannel($channel->getId()); + $numberOfNodes = count($channel->getNodes()); + + $this->assertEquals(1, $numberOfNodes); + + $result = $this->client->removeNodeFromChannel($channel->getId(), $this->admin->getId(), $nodeId); + + $this->assertEquals(true, $result); + + $channel = $this->client->getChannel($channel->getId()); + + $this->assertEquals($numberOfNodes - 1, count($channel->getNodes())); + } + + public function testCanSearchByText() + { + $channels = $this->searchChannels([ + 'search' => uniqid(), + ]); + + $this->assertEquals(0, count($channels)); + } + + public function testCanSortByName() + { + $this->canSortBy('name'); + } + + public function testCanSortByDescription() + { + $this->canSortBy('description'); + } + + public function testCanSortByNodeLastAddedAt() + { + $this->canSortBy('nodeLastAddedAt'); + } + + private function canSortBy($name) + { + $channels = $this->searchChannels([ + 'sort' => [ + $name => 'asc', + ], + ]); + $reversedChannels = $this->searchChannels([ + 'sort' => [ + $name => 'desc', + ], + ]); + + $channels = iterator_to_array($channels); + $reversedChannels = iterator_to_array($reversedChannels); + + $this->assertTrue(count($channels) > 1); + $this->assertTrue(count($reversedChannels) > 1); + $this->assertEquals(count($channels), count($reversedChannels)); + $this->assertNotEquals($channels, $reversedChannels); + + // for ($i = 0; $i < count($channels); $i++) { + // $this->assertEquals($channels[$i], $reversedChannels[count($reversedChannels) - 1 - $i]); + // } + } + + private function getChannelName() + { + return 'Channel ' . mt_rand(); + } + + // public function testChannels() + // { + // $channels = $this->searchChannels(); + // $this->assertNotNull($channels); + // } + + // public function testCanCreateChannel() + // { + // $channels = $this->searchChannels(); + // $numberOfChannels = count($channels); + + // $data = [ + // 'name' => uniqid('test'), + // 'description' => uniqid('test'), + // 'adminId' => uniqid('test'), + // ]; + + // $channel = $this->client->createChannel($data); + + // $this->assertEquals($data['email'], $channel->getEmail()); + // $this->assertEquals($data['firstName'], $channel->getFirstName()); + + // $channels = $this->searchChannels(); + // $newNumberOfChannels = count($channels); + + // $this->assertEquals($numberOfChannels + 1, $newNumberOfChannels); + // } + + // public function testCanDeleteChannel() + // { + // $channels = $this->searchChannels(); + // $numberOfChannels = count($channels); + + // $this->assertTrue(count($channels) > 0); + + // $channels->rewind(); + // $channel = $channels->current(); + // $result = $this->client->deleteChannel($channel->getId()); + // $this->assertTrue($result); + + // $result = $this->client->deleteChannel(uniqid()); + // $this->assertFalse($result); + + // $channels = $this->searchChannels(); + // $newNumberOfChannels = count($channels); + + // $this->assertEquals($numberOfChannels - 1, $newNumberOfChannels); + // } + + private function searchChannels(array $query = []) + { + $query += ['amount' => 1000]; + return $this->client->searchChannels($query); + } +} diff --git a/Tests/WebService/NodeTest.php b/Tests/WebService/NodeTest.php index a253317..11d5d17 100644 --- a/Tests/WebService/NodeTest.php +++ b/Tests/WebService/NodeTest.php @@ -2,19 +2,17 @@ namespace Bpi\Sdk\Tests\WebService; -require_once __DIR__ . '/WebServiceTestCase.php'; - -class NodeWebServiceTest extends WebServiceTestCase +class NodeTest extends WebServiceTestCase { public function testNodes() { - $nodes = $this->client->searchNodes([]); - $this->assertEquals(0, count($nodes)); + $nodes = $this->searchNodes(); + $this->assertNotNull($nodes); } public function testCanCreateNode() { - $nodes = $this->client->searchNodes(); + $nodes = $this->searchNodes(); $numberOfNodes = count($nodes); $data = [ @@ -25,12 +23,12 @@ public function testCanCreateNode() $this->assertEquals($data['title'], $node->getProperties()['title']); - $nodes = $this->client->searchNodes(); + $nodes = $this->searchNodes(); $newNumberOfNodes = count($nodes); $this->assertEquals($numberOfNodes + 1, $newNumberOfNodes); - $nodes = $this->client->searchNodes(['search' => $data['title']]); + $nodes = $this->searchNodes(['search' => $data['title']]); $this->assertEquals(1, count($nodes)); $nodes->rewind(); $this->assertEquals($data['title'], $nodes->current()->getProperties()['title']); @@ -38,37 +36,57 @@ public function testCanCreateNode() public function testCanCreateNodeWithAssets() { - $nodes = $this->client->searchNodes(); + $nodes = $this->searchNodes(); $numberOfNodes = count($nodes); $data = [ 'title' => uniqid(__METHOD__), - 'category' => 'Test', - 'audience' => 'Test', - 'images' => [ + 'assets' => [ [ 'path' => 'https://placekitten.com/200/400', + 'name' => 'Kittens', 'alt' => 'Kittens', 'title' => 'Kittens', + 'type' => 'content_image', + ], + [ + 'path' => 'https://placekitten.com/400/200', + 'name' => 'MoreKittens', + 'alt' => 'More kittens', + 'title' => 'More kittens', + 'type' => 'content_image', ], [ 'path' => 'https://placekitten.com/400/200', + 'name' => 'Kittens', 'alt' => 'Kittens', 'title' => 'Kittens', + 'type' => 'decorative_image', ], ], ]; $node = $this->createNode($data); - $nodes = $this->client->searchNodes(); + $nodes = $this->searchNodes(); $newNumberOfNodes = count($nodes); $this->assertEquals($numberOfNodes + 1, $newNumberOfNodes); $this->assertEquals($data['title'], $node->getProperties()['title']); - $this->assertEquals(2, count($node->getAssets())); + + $assets = $node->getAssets(); + $this->assertEquals(2, count($assets)); + $this->assertArrayHasKey('content_image', $assets); + $images = $assets['content_image']; + $this->assertEquals(2, count($images)); + $this->assertEquals('Kittens', $images[0]['title']); + $this->assertEquals('More kittens', $images[1]['title']); + + $this->assertArrayHasKey('decorative_image', $assets); + $images = $assets['decorative_image']; + $this->assertEquals(1, count($images)); } public function testCanLimitNodes() @@ -76,10 +94,10 @@ public function testCanLimitNodes() $this->createNode(); $this->createNode(); - $nodes = $this->client->searchNodes(); + $nodes = $this->searchNodes(); $this->assertTrue(count($nodes) > 1); - $nodes = $this->client->searchNodes([ + $nodes = $this->searchNodes([ 'amount' => 1, ]); @@ -101,7 +119,7 @@ public function testCanGetNode() public function testCanGetFacets() { - $nodes = $this->client->searchNodes([]); + $nodes = $this->searchNodes(); $facets = $nodes->getFacets()->getFacets(); $this->createNode(['category' => 'Book']); @@ -115,14 +133,14 @@ public function testCanGetFacets() public function testCanFilterOnFacet() { - $nodes = $this->client->searchNodes([]); + $nodes = $this->searchNodes(); $facets = $nodes->getFacets()->getFacets(); if ($facets) { foreach ($facets as $facet) { $facetName = $facet->getFacetName(); foreach ($facet->getFacetTerms() as $term) { - $nodes = $this->client->searchNodes([ + $nodes = $this->searchNodes([ 'filter' => [ $facetName => [ $term->getName(), @@ -147,20 +165,20 @@ public function testCanDeleteNode() { $node = $this->createNode(); - $nodes = $this->client->searchNodes(); + $nodes = $this->searchNodes(); $numberOfNodes = count($nodes); $result = $this->client->deleteNode($node->getProperties()['id']); $this->assertEquals(true, $result); - $nodes = $this->client->searchNodes(); + $nodes = $this->searchNodes(); $this->assertEquals($numberOfNodes - 1, count($nodes)); } public function testCanSearchByText() { - $nodes = $this->client->searchNodes([ + $nodes = $this->searchNodes([ 'search' => uniqid(__METHOD__), ]); @@ -201,12 +219,12 @@ public function testCanGetDictionaries() private function canSortBy($name) { - $nodes = $this->client->searchNodes([ + $nodes = $this->searchNodes([ 'sort' => [ $name => 'asc', ], ]); - $reversedNodes = $this->client->searchNodes([ + $reversedNodes = $this->searchNodes([ 'sort' => [ $name => 'desc', ], @@ -223,7 +241,7 @@ private function canSortBy($name) private function createNode(array $data = []) { - $data = array_merge([ + $data += [ 'title' => uniqid(__METHOD__), 'body' => '', 'teaser' => '', @@ -242,7 +260,7 @@ private function createNode(array $data = []) 'tags' => 'test', 'url' => '', 'data' => '', - ], $data); + ]; $node = $this->client->push($data); @@ -252,4 +270,10 @@ private function createNode(array $data = []) return $node; } + + private function searchNodes(array $query = []) + { + $query += ['amount' => 1000]; + return $this->client->searchNodes($query); + } } diff --git a/Tests/WebService/UserTest.php b/Tests/WebService/UserTest.php new file mode 100644 index 0000000..078ff85 --- /dev/null +++ b/Tests/WebService/UserTest.php @@ -0,0 +1,101 @@ +searchUsers([]); + $this->assertNotNull($users); + } + + public function testCanCreateUser() + { + $users = $this->searchUsers(); + $numberOfUsers = count($users); + + $data = [ + 'externalId' => uniqid('test'), + 'email' => uniqid('test') . '@example.com', + 'firstName' => uniqid('test'), + ]; + + $user = $this->client->createUser($data); + + $this->assertEquals($data['email'], $user->getEmail()); + $this->assertEquals($data['firstName'], $user->getFirstName()); + + $users = $this->searchUsers(); + $newNumberOfUsers = count($users); + + $this->assertEquals($numberOfUsers + 1, $newNumberOfUsers); + } + + // public function testCanCreateUser() + // { + // $users = $this->searchUsers(); + // $numberOfUsers = count($users); + + // $user = $this->client->createUser([ + // 'externalId' => mt_rand(), + // 'email' => mt_rand() . '@example.com', + // ]); + + // $users = $this->searchUsers(); + // $newNumberOfUsers = count($users); + + // $this->assertEquals($numberOfUsers + 1, $newNumberOfUsers); + // } + + public function testCanLimitUsers() + { + $this->client->createUser([ 'externalId' => mt_rand(), 'email' => mt_rand() . '@example.com' ]); + $this->client->createUser([ 'externalId' => mt_rand(), 'email' => mt_rand() . '@example.com' ]); + + $users = $this->searchUsers([ + 'amount' => 1, + ]); + + $this->assertEquals(1, count($users)); + } + + public function testCanGetUser() + { + $newUser = $this->client->createUser([ 'externalId' => mt_rand(), 'email' => mt_rand() . '@example.com' ]); + + $user = $this->client->getUser($newUser->getId()); + + $this->assertEquals($newUser, $user); + } + + public function testCanSearchUsersByEmail() + { + $newUser = $this->client->createUser([ 'externalId' => mt_rand(), 'email' => mt_rand() . '@example.com', 'firstName' => mt_rand(), 'lastName' => mt_rand() ]); + + $users = $this->searchUsers([ 'search' => $newUser->getEmail() ]); + + $users->rewind(); + $this->assertEquals(1, count($users)); + $this->assertEquals($newUser, $users->current()); + } + + public function testCanUpdateUser() + { + $user = $this->client->createUser([ 'externalId' => mt_rand(), 'email' => mt_rand() . '@example.com' ]); + + $email = $user->getEmail() . mt_rand(); + $updatedUser = $this->client->updateUser($user->getId(), [ 'email' => $email ]); + $this->assertEquals($email, $updatedUser->getEmail()); + + $firstName = $user->getFirstName() . mt_rand(); + $updatedUser = $this->client->updateUser($user->getId(), [ 'firstName' => $firstName ]); + $this->assertEquals($firstName, $updatedUser->getFirstName()); + } + + private function searchUsers(array $query = []) + { + $query += ['amount' => 1000]; + return $this->client->searchUsers($query); + } +} diff --git a/Tests/WebService/WebServiceTestCase.php b/Tests/WebService/WebServiceTestCase.php index acf8432..b0024d6 100644 --- a/Tests/WebService/WebServiceTestCase.php +++ b/Tests/WebService/WebServiceTestCase.php @@ -34,4 +34,9 @@ public function setUp() $this->client = new \Bpi($environment['BPI_WS_ENDPOINT'], $environment['BPI_WS_AGENCY_ID'], $environment['BPI_WS_API_KEY'], $environment['BPI_WS_SECRET_KEY']); } } + + protected function getRandomName() + { + return uniqid(__METHOD__); + } } diff --git a/Tests/bootstrap.php b/Tests/bootstrap.php new file mode 100644 index 0000000..f3a2f16 --- /dev/null +++ b/Tests/bootstrap.php @@ -0,0 +1,13 @@ + + bootstrap="Tests/bootstrap.php"> ./Tests/ @@ -19,7 +18,7 @@ - ./ + ./Bpi ./Resources ./Tests