11# frozen_string_literal: true
22
3+ require_relative 'mappers/environment'
4+ require_relative 'mappers/identity'
5+ require_relative 'mappers/segments'
6+
37module Flagsmith
48 module Engine
59 module Evaluation
@@ -13,12 +17,8 @@ module Mappers
1317 # @param override_traits [Array<Flagsmith::Engine::Identities::Trait>, nil] Optional override traits
1418 # @return [Hash] Evaluation context with environment, features, segments, and optionally identity
1519 def self . get_evaluation_context ( environment , identity = nil , override_traits = nil )
16- environment_context = map_environment_model_to_evaluation_context ( environment )
17- identity_context = identity ? map_identity_model_to_identity_context ( identity , override_traits ) : nil
18-
19- context = environment_context . dup
20- context [ :identity ] = identity_context if identity_context
21-
20+ context = map_environment_model_to_evaluation_context ( environment )
21+ context [ :identity ] = map_identity_model_to_identity_context ( identity , override_traits ) if identity
2222 context
2323 end
2424
@@ -27,85 +27,15 @@ def self.get_evaluation_context(environment, identity = nil, override_traits = n
2727 # @param environment [Flagsmith::Engine::Environment] The environment model
2828 # @return [Hash] Context with :environment, :features, and :segments keys
2929 def self . map_environment_model_to_evaluation_context ( environment )
30- environment_context = {
31- key : environment . api_key ,
32- name : environment . project . name
30+ context = {
31+ environment : Environment . build_environment_context ( environment ) ,
32+ features : Environment . build_features_context ( environment . feature_states ) ,
33+ segments : Segments . build_segments_context ( environment . project . segments )
3334 }
3435
35- # Map feature states to features hash
36- features = { }
37- environment . feature_states . each do |fs |
38- # Map multivariate values if present
39- variants = nil
40- if fs . multivariate_feature_state_values &.any?
41- variants = fs . multivariate_feature_state_values . map do |mv |
42- {
43- value : mv . multivariate_feature_option . value ,
44- weight : mv . percentage_allocation ,
45- priority : mv . id || uuid_to_big_int ( mv . mv_fs_value_uuid )
46- }
47- end
48- end
49-
50- feature_hash = {
51- key : fs . django_id &.to_s || fs . uuid ,
52- feature_key : fs . feature . id . to_s ,
53- name : fs . feature . name ,
54- enabled : fs . enabled ,
55- value : fs . get_value
56- }
57-
58- feature_hash [ :variants ] = variants if variants
59- priority = fs . feature_segment &.priority
60- feature_hash [ :priority ] = priority unless priority . nil?
61- feature_hash [ :metadata ] = { flagsmith_id : fs . feature . id }
62-
63- features [ fs . feature . name ] = feature_hash
64- end
65-
66- # Map segments from project
67- segments = { }
68- environment . project . segments . each do |segment |
69- overrides = segment . feature_states . map do |fs |
70- override_hash = {
71- key : fs . django_id &.to_s || fs . uuid ,
72- feature_key : fs . feature . id . to_s ,
73- name : fs . feature . name ,
74- enabled : fs . enabled ,
75- value : fs . get_value
76- }
77- override_hash [ :priority ] = fs . feature_segment . priority if fs . feature_segment &.priority
78- override_hash [ :metadata ] = { flagsmith_id : fs . feature . id }
79- override_hash
80- end
36+ context [ :segments ] . merge! ( Identity . map_overrides_to_segments ( environment . identity_overrides ) ) if environment . identity_overrides &.any?
8137
82- segments [ segment . id . to_s ] = {
83- key : segment . id . to_s ,
84- name : segment . name ,
85- rules : segment . rules . map { |rule | map_segment_rule_model_to_rule ( rule ) } ,
86- overrides : overrides ,
87- metadata : {
88- source : 'API' ,
89- flagsmith_id : segment . id
90- }
91- }
92- end
93-
94- # Map identity overrides to segments
95- if environment . identity_overrides &.any?
96- identity_override_segments = map_identity_overrides_to_segments ( environment . identity_overrides )
97- segments . merge! ( identity_override_segments )
98- end
99-
100- {
101- environment : environment_context ,
102- features : features ,
103- segments : segments
104- }
105- end
106-
107- def self . uuid_to_big_int ( uuid )
108- uuid . gsub ( '-' , '' ) . to_i ( 16 )
38+ context
10939 end
11040
11141 # Maps identity model to identity context
@@ -114,108 +44,23 @@ def self.uuid_to_big_int(uuid)
11444 # @param override_traits [Array<Flagsmith::Engine::Identities::Trait>, nil] Optional override traits
11545 # @return [Hash] Identity context with :identifier, :key, and :traits
11646 def self . map_identity_model_to_identity_context ( identity , override_traits = nil )
117- # Use override traits if provided, otherwise use identity's traits
118- traits = override_traits || identity . identity_traits
119-
120- # Map traits to a hash with trait key => trait value
121- traits_hash = { }
122- traits . each do |trait |
123- traits_hash [ trait . trait_key ] = trait . trait_value
124- end
125-
126- {
127- identifier : identity . identifier ,
128- key : identity . django_id &.to_s || identity . composite_key ,
129- traits : traits_hash
130- }
47+ Identity . build_environment_context ( identity , override_traits )
13148 end
13249
13350 # Maps segment rule model to rule hash
13451 #
13552 # @param rule [Flagsmith::Engine::Segments::Rule] The segment rule model
13653 # @return [Hash] Mapped rule with :type, :conditions, and :rules
13754 def self . map_segment_rule_model_to_rule ( rule )
138- result = {
139- type : rule . type
140- }
141-
142- # Map conditions if present
143- result [ :conditions ] = ( rule . conditions || [ ] ) . map do |condition |
144- { property : condition . property , operator : condition . operator , value : condition . value }
145- end
146-
147- result [ :rules ] = if rule . rules &.any?
148- rule . rules . map { |nested_rule | map_segment_rule_model_to_rule ( nested_rule ) }
149- else
150- [ ]
151- end
152-
153- result
55+ Segments . map_rule ( rule )
15456 end
15557
15658 # Maps identity overrides to segments
15759 #
15860 # @param identity_overrides [Array<Flagsmith::Engine::Identity>] Array of identity override models
15961 # @return [Hash] Segments hash for identity overrides
16062 def self . map_identity_overrides_to_segments ( identity_overrides )
161- segments = { }
162- features_to_identifiers = { }
163-
164- identity_overrides . each do |identity |
165- next if identity . identity_features . nil? || identity . identity_features . none?
166-
167- # Sort features by name for consistent hashing
168- sorted_features = identity . identity_features . to_a . sort_by { |fs | fs . feature . name }
169-
170- # Create override keys for hashing
171- overrides_key = sorted_features . map do |fs |
172- {
173- feature_key : fs . feature . id . to_s ,
174- name : fs . feature . name ,
175- enabled : fs . enabled ,
176- value : fs . get_value ,
177- priority : STRONGEST_PRIORITY ,
178- metadata : {
179- flagsmith_id : fs . feature . id
180- }
181- }
182- end
183-
184- # Create hash of the overrides to group identities with same overrides
185- overrides_hash = overrides_key . hash
186-
187- features_to_identifiers [ overrides_hash ] ||= { identifiers : [ ] , overrides : overrides_key }
188- features_to_identifiers [ overrides_hash ] [ :identifiers ] << identity . identifier
189- end
190-
191- # Create segments for each unique set of overrides
192- features_to_identifiers . each do |overrides_hash , data |
193- segment_key = "identity_override_#{ overrides_hash } "
194-
195- segments [ segment_key ] = {
196- key : segment_key ,
197- name : 'identity_override' ,
198- rules : [
199- {
200- type : 'ALL' ,
201- conditions : [
202- {
203- property : '$.identity.identifier' ,
204- operator : 'IN' ,
205- value : data [ :identifiers ]
206- }
207- ] ,
208- rules : [ ]
209- }
210- ] ,
211- metadata : {
212- source : 'identity_override'
213- } ,
214- overrides : data [ :overrides ]
215- }
216- end
217-
218- segments
63+ Identity . map_overrides_to_segments ( identity_overrides )
21964 end
22065 end
22166 end
0 commit comments