/core/components/simplesearch/model/simplesearch/driver/libs/Elastica/Bulk.php

https://gitlab.com/haque.mdmanzurul/nga-loyaltymatters · PHP · 400 lines · 237 code · 59 blank · 104 comment · 27 complexity · c5b1604522f6f3f35dffb298c690dc33 MD5 · raw file

  1. <?php
  2. namespace Elastica;
  3. use Elastica\Document;
  4. use Elastica\Exception\Bulk\ResponseException as BulkResponseException;
  5. use Elastica\Exception\Bulk\UdpException;
  6. use Elastica\Exception\InvalidException;
  7. use Elastica\Request;
  8. use Elastica\Response;
  9. use Elastica\Client;
  10. use Elastica\Index;
  11. use Elastica\Type;
  12. use Elastica\Bulk\Action;
  13. use Elastica\Bulk\Action\AbstractDocument as AbstractDocumentAction;
  14. use Elastica\Bulk\ResponseSet;
  15. use Elastica\Bulk\Response as BulkResponse;
  16. class Bulk
  17. {
  18. const DELIMITER = "\n";
  19. const UDP_DEFAULT_HOST = 'localhost';
  20. const UDP_DEFAULT_PORT = 9700;
  21. /**
  22. * @var \Elastica\Client
  23. */
  24. protected $_client;
  25. /**
  26. * @var \Elastica\Bulk\Action[]
  27. */
  28. protected $_actions = array();
  29. /**
  30. * @var string
  31. */
  32. protected $_index = '';
  33. /**
  34. * @var string
  35. */
  36. protected $_type = '';
  37. /**
  38. * @param \Elastica\Client $client
  39. */
  40. public function __construct(Client $client)
  41. {
  42. $this->_client = $client;
  43. }
  44. /**
  45. * @param string|\Elastica\Index $index
  46. * @return \Elastica\Bulk
  47. */
  48. public function setIndex($index)
  49. {
  50. if ($index instanceof Index) {
  51. $index = $index->getName();
  52. }
  53. $this->_index = (string) $index;
  54. return $this;
  55. }
  56. /**
  57. * @return string
  58. */
  59. public function getIndex()
  60. {
  61. return $this->_index;
  62. }
  63. /**
  64. * @return bool
  65. */
  66. public function hasIndex()
  67. {
  68. return '' !== $this->getIndex();
  69. }
  70. /**
  71. * @param string|\Elastica\Type $type
  72. * @return \Elastica\Bulk
  73. */
  74. public function setType($type)
  75. {
  76. if ($type instanceof Type) {
  77. $this->setIndex($type->getIndex()->getName());
  78. $type = $type->getName();
  79. }
  80. $this->_type = (string) $type;
  81. return $this;
  82. }
  83. /**
  84. * @return string
  85. */
  86. public function getType()
  87. {
  88. return $this->_type;
  89. }
  90. /**
  91. * @return bool
  92. */
  93. public function hasType()
  94. {
  95. return '' !== $this->_type;
  96. }
  97. /**
  98. * @return string
  99. */
  100. public function getPath()
  101. {
  102. $path = '/';
  103. if ($this->hasIndex()) {
  104. $path.= $this->getIndex() . '/';
  105. if ($this->hasType()) {
  106. $path.= $this->getType() . '/';
  107. }
  108. }
  109. $path.= '_bulk';
  110. return $path;
  111. }
  112. /**
  113. * @param \Elastica\Bulk\Action $action
  114. * @return \Elastica\Bulk
  115. */
  116. public function addAction(Action $action)
  117. {
  118. $this->_actions[] = $action;
  119. return $this;
  120. }
  121. /**
  122. * @param \Elastica\Bulk\Action[] $actions
  123. * @return \Elastica\Bulk
  124. */
  125. public function addActions(array $actions)
  126. {
  127. foreach ($actions as $action) {
  128. $this->addAction($action);
  129. }
  130. return $this;
  131. }
  132. /**
  133. * @return \Elastica\Bulk\Action[]
  134. */
  135. public function getActions()
  136. {
  137. return $this->_actions;
  138. }
  139. /**
  140. * @param \Elastica\Document $document
  141. * @param string $opType
  142. * @return \Elastica\Bulk
  143. */
  144. public function addDocument(Document $document, $opType = null)
  145. {
  146. $action = AbstractDocumentAction::create($document, $opType);
  147. return $this->addAction($action);
  148. }
  149. /**
  150. * @param \Elastica\Document[] $documents
  151. * @param string $opType
  152. * @return \Elastica\Bulk
  153. */
  154. public function addDocuments(array $documents, $opType = null)
  155. {
  156. foreach ($documents as $document) {
  157. $this->addDocument($document, $opType);
  158. }
  159. return $this;
  160. }
  161. /**
  162. * @param \Elastica\Script $data
  163. * @param string $opType
  164. * @return \Elastica\Bulk
  165. */
  166. public function addScript(Script $script, $opType = null)
  167. {
  168. $action = AbstractDocumentAction::create($script, $opType);
  169. return $this->addAction($action);
  170. }
  171. /**
  172. * @param \Elastica\Document[] $scripts
  173. * @param string $opType
  174. * @return \Elastica\Bulk
  175. */
  176. public function addScripts(array $scripts, $opType = null)
  177. {
  178. foreach ($scripts as $document) {
  179. $this->addScript($document, $opType);
  180. }
  181. return $this;
  182. }
  183. /**
  184. * @param \Elastica\Script|\Elastica\Document\array $data
  185. * @param string $opType
  186. * @return \Elastica\Bulk
  187. */
  188. public function addData($data, $opType = null)
  189. {
  190. if(!is_array($data)){
  191. $data = array($data);
  192. }
  193. foreach ($data as $actionData){
  194. if ($actionData instanceOf Script) {
  195. $this->addScript($actionData, $opType);
  196. }else if ($actionData instanceof Document) {
  197. $this->addDocument($actionData, $opType);
  198. }else{
  199. throw new \InvalidArgumentException("Data should be a Document, a Script or an array containing Documents and/or Scripts");
  200. }
  201. }
  202. return $this;
  203. }
  204. /**
  205. * @param array $data
  206. * @return \Elastica\Bulk
  207. * @throws \Elastica\Exception\InvalidException
  208. */
  209. public function addRawData(array $data)
  210. {
  211. foreach ($data as $row) {
  212. if (is_array($row)) {
  213. $opType = key($row);
  214. $metadata = reset($row);
  215. if (Action::isValidOpType($opType)) {
  216. // add previous action
  217. if (isset($action)) {
  218. $this->addAction($action);
  219. }
  220. $action = new Action($opType, $metadata);
  221. } elseif (isset($action)) {
  222. $action->setSource($row);
  223. $this->addAction($action);
  224. $action = null;
  225. } else {
  226. throw new InvalidException('Invalid bulk data, source must follow action metadata');
  227. }
  228. } else {
  229. throw new InvalidException('Invalid bulk data, should be array of array, Document or Bulk/Action');
  230. }
  231. }
  232. // add last action if available
  233. if (isset($action)) {
  234. $this->addAction($action);
  235. }
  236. return $this;
  237. }
  238. /**
  239. * @return string
  240. */
  241. public function __toString()
  242. {
  243. return $this->toString();
  244. }
  245. /**
  246. * @return string
  247. */
  248. public function toString()
  249. {
  250. $data = '';
  251. foreach ($this->getActions() as $action) {
  252. $data.= $action->toString();
  253. }
  254. return $data;
  255. }
  256. /**
  257. * @return array
  258. */
  259. public function toArray()
  260. {
  261. $data = array();
  262. foreach ($this->getActions() as $action) {
  263. foreach ($action->toArray() as $row) {
  264. $data[] = $row;
  265. }
  266. }
  267. return $data;
  268. }
  269. /**
  270. * @return \Elastica\Bulk\ResponseSet
  271. */
  272. public function send()
  273. {
  274. $path = $this->getPath();
  275. $data = $this->toString();
  276. $response = $this->_client->request($path, Request::PUT, $data);
  277. return $this->_processResponse($response);
  278. }
  279. /**
  280. * @param \Elastica\Response $response
  281. * @throws Exception\Bulk\ResponseException
  282. * @throws Exception\InvalidException
  283. * @return \Elastica\Bulk\ResponseSet
  284. */
  285. protected function _processResponse(Response $response)
  286. {
  287. $responseData = $response->getData();
  288. $actions = $this->getActions();
  289. $bulkResponses = array();
  290. if (isset($responseData['items']) && is_array($responseData['items'])) {
  291. foreach ($responseData['items'] as $key => $item) {
  292. if (!isset($actions[$key])) {
  293. throw new InvalidException('No response found for action #' . $key);
  294. }
  295. $action = $actions[$key];
  296. $opType = key($item);
  297. $bulkResponseData = reset($item);
  298. if ($action instanceof AbstractDocumentAction) {
  299. $data = $action->getData();
  300. if ($data instanceof Document && $data->isAutoPopulate()
  301. || $this->_client->getConfigValue(array('document', 'autoPopulate'), false)
  302. ) {
  303. if (!$data->hasId() && isset($bulkResponseData['_id'])) {
  304. $data->setId($bulkResponseData['_id']);
  305. }
  306. if (isset($bulkResponseData['_version'])) {
  307. $data->setVersion($bulkResponseData['_version']);
  308. }
  309. }
  310. }
  311. $bulkResponses[] = new BulkResponse($bulkResponseData, $action, $opType);
  312. }
  313. }
  314. $bulkResponseSet = new ResponseSet($response, $bulkResponses);
  315. if ($bulkResponseSet->hasError()) {
  316. throw new BulkResponseException($bulkResponseSet);
  317. }
  318. return $bulkResponseSet;
  319. }
  320. /**
  321. * @param string $host
  322. * @param int $port
  323. * @throws \Elastica\Exception\Bulk\UdpException
  324. */
  325. public function sendUdp($host = null, $port = null)
  326. {
  327. if (null === $host) {
  328. $host = $this->_client->getConfigValue(array('udp', 'host'), self::UDP_DEFAULT_HOST);
  329. }
  330. if (null === $port) {
  331. $port = $this->_client->getConfigValue(array('udp', 'port'), self::UDP_DEFAULT_PORT);
  332. }
  333. $message = $this->toString();
  334. $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
  335. $result = socket_sendto($socket, $message, strlen($message), 0, $host, $port);
  336. socket_close($socket);
  337. if (false === $result) {
  338. throw new UdpException('UDP request failed');
  339. }
  340. }
  341. }