1<?php 2 3namespace Elastica\Script; 4 5use Elastica\AbstractUpdateAction; 6use Elastica\Exception\InvalidException; 7 8/** 9 * Base class for Script object. 10 * 11 * Wherever scripting is supported in the Elasticsearch API, scripts can be referenced as "inline", "id" or "file". 12 * 13 * @author Nicolas Assing <nicolas.assing@gmail.com> 14 * @author Tobias Schultze <http://tobion.de> 15 * @author Martin Janser <martin.janser@liip.ch> 16 * 17 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html 18 */ 19abstract class AbstractScript extends AbstractUpdateAction 20{ 21 public const LANG_MOUSTACHE = 'moustache'; 22 public const LANG_EXPRESSION = 'expression'; 23 public const LANG_PAINLESS = 'painless'; 24 25 /** 26 * @var string|null 27 */ 28 private $_lang; 29 30 /** 31 * @var bool|null 32 */ 33 private $scriptedUpsert; 34 35 /** 36 * @param string|null $lang Script language, see constants 37 * @param string|null $documentId Document ID the script action should be performed on (only relevant in update context) 38 */ 39 public function __construct(?array $params = null, ?string $lang = null, ?string $documentId = null) 40 { 41 if ($params) { 42 $this->setParams($params); 43 } 44 45 if (null !== $lang) { 46 $this->setLang($lang); 47 } 48 49 if (null !== $documentId) { 50 $this->setId($documentId); 51 } 52 } 53 54 /** 55 * Factory to create a script object from data structure (reverse toArray). 56 * 57 * @param AbstractScript|array|string $data 58 * 59 * @throws InvalidException 60 * 61 * @return Script|ScriptId|self 62 */ 63 public static function create($data) 64 { 65 if ($data instanceof self) { 66 return $data; 67 } 68 69 if (\is_array($data)) { 70 return self::_createFromArray($data); 71 } 72 73 if (\is_string($data)) { 74 $class = self::class === static::class ? Script::class : static::class; 75 76 return new $class($data); 77 } 78 79 throw new InvalidException('Failed to create script. Invalid data passed.'); 80 } 81 82 public function setLang(string $lang): self 83 { 84 $this->_lang = $lang; 85 86 return $this; 87 } 88 89 public function getLang(): ?string 90 { 91 return $this->_lang; 92 } 93 94 /** 95 * {@inheritdoc} 96 */ 97 public function toArray(): array 98 { 99 $array = $this->getScriptTypeArray(); 100 101 if ($this->_params) { 102 $array['params'] = $this->_convertArrayable($this->_params); 103 } 104 105 if (null !== $this->_lang) { 106 $array['lang'] = $this->_lang; 107 } 108 109 return ['script' => $array]; 110 } 111 112 /** 113 * Returns an array with the script type as key and the script content as value. 114 */ 115 abstract protected function getScriptTypeArray(): array; 116 117 private static function _createFromArray(array $data) 118 { 119 $params = $data['script']['params'] ?? []; 120 $lang = $data['script']['lang'] ?? null; 121 122 if (!\is_array($params)) { 123 throw new InvalidException('Script params must be an array'); 124 } 125 126 if (isset($data['script']['source'])) { 127 return new Script( 128 $data['script']['source'], 129 $params, 130 $lang 131 ); 132 } 133 134 if (isset($data['script']['id'])) { 135 return new ScriptId( 136 $data['script']['id'], 137 $params, 138 $lang 139 ); 140 } 141 142 throw new InvalidException('Failed to create script. Invalid data passed.'); 143 } 144 145 public function setScriptedUpsert(bool $scriptedUpsert): void 146 { 147 $this->scriptedUpsert = $scriptedUpsert; 148 } 149 150 public function getScriptedUpsert(): ?bool 151 { 152 return $this->scriptedUpsert; 153 } 154} 155