Skip to content

Commit b741ee8

Browse files
committed
Extracted a whole bunch of things from the child process adapter into the AbstractSyncAdapter so it can be used in the pthreads adapter in time
1 parent 9aa22c2 commit b741ee8

2 files changed

Lines changed: 279 additions & 190 deletions

File tree

src/AbstractSyncAdapter.php

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
<?php
2+
3+
namespace React\Filesystem;
4+
5+
use DateTimeImmutable;
6+
use React\Filesystem\Node\NodeInterface;
7+
use React\Filesystem\Stream\StreamFactory;
8+
use React\Promise\FulfilledPromise;
9+
use React\Promise\PromiseInterface;
10+
use React\Promise\RejectedPromise;
11+
use WyriHaximus\React\ChildProcess\Messenger\Messages\Factory;
12+
use WyriHaximus\React\ChildProcess\Messenger\Messenger;
13+
14+
abstract class AbstractSyncAdapter implements AdapterInterface
15+
{
16+
/**
17+
* @var array
18+
*/
19+
protected $fileDescriptors = [];
20+
21+
/**
22+
* @var TypeDetectorInterface[]
23+
*/
24+
protected $typeDetectors = [];
25+
26+
/**
27+
* @var PermissionFlagResolver
28+
*/
29+
protected $permissionFlagResolver;
30+
31+
/**
32+
* @var CallInvokerInterface
33+
*/
34+
protected $invoker;
35+
36+
/**
37+
* @var array
38+
*/
39+
protected $options = [
40+
'lsFlags' => SCANDIR_SORT_NONE,
41+
];
42+
43+
/**
44+
* @param string $path
45+
* @return PromiseInterface
46+
*/
47+
public function rmdir($path)
48+
{
49+
return $this->invoker->invokeCall('rmdir', [
50+
'path' => $path,
51+
]);
52+
}
53+
54+
/**
55+
* @param string $path
56+
* @return PromiseInterface
57+
*/
58+
public function unlink($path)
59+
{
60+
return $this->invoker->invokeCall('unlink', [
61+
'path' => $path,
62+
]);
63+
}
64+
65+
/**
66+
* @param string $path
67+
* @param int $uid
68+
* @param int $gid
69+
* @return PromiseInterface
70+
*/
71+
public function chown($path, $uid, $gid)
72+
{
73+
return $this->invoker->invokeCall('chown', [
74+
'path' => $path,
75+
'uid' => $uid,
76+
'gid' => $gid,
77+
]);
78+
}
79+
80+
/**
81+
* @param string $filename
82+
* @return PromiseInterface
83+
*/
84+
public function stat($filename)
85+
{
86+
return $this->invoker->invokeCall('stat', [
87+
'path' => $filename,
88+
])->then(function ($stat) {
89+
$stat['atime'] = new DateTimeImmutable('@' . $stat['atime']);
90+
$stat['mtime'] = new DateTimeImmutable('@' . $stat['mtime']);
91+
$stat['ctime'] = new DateTimeImmutable('@' . $stat['ctime']);
92+
return \React\Promise\resolve($stat);
93+
});
94+
}
95+
96+
/**
97+
* @param string $path
98+
* @return PromiseInterface
99+
*/
100+
public function ls($path)
101+
{
102+
$stream = new ObjectStream();
103+
104+
$this->invoker->invokeCall('readdir', [
105+
'path' => $path,
106+
'flags' => $this->options['lsFlags'],
107+
])->then(function ($result) use ($path, $stream) {
108+
$this->processLsContents($path, $result, $stream);
109+
});
110+
111+
return $stream;
112+
}
113+
114+
protected function processLsContents($basePath, $result, ObjectStream $stream)
115+
{
116+
$promises = [];
117+
118+
foreach ($result as $entry) {
119+
$path = $basePath . DIRECTORY_SEPARATOR . $entry['name'];
120+
$node = [
121+
'path' => $path,
122+
'type' => $entry['type'],
123+
];
124+
$promises[] = \React\Filesystem\detectType($this->typeDetectors, $node)->then(function (NodeInterface $node) use ($stream) {
125+
$stream->write($node);
126+
127+
return new FulfilledPromise();
128+
});
129+
}
130+
131+
\React\Promise\all($promises)->then(function () use ($stream) {
132+
$stream->close();
133+
});
134+
}
135+
136+
/**
137+
* @param string $path
138+
* @param $mode
139+
* @return PromiseInterface
140+
*/
141+
public function touch($path, $mode = self::CREATION_MODE)
142+
{
143+
return $this->invoker->invokeCall('touch', [
144+
'path' => $path,
145+
'mode' => decoct($this->permissionFlagResolver->resolve($mode)),
146+
]);
147+
}
148+
149+
/**
150+
* @param string $path
151+
* @param string $flags
152+
* @param $mode
153+
* @return PromiseInterface
154+
*/
155+
public function open($path, $flags, $mode = self::CREATION_MODE)
156+
{
157+
return new RejectedPromise();
158+
$id = null;
159+
return \WyriHaximus\React\ChildProcess\Messenger\Factory::parentFromClass(self::CHILD_CLASS_NAME, $this->loop)->then(function (Messenger $messenger) use (&$id, $path, $flags, $mode) {
160+
$id = count($this->fileDescriptors);
161+
$this->fileDescriptors[$id] = $messenger;
162+
return $this->fileDescriptors[$id]->rpc(Factory::rpc('open', [
163+
'path' => $path,
164+
'flags' => $flags,
165+
'mode' => $mode,
166+
]));
167+
})->then(function () use ($path, $flags, &$id) {
168+
return \React\Promise\resolve(StreamFactory::create($path, $id, $flags, $this));
169+
});
170+
}
171+
172+
/**
173+
* @param $fileDescriptor
174+
* @param int $length
175+
* @param int $offset
176+
* @return PromiseInterface
177+
*/
178+
public function read($fileDescriptor, $length, $offset)
179+
{
180+
return new RejectedPromise();
181+
return $this->fileDescriptors[$fileDescriptor]->rpc(Factory::rpc('read', [
182+
'length' => $length,
183+
'offset' => $offset,
184+
]))->then(function ($payload) {
185+
return \React\Promise\resolve($payload['chunk']);
186+
});
187+
}
188+
189+
/**
190+
* @param $fileDescriptor
191+
* @param string $data
192+
* @param int $length
193+
* @param int $offset
194+
* @return PromiseInterface
195+
*/
196+
public function write($fileDescriptor, $data, $length, $offset)
197+
{
198+
return new RejectedPromise();
199+
return $this->fileDescriptors[$fileDescriptor]->rpc(Factory::rpc('write', [
200+
'chunk' => $data,
201+
'length' => $length,
202+
'offset' => $offset,
203+
]));
204+
}
205+
206+
/**
207+
* @param resource $fd
208+
* @return PromiseInterface
209+
*/
210+
public function close($fd)
211+
{
212+
return new RejectedPromise();
213+
$fileDescriptor = $this->fileDescriptors[$fd];
214+
unset($this->fileDescriptors[$fd]);
215+
return $fileDescriptor->rpc(Factory::rpc('close'))->then(function () use ($fileDescriptor) {
216+
return $fileDescriptor->softTerminate();
217+
}, function () use ($fileDescriptor) {
218+
return $fileDescriptor->softTerminate();
219+
});
220+
}
221+
222+
/**
223+
* @param string $fromPath
224+
* @param string $toPath
225+
* @return PromiseInterface
226+
*/
227+
public function rename($fromPath, $toPath)
228+
{
229+
return $this->invoker->invokeCall('rename', [
230+
'from' => $fromPath,
231+
'to' => $toPath,
232+
]);
233+
}
234+
235+
/**
236+
* @param string $path
237+
* @return PromiseInterface
238+
*/
239+
public function readlink($path)
240+
{
241+
return $this->invoker->invokeCall('readlink', [
242+
'path' => $path,
243+
])->then(function ($result) {
244+
return \React\Promise\resolve($result['path']);
245+
});
246+
}
247+
248+
/**
249+
* @param string $fromPath
250+
* @param string $toPath
251+
* @return PromiseInterface
252+
*/
253+
public function symlink($fromPath, $toPath)
254+
{
255+
return $this->invoker->invokeCall('symlink', [
256+
'from' => $fromPath,
257+
'to' => $toPath,
258+
])->then(function ($result) {
259+
return \React\Promise\resolve($result['result']);
260+
});
261+
}
262+
263+
/**
264+
* @inheritDoc
265+
*/
266+
public function detectType($path)
267+
{
268+
return \React\Filesystem\detectType($this->typeDetectors, [
269+
'path' => $path,
270+
]);
271+
}
272+
}

0 commit comments

Comments
 (0)