55namespace imperazim \form \custom ;
66
77use JsonSerializable ;
8- use InvalidArgumentException ;
98use pocketmine \player \Player ;
9+ use pocketmine \form \FormValidationException ;
1010use imperazim \form \Form ;
1111use imperazim \form \FormData ;
1212use imperazim \form \FormResult ;
1313use imperazim \form \base \elements \Title ;
1414use imperazim \form \custom \elements \ElementCollection ;
15+ use imperazim \form \custom \elements \ValidatedInput ;
1516use imperazim \form \custom \response \CustomResponse ;
1617
1718/**
@@ -24,8 +25,8 @@ abstract class CustomForm extends Form {
2425 /** @var FormData Form data container */
2526 private FormData $ formData ;
2627
27- /** @var Player Target player */
28- private Player $ player ;
28+ /** @var \WeakReference< Player> Target player */
29+ private \ WeakReference $ playerRef ;
2930
3031 /** @var bool Bypass validation */
3132 private bool $ force ;
@@ -42,7 +43,7 @@ public function __construct(
4243 array |FormData $ data = [],
4344 bool $ force = false
4445 ) {
45- $ this ->player = $ player ;
46+ $ this ->playerRef = \WeakReference:: create ( $ player) ;
4647 $ this ->force = $ force ;
4748 $ this ->formData = $ data instanceof FormData ? $ data : new FormData ($ data );
4849
@@ -101,9 +102,9 @@ abstract protected function onClose(
101102 * @param Player $player Responding player
102103 * @param mixed $raw Raw response data
103104 */
104- public function handleResponse (Player $ player , $ raw ): void {
105+ public function handleResponse (Player $ player , mixed $ raw ): void {
105106 if ($ raw !== null && !is_array ($ raw )) {
106- throw new InvalidArgumentException ("Response data must be array or null. " );
107+ throw new FormValidationException ("Response data must be array or null. " );
107108 }
108109
109110 $ elements = $ this ->getCachedElements ($ player , $ this ->formData );
@@ -112,10 +113,17 @@ public function handleResponse(Player $player, $raw): void {
112113
113114 if (is_array ($ raw )) {
114115 foreach ($ elements as $ idx => $ element ) {
116+ if (!$ element ->hasId ()) continue ;
115117 $ elementMap [$ element ->getId ()] = $ element ;
116118
117119 if ($ element ->hasValue () && array_key_exists ($ idx , $ raw )) {
118120 $ idMap [$ element ->getId ()] = $ raw [$ idx ];
121+
122+ if ($ element instanceof ValidatedInput) {
123+ if (!$ element ->validate ((string ) $ raw [$ idx ])) {
124+ throw new FormValidationException ($ element ->getErrorMessage ());
125+ }
126+ }
119127 }
120128 }
121129 }
@@ -132,7 +140,7 @@ public function handleResponse(Player $player, $raw): void {
132140
133141 $ valueElementCount = count (array_filter ($ elements , fn ($ e ) => $ e ->hasValue ()));
134142 if (!$ this ->force && count ($ idMap ) !== $ valueElementCount ) {
135- throw new InvalidArgumentException ("Invalid number of fields. " );
143+ throw new FormValidationException ("Invalid number of fields. " );
136144 }
137145
138146 $ result = $ this ->onSubmit ($ player , $ response );
@@ -149,7 +157,11 @@ public function handleResponse(Player $player, $raw): void {
149157 * @return array Serialized data
150158 */
151159 protected function serializeFormData (): array {
152- $ elements = $ this ->getCachedElements ($ this ->player , $ this ->formData );
160+ $ player = $ this ->playerRef ->get ();
161+ if ($ player === null ) {
162+ return ['content ' => []];
163+ }
164+ $ elements = $ this ->getCachedElements ($ player , $ this ->formData );
153165 return [
154166 'content ' => array_map (
155167 fn (JsonSerializable $ e ) => $ e ->jsonSerialize (),
@@ -168,22 +180,15 @@ protected function getFormType(): string {
168180 }
169181
170182 /**
171- * Gets and validates cached elements.
183+ * Gets cached elements.
172184 *
173185 * @param Player $player Viewing player
174186 * @param FormData $data Form data
175- * @return array Validated elements
176- * @throws InvalidArgumentException If elements lack IDs
187+ * @return array Elements array
177188 */
178189 private function getCachedElements (Player $ player , FormData $ data ): array {
179190 if ($ this ->elementsCache === null ) {
180191 $ this ->elementsCache = $ this ->elements ($ player , $ data );
181-
182- foreach ($ this ->elementsCache as $ element ) {
183- if (!$ element ->hasId ()) {
184- throw new InvalidArgumentException ("All elements must have an ID. " );
185- }
186- }
187192 }
188193 return iterator_to_array ($ this ->elementsCache );
189194 }
0 commit comments