1+ <?php
2+
3+ namespace App \Console \Commands ;
4+
5+ use Api2Cart \Client \Model \ModelInterface ;
6+ use App \Models \User ;
7+ use App \Services \Api2Cart ;
8+ use Carbon \Carbon ;
9+ use GuzzleHttp \Promise \Promise ;
10+ use GuzzleHttp \Promise \Utils as GuzzleHttpPromiseUtils ;
11+ use Illuminate \Console \Command ;
12+ use Illuminate \Support \Collection ;
13+ use Illuminate \Support \Facades \Auth ;
14+
15+ class MakeRequest extends Command
16+ {
17+ private $ _api2Cart ;
18+
19+ /**
20+ * The name and signature of the console command.
21+ *
22+ * @var string
23+ */
24+ protected $ signature = 'sendRequestToA2C
25+ {method : Method name}
26+ {parameters : base64encoded parameters}
27+ {resultEntity : Result entity in response}
28+ {resultEntityCount : Count of entity in response}
29+ {--subEntities=no : Get sub entities}
30+ {--subEntityId=id : SubEntity ID} ' ;
31+
32+ /**
33+ * The console command description.
34+ *
35+ * @var string
36+ */
37+ protected $ description = 'Send request to Api2Cart ' ;
38+
39+ /**
40+ * Create a new command instance.
41+ *
42+ * @return void
43+ */
44+ public function __construct (Api2Cart $ api2Cart )
45+ {
46+ $ this ->_api2Cart = $ api2Cart ;
47+ parent ::__construct ();
48+ }
49+
50+ /**
51+ * Execute the console command.
52+ *
53+ * @return void
54+ * @throws \Throwable
55+ */
56+ public function handle ()
57+ {
58+ $ userId = $ _SERVER ['USER_ID ' ];
59+
60+ $ user = User::find ($ userId );
61+
62+ if ($ user ) {
63+ $ logs = collect ([]);
64+ $ entities = collect ([]);
65+ Auth::login ($ user );
66+ $ this ->_api2Cart ->setApiKey ($ user ->api2cart_key );
67+ $ resultEntity = $ this ->argument ('resultEntity ' );
68+ $ resultEntityCount = $ this ->argument ('resultEntityCount ' );
69+ $ method = $ this ->argument ('method ' );
70+
71+ $ parameters = json_decode (base64_decode ($ this ->argument ('parameters ' )), true );
72+ $ cartId = $ parameters ['cart_id ' ] ?? '' ;
73+ unset($ parameters ['cart_id ' ]);
74+ $ subEntities = strtolower ($ this ->option ('subEntities ' ));
75+
76+ $ result = $ this ->_api2Cart ->{$ method }(...$ parameters );
77+
78+ $ entities = $ this ->_getEntities ($ result , $ resultEntityCount , $ resultEntity , $ entities , $ cartId );
79+
80+ if (isset ($ result ['pagination ' ]['next ' ]) && strlen ($ result ['pagination ' ]['next ' ])) {
81+ while (isset ($ result ['pagination ' ]['next ' ]) && strlen ($ result ['pagination ' ]['next ' ])) {
82+ $ result = $ this ->_api2Cart ->{$ method . 'Page ' }(null , $ result ['pagination ' ]['next ' ]);
83+ $ entities = $ this ->_getEntities ($ result , $ resultEntityCount , $ resultEntity , $ entities , $ cartId );
84+ }
85+ }
86+
87+ if ($ entities ->count ()) {
88+ $ entities = $ entities ->keyBy ('id ' );
89+ }
90+
91+ if ($ subEntities !== 'no ' ) {
92+ $ subEntityId = strtolower ($ this ->option ('subEntityId ' ));
93+ $ entitiesIds = $ entities ->pluck ($ subEntityId )->all ();
94+
95+ $ maxConcurrent = 5 ;
96+
97+ /**
98+ * @var Promise[] $promises
99+ */
100+ $ promises = [];
101+ $ subEntitiesResults = [];
102+
103+ foreach ($ entitiesIds as $ entityId ) {
104+ if (count ($ promises ) >= $ maxConcurrent ) {
105+ GuzzleHttpPromiseUtils::unwrap ($ promises );
106+
107+ foreach ($ promises as $ entityId => $ promise ) {
108+ if ($ promise ->getState () === Promise::FULFILLED ) {
109+
110+ /**
111+ * @var ModelInterface $result
112+ */
113+ $ result = $ promise ->wait ()[0 ] ?? [];
114+
115+ if ($ result instanceof ModelInterface && $ result ->getReturnCode () === 10 ) {
116+ list ($ promise , $ callback ) = $ this ->_api2Cart ->{$ subEntities }($ entityId );
117+ $ subEntitiesResults [$ entityId ]['callback ' ] = $ callback ;
118+ $ promises [$ entityId ] = $ promise ;
119+ break 2 ;
120+ } else {
121+ $ subEntitiesResults [$ entityId ]['result ' ] = $ result ;
122+ }
123+ }
124+ }
125+
126+ $ promises = [];
127+ usleep (1000000 );
128+ }
129+
130+ list ($ promise , $ callback ) = $ this ->_api2Cart ->{$ subEntities }($ entityId );
131+ $ subEntitiesResults [$ entityId ]['callback ' ] = $ callback ;
132+ $ promises [$ entityId ] = $ promise ;
133+ }
134+
135+ GuzzleHttpPromiseUtils::unwrap ($ promises );
136+
137+ foreach ($ promises as $ entityId => $ promise ) {
138+ $ subEntitiesResults [$ entityId ]['result ' ] = $ promise ->wait ()[0 ] ?? [];
139+ }
140+
141+ $ entities = $ entities ->transform (function ($ item ) use ($ subEntitiesResults , $ subEntityId ) {
142+ if (isset ($ subEntitiesResults [$ item [$ subEntityId ]]['result ' ])
143+ && $ subEntitiesResults [$ item [$ subEntityId ]]['result ' ] instanceof ModelInterface
144+ ) {
145+ $ item ['sub_entities ' ] = $ subEntitiesResults [$ item [$ subEntityId ]]['callback ' ]($ subEntitiesResults [$ item [$ subEntityId ]]['result ' ]);
146+ }
147+
148+ return $ item ;
149+ });
150+ }
151+
152+ foreach ($ this ->_api2Cart ->getLog ()->all () as $ item ) {
153+ $ logs ->push ($ item );
154+ }
155+
156+ if (isset ($ entities ->first ()->create_at )) {
157+ $ entities = $ entities ->sortBy ('create_at.value ' );
158+ } else {
159+ $ entities = $ entities ->sortBy ('id ' );
160+ }
161+
162+ $ data = collect ([
163+ 'result ' => $ entities ,
164+ 'logs ' => $ this ->_api2Cart ->getLog ()->all ()
165+ ]);
166+
167+ $ this ->getOutput ()->write ($ data ->toJson ());
168+ } else {
169+ $ this ->error ('User not found ' );
170+ }
171+ }
172+
173+ /**
174+ * @param array $result Result
175+ * @param string $resultEntityCount Result entity count field name
176+ * @param string $resultEntity Result entity field name
177+ * @param Collection $entities Entities
178+ * @param string $cartId Cart ID
179+ *
180+ * @return Collection
181+ */
182+ protected function _getEntities (
183+ array $ result , $ resultEntityCount , $ resultEntity , Collection $ entities , string $ cartId
184+ ): Collection
185+ {
186+ $ resEntities = (!empty ($ result ['result ' ][$ resultEntityCount ]))
187+ ? collect ($ result ['result ' ][$ resultEntity ])
188+ : collect ([]);
189+
190+ if ($ resEntities ->count ()) {
191+ foreach ($ resEntities as $ item ) {
192+ $ newItem = $ item ;
193+ $ newItem ['create_at ' ]['value ' ] = Carbon::parse ($ item ['create_at ' ]['value ' ])->setTimezone ('UTC ' )->format ("Y-m-d\TH:i:sO " );
194+ $ newItem ['cart_id ' ] = $ cartId ;
195+ $ entities ->push ($ newItem );
196+ }
197+ }
198+
199+ return $ entities ;
200+ }
201+ }
0 commit comments