11<?php
2+ declare (strict_types=1 );
3+
24namespace ScriptFUSION \Porter ;
35
6+ use Amp \Iterator ;
47use Amp \Producer ;
58use Amp \Promise ;
69use Psr \Container \ContainerInterface ;
2225use ScriptFUSION \Porter \Provider \Resource \ProviderResource ;
2326use ScriptFUSION \Porter \Specification \AsyncImportSpecification ;
2427use ScriptFUSION \Porter \Specification \ImportSpecification ;
28+ use ScriptFUSION \Porter \Transform \AsyncTransformer ;
2529use ScriptFUSION \Porter \Transform \Transformer ;
2630
2731/**
@@ -58,7 +62,7 @@ public function __construct(ContainerInterface $providers)
5862 *
5963 * @throws ImportException Provider failed to return an iterator.
6064 */
61- public function import (ImportSpecification $ specification )
65+ public function import (ImportSpecification $ specification ): PorterRecords
6266 {
6367 $ specification = clone $ specification ;
6468
@@ -86,7 +90,7 @@ public function import(ImportSpecification $specification)
8690 *
8791 * @throws ImportException More than one record was imported.
8892 */
89- public function importOne (ImportSpecification $ specification )
93+ public function importOne (ImportSpecification $ specification ): ? array
9094 {
9195 $ results = $ this ->import ($ specification );
9296
@@ -103,7 +107,7 @@ public function importOne(ImportSpecification $specification)
103107 return $ one ;
104108 }
105109
106- private function fetch (ProviderResource $ resource , $ providerName , ConnectionContext $ context )
110+ private function fetch (ProviderResource $ resource , $ providerName , ConnectionContext $ context ): \ Iterator
107111 {
108112 $ provider = $ this ->getProvider ($ providerName ?: $ resource ->getProviderClassName ());
109113
@@ -127,7 +131,7 @@ private function fetch(ProviderResource $resource, $providerName, ConnectionCont
127131 return $ resource ->fetch (new ImportConnector ($ connector , $ context ));
128132 }
129133
130- public function importAsync (AsyncImportSpecification $ specification ): Producer
134+ public function importAsync (AsyncImportSpecification $ specification ): Iterator
131135 {
132136 $ specification = clone $ specification ;
133137
@@ -137,15 +141,7 @@ public function importAsync(AsyncImportSpecification $specification): Producer
137141 ConnectionContextFactory::create ($ specification )
138142 );
139143
140- // if (!$records instanceof ProviderRecords) {
141- // $records = $this->createProviderRecords($records, $specification->getResource());
142- // }
143-
144- // $records = $this->transformRecords($records, $specification->getTransformers(), $specification->getContext());
145-
146- // return $this->createPorterRecords($records, $specification);
147-
148- return $ records ;
144+ return $ this ->transformAsync ($ records , $ specification ->getTransformers (), $ specification ->getContext ());
149145 }
150146
151147 public function importOneAsync (AsyncImportSpecification $ specification ): Promise
@@ -157,15 +153,15 @@ public function importOneAsync(AsyncImportSpecification $specification): Promise
157153
158154 $ one = $ results ->getCurrent ();
159155
160- if (( yield $ results ->advance ()) !== false ) {
156+ if (yield $ results ->advance ()) {
161157 throw new ImportException ('Cannot import one: more than one record imported. ' );
162158 }
163159
164160 return $ one ;
165161 });
166162 }
167163
168- private function fetchAsync (AsyncResource $ resource , $ providerName , ConnectionContext $ context ): Producer
164+ private function fetchAsync (AsyncResource $ resource , $ providerName , ConnectionContext $ context ): Iterator
169165 {
170166 $ provider = $ this ->getProvider ($ providerName ?: $ resource ->getProviderClassName ());
171167
@@ -201,7 +197,7 @@ private function fetchAsync(AsyncResource $resource, $providerName, ConnectionCo
201197 *
202198 * @return RecordCollection
203199 */
204- private function transformRecords (RecordCollection $ records , array $ transformers , $ context )
200+ private function transformRecords (RecordCollection $ records , array $ transformers , $ context ): RecordCollection
205201 {
206202 foreach ($ transformers as $ transformer ) {
207203 if ($ transformer instanceof PorterAware) {
@@ -214,19 +210,50 @@ private function transformRecords(RecordCollection $records, array $transformers
214210 return $ records ;
215211 }
216212
217- private function createProviderRecords (\Iterator $ records , ProviderResource $ resource )
213+ private function transformAsync (Iterator $ records , array $ transformers , $ context ): Producer
214+ {
215+ return new Producer (static function (\Closure $ emit ) use ($ records , $ transformers , $ context ) {
216+ while (yield $ records ->advance ()) {
217+ $ record = $ records ->getCurrent ();
218+
219+ foreach ($ transformers as $ transformer ) {
220+ if (!$ transformer instanceof AsyncTransformer) {
221+ // TODO: Proper exception or separate async stack.
222+ throw new \RuntimeException ('Cannot use sync transformer. ' );
223+ }
224+
225+ $ record = yield $ transformer ->transformAsync ($ record , $ context );
226+
227+ if ($ record === null ) {
228+ // Do not process more transformers.
229+ break ;
230+ }
231+ }
232+
233+ if ($ record !== null ) {
234+ if (!\is_array ($ record )) {
235+ throw new \RuntimeException ('Unexpected type: record must be array or null. ' );
236+ }
237+
238+ yield $ emit ($ record );
239+ }
240+ }
241+ });
242+ }
243+
244+ private function createProviderRecords (\Iterator $ records , ProviderResource $ resource ): ProviderRecords
218245 {
219246 if ($ records instanceof \Countable) {
220- return new CountableProviderRecords ($ records , count ($ records ), $ resource );
247+ return new CountableProviderRecords ($ records , \ count ($ records ), $ resource );
221248 }
222249
223250 return new ProviderRecords ($ records , $ resource );
224251 }
225252
226- private function createPorterRecords (RecordCollection $ records , ImportSpecification $ specification )
253+ private function createPorterRecords (RecordCollection $ records , ImportSpecification $ specification ): PorterRecords
227254 {
228255 if ($ records instanceof \Countable) {
229- return new CountablePorterRecords ($ records , count ($ records ), $ specification );
256+ return new CountablePorterRecords ($ records , \ count ($ records ), $ specification );
230257 }
231258
232259 return new PorterRecords ($ records , $ specification );
0 commit comments