Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split flows.Environment into AssetsEnvironment and SessionEnvironment #1176

Merged
merged 1 commit into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flows/engine/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (s *session) SetType(type_ flows.FlowType) { s.type_ = type_ }

func (s *session) Environment() envs.Environment { return s.env }
func (s *session) SetEnvironment(env envs.Environment) { s.env = env }
func (s *session) MergedEnvironment() envs.Environment { return flows.NewEnvironment(s) }
func (s *session) MergedEnvironment() envs.Environment { return flows.NewSessionEnvironment(s) }

func (s *session) Contact() *flows.Contact { return s.contact }
func (s *session) SetContact(contact *flows.Contact) { s.contact = contact }
Expand Down
108 changes: 59 additions & 49 deletions flows/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,68 +10,26 @@
"golang.org/x/exp/slices"
)

type environment struct {
type assetsEnvironment struct {
envs.Environment

session Session
locationResolver envs.LocationResolver
}

// NewEnvironment creates a new environment from a session's base environment that merges some properties with
// those from the contact, and adds support for location resolving using the session's locations assets.
func NewEnvironment(s Session) envs.Environment {
// NewAssetsEnvironment creates a new environment from a base environment and adds support for location resolving using
// location assets.
func NewAssetsEnvironment(e envs.Environment, la *LocationAssets) envs.Environment {
var locationResolver envs.LocationResolver

hierarchies := s.Assets().Locations().Hierarchies()
hierarchies := la.Hierarchies()
if len(hierarchies) > 0 {
locationResolver = &assetLocationResolver{hierarchies[0]}
}

return &environment{
Environment: s.Environment(),
session: s,
locationResolver: locationResolver,
}
}

func (e *environment) Timezone() *time.Location {
contact := e.session.Contact()

// if we have a contact and they have a timezone that overrides the base enviroment's timezone
if contact != nil && contact.Timezone() != nil {
return contact.Timezone()
}
return e.Environment.Timezone()
}

func (e *environment) DefaultLanguage() envs.Language {
contact := e.session.Contact()

// if we have a contact and they have a language and it's an allowed language that overrides the base environment's languuage
if contact != nil && contact.Language() != envs.NilLanguage && slices.Contains(e.AllowedLanguages(), contact.Language()) {
return contact.Language()
}
return e.Environment.DefaultLanguage()
return &assetsEnvironment{Environment: e, locationResolver: locationResolver}
}

func (e *environment) DefaultCountry() envs.Country {
contact := e.session.Contact()

// if we have a contact and they have a preferred channel with a country that overrides the base environment's country
if contact != nil {
cc := contact.Country()
if cc != envs.NilCountry {
return cc
}
}
return e.Environment.DefaultCountry()
}

func (e *environment) DefaultLocale() envs.Locale {
return envs.NewLocale(e.DefaultLanguage(), e.DefaultCountry())
}

func (e *environment) LocationResolver() envs.LocationResolver {
func (e *assetsEnvironment) LocationResolver() envs.LocationResolver {
return e.locationResolver
}

Expand Down Expand Up @@ -125,3 +83,55 @@
func (r *assetLocationResolver) LookupLocation(path envs.LocationPath) *envs.Location {
return r.locations.FindByPath(path)
}

type sessionEnvironment struct {
envs.Environment

session Session
}

// NewSessionEnvironment creates a new environment from a session's base environment that merges some properties with
// those from the contact.
func NewSessionEnvironment(s Session) envs.Environment {
return &sessionEnvironment{
Environment: NewAssetsEnvironment(s.Environment(), s.Assets().Locations()),
session: s,
}
}

func (e *sessionEnvironment) Timezone() *time.Location {
contact := e.session.Contact()

// if we have a contact and they have a timezone that overrides the base enviroment's timezone
if contact != nil && contact.Timezone() != nil {
return contact.Timezone()
}
return e.Environment.Timezone()
}

func (e *sessionEnvironment) DefaultLanguage() envs.Language {
contact := e.session.Contact()

// if we have a contact and they have a language and it's an allowed language that overrides the base environment's languuage
if contact != nil && contact.Language() != envs.NilLanguage && slices.Contains(e.AllowedLanguages(), contact.Language()) {
return contact.Language()
}
return e.Environment.DefaultLanguage()
}

func (e *sessionEnvironment) DefaultCountry() envs.Country {
contact := e.session.Contact()

// if we have a contact and they have a preferred channel with a country that overrides the base environment's country
if contact != nil {
cc := contact.Country()
if cc != envs.NilCountry {
return cc
}
}
return e.Environment.DefaultCountry()

Check warning on line 132 in flows/environment.go

View check run for this annotation

Codecov / codecov/patch

flows/environment.go#L132

Added line #L132 was not covered by tests
}

func (e *sessionEnvironment) DefaultLocale() envs.Locale {
return envs.NewLocale(e.DefaultLanguage(), e.DefaultCountry())
}
14 changes: 7 additions & 7 deletions flows/environment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ var assetsJSON = `{
]
}`

func TestEnvironmentLocationResolving(t *testing.T) {
func TestAssetsEnvironment(t *testing.T) {
env := envs.NewBuilder().WithDefaultCountry("RW").Build()
source, err := static.NewSource([]byte(assetsJSON))
require.NoError(t, err)
Expand All @@ -82,14 +82,14 @@ func TestEnvironmentLocationResolving(t *testing.T) {
session, _, err := eng.NewSession(sa, trigger)
require.NoError(t, err)

senv := session.MergedEnvironment()
assert.Equal(t, envs.Country("RW"), senv.DefaultCountry())
require.NotNil(t, senv.LocationResolver())
aenv := flows.NewAssetsEnvironment(env, session.Assets().Locations())
assert.Equal(t, envs.Country("RW"), aenv.DefaultCountry())
require.NotNil(t, aenv.LocationResolver())

kigali := senv.LocationResolver().LookupLocation("Rwanda > Kigali City")
kigali := aenv.LocationResolver().LookupLocation("Rwanda > Kigali City")
assert.Equal(t, "Kigali City", kigali.Name())

matches := senv.LocationResolver().FindLocationsFuzzy("gisozi town", flows.LocationLevelWard, nil)
matches := aenv.LocationResolver().FindLocationsFuzzy("gisozi town", flows.LocationLevelWard, nil)
assert.Equal(t, 1, len(matches))
assert.Equal(t, "Gisozi", matches[0].Name())
}
Expand All @@ -107,7 +107,7 @@ const contactJSON = `{
]
}`

func TestEnvironmentMerging(t *testing.T) {
func TestSessionEnvironment(t *testing.T) {
tzRW, _ := time.LoadLocation("Africa/Kigali")
tzEC, _ := time.LoadLocation("America/Guayaquil")
tzUK, _ := time.LoadLocation("Europe/London")
Expand Down
Loading