1<?php 2 3/** 4 * This file is part of the FreeDSx LDAP package. 5 * 6 * (c) Chad Sikorra <Chad.Sikorra@gmail.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace FreeDSx\Ldap\Server\Paging; 13 14use DateTime; 15use DateTimeInterface; 16use FreeDSx\Ldap\Control\ControlBag; 17use FreeDSx\Ldap\Control\PagingControl; 18use FreeDSx\Ldap\Operation\Request\SearchRequest; 19 20/** 21 * Encapsulates the paging request from a client and provides some helpful methods. 22 * 23 * @author Chad Sikorra <Chad.Sikorra@gmail.com> 24 */ 25final class PagingRequest 26{ 27 /** 28 * @var PagingControl 29 */ 30 private $control; 31 32 /** 33 * @var SearchRequest 34 */ 35 private $request; 36 37 /** 38 * @var ControlBag 39 */ 40 private $controls; 41 42 /** 43 * @var int 44 */ 45 private $iteration = 1; 46 47 /** 48 * @var string 49 */ 50 private $nextCookie; 51 52 /** 53 * @var DateTimeInterface|null 54 */ 55 private $lastProcessed = null; 56 57 /** 58 * @var DateTimeInterface 59 */ 60 private $created; 61 62 /** 63 * @var string 64 */ 65 private $uniqueId; 66 67 /** 68 * @var bool 69 */ 70 private $hasProcessed = false; 71 72 public function __construct( 73 PagingControl $control, 74 SearchRequest $request, 75 ControlBag $controls, 76 string $nextCookie, 77 ?DateTimeInterface $created = null, 78 ?string $uniqueId = null 79 ) { 80 $this->control = $control; 81 $this->request = $request; 82 $this->controls = $controls; 83 $this->nextCookie = $nextCookie; 84 $this->created = $created ?? new DateTime(); 85 $this->uniqueId = $uniqueId ?? random_bytes(16); 86 } 87 88 /** 89 * An opaque value that uniquely identifies this paging request across its lifecycle. 90 * 91 * @return string 92 */ 93 public function getUniqueId(): string 94 { 95 return $this->uniqueId; 96 } 97 98 /** 99 * Whether the paging control is considered critical or not. 100 * 101 * @return bool 102 */ 103 public function isCritical(): bool 104 { 105 return $this->control->getCriticality(); 106 } 107 108 /** 109 * When the paging request was originally created. 110 * 111 * @return DateTimeInterface 112 */ 113 public function createdAt(): DateTimeInterface 114 { 115 return $this->created; 116 } 117 118 /** 119 * When the request was last processed. May be null if not processed yet. 120 * 121 * @return DateTimeInterface|null 122 */ 123 public function lastProcessedAt(): ?DateTimeInterface 124 { 125 return $this->lastProcessed; 126 } 127 128 /** 129 * @return SearchRequest 130 */ 131 public function getSearchRequest(): SearchRequest 132 { 133 return $this->request; 134 } 135 136 /** 137 * @return ControlBag 138 */ 139 public function controls(): ControlBag 140 { 141 return $this->controls; 142 } 143 144 /** 145 * @return string 146 */ 147 public function getCookie(): string 148 { 149 return $this->control->getCookie(); 150 } 151 152 /** 153 * The current iteration of paging that this request represents. Incremented by one for each request. 154 * 155 * @return int 156 */ 157 public function getIteration(): int 158 { 159 return $this->iteration; 160 } 161 162 /** 163 * The size of the result set to return, as requested by the client. 164 * 165 * @return int 166 */ 167 public function getSize(): int 168 { 169 return $this->control->getSize(); 170 } 171 172 /** 173 * Whether this represents a request to abandon the paging request. 174 * 175 * @return bool 176 */ 177 public function isAbandonRequest(): bool 178 { 179 return $this->control->getSize() === 0 180 && $this->control->getCookie() !== ''; 181 } 182 183 /** 184 * Whether this represents the start of an unprocessed paging request. 185 * 186 * @return bool 187 */ 188 public function isPagingStart(): bool 189 { 190 if ($this->hasProcessed) { 191 return false; 192 } 193 194 return $this->control->getCookie() === '' 195 && $this->control->getSize() >= 0; 196 } 197 198 /** 199 * @return string 200 * @internal 201 */ 202 public function getNextCookie(): string 203 { 204 return $this->nextCookie; 205 } 206 207 /** 208 * @param PagingControl $pagingControl 209 * @internal 210 */ 211 public function updatePagingControl(PagingControl $pagingControl): void 212 { 213 $this->control = $pagingControl; 214 } 215 216 /** 217 * @param string $cookie 218 * @internal 219 */ 220 public function updateNextCookie(string $cookie): void 221 { 222 $this->nextCookie = $cookie; 223 } 224 225 /** 226 * @internal 227 */ 228 public function markProcessed(): void 229 { 230 $this->lastProcessed = new DateTime(); 231 $this->iteration++; 232 $this->hasProcessed = true; 233 } 234} 235