1+ <?php 
2+ 
3+ namespace  Saraf \QB \QueryBuilder \Clauses ;
4+ 
5+ use  Saraf \QB \QueryBuilder \Core \DBFactory ;
6+ use  Saraf \QB \QueryBuilder \Core \DBWorker ;
7+ use  Saraf \QB \QueryBuilder \Exceptions \TransactionException ;
8+ use  Saraf \QB \QueryBuilder \Helpers \QueryResult \QueryResult ;
9+ use  Saraf \QB \QueryBuilder \Helpers \QueryResult \QueryResultCollection ;
10+ use  function  React \Promise \reject ;
11+ use  function  React \Promise \resolve ;
12+ 
13+ class  Transaction
14+ {
15+     protected  array  $ queries  = [];
16+     protected  QueryResultCollection   $ queryResultCollection ;
17+     private  ?DBWorker   $ connection  = null ;
18+ 
19+     public  function  __construct (
20+         protected  ?DBFactory   $ dbFactory  = null ,
21+     )
22+     {
23+         $ this  ->queryResultCollection  = new  QueryResultCollection ();
24+         $ this  ->connection  = !is_null ($ this  ->dbFactory ) ? $ this  ->dbFactory ->reserveConnection () : null ;
25+     }
26+ 
27+     public  function  addQuery (string  $ name , Select  |Update  |Delete  |Insert   $ query , ?\Closure   $ callback  = null ): static 
28+     {
29+         $ this  ->queries [] = compact ('name ' , 'query ' , 'callback ' );
30+         return  $ this  ;
31+     }
32+ 
33+     /** 
34+      * @throws TransactionException 
35+      */ 
36+     public  function  compile (): \React \Promise \PromiseInterface  
37+     {
38+         if  (count ($ this  ->queries ) === 0 ) {
39+             throw  new  TransactionException ('There are no queries inside transaction. ' );
40+         }
41+ 
42+         return  $ this  ->connection ->query ("START TRANSACTION " )
43+             ->then (function  () {
44+                 return  $ this  ->resolveQueries ();
45+             })
46+             ->finally (function  () {
47+                 $ this  ->dbFactory ->releaseConnection ($ this  ->connection );
48+             });
49+     }
50+ 
51+     protected  function  resolveQueries (): \React \Promise \PromiseInterface  
52+     {
53+         if  (count ($ this  ->queries ) === 0 ) {
54+             $ this  ->connection ->query ('COMMIT ' );
55+             return  resolve ($ this  ->queryResultCollection ->last ()->toArray ());
56+         }
57+ 
58+         $ queryItem  = array_shift ($ this  ->queries );
59+ 
60+         $ query  = $ queryItem ['query ' ];
61+         $ callback  = $ queryItem ['callback ' ];
62+         $ name  = $ queryItem ['name ' ];
63+ 
64+         return  $ query ->compile ()->getQuery ()->then (function  ($ result ) use  ($ query , $ callback , $ name ) {
65+             $ queryString  = $ result ['query ' ];
66+             return  $ this  ->connection ->query ($ queryString )
67+                 ->then (function  ($ result ) use  ($ query , $ callback , $ name , $ queryString ) {
68+                     if  (!$ result ['result ' ]) {
69+                         $ this  ->connection ->query ('ROLLBACK ' );
70+                         return  reject (throw  new  TransactionException ('Transaction rolled back due to  '  . $ result ['error ' ]));
71+                     }
72+ 
73+                     $ queryResult  = new  QueryResult (
74+                         $ result ['result ' ],
75+                         @$ result ['count ' ] ?? null ,
76+                         @$ result ['rows ' ] ?? [],
77+                         @$ result ['affectedRows ' ] ?? null ,
78+                         @$ result ['insertId ' ] ?? null ,
79+                     );
80+ 
81+                     if  (is_null ($ callback ) || $ callback ($ queryResult , $ this  ->queryResultCollection )) {
82+                         $ this  ->queryResultCollection ->add ($ name , $ queryResult );
83+                         return  $ this  ->resolveQueries ();
84+                     }
85+ 
86+                     $ this  ->connection ->query ('ROLLBACK ' );
87+                     return  reject (throw  new  TransactionException ("Transaction rolled back,callback for query  {$ queryString } doesn't return true " ));
88+                 });
89+         });
90+     }
91+ }
0 commit comments