@@ -33,6 +33,9 @@ class CurlEventPublisher implements EventPublisher
3333 /** @var int */
3434 private $ _connectTimeout ;
3535
36+ /** @var bool */
37+ private $ _isWindows ;
38+
3639 public function __construct (string $ sdkKey , array $ options = array ())
3740 {
3841 $ this ->_sdkKey = $ sdkKey ;
@@ -56,16 +59,33 @@ public function __construct(string $sdkKey, array $options = array())
5659 }
5760
5861 $ this ->_connectTimeout = $ options ['connect_timeout ' ];
62+ $ this ->_isWindows = PHP_OS_FAMILY == 'Windows ' ;
5963 }
6064
6165 public function publish (string $ payload ): bool
6266 {
63- $ args = $ this ->createArgs ($ payload );
67+ if (!$ this ->_isWindows ) {
68+ $ args = $ this ->createCurlArgs ($ payload );
69+ return $ this ->makeCurlRequest ($ args );
70+ }
71+
72+ $ tmpfile = tempnam (sys_get_temp_dir (), 'ld- ' );
73+ if ($ tmpfile === false ) {
74+ return false ;
75+ }
76+
77+ if (file_put_contents ($ tmpfile , $ payload ) === false ) {
78+ return false ;
79+ };
80+
81+ $ args = $ this ->createPowershellArgs ($ tmpfile );
82+ $ this ->makePowershellRequest ($ args );
83+
84+ return true ;
6485
65- return $ this ->makeRequest ($ args );
6686 }
6787
68- private function createArgs (string $ payload ): string
88+ private function createCurlArgs (string $ payload ): string
6989 {
7090 $ scheme = $ this ->_ssl ? "https:// " : "http:// " ;
7191 $ args = " -X POST " ;
@@ -83,10 +103,48 @@ private function createArgs(string $payload): string
83103 /**
84104 * @psalm-suppress ForbiddenCode
85105 */
86- private function makeRequest (string $ args ): bool
106+ private function makeCurlRequest (string $ args ): bool
87107 {
88108 $ cmd = $ this ->_curl . " " . $ args . ">> /dev/null 2>&1 & " ;
89109 shell_exec ($ cmd );
90110 return true ;
91111 }
112+
113+ private function createPowershellArgs (string $ payloadFile ): string
114+ {
115+ $ headers = [
116+ 'Content-Type ' => 'application/json ' ,
117+ 'Authorization ' => $ this ->_sdkKey ,
118+ 'User-Agent ' => 'PHPClient/ ' . LDClient::VERSION ,
119+ 'X-LaunchDarkly-Event-Schema ' => EventPublisher::CURRENT_SCHEMA_VERSION ,
120+ 'Accept ' => 'application/json ' ,
121+ ];
122+
123+ $ headerString = "" ;
124+ foreach ($ headers as $ key => $ value ) {
125+ $ headerString .= sprintf ("'%s'='%s'; " , $ key , $ value );
126+ }
127+
128+ $ scheme = $ this ->_ssl ? "https:// " : "http:// " ;
129+ $ args = " Invoke-WebRequest " ;
130+ $ args .= " -Method POST " ;
131+ $ args .= " -UseBasicParsing " ;
132+ $ args .= " -InFile $ payloadFile " ;
133+ $ args .= " -H @{ " . $ headerString . "} " ;
134+ $ args .= " -Uri " . escapeshellarg ($ scheme . $ this ->_host . ": " . $ this ->_port . $ this ->_path . "/bulk " );
135+ $ args .= " ; Remove-Item $ payloadFile " ;
136+
137+ return $ args ;
138+ }
139+
140+ /**
141+ * @psalm-suppress ForbiddenCode
142+ */
143+ private function makePowershellRequest (string $ args ): bool
144+ {
145+ $ cmd = base64_encode (iconv ("UTF-8 " , "UTF-16LE " , utf8_encode ($ args )));
146+ shell_exec ("start /B powershell.exe -encodedCommand $ cmd > nul 2>&1 " );
147+
148+ return true ;
149+ }
92150}
0 commit comments