Current section
Files
Jump to
Current section
Files
src/lib/wf_validation.erl
% vim: sw=4 ts=4 et ft=erlang
% Nitrogen Web Framework for Erlang
% Copyright (c) 2024 Jesse Gumm
% See MIT-LICENSE for licensing information.
-module (wf_validation).
-include ("wf.hrl").
-export ([validate/0,
register_validator/3,
clear_all_validators/0,
clear_specific_validators/2,
clear_target_validators/1,
clear_trigger_validators/1
]).
-define(VALIDATOR_STATE_KEY, '$NITROGEN_VALIDATORS').
get_validators() ->
state_handler:get_state(?VALIDATOR_STATE_KEY, []).
set_validators(Validators) ->
state_handler:set_state(?VALIDATOR_STATE_KEY, Validators).
clear_all_validators() ->
set_validators([]).
clear_specific_validators(Trigger, Target) ->
Validators = get_validators(),
FilteredValidators = [X || X={ValGroup, ValPath, _} <- Validators, not(ValGroup==Trigger andalso ValPath==Target)],
set_validators(FilteredValidators).
clear_target_validators(Target) ->
Validators = get_validators(),
FilteredValidators = [X || X={_, ValPath, _} <- Validators, ValPath =/= Target],
set_validators(FilteredValidators).
clear_trigger_validators(Trigger) ->
Validators = get_validators(),
FilteredValidators = [X || X={ValGroup, _, _} <- Validators, ValGroup =/= Trigger],
set_validators(FilteredValidators).
%% NOTE: This function is called from validator_custom. It was originally
%% implemented there as well, but it was confusing where and how server-side
%% validations were established.
register_validator(TriggerPath, TargetPath, Record) ->
V = {TriggerPath, TargetPath, Record},
Validators = get_validators(),
NewValidators = (Validators -- [V]) ++ [V],
set_validators(NewValidators).
validate() ->
% Some values...
ValidationGroup = wf_context:event_validation_group(),
Validators = get_validators(),
% Get all validators that match the validation group.
% ValidationGroup is a string.
Validators1 = [X || X={VG, _, _} <- Validators, ValidationGroup == VG],
% Now, run through each matching validator.
% Stop validating a TargetPath when it has failed.
F2 = fun({_, TargetPath, Record}, FailedPaths) ->
case lists:member(TargetPath, FailedPaths) of
true ->
FailedPaths;
false ->
Function = Record#custom.function,
Text = Record#custom.text,
Value = case wf:qs(TargetPath) of
[V | _] -> V;
[] -> undefined
end,
case Function(Record#custom.tag, Value) of
true ->
FailedPaths;
false ->
wf:wire(#validation_error{target=TargetPath, text=Text, attach_to=Record#custom.attach_to}),
[TargetPath|FailedPaths]
end
end
end,
FailedPaths1 = lists:foldl(F2, [], Validators1),
{ok, FailedPaths1 == []}.