4747use CommonITILActor ;
4848use CommonITILObject ;
4949use CommonITILValidation ;
50- use Glpi \Form \Category ;
5150use GlpiPlugin \Moreoptions \Config ;
5251use Group_Item ;
5352use Group_Problem ;
@@ -70,6 +69,7 @@ class Controller extends CommonDBTM
7069{
7170 public $ dohistory = true ;
7271 public static $ rightname = 'config ' ;
72+ private static bool $ solution_check_done = false ;
7373 public static function getTypeName ($ nb = 0 ): string
7474 {
7575 return __s ("Controller " , "moreoptions " );
@@ -271,27 +271,48 @@ private static function addGroupsForActorType(CommonDBTM $item, Config $moconfig
271271 }
272272 }
273273
274- public static function beforeCloseITILObject (CommonITILObject $ item ): void
274+ public static function beforeCloseITILObject (CommonDBTM $ item ): void
275275 {
276276 if (!is_array ($ item ->input )) {
277277 return ;
278278 }
279279
280- if (
281- (isset ($ item ->input ['status ' ]) && ($ item ->input ['status ' ] == CommonITILObject::CLOSED || $ item ->input ['status ' ] == CommonITILObject::SOLVED ))
282- || $ item ->fields ['status ' ] == CommonITILObject::CLOSED
283- || $ item ->fields ['status ' ] == CommonITILObject::SOLVED
280+ $ closed = true ;
281+
282+ if ($ item instanceof ITILSolution) {
283+ $ itemtype = $ item ->input ['itemtype ' ] ?? null ;
284+
285+ $ parent_item = getItemForItemType ($ itemtype );
286+
287+ if (!$ parent_item || !$ parent_item ->getFromDB ($ item ->input ['items_id ' ])) {
288+ return ;
289+ }
290+
291+ $ closed = self ::requireFieldsToClose ($ parent_item , true );
292+ $ closed = self ::preventClosure ($ parent_item ) && $ closed ;
293+ self ::$ solution_check_done = true ;
294+ } elseif (
295+ $ item instanceof CommonITILObject
296+ && isset ($ item ->input ['status ' ])
297+ && ($ item ->input ['status ' ] == CommonITILObject::CLOSED || $ item ->input ['status ' ] == CommonITILObject::SOLVED )
284298 ) {
285- self ::requireFieldsToClose ($ item );
286- self ::preventClosure ($ item );
299+ if (self ::$ solution_check_done && $ item ->input ['status ' ] == CommonITILObject::SOLVED ) {
300+ return ;
301+ }
302+ $ closed = self ::requireFieldsToClose ($ item );
303+ $ closed = self ::preventClosure ($ item ) && $ closed ;
304+ }
305+
306+ if (!$ closed ) {
307+ $ item ->input = false ;
287308 }
288309 }
289310
290- public static function preventClosure (CommonDBTM $ item ): void
311+ public static function preventClosure (CommonDBTM $ item ): bool
291312 {
292313 $ conf = Config::getConfig ();
293314 if ($ conf ->fields ['is_active ' ] != 1 ) {
294- return ;
315+ return true ;
295316 }
296317
297318 $ tasks = [];
@@ -319,21 +340,24 @@ public static function preventClosure(CommonDBTM $item): void
319340 if (is_array ($ t ) && isset ($ t ['state ' ]) && $ t ['state ' ] == Planning::TODO ) {
320341 Session::addMessageAfterRedirect (__s ('The ticket you wish to close has tasks that need to be completed. ' , 'moreoptions ' ), false , ERROR );
321342 $ item ->input = false ;
322- return ;
343+ return false ;
323344 }
324345 }
346+ return true ;
325347 }
326348
327- public static function requireFieldsToClose (CommonDBTM $ item ): void
349+ public static function requireFieldsToClose (CommonDBTM $ item, bool $ is_solution = false ): bool
328350 {
329351 $ conf = Config::getConfig ();
330352 if ($ conf ->fields ['is_active ' ] != 1 ) {
331- return ;
353+ return true ;
332354 }
333355
334356 $ message = '' ;
335357 $ itemtype = get_class ($ item );
336358
359+ $ data = array_merge ($ item ->fields , is_array ($ item ->input ) ? $ item ->input : []);
360+
337361 // Determine the configuration suffix and actor classes based on item type
338362 $ configSuffix = '_ ' . strtolower ($ itemtype );
339363 $ userClass = $ item ->userlinkclass ?? '' ;
@@ -342,18 +366,20 @@ public static function requireFieldsToClose(CommonDBTM $item): void
342366
343367 // Check for required technician
344368 if ($ conf ->fields ['require_technician_to_close ' . $ configSuffix ] == 1 ) {
345- if (is_a ($ userClass , CommonDBTM::class, true )) {
369+ if ($ is_solution && $ itemtype === 'Ticket ' && !empty ($ _SESSION ['glpiset_solution_tech ' ])) {
370+ // GLPI will auto-assign the solution author as technician in post_addItem
371+ } elseif (is_a ($ userClass , CommonDBTM::class, true )) {
346372 $ tech = new $ userClass ();
373+ $ techs = $ tech ->find ([
374+ $ itemIdField => $ data ['id ' ],
375+ 'type ' => CommonITILActor::ASSIGN ,
376+ ]);
377+ if (count ($ techs ) == 0 ) {
378+ $ message .= '- ' . __s ('Technician ' ) . '<br> ' ;
379+ }
347380 } else {
348381 // If the user class is not valid, skip this check
349- return ;
350- }
351- $ techs = $ tech ->find ([
352- $ itemIdField => $ item ->fields ['id ' ],
353- 'type ' => CommonITILActor::ASSIGN ,
354- ]);
355- if (count ($ techs ) == 0 ) {
356- $ message .= '- ' . __s ('Technician ' ) . '<br> ' ;
382+ return false ;
357383 }
358384 }
359385
@@ -363,10 +389,10 @@ public static function requireFieldsToClose(CommonDBTM $item): void
363389 $ group = new $ groupClass ();
364390 } else {
365391 // If the group class is not valid, skip this check
366- return ;
392+ return false ;
367393 }
368394 $ groups = $ group ->find ([
369- $ itemIdField => $ item -> fields ['id ' ],
395+ $ itemIdField => $ data ['id ' ],
370396 'type ' => CommonITILActor::ASSIGN ,
371397 ]);
372398 if (count ($ groups ) == 0 ) {
@@ -376,27 +402,29 @@ public static function requireFieldsToClose(CommonDBTM $item): void
376402
377403 // Check for required category
378404 if ($ conf ->fields ['require_category_to_close ' . $ configSuffix ] == 1 ) {
379- if ((!isset ($ item -> input ['itilcategories_id ' ]) || empty ($ item -> input ['itilcategories_id ' ]))) {
405+ if ((!isset ($ data ['itilcategories_id ' ]) || empty ($ data ['itilcategories_id ' ]))) {
380406 $ message .= '- ' . __s ('Category ' ) . '<br> ' ;
381407 }
382408 }
383409
384410 // Check for required location
385411 if ($ conf ->fields ['require_location_to_close ' . $ configSuffix ] == 1 ) {
386- if ((!isset ($ item -> input ['locations_id ' ]) || empty ($ item -> input ['locations_id ' ]))) {
412+ if ((!isset ($ data ['locations_id ' ]) || empty ($ data ['locations_id ' ]))) {
387413 $ message .= '- ' . __s ('Location ' ) . '<br> ' ;
388414 }
389415 }
390416
391417 // Check if solution exists before closing
392- if ($ conf ->fields ['require_solution_to_close ' . $ configSuffix ] == 1
393- && is_array ($ item ->input )
394- && isset ($ item ->input ['status ' ])
395- && $ item ->input ['status ' ] == CommonITILObject::CLOSED ) {
418+ if (
419+ !$ is_solution
420+ && $ conf ->fields ['require_solution_to_close ' . $ configSuffix ] == 1
421+ && isset ($ data ['status ' ])
422+ && $ data ['status ' ] == CommonITILObject::CLOSED
423+ ) {
396424 $ solution = new ITILSolution ();
397425 $ solutions = $ solution ->find ([
398426 'itemtype ' => $ itemtype ,
399- 'items_id ' => $ item -> fields ['id ' ],
427+ 'items_id ' => $ data ['id ' ],
400428 'NOT ' => [
401429 'status ' => CommonITILValidation::REFUSED ,
402430 ],
@@ -411,9 +439,9 @@ public static function requireFieldsToClose(CommonDBTM $item): void
411439
412440 $ message = sprintf (__s ('To close this %s, you must fill in the following fields: ' , 'moreoptions ' ), $ itemTypeLabel ) . '<br> ' . $ message ;
413441 Session::addMessageAfterRedirect ($ message , false , ERROR );
414- $ item ->input = false ;
415- return ;
442+ return false ;
416443 }
444+ return true ;
417445 }
418446
419447 public static function checkTaskRequirements (CommonDBTM $ item ): CommonDBTM
0 commit comments