@@ -40,7 +40,7 @@ class ClientSyncHandler extends ClientBasicHandler
40
40
{
41
41
use ClientSearchTrait;
42
42
43
- private ? SyncRequest $ syncRequest = null ;
43
+ private SyncRequest $ syncRequest ;
44
44
45
45
private SyncRequestControl $ syncRequestControl ;
46
46
@@ -52,6 +52,8 @@ class ClientSyncHandler extends ClientBasicHandler
52
52
53
53
private ?Closure $ syncIdSetHandler = null ;
54
54
55
+ private ?Closure $ cookieUpdateHandler = null ;
56
+
55
57
/**
56
58
* {@inheritDoc}
57
59
*/
@@ -79,13 +81,28 @@ public function handleResponse(
79
81
80
82
try {
81
83
do {
84
+ $ this ->syncRequestControl ->setCookie ($ this ->session ->getCookie ());
82
85
$ searchDone = self ::search (
83
86
$ messageFrom ,
84
87
$ messageTo ,
85
88
$ queue ,
86
89
);
90
+ // @todo This should be a configurable option or a specific exception...
87
91
if ($ this ->isRefreshRequired ($ searchDone )) {
88
- $ this ->syncRequestControl ->setCookie (null );
92
+ // We need to regenerate a search request / response with a new cookie...
93
+ $ this ->syncRequestControl ->setCookie (
94
+ $ searchDone
95
+ ->controls ()
96
+ ->getByClass (SyncDoneControl::class)
97
+ ?->getCookie()
98
+ );
99
+ $ messageTo = new LdapMessageRequest (
100
+ $ queue ->generateId (),
101
+ $ this ->syncRequest ,
102
+ ...$ messageFrom ->controls ()->toArray ()
103
+ );
104
+ $ messageFrom = $ queue ->sendMessage ($ messageTo )
105
+ ->getMessage ($ messageTo ->getMessageId ());
89
106
}
90
107
} while (!$ this ->isSyncComplete ($ searchDone ));
91
108
@@ -95,12 +112,14 @@ public function handleResponse(
95
112
}
96
113
}
97
114
98
-
99
115
/**
100
116
* We need to set up / verify the initial sync session and message handlers before starting the overall sync process.
101
117
*/
102
118
private function initializeSync (LdapMessageRequest $ messageTo ): void
103
119
{
120
+ /** @var SyncRequest $searchRequest */
121
+ $ searchRequest = $ messageTo ->getRequest ();
122
+ $ this ->syncRequest = $ searchRequest ;
104
123
$ this ->syncRequestControl = $ messageTo ->controls ()
105
124
->getByClass (SyncRequestControl::class) ?? throw new RuntimeException (sprintf (
106
125
'Expected a "%s", but there is none. ' ,
@@ -118,18 +137,15 @@ private function initializeSync(LdapMessageRequest $messageTo): void
118
137
cookie: $ this ->syncRequestControl ->getCookie (),
119
138
);
120
139
121
- /** @var SyncRequest $searchRequest */
122
- $ searchRequest = $ messageTo ->getRequest ();
123
- $ this ->syncRequest = $ searchRequest ;
124
-
125
140
// We override these with our own, so save them here for now.
126
- $ this ->syncEntryHandler = $ searchRequest ->getEntryHandler ();
127
- $ this ->syncReferralHandler = $ searchRequest ->getReferralHandler ();
128
- $ this ->syncIdSetHandler = $ searchRequest ->getIdSetHandler ();
129
-
130
- $ searchRequest ->useEntryHandler ($ this ->processSyncEntry (...));
131
- $ searchRequest ->useReferralHandler ($ this ->processSyncReferral (...));
132
- $ searchRequest ->useIntermediateResponseHandler ($ this ->processIntermediateResponse (...));
141
+ $ this ->syncEntryHandler = $ this ->syncRequest ->getEntryHandler ();
142
+ $ this ->syncReferralHandler = $ this ->syncRequest ->getReferralHandler ();
143
+ $ this ->syncIdSetHandler = $ this ->syncRequest ->getIdSetHandler ();
144
+ $ this ->cookieUpdateHandler = $ this ->syncRequest ->getCookieUpdateHandler ();
145
+
146
+ $ this ->syncRequest ->useEntryHandler ($ this ->processSyncEntry (...));
147
+ $ this ->syncRequest ->useReferralHandler ($ this ->processSyncReferral (...));
148
+ $ this ->syncRequest ->useIntermediateResponseHandler ($ this ->processIntermediateResponse (...));
133
149
}
134
150
135
151
/**
@@ -138,10 +154,6 @@ private function initializeSync(LdapMessageRequest $messageTo): void
138
154
*/
139
155
private function resetRequestHandlers (): void
140
156
{
141
- if ($ this ->syncRequest === null ) {
142
- return ;
143
- }
144
-
145
157
if ($ this ->syncEntryHandler !== null ) {
146
158
$ this ->syncRequest ->useEntryHandler ($ this ->syncEntryHandler );
147
159
}
@@ -155,7 +167,7 @@ private function resetRequestHandlers(): void
155
167
156
168
private function isContentUpdatePoll (): bool
157
169
{
158
- return ! empty ( $ this ->syncRequestControl ->getCookie ()) ;
170
+ return $ this ->syncRequestControl ->getCookie () !== null ;
159
171
}
160
172
161
173
private function processSyncEntry (EntryResult $ entryResult ): void
@@ -189,26 +201,23 @@ private function processIntermediateResponse(LdapMessageResponse $messageFrom):
189
201
$ response = $ messageFrom ->getResponse ();
190
202
191
203
if ($ response instanceof SyncRefreshDelete) {
192
- $ this ->syncRequestControl ->setCookie ($ response ->getCookie ());
193
- $ this ->session
194
- ->updatePhase (Session::PHASE_DELETE )
195
- ->updateCookie ($ response ->getCookie ());
204
+ $ this ->updateCookie ($ response ->getCookie ());
205
+ $ this ->session ->updatePhase (Session::PHASE_DELETE );
196
206
} elseif ($ response instanceof SyncRefreshPresent) {
197
- $ this ->syncRequestControl ->setCookie ($ response ->getCookie ());
198
- $ this ->session
199
- ->updatePhase (Session::PHASE_PRESENT )
200
- ->updateCookie ($ response ->getCookie ());
207
+ $ this ->updateCookie ($ response ->getCookie ());
208
+ $ this ->session ->updatePhase (Session::PHASE_PRESENT );
201
209
} elseif ($ response instanceof SyncNewCookie) {
202
- $ this ->session ->updateCookie ($ response ->getCookie ());
203
- $ this ->syncRequestControl ->setCookie ($ response ->getCookie ());
204
- } elseif ($ response instanceof SyncIdSet && $ this ->syncIdSetHandler ) {
205
- $ this ->session ->updateCookie ($ response ->getCookie ());
206
- $ this ->syncRequestControl ->setCookie ($ response ->getCookie ());
207
- call_user_func (
208
- $ this ->syncIdSetHandler ,
209
- new SyncIdSetResult ($ messageFrom ),
210
- $ this ->session ,
211
- );
210
+ $ this ->updateCookie ($ response ->getCookie ());
211
+ } elseif ($ response instanceof SyncIdSet) {
212
+ $ this ->updateCookie ($ response ->getCookie ());
213
+
214
+ if ($ this ->syncIdSetHandler instanceof Closure) {
215
+ call_user_func (
216
+ $ this ->syncIdSetHandler ,
217
+ new SyncIdSetResult ($ messageFrom ),
218
+ $ this ->session ,
219
+ );
220
+ }
212
221
}
213
222
}
214
223
@@ -219,8 +228,12 @@ private function isSyncComplete(LdapMessageResponse $response): bool
219
228
$ syncDone = $ response ->controls ()
220
229
->getByClass (SyncDoneControl::class);
221
230
222
- return $ syncDone === null
223
- || $ result ->getResultCode () === ResultCode::SUCCESS ;
231
+ if ($ syncDone === null ) {
232
+ return true ;
233
+ }
234
+ $ this ->updateCookie ($ syncDone ->getCookie ());
235
+
236
+ return $ result ->getResultCode () === ResultCode::SUCCESS ;
224
237
}
225
238
226
239
private function isRefreshRequired (LdapMessageResponse $ response ): bool
@@ -230,4 +243,25 @@ private function isRefreshRequired(LdapMessageResponse $response): bool
230
243
231
244
return $ result ->getResultCode () === ResultCode::SYNCHRONIZATION_REFRESH_REQUIRED ;
232
245
}
246
+
247
+ /**
248
+ * Update the cookie in all the spots if it was actually returned and different from what we already have saved.
249
+ * Some controls / requests will return the cookie, but they are not required to actually provide a value.
250
+ */
251
+ private function updateCookie (?string $ cookie ): void
252
+ {
253
+ if ($ cookie === null || $ this ->session ->getCookie () === $ cookie ) {
254
+ return ;
255
+ }
256
+
257
+ $ this ->syncRequestControl ->setCookie ($ cookie );
258
+ $ this ->session ->updateCookie ($ cookie );
259
+
260
+ if ($ this ->cookieUpdateHandler !== null ) {
261
+ call_user_func (
262
+ $ this ->cookieUpdateHandler ,
263
+ $ cookie
264
+ );
265
+ }
266
+ }
233
267
}
0 commit comments