bookboon/api-php

View on GitHub
src/Entity/Book.php

Summary

Maintainability
C
1 day
Test Coverage
C
71%
<?php

namespace Bookboon\Api\Entity;

use Bookboon\Api\Bookboon;
use Bookboon\Api\Client\BookboonResponse;
use Bookboon\Api\Client\ClientInterface;
use Bookboon\Api\Exception\UsageException;

abstract class Book extends Entity
{
    const _OWN_TYPE = '';

    const TYPE_AUDIO = 'audio';
    const TYPE_PDF = 'pdf';
    const TYPE_VIDEO = 'video';
    const TYPE_AUDIOTALK = 'audioTalk';
    const TYPE_CLASSROOM = 'classroom';

    const FORMAT_PDF = 'pdf';
    const FORMAT_EPUB = 'epub';
    const FORMAT_MOBI = 'mobi';
    const FORMAT_VIDEO = 'video';
    const FORMAT_M4B = 'm4b';
    const FORMAT_M3U = 'm3u';

    /**
     * @param Bookboon $bookboon
     * @param string $bookId
     * @param bool $extendedMetadata
     * @param array $params
     * @return BookboonResponse<Book>
     * @throws UsageException
     * @throws \Bookboon\Api\Exception\ApiDecodeException
     */
    public static function get(Bookboon $bookboon, string $bookId, bool $extendedMetadata = false, array $params = []) : BookboonResponse
    {
        $bResponse = $bookboon->rawRequest(
            "/v1/books/$bookId",
            array_merge($params, ['extendedMetadata' => $extendedMetadata ? 'true' : 'false']),
            ClientInterface::HTTP_GET,
            true,
            Book::class
        );

        $bResponse->setEntityStore(
            new EntityStore(
                [
                    static::objectTransformer($bResponse->getReturnArray())
                ],
                Book::class
            )
        );

        return $bResponse;
    }

    /**
     * Get many books
     *
     * @param Bookboon $bookboon
     * @param string[] $bookIds
     * @param bool $extendedMetadata
     * @return BookboonResponse<Book>
     * @throws \Bookboon\Api\Exception\UsageException
     */
    public static function getMultiple(
        Bookboon $bookboon,
        array $bookIds,
        bool $extendedMetadata = false
    ) : BookboonResponse {
        if (count($bookIds) === 0) {
            throw new UsageException('At least one id is required for bookIds');
        }

        $variables = [
            'id' => $bookIds,
            'extendedMetadata' => $extendedMetadata ? 'true' : 'false'
        ];

        $bResponse = $bookboon->rawRequest(
            '/v1/books',
            $variables,
            ClientInterface::HTTP_GET,
            true,
            Book::class
        );

        $bResponse->setEntityStore(
            new EntityStore(static::getEntitiesFromArray($bResponse->getReturnArray()), Book::class)
        );

        return $bResponse;
    }

    /**
     * Get many books
     *
     * @param Bookboon $bookboon
     * @param bool $extendedMetadata
     * @param array $bookTypes
     * @return BookboonResponse<Book>
     * @throws \Bookboon\Api\Exception\UsageException
     *
     * @deprecated Should not be used for performance reasons
     */
    public static function getAll(
        Bookboon $bookboon,
        bool $extendedMetadata = false,
        array $bookTypes = [self::_OWN_TYPE]
    ) : BookboonResponse {
        $variables = [
            'bookType' => join(',', $bookTypes),
            'extendedMetadata' => $extendedMetadata ? 'true' : 'false'
        ];

        $bResponse = $bookboon->rawRequest(
            '/v1/books',
            $variables,
            ClientInterface::HTTP_GET,
            true,
            Book::class
        );

        $bResponse->setEntityStore(
            new EntityStore(static::getEntitiesFromArray($bResponse->getReturnArray()), Book::class)
        );

        return $bResponse;
    }
    /**
     * Get many books by filter
     *
     * @param Bookboon $bookboon
     * @param array $bookTypes
     * @param array $filters
     * @return BookboonResponse<Book>
     * @throws \Bookboon\Api\Exception\UsageException
     **/
    public static function getByFilters(
        Bookboon $bookboon,
        array $bookTypes = [self::_OWN_TYPE],
        array $filters = []
    ) : BookboonResponse {
        $variables = [
            'bookType' => join(',', $bookTypes),
        ];

        $variables = array_merge($variables, $filters);

        $bResponse = $bookboon->rawRequest(
            '/v1/books',
            $variables,
            ClientInterface::HTTP_GET,
            true,
            Book::class
        );

        $bResponse->setEntityStore(
            new EntityStore(static::getEntitiesFromArray($bResponse->getReturnArray()), Book::class)
        );

        return $bResponse;
    }

