PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.2
Elementor Website Builder – more than just a page builder v4.3.2
4.3.2 4.3.1 4.3.0 4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 All 455 releases
elementor / vendor_prefixed / mixpanel / lib / ConsumerStrategies / SocketConsumer.php

SocketConsumer.php in Elementor Website Builder – more than just a page builder 4.3.2, at vendor_prefixed/mixpanel/lib/ConsumerStrategies/SocketConsumer.php

261 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ElementorDeps;
4
5 /**
6 * Portions of this class were borrowed from
7 * https://github.com/segmentio/analytics-php/blob/master/lib/Analytics/Consumer/Socket.php.
8 * Thanks for the work!
9 *
10 * WWWWWW||WWWWWW
11 * W W W||W W W
12 * ||
13 * ( OO )__________
14 * / | \
15 * /o o| MIT \
16 * \___/||_||__||_|| *
17 * || || || ||
18 * _||_|| _||_||
19 * (__|__|(__|__|
20 * (The MIT License)
21 *
22 * Copyright (c) 2013 Segment.io Inc. [email protected]
23 *
24 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
25 * documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the
26 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
27 * permit persons to whom the Software is furnished to do so, subject to the following conditions:
28 *
29 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
30 * Software.
31 *
32 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
33 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
34 * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
35 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37 require_once \dirname(__FILE__) . "/AbstractConsumer.php";
38 /**
39 * Consumes messages and writes them to host/endpoint using a persistent socket
40 */
41 class ConsumerStrategies_SocketConsumer extends ConsumerStrategies_AbstractConsumer
42 {
43 /**
44 * @var string the host to connect to (e.g. api.mixpanel.com)
45 */
46 private $_host;
47 /**
48 * @var string the host-relative endpoint to write to (e.g. /engage)
49 */
50 private $_endpoint;
51 /**
52 * @var int connect_timeout the socket connection timeout in seconds
53 */
54 private $_connect_timeout;
55 /**
56 * @var string the protocol to use for the socket connection
57 */
58 private $_protocol;
59 /**
60 * @var resource holds the socket resource
61 */
62 private $_socket;
63 /**
64 * @var bool whether or not to wait for a response
65 */
66 private $_async;
67 /**
68 * @var int the port to use for the socket connection
69 */
70 private $_port;
71 /**
72 * Creates a new SocketConsumer and assigns properties from the $options array
73 * @param array $options
74 */
75 public function __construct($options = array())
76 {
77 parent::__construct($options);
78 $this->_host = $options['host'];
79 $this->_endpoint = $options['endpoint'];
80 $this->_connect_timeout = isset($options['connect_timeout']) ? $options['connect_timeout'] : 5;
81 $this->_async = isset($options['async']) && $options['async'] === \false ? \false : \true;
82 if (\array_key_exists('use_ssl', $options) && $options['use_ssl'] == \true) {
83 $this->_protocol = "ssl";
84 $this->_port = 443;
85 } else {
86 $this->_protocol = "tcp";
87 $this->_port = 80;
88 }
89 }
90 /**
91 * Write using a persistent socket connection.
92 * @param array $batch
93 * @return bool
94 */
95 public function persist($batch)
96 {
97 $socket = $this->_getSocket();
98 if (!\is_resource($socket)) {
99 return \false;
100 }
101 $data = "data=" . $this->_encode($batch);
102 $body = "";
103 $body .= "POST " . $this->_endpoint . " HTTP/1.1\r\n";
104 $body .= "Host: " . $this->_host . "\r\n";
105 $body .= "Content-Type: application/x-www-form-urlencoded\r\n";
106 $body .= "Accept: application/json\r\n";
107 $body .= "Content-length: " . \strlen($data) . "\r\n";
108 $body .= "\r\n";
109 $body .= $data;
110 return $this->_write($socket, $body);
111 }
112 /**
113 * Return cached socket if open or create a new persistent socket
114 * @return bool|resource
115 */
116 private function _getSocket()
117 {
118 if (\is_resource($this->_socket)) {
119 if ($this->_debug()) {
120 $this->_log("Using existing socket");
121 }
122 return $this->_socket;
123 } else {
124 if ($this->_debug()) {
125 $this->_log("Creating new socket at " . \time());
126 }
127 return $this->_createSocket();
128 }
129 }
130 /**
131 * Attempt to open a new socket connection, cache it, and return the resource
132 * @param bool $retry
133 * @return bool|resource
134 */
135 private function _createSocket($retry = \true)
136 {
137 try {
138 $socket = \pfsockopen($this->_protocol . "://" . $this->_host, $this->_port, $err_no, $err_msg, $this->_connect_timeout);
139 if ($this->_debug()) {
140 $this->_log("Opening socket connection to " . $this->_protocol . "://" . $this->_host . ":" . $this->_port);
141 }
142 if ($err_no != 0) {
143 $this->_handleError($err_no, $err_msg);
144 return $retry == \true ? $this->_createSocket(\false) : \false;
145 } else {
146 // cache the socket
147 $this->_socket = $socket;
148 return $socket;
149 }
150 } catch (\Exception $e) {
151 $this->_handleError($e->getCode(), $e->getMessage());
152 return $retry == \true ? $this->_createSocket(\false) : \false;
153 }
154 }
155 /**
156 * Attempt to close and dereference a socket resource
157 */
158 private function _destroySocket()
159 {
160 $socket = $this->_socket;
161 $this->_socket = null;
162 \fclose($socket);
163 }
164 /**
165 * Write $data through the given $socket
166 * @param $socket
167 * @param $data
168 * @param bool $retry
169 * @return bool
170 */
171 private function _write($socket, $data, $retry = \true)
172 {
173 $bytes_sent = 0;
174 $bytes_total = \strlen($data);
175 $socket_closed = \false;
176 $success = \true;
177 $max_bytes_per_write = 8192;
178 // if we have no data to write just return true
179 if ($bytes_total == 0) {
180 return \true;
181 }
182 // try to write the data
183 while (!$socket_closed && $bytes_sent < $bytes_total) {
184 try {
185 $bytes = \fwrite($socket, $data, $max_bytes_per_write);
186 if ($this->_debug()) {
187 $this->_log("Socket wrote " . $bytes . " bytes");
188 }
189 // if we actually wrote data, then remove the written portion from $data left to write
190 if ($bytes > 0) {
191 $data = \substr($data, $max_bytes_per_write);
192 }
193 } catch (\Exception $e) {
194 $this->_handleError($e->getCode(), $e->getMessage());
195 $socket_closed = \true;
196 }
197 if (isset($bytes) && $bytes) {
198 $bytes_sent += $bytes;
199 } else {
200 $socket_closed = \true;
201 }
202 }
203 // create a new socket if the current one is closed and retry the message
204 if ($socket_closed) {
205 $this->_destroySocket();
206 if ($retry) {
207 if ($this->_debug()) {
208 $this->_log("Retrying socket write...");
209 }
210 $socket = $this->_getSocket();
211 if ($socket) {
212 return $this->_write($socket, $data, \false);
213 }
214 }
215 return \false;
216 }
217 // only wait for the response in debug mode or if we explicitly want to be synchronous
218 if ($this->_debug() || !$this->_async) {
219 $res = $this->handleResponse(\fread($socket, 2048));
220 if ($res["status"] != "200") {
221 $this->_handleError($res["status"], $res["body"]);
222 $success = \false;
223 }
224 }
225 return $success;
226 }
227 /**
228 * Parse the response from a socket write (only used for debugging)
229 * @param $response
230 * @return array
231 */
232 private function handleResponse($response)
233 {
234 $lines = \explode("\n", $response);
235 // extract headers
236 $headers = array();
237 foreach ($lines as $line) {
238 $kvsplit = \explode(":", $line);
239 if (\count($kvsplit) == 2) {
240 $header = $kvsplit[0];
241 $value = $kvsplit[1];
242 $headers[$header] = \trim($value);
243 }
244 }
245 // extract status
246 $line_one_exploded = \explode(" ", $lines[0]);
247 $status = $line_one_exploded[1];
248 // extract body
249 $body = $lines[\count($lines) - 1];
250 // if the connection has been closed lets kill the socket
251 if (isset($headers["Connection"]) and $headers['Connection'] == "close") {
252 $this->_destroySocket();
253 if ($this->_debug()) {
254 $this->_log("Server told us connection closed so lets destroy the socket so it'll reconnect on next call");
255 }
256 }
257 $ret = array("status" => $status, "body" => $body);
258 return $ret;
259 }
260 }
261