1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 
<?php
namespace Omeka\Api;

/**
 * API request.
 */
class Request
{
    const SEARCH = 'search';
    const CREATE = 'create';
    const BATCH_CREATE = 'batch_create';
    const BATCH_UPDATE = 'batch_update';
    const BATCH_DELETE = 'batch_delete';
    const READ = 'read';
    const UPDATE = 'update';
    const DELETE = 'delete';

    /**
     * @var array
     */
    protected $operations = [
        self::SEARCH, self::CREATE, self::BATCH_CREATE, self::BATCH_UPDATE,
        self::READ, self::UPDATE, self::DELETE, self::BATCH_DELETE,
    ];

    /**
     * @var string
     */
    protected $operation;

    /**
     * @var string
     */
    protected $resource;

    /**
     * @var mixed
     */
    protected $id;

    /**
     * @var array
     */
    protected $ids = [];

    /**
     * @var array
     */
    protected $fileData = [];

    /**
     * @var array
     */
    protected $options = [];

    /**
     * @var array
     */
    protected $content = [];

    /**
     * Construct an API request.
     *
     * @throws Exception\BadRequestException
     * @param string $operation The request operation
     * @param string $resource The request resource
     */
    public function __construct($operation, $resource)
    {
        if (!in_array($operation, $this->operations)) {
            throw new Exception\BadRequestException(sprintf(
                'The API does not support the "%s" request operation.',
                $operation
            ));
        }
        if (!is_string($resource)) {
            throw new Exception\BadRequestException(sprintf(
                'The API request resource must be a string. Type "%s" given.',
                gettype($resource)
            ));
        }
        if ('' === $resource) {
            throw new Exception\BadRequestException('The API request must include a resource. None given.');
        }

        $this->operation = $operation;
        $this->resource = $resource;
    }

    /**
     * Get the request operation.
     *
     * @return string
     */
    public function getOperation()
    {
        return $this->operation;
    }

    /**
     * Get the request resource.
     *
     * @return string
     */
    public function getResource()
    {
        return $this->resource;
    }

    /**
     * Set the request resource ID.
     *
     * @param mixed $id
     */
    public function setId($id)
    {
        $this->id = $id;
        return $this;
    }

    /**
     * Get the request resource ID.
     *
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set the request resource IDs.
     *
     * @param mixed $id
     */
    public function setIds(array $ids)
    {
        $this->ids = $ids;
        return $this;
    }

    /**
     * Get the request resource IDs.
     *
     * @return mixed
     */
    public function getIds()
    {
        return $this->ids;
    }

    /**
     * Set the file data for the request.
     *
     * @param array $fileData
     */
    public function setFileData(array $fileData)
    {
        $this->fileData = $fileData;
        return $this;
    }

    /**
     * Get the file data for the request.
     *
     * @return array
     */
    public function getFileData()
    {
        return $this->fileData;
    }

    /**
     * Set a request option or options.
     *
     * Options that affect the execution of a request are:
     *
     * - initialize: (bool) Set whether to initialize the request during
     *     execute() (e.g. trigger API-pre events). Default is true.
     * - finalize: (bool) Set whether to finalize the request during execute()
     *     (e.g. trigger API-post events and transform response content
     *     according to the "responseContent" option). Default is true.
     * - returnScalar: (string) Set which field/column to return as an array of
     *     scalars during a SEARCH request. The request will not finalize when
     *     this option is set. Default is false (default behavior).
     * - isPartial: (bool) Set whether this is a partial UPDATE request (aka
     *     PATCH). Default is false.
     * - collectionAction: (string) Set which action to take on certain
     *     collections during a partial UPDATE request. Default is "replace",
     *     which is normal UPDATE behavior. The actions are:
     *     - replace: the passed data replaces the collection
     *     - append: append passed data to collections
     *     - remove: remove passed data from collections
     * - continueOnError: (bool) Set whether a BATCH_CREATE operation should
     *     continue processing on error. Default is false.
     * - flushEntityManager: (bool) Set whether to flush the entity manager
     *     during CREATE, UPDATE, and DELETE. Default is true.
     * - responseContent: (string) Set the type of content the API response
     *     should contain. Default is "representation". The types are:
     *     - representation: an API resource representation (implements Omeka\Api\Representation\RepresentationInterface)
     *     - reference: an API resource reference (instance of Omeka\Api\Representation\ResourceReference)
     *     - resource: an API resource (implements Omeka\Api\ResourceInterface)
     *
     * @param string|int|array $spec
     * @param mixed $value
     */
    public function setOption($spec, $value = null)
    {
        if (is_array($spec)) {
            foreach ($spec as $key => $value) {
                $this->options[$key] = $value;
            }
        } else {
            $this->options[$spec] = $value;
        }
        return $this;
    }

    /**
     * Get all options or a single option as specified by key.
     *
     * @param null|string|int $key
     * @param null|mixed $default
     * @return mixed
     */
    public function getOption($key = null, $default = null)
    {
        if (null === $key) {
            return $this->options;
        }
        if (array_key_exists($key, $this->options)) {
            return $this->options[$key];
        }
        return $default;
    }

    /**
     * Set request content.
     *
     * The API request content must always be an array.
     *
     * @param array $value
     */
    public function setContent(array $value)
    {
        $this->content = $value;
        return $this;
    }

    /**
     * Get request content.
     *
     * @return array
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Get a value from the content by key.
     *
     * @param string $key
     * @param mixed $default
     * @return mixed
     */
    public function getValue($key, $default = null)
    {
        $data = $this->getContent();
        return array_key_exists($key, $data) ? $data[$key] : $default;
    }
}