1<?php
2
3namespace Elastica\Bulk;
4
5use Elastica\Bulk;
6use Elastica\Index;
7use Elastica\JSON;
8
9class Action
10{
11    public const OP_TYPE_CREATE = 'create';
12    public const OP_TYPE_INDEX = 'index';
13    public const OP_TYPE_DELETE = 'delete';
14    public const OP_TYPE_UPDATE = 'update';
15
16    /**
17     * @var array
18     */
19    public static $opTypes = [
20        self::OP_TYPE_CREATE,
21        self::OP_TYPE_INDEX,
22        self::OP_TYPE_DELETE,
23        self::OP_TYPE_UPDATE,
24    ];
25
26    /**
27     * @var string
28     */
29    protected $_opType;
30
31    /**
32     * @var array
33     */
34    protected $_metadata = [];
35
36    /**
37     * @var array|string
38     */
39    protected $_source = [];
40
41    public function __construct(string $opType = self::OP_TYPE_INDEX, array $metadata = [], array $source = [])
42    {
43        $this->setOpType($opType);
44        $this->setMetadata($metadata);
45        $this->setSource($source);
46    }
47
48    public function __toString(): string
49    {
50        $string = JSON::stringify($this->getActionMetadata(), \JSON_FORCE_OBJECT).Bulk::DELIMITER;
51
52        if ($this->hasSource()) {
53            $source = $this->getSource();
54            if (\is_string($source)) {
55                $string .= $source;
56            } elseif (\is_array($source) && \array_key_exists('doc', $source) && \is_string($source['doc'])) {
57                if (isset($source['doc_as_upsert'])) {
58                    $docAsUpsert = ', "doc_as_upsert": '.($source['doc_as_upsert'] ? 'true' : 'false');
59                } else {
60                    $docAsUpsert = '';
61                }
62                $string .= '{"doc": '.$source['doc'].$docAsUpsert.'}';
63            } else {
64                $string .= JSON::stringify($source, \JSON_UNESCAPED_UNICODE);
65            }
66            $string .= Bulk::DELIMITER;
67        }
68
69        return $string;
70    }
71
72    /**
73     * @return $this
74     */
75    public function setOpType(string $type): self
76    {
77        $this->_opType = $type;
78
79        return $this;
80    }
81
82    public function getOpType(): string
83    {
84        return $this->_opType;
85    }
86
87    /**
88     * @return $this
89     */
90    public function setMetadata(array $metadata): self
91    {
92        $this->_metadata = $metadata;
93
94        return $this;
95    }
96
97    public function getMetadata(): array
98    {
99        return $this->_metadata;
100    }
101
102    public function getActionMetadata(): array
103    {
104        return [$this->_opType => $this->getMetadata()];
105    }
106
107    /**
108     * @param array|string $source
109     *
110     * @return $this
111     */
112    public function setSource($source): self
113    {
114        $this->_source = $source;
115
116        return $this;
117    }
118
119    /**
120     * @return array|string
121     */
122    public function getSource()
123    {
124        return $this->_source;
125    }
126
127    public function hasSource(): bool
128    {
129        return !empty($this->_source);
130    }
131
132    /**
133     * @param Index|string $index
134     *
135     * @return $this
136     */
137    public function setIndex($index): self
138    {
139        if ($index instanceof Index) {
140            $index = $index->getName();
141        }
142        $this->_metadata['_index'] = $index;
143
144        return $this;
145    }
146
147    /**
148     * @return $this
149     */
150    public function setId(string $id): self
151    {
152        $this->_metadata['_id'] = $id;
153
154        return $this;
155    }
156
157    /**
158     * @param int|string $routing
159     *
160     * @return $this
161     */
162    public function setRouting($routing): self
163    {
164        $this->_metadata['routing'] = $routing;
165
166        return $this;
167    }
168
169    public function toArray(): array
170    {
171        $data[] = $this->getActionMetadata();
172        if ($this->hasSource()) {
173            $data[] = $this->getSource();
174        }
175
176        return $data;
177    }
178
179    /**
180     * @deprecated since version 7.1.3, use the "__toString()" method or cast to string instead.
181     */
182    public function toString(): string
183    {
184        \trigger_deprecation('ruflin/elastica', '7.1.3', 'The "%s()" method is deprecated, use "__toString()" or cast to string instead. It will be removed in 8.0.', __METHOD__);
185
186        return (string) $this;
187    }
188
189    public static function isValidOpType(?string $opType = null): bool
190    {
191        return \in_array($opType, self::$opTypes, true);
192    }
193}
194