77
88use Icinga \Application \Hook ;
99use Icinga \Application \Logger ;
10+ use Icinga \Exception \ConfigurationError ;
1011use Icinga \Exception \Http \HttpNotFoundException ;
1112use Icinga \Module \Notifications \Common \Auth ;
1213use Icinga \Module \Notifications \Common \Database ;
1314use Icinga \Module \Notifications \Common \Links ;
1415use Icinga \Module \Notifications \Forms \EventRuleConfigElements \NotificationConfigProvider ;
1516use Icinga \Module \Notifications \Forms \EventRuleConfigForm ;
1617use Icinga \Module \Notifications \Forms \EventRuleForm ;
17- use Icinga \Module \Notifications \Hook \V1 \SourceHook ;
18+ use Icinga \Module \Notifications \Hook \V2 \SourceHook ;
1819use Icinga \Module \Notifications \Model \Rule ;
1920use Icinga \Module \Notifications \Model \Source ;
21+ use Icinga \Module \Notifications \Web \Control \SearchEditor \RuleFilterSuggestions ;
22+ use Icinga \Module \Notifications \Util \RuleSerializer ;
2023use Icinga \Module \Notifications \Web \Control \SearchBar \ExtraTagSuggestions ;
2124use Icinga \Web \Notification ;
2225use Icinga \Web \Session ;
2326use ipl \Html \Contract \Form ;
2427use ipl \Html \Html ;
2528use ipl \Stdlib \Filter ;
29+ use ipl \Stdlib \Filter \Condition ;
2630use ipl \Web \Compat \CompatController ;
27- use ipl \Web \Compat \CompatForm ;
31+ use ipl \Web \Control \SearchBar \SearchException ;
32+ use ipl \Web \Control \SearchEditor ;
33+ use ipl \Web \Filter \QueryString ;
2834use ipl \Web \Url ;
2935use ipl \Web \Widget \Icon ;
3036use ipl \Web \Widget \Link ;
37+ use JsonException ;
3138use Psr \Http \Message \ServerRequestInterface ;
3239use Throwable ;
3340
@@ -195,7 +202,65 @@ public function searchEditorAction(): void
195202 {
196203 $ ruleId = (int ) $ this ->params ->getRequired ('id ' );
197204 $ filter = $ this ->params ->get ('object_filter ' , $ this ->session ->get ('object_filter ' ));
205+ $ hook = $ this ->resolveSourceHook ($ ruleId );
198206
207+ $ parsedFilter = null ;
208+ if ($ filter ) {
209+ try {
210+ $ parsedFilter = json_decode ($ filter , true , flags: JSON_THROW_ON_ERROR );
211+ } catch (JsonException $ e ) {
212+ Logger::error ('Failed to parse rule filter configuration: %s (Error: %s) ' , $ filter , $ e );
213+ throw new ConfigurationError ($ this ->translate (
214+ 'Failed to parse rule filter configuration. Please contact your system administrator. '
215+ ));
216+ }
217+ }
218+
219+ $ editor = (new SearchEditor ())
220+ ->setQueryString ($ parsedFilter ['qs ' ] ?? '' )
221+ ->setSuggestionUrl (
222+ Url::fromPath (
223+ 'notifications/event-rule/suggest ' ,
224+ ['id ' => $ ruleId , '_disableLayout ' => true , 'showCompact ' => true ]
225+ )
226+ )
227+ ->setAction (Url::fromRequest ()->with ('object_filter ' , $ filter )->getAbsoluteUrl ())
228+ ->on (
229+ SearchEditor::ON_VALIDATE_COLUMN ,
230+ function (Condition $ condition ) use ($ hook ) {
231+ if (! $ hook ->isValidCondition ($ condition )) {
232+ throw new SearchException ($ this ->translate ('Is not a valid column ' ));
233+ }
234+
235+ $ condition ->metaData ()->set ('jsonPaths ' , $ hook ->getJsonPaths ($ condition ));
236+ }
237+ )
238+ ->on (Form::ON_SUBMIT , function (SearchEditor $ form ) use ($ ruleId , $ hook ) {
239+ $ this ->session ->set (
240+ 'object_filter ' ,
241+ (new RuleSerializer ($ form ->getFilter ()))->getJson ()
242+ );
243+ $ this ->redirectNow (Links::eventRule ($ ruleId )->setParam ('_filterOnly ' ));
244+ });
245+
246+ $ editor ->getParser ()->on (QueryString::ON_CONDITION , $ hook ->enrichCondition (...));
247+ $ editor ->handleRequest ($ this ->getServerRequest ());
248+
249+ $ this ->getDocument ()->addHtml ($ editor );
250+
251+ $ this ->setTitle ($ this ->translate ('Adjust Filter ' ));
252+ }
253+
254+ public function suggestAction (): void
255+ {
256+ $ hook = $ this ->resolveSourceHook ((int ) $ this ->params ->getRequired ('id ' ));
257+ $ suggestions = new RuleFilterSuggestions ($ hook );
258+ $ suggestions ->forRequest ($ this ->getServerRequest ());
259+ $ this ->getDocument ()->addHtml ($ suggestions );
260+ }
261+
262+ protected function resolveSourceHook (int $ ruleId ): SourceHook
263+ {
199264 $ source = null ;
200265 if ($ ruleId !== -1 ) {
201266 $ source = Rule::on (Database::get ())
@@ -217,7 +282,7 @@ public function searchEditorAction(): void
217282 }
218283
219284 $ hook = null ;
220- foreach (Hook::all ('Notifications/v1 /Source ' ) as $ h ) {
285+ foreach (Hook::all ('Notifications/v2 /Source ' ) as $ h ) {
221286 /** @var SourceHook $h */
222287 try {
223288 if ($ h ->getSourceType () === $ source ->type ) {
@@ -237,51 +302,7 @@ public function searchEditorAction(): void
237302 ), $ source ->type ));
238303 }
239304
240- if (! $ filter ) {
241- $ targets = $ hook ->getRuleFilterTargets ($ source ->id );
242- if (count ($ targets ) === 1 && ! is_array (reset ($ targets ))) {
243- $ filter = key ($ targets );
244- } else {
245- $ target = null ;
246- $ form = (new CompatForm ())
247- ->applyDefaultElementDecorators ()
248- ->setAction (Url::fromRequest ()->getAbsoluteUrl ())
249- ->addElement ('select ' , 'target ' , [
250- 'required ' => true ,
251- 'label ' => $ this ->translate ('Filter Target ' ),
252- 'options ' => ['' => ' - ' . $ this ->translate ('Please choose ' ) . ' - ' ] + $ targets ,
253- 'disabledOptions ' => ['' ]
254- ])
255- ->addElement ('submit ' , 'btn_submit ' , [
256- // translators: shown on a submit button to proceed to the next step of a form wizard
257- 'label ' => $ this ->translate ('Next ' )
258- ])
259- ->on (Form::ON_SUBMIT , function (CompatForm $ form ) use (&$ target ) {
260- $ target = $ form ->getValue ('target ' );
261- })
262- ->handleRequest ($ this ->getServerRequest ());
263-
264- if ($ target !== null ) {
265- $ filter = $ target ;
266- } else {
267- $ this ->addContent ($ form );
268- }
269- }
270- }
271-
272- if ($ filter ) {
273- $ form = $ hook ->getRuleFilterEditor ($ filter )
274- ->setAction (Url::fromRequest ()->with ('object_filter ' , $ filter )->getAbsoluteUrl ())
275- ->on (Form::ON_SUBMIT , function (Form $ form ) use ($ ruleId , $ hook ) {
276- $ this ->session ->set ('object_filter ' , $ hook ->serializeRuleFilter ($ form ));
277- $ this ->redirectNow (Links::eventRule ($ ruleId )->setParam ('_filterOnly ' ));
278- })
279- ->handleRequest ($ this ->getServerRequest ());
280-
281- $ this ->getDocument ()->addHtml ($ form );
282- }
283-
284- $ this ->setTitle ($ this ->translate ('Adjust Filter ' ));
305+ return $ hook ;
285306 }
286307
287308 public function editAction (): void
0 commit comments