    /**
     * @param array $objectArray
     * @return Book
     */
    public static function objectTransformer(array $objectArray)
    {
        $className = 'Bookboon\Api\Entity\\' . ucfirst($objectArray['_type']) . 'Book';

        /** @var Book $book */
        $book = new $className($objectArray);

        return $book;
    }

    /**
     * @psalm-suppress LessSpecificImplementedReturnType
     * @param array $array
     * @return array<Book>
     */
    public static function getEntitiesFromArray(array $array) : array
    {
        $entities = [];

        foreach ($array as $object) {
            if (in_array(
                $object['_type'],
                [self::TYPE_PDF, self::TYPE_AUDIO, self::TYPE_VIDEO, self::TYPE_AUDIOTALK, self::TYPE_CLASSROOM],
                true)
            ) {
                $entities[] = self::objectTransformer($object);
            }
        }

        return $entities;
    }


    /**
     * Get the download url.
     *
     * @param Bookboon $bookboon
     * @param string $bookId
     * @param array $variables
     * @param string $format
     * @return string
     * @throws \Bookboon\Api\Exception\UsageException
     */
    public static function getDownloadUrl(
        Bookboon $bookboon,
        string $bookId,
        array $variables,
        string $format = self::FORMAT_PDF
    ) : string {
        $variables['format'] = $format;

        $bResponse = $bookboon->rawRequest("/v1/books/$bookId/download", $variables, ClientInterface::HTTP_POST);

        return $bResponse->getReturnArray()['url'];
    }

    /**
     * Search.
     *
     * @param Bookboon $bookboon
     * @param string $query
     * @param int $limit
     * @param int $offset
     * @param array $bookTypes
     * @return BookboonResponse<Book>
     * @throws UsageException
     * @throws \Bookboon\Api\Exception\ApiDecodeException
     */
    public static function search(
        Bookboon $bookboon,
        string $query,
        int $limit = 10,
        int $offset = 0,
         array $bookTypes = ['professional']
    ) : BookboonResponse {
        $bResponse = $bookboon->rawRequest(
            '/v1/search',
            ['q' => $query, 'limit' => $limit, 'offset' => $offset, 'bookType' => join(',', $bookTypes)],
            ClientInterface::HTTP_GET,
            true,
            Book::class
        );

        $bResponse->setEntityStore(
            new EntityStore(Book::getEntitiesFromArray($bResponse->getReturnArray()), Book::class)
        );

        return $bResponse;
    }

    /**
     * Recommendations.
     *
     * @param Bookboon $bookboon
     * @param array $bookTypes
     * @param array $bookIds array of book ids to base recommendations on, can be empty
     * @param int $limit
     * @param array $params
     * @return BookboonResponse<Book>
     * @throws \Bookboon\Api\Exception\UsageException
     */
    public static function recommendations(
        Bookboon $bookboon,
        array $bookIds = [],
        int $limit = 5,
        array $bookTypes = ['professional'],
        array $params = []
    ) : BookboonResponse {
        $bResponse = $bookboon->rawRequest(
            '/v1/recommendations',
            array_merge($params, [
                'limit' => $limit,
                'books' => $bookIds,
                'bookType' => join(',', $bookTypes)
            ]),
            ClientInterface::HTTP_GET,
            true,
            Book::class
        );

        $bResponse->setEntityStore(
            new EntityStore(Book::getEntitiesFromArray($bResponse->getReturnArray()), Book::class)
        );

        return $bResponse;
    }

    protected function isValid(array $array) : bool
    {
        return isset($array['_id'], $array['title'], $array['authors'], $array['thumbnail']);
    }

    /**
     * @return string UUID of entity
     */
    public function getId()
    {
        return $this->safeGet('_id');
    }

    /**
     * @return string slug
     */
    public function getSlug()
    {
        return $this->safeGet('_slug');
    }

    /**
     * @return string link to category on bookboon.com
     */
    public function getHomepage()
    {
        return $this->safeGet('homepage');
    }

    /**
     * Return the title.
     *
     * @return string title
     */
    public function getTitle()
    {
        return $this->safeGet('title');
    }

    /**
     * Returns the subtitle.
     *
     * @return string subtitle
     */
    public function getSubtitle()
    {
        return $this->safeGet('subtitle');
    }

    /**
     * Return authors.
     *
     * @return string semicolon separated list of authors
     */
    public function getAuthors()
    {
        return $this->safeGet('authors');
    }

    /**
     * Return ISBN number.
     *
     * @return string ISBN number
     */
    public function getIsbn()
    {
        return $this->safeGet('isbn');
    }

    /**
     * Returns closes thumbnail size to input, default 210px.
     *
     * @param int  $size appromimate size
     *
     * @return string url for thumbnail
     */
    public function getThumbnail(int $size = 210)
    {
        return $this->thumbnailResolver($this->safeGet('thumbnail', []), $size);
    }

    /**
     * Returns closes raw thumbnail (without branding) size to input, default 210px.
     *
     * @param int $size appromimate size
     * @param string $type
     *
     * @return string url for thumbnail
     */
    public function getThumbnailRaw(int $size = 210, string $type = 'default')
    {
        $thumbUrl = $this->safeGet('thumbnail')[0]['_link'];
        $thumbnailParts = explode('/', $thumbUrl);

        return "{$thumbnailParts[0]}//{$thumbnailParts[2]}/thumbnail/b/$size/{$this->getId()}/$type.jpg";
    }

    /**
     * Return language name.
     *
     * @return string language name
     */
    public function getLanguageName()
    {
        $language = $this->safeGet('language');

        return $language['name'] ?? '';
    }

    /**
     * Returns ISO language code.
     *
     * @return string language ISO 639-1 code
     */
    public function getLanguageCode()
    {
        $language = $this->safeGet('language');

        return $language['code'] ?? '';
    }

    /**
     * Return publish date.
     *
     * @return string date of publishing
     */
    public function getPublished()
    {
        return $this->safeGet('published');
    }

    /**
     * Return book abstract.
     *
     * @return string
     */
    public function getAbstract()
    {
        return $this->safeGet('abstract');
    }

    /**
     * Return book edition.
     *
     * @return int
     */
    public function getEdition()
    {
        return $this->safeGet('edition');
    }

    /**
     * Return number of pages.
     *
     * @return int number of pages
     */
    public function getPages()
    {
        return $this->safeGet('pages');
    }

    /**
     * Return average rating.
     *
     * @return float|false if no ratings given returns false
     */
    public function getRatingAverage()
    {
        $rating = $this->safeGet('rating');

        return isset($rating['average']) ? $rating['average'] : false;
    }

    /**
     * Return number of ratings given.
     *
     * @return int
     */
    public function getRatingCount()
    {
        $rating = $this->safeGet('rating');

        return isset($rating['count']) ? $rating['count'] : 0;
    }

    /**
     * Return available formats.
     *
     * @return array of strings
     */
    public function getFormats()
    {
        return $this->safeGet('formats');
    }

    /**
     * Return price set on book.
     *
     * @return float
     */
    public function getPrice()
    {
        return $this->safeGet('price');
    }

    /**
     * @return string
     */
    public function getPriceLevel()
    {
        return $this->safeGet('priceLevel');
    }

    /**
     * Return price level set on book.
     *
     * @return int
     */
    public function getPremiumLevel()
    {
        return $this->safeGet('premiumLevel');
    }

    /**
     * Return book version.
     *
     * @return int version
     */
    public function getVersion()
    {
        return $this->safeGet('version');
    }

    /**
     * Return search context, only on search calls.
     *
     * @return string|false if not set
     */
    public function getContext()
    {
        return $this->safeGet('context');
    }

    /**
     * Returns array of book details.
     *
     * @return array of Details
     */
    public function getDetails()
    {
        return Detail::getEntitiesFromArray($this->safeGet('details', []));
    }

    /**
     * Return array of similar books.
     *
     * @return array of Book
     */
    public function getSimilarBooks()
    {
        return self::getEntitiesFromArray($this->safeGet('similar', []));
    }

    /**
     * Return array of book reviews.
     *
     * @return array of Review
     */
    public function getReviews()
    {
        return Review::getEntitiesFromArray($this->safeGet('reviews', []));
    }

    /**
     * Returns true if Epub format is available.
     *
     * @return bool
     */
    public function hasEpub()
    {
        return in_array('epub', $this->getFormats());
    }

    /**
     * Returns true if PDF format is available.
     *
     * @return bool
     */
    public function hasPdf()
    {
        return in_array('pdf', $this->getFormats());
    }
}