9
9
use spaceonfire \Collection \CollectionInterface ;
10
10
use spaceonfire \Collection \TypedCollection ;
11
11
use spaceonfire \Criteria \Bridge \SpiralPagination \PaginableCriteria ;
12
+ use spaceonfire \Criteria \Criteria ;
12
13
use spaceonfire \Criteria \CriteriaInterface ;
13
14
use spaceonfire \DataSource \EntityInterface ;
14
15
use spaceonfire \DataSource \MapperInterface ;
@@ -21,11 +22,27 @@ class CycleQuery implements QueryInterface
21
22
* @var Select
22
23
*/
23
24
protected $ select ;
25
+
24
26
/**
25
27
* @var MapperInterface
26
28
*/
27
29
protected $ mapper ;
28
30
31
+ /**
32
+ * @var CriteriaInterface|null
33
+ */
34
+ protected $ criteria ;
35
+
36
+ /**
37
+ * @var int|null
38
+ */
39
+ protected $ limit ;
40
+
41
+ /**
42
+ * @var int|null
43
+ */
44
+ protected $ offset ;
45
+
29
46
/**
30
47
* CycleQuery constructor.
31
48
* @param Select $select
@@ -40,18 +57,30 @@ public function __construct(Select $select, MapperInterface $mapper)
40
57
/**
41
58
* @inheritDoc
42
59
*/
43
- public function limit (int $ limit ): QueryInterface
60
+ public function limit (?int $ limit ): QueryInterface
61
+ {
62
+ $ this ->limit = $ limit ;
63
+
64
+ return $ this ;
65
+ }
66
+
67
+ /**
68
+ * @inheritDoc
69
+ */
70
+ public function offset (?int $ offset ): QueryInterface
44
71
{
45
- $ this ->select ->limit ($ limit );
72
+ $ this ->offset = $ offset ;
73
+
46
74
return $ this ;
47
75
}
48
76
49
77
/**
50
78
* @inheritDoc
51
79
*/
52
- public function offset ( int $ offset ): QueryInterface
80
+ public function matching ( CriteriaInterface $ criteria ): QueryInterface
53
81
{
54
- $ this ->select ->offset ($ offset );
82
+ $ this ->criteria = $ criteria ;
83
+
55
84
return $ this ;
56
85
}
57
86
@@ -60,7 +89,7 @@ public function offset(int $offset): QueryInterface
60
89
*/
61
90
public function fetchOne (): ?EntityInterface
62
91
{
63
- $ entity = $ this ->select ->fetchOne ();
92
+ $ entity = $ this ->makeSelect () ->fetchOne ();
64
93
65
94
if ($ entity === null ) {
66
95
return null ;
@@ -80,54 +109,69 @@ public function fetchOne(): ?EntityInterface
80
109
*/
81
110
public function fetchAll (): CollectionInterface
82
111
{
83
- $ items = $ this ->select ->fetchAll ();
112
+ $ items = $ this ->makeSelect () ->fetchAll ();
84
113
85
114
return new TypedCollection ($ items , EntityInterface::class);
86
115
}
87
116
88
117
/**
89
118
* @inheritDoc
90
119
*/
91
- public function matching (CriteriaInterface $ criteria ): QueryInterface
120
+ public function count (?string $ column = null ): int
121
+ {
122
+ $ select = clone $ this ->select ;
123
+
124
+ if (null !== $ this ->criteria ) {
125
+ $ criteria = clone $ this ->criteria ;
126
+ $ criteria ->limit (null );
127
+ $ criteria ->offset (null );
128
+
129
+ $ select = $ this ->applyCriteria ($ select , $ criteria );
130
+ }
131
+
132
+ return $ select ->count ($ column );
133
+ }
134
+
135
+ private function makeSelect (): Select
136
+ {
137
+ $ select = clone $ this ->select ;
138
+
139
+ $ criteria = null === $ this ->criteria ? new Criteria () : clone $ this ->criteria ;
140
+ $ criteria ->limit ($ this ->limit ?? $ criteria ->getLimit ());
141
+ $ criteria ->offset ($ this ->offset ?? $ criteria ->getOffset ());
142
+
143
+ return $ this ->applyCriteria ($ select , $ criteria );
144
+ }
145
+
146
+ private function applyCriteria (Select $ select , CriteriaInterface $ criteria ): Select
92
147
{
93
148
if ($ expression = $ criteria ->getWhere ()) {
94
149
$ scope = (new CycleQueryExpressionVisitor ($ this ->mapper ))->dispatch ($ expression );
95
- $ this -> select ->andWhere ($ scope );
150
+ $ select ->andWhere ($ scope );
96
151
}
97
152
98
153
foreach ($ criteria ->getOrderBy () as $ key => $ order ) {
99
- $ this -> select ->orderBy (
154
+ $ select ->orderBy (
100
155
$ this ->mapper ->convertNameToStorage ($ key ),
101
156
$ order === SORT_ASC ? SelectQuery::SORT_ASC : SelectQuery::SORT_DESC
102
157
);
103
158
}
104
159
105
160
if ($ criteria instanceof PaginableCriteria) {
106
- $ criteria ->paginate ($ this );
161
+ $ criteria ->paginate ($ select );
107
162
} else {
108
163
if ($ criteria ->getOffset ()) {
109
- $ this ->offset ($ criteria ->getOffset ());
164
+ $ select ->offset ($ criteria ->getOffset ());
110
165
}
111
166
112
167
if ($ criteria ->getLimit () !== null ) {
113
- $ this ->limit ($ criteria ->getLimit ());
168
+ $ select ->limit ($ criteria ->getLimit ());
114
169
}
115
170
}
116
171
117
172
// TODO: support load options
118
- $ this ->select ->load ($ criteria ->getInclude ());
119
-
120
- return $ this ;
121
- }
173
+ $ select ->load ($ criteria ->getInclude ());
122
174
123
- /**
124
- * @inheritDoc
125
- */
126
- public function count (?string $ column = null ): int
127
- {
128
- $ select = clone $ this ->select ;
129
- $ select ->limit (-1 );
130
- $ select ->offset (0 );
131
- return $ select ->count ($ column );
175
+ return $ select ;
132
176
}
133
177
}
0 commit comments