superdesk/contentapi-sdk-php

View on GitHub
src/Superdesk/ContentApiSdk/Api/Request/RequestParameters.php

Summary

Maintainability
A
2 hrs
Test Coverage
<?php

/**
 * This file is part of the PHP SDK library for the Superdesk Content API.
 *
 * Copyright 2015 Sourcefabric z.u. and contributors.
 *
 * For the full copyright and license information, please see the
 * AUTHORS and LICENSE files distributed with this source code.
 *
 * @copyright 2015 Sourcefabric z.รบ.
 * @license http://www.superdesk.org/license
 */

namespace Superdesk\ContentApiSdk\Api\Request;

use Superdesk\ContentApiSdk\Exception\InvalidArgumentException;
use DateTime;

/**
 * Request parameter class.
 */
class RequestParameters
{
    const DEFAULT_PAGE = 1;
    const DEFAULT_MAX_RESULTS = 25;

    /**
     * Start date.
     *
     * @var DateTime|null
     */
    protected $startDate;

    /**
     * End date.
     *
     * @var DateTime|null
     */
    protected $endDate;

    /**
     * Query for text search.
     *
     * @var string|null
     */
    protected $query;

    /**
     * Page.
     *
     * @var int
     */
    protected $page = self::DEFAULT_PAGE;

    /**
     * Max results per page.
     *
     * @var int
     */
    protected $maxResults = self::DEFAULT_MAX_RESULTS;

    /**
     * Include fields list. These fields will be set in your packages or items.
     *
     * @var array|null
     */
    protected $includeFields;

    /**
     * Exclude fields lists. These fields won't be set in your packages or items.
     *
     * @var array|null
     */
    protected $excludeFields;

    /**
     * Mapping array, which links correct parameter name for API with proper
     * method.
     *
     * @var string[]
     */
    protected $propertyMapping = array(
        'start_date' => 'StartDate',
        'end_date' => 'EndDate',
        'q' => 'Query',
        'page' => 'Page',
        'max_results' => 'MaxResults',
        'include_fields' => 'IncludeFields',
        'exclude_fields' => 'ExcludeFields',
    );

    /**
     * Returns start date.
     *
     * @return DateTime|null
     */
    public function getStartDate()
    {
        return $this->startDate;
    }

    /**
     * Sets start date. Will accept a string formatted 'yyyy-mm-dd' or DateTime
     * object.
     *
     * @param string|DateTime|null $startDate
     *
     * @return self
     */
    public function setStartDate($startDate)
    {
        $this->setProperty('startDate', $startDate, 'validateDate');

        return $this;
    }

    /**
     * Returns end date.
     *
     * @return DateTime|null
     */
    public function getEndDate()
    {
        return $this->endDate;
    }

    /**
     * Sets end date. Will accept string formatted 'yyyy-mm-dd' or DateTIme
     * object.
     *
     * @param string|DateTime|null $endDate
     *
     * @return self
     */
    public function setEndDate($endDate)
    {
        $this->setProperty('endDate', $endDate, 'validateDate');

        return $this;
    }

    /**
     * Returns text query.
     *
     * @return string
     */
    public function getQuery()
    {
        return $this->query;
    }

    /**
     * Sets query parameters.
     *
     * @param string|null $query
     *
     * @return self
     */
    public function setQuery($query)
    {
        if (!is_string($query) && $query !== null) {
            throw new InvalidArgumentException('Parameter query should be of type string or null.');
        }

        $this->query = $query;

        return $this;
    }

    /**
     * Returns page number.
     *
     * @return int
     */
    public function getPage()
    {
        return $this->page;
    }

    /**
     * Sets page number. If null is supplied, resets to class default.
     *
     * @param int|null $page
     *
     * @return self
     */
    public function setPage($page)
    {
        if ($page === null) {
            $page = self::DEFAULT_PAGE;
        }

        $this->setProperty('page', $page, 'validateNumeric');

        return $this;
    }

    /**
     * Returns maximum results per page.
     *
     * @return int
     */
    public function getMaxResults()
    {
        return $this->maxResults;
    }

    /**
     * Sets maximum results per page. If null is supplied, resets to class
     * default.
     *
     * @param int|nul $maxResults
     *
     * @return self
     */
    public function setMaxResults($maxResults)
    {
        if ($maxResults === null) {
            $maxResults = self::DEFAULT_MAX_RESULTS;
        }

        $this->setProperty('maxResults', $maxResults, 'validateNumeric');

        return $this;
    }

    /**
     * Returns include fields.
     *
     * @return array
     */
    public function getIncludeFields()
    {
        return $this->includeFields;
    }

    /**
     * Sets include fields.
     *
     * @param array|null $includeFields
     *
     * @return self
     */
    public function setIncludeFields($includeFields)
    {
        $this->setProperty('includeFields', $includeFields, 'validateStringOrArray');

        return $this;
    }

    /**
     * Gets exclude fields.
     *
     * @return array
     */
    public function getExcludeFields()
    {
        return $this->excludeFields;
    }

    /**
     * Sets exclude fields
     *
     * @param array|null
     *
     * @return self
     */
    public function setExcludeFields($excludeFields)
    {
        $this->setProperty('excludeFields', $excludeFields, 'validateStringOrArray');

        return $this;
    }

    /**
     * Validate date parameter input and converts to DateTime.
     *
     * @param  string|DateTime $date When string format yyyy-mm-dd should be used
     *
     * @return DateTime
     * @throws InvalidArgumentException
     */
    private function validateDate($date)
    {
        if ($date instanceof \DateTime) {
            return $date;
        }

        if (!is_string($date)) {
            throw new InvalidArgumentException('Parameter should be of type string or DateTime.');
        } elseif (!preg_match('/\d\d\d\d\-\d\d\-\d\d/', $date)) {
            throw new InvalidArgumentException('Parameter %s has invalid format, please use yyyy-mm-dd.');
        }

        return new DateTime($date);
    }

    /**
     * Arguments of type string and array are valid. String will be split on ,
     * and converted to an array.
     *
     * @param  string|array $value
     *
     * @return array
     * @throws InvalidArgumentException
     */
    private function validateStringOrArray($value)
    {
        if (!is_string($value) && !is_array($value)) {
            throw new InvalidArgumentException('Parameter should be of type string or array.');
        } elseif (is_string($value)) {
            $value = array_map('trim', explode(',', $value));
        }

        return $value;
    }

    /**
     * Validates if value is numeric.
     *
     * @param  string|int $value
     *
     * @return int
     * @throws InvalidArgumentException
     */
    private function validateNumeric($value)
    {
        if (!is_int($value) && !ctype_digit($value)) {
            throw new InvalidArgumentException('Parameter should be of type integer.');
        } elseif (!is_int($value)) {
            $value = (int) $value;
        }

        return $value;
    }

    /**
     * Helper function for setting a property. Sets a proprety to a value, by
     * pulling it through a validator function. If null is specified as value
     * then property will be set to null as well..
     *
     * @param string $property Property name
     * @param mixed $value Value of the property
     * @param string $validator Name of the validator method
     *
     * @throws InvalidArgumentException
     */
    private function setProperty($property, $value, $validator)
    {
        if ($value !== null) {
            try {
                $this->$property = $this->$validator($value);
            } catch (InvalidArgumentException $e) {
                throw new InvalidArgumentException(sprintf('Invalid value for %s parameter.', $property), $e->getCode(), $e);
            }
        } else {
            $this->$property = null;
        }
    }

    /**
     * Internal method to get the correct method when only a query parameter
     * key is available.
     *
     * @param  string $queryKey [description]
     * @param  string $action This will be prepended to the method name,
     *                        defaults to 'get'.
     *
     * @return string|null Returns the method or null when the key doesn't exist.
     */
    private function getMethodForQueryKey($queryKey, $action = 'get')
    {
        if (isset($this->propertyMapping[$queryKey])) {
            return sprintf('%s%s', $action, $this->propertyMapping[$queryKey]);
        }

        return null;
    }

    /**
     * Returns all properties either as an array or http query string.
     *
     * @param  boolean $buildHttpQuery Build query from array
     *
     * @return mixed[]|string
     */
    public function getAllParameters($buildHttpQuery = false)
    {
        $httpQuery = array();

        foreach ($this->propertyMapping as $uriParameter => $methodPart) {

            $method = $this->getMethodForQueryKey($uriParameter);
            $value = $this->$method();

            if ($value instanceof DateTIme) {
                $value = $value->format('Y-m-d');
            }

            $httpQuery[$uriParameter] = $value;
        }

        return ($buildHttpQuery) ? http_build_query($httpQuery) : $httpQuery;
    }

    /**
     * Uses an array of query parameters and sets the values for the current
     * RequestParameters object. Does an internal check whether the query key
     * is a valid API query key.
     *
     * @param  array $requestParameters
     *
     * @return self Returns the current object with the properties set
     */
    public function setQueryParameterArray(array $requestParameters = array())
    {
        foreach ($requestParameters as $key => $value) {
            if (isset($this->propertyMapping[$key])) {
                $method = $this->getMethodForQueryKey($key, 'set');
                $this->$method($value);
            }
        }

        return $this;
    }
}