apidae 0.9.26 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b655d3179ca371fef82c07047d90d697237f1865
4
- data.tar.gz: ff4982ec6b58a36f49cf8f370cf4fea62d637af4
3
+ metadata.gz: b71bd513f58e234253653471aa9a71ac9d0c2128
4
+ data.tar.gz: 7564dab0a718de8e97f06bdba7373513265a1031
5
5
  SHA512:
6
- metadata.gz: 9cdc066df96e9ca1980e07eb9b6f1b95d8cc7e8c1cd43e9943d69cf454f8a47f49870daafdf5db472c3ffcd4a2bb2ac01004c13106713b93a0670f8390d6cff0
7
- data.tar.gz: 016220b014fcbc5f2be9e4b3392f379dcd8555500c8c7f7057cdfd23fa61cf61c115f32f404a2cfdff87067c27d68e831dfe25c496b432f3293b02e1122d9cbb
6
+ metadata.gz: ee5d3cbb3aa547a36f7131ee07819b0daf560808a977facfc62bf9ade35f04909400b2a9ca2279b50d8b452de3bb72c6f24ebc289c0e5425c6f22d37a5d2407b
7
+ data.tar.gz: 7b4466705605f967acb6026c0887c1ec00a448196d478b1ca47187701f833cb94367b338b45199a480e2f20374337ed54f4ff23e43e3a8509e29da5162bd9391
@@ -2,5 +2,24 @@ module Apidae
2
2
  class ApplicationController < ActionController::Base
3
3
  protect_from_forgery with: :exception
4
4
  before_action Rails.application.config.apidae_auth
5
+ before_action :check_user_data!
6
+
7
+ def apidae_user
8
+ send(Rails.application.config.apidae_user) if Rails.application.config.respond_to?(:apidae_user)
9
+ end
10
+
11
+ def user_is_admin?
12
+ apidae_user && Rails.application.config.respond_to?(:apidae_admin) && Rails.application.config.apidae_admin.call(apidae_user)
13
+ end
14
+
15
+ def user_has_data?
16
+ apidae_user && apidae_user.respond_to?(:apidae_projects_ids) && !apidae_user.apidae_projects_ids.blank?
17
+ end
18
+
19
+ def check_user_data!
20
+ unless user_has_data? || user_is_admin?
21
+ redirect_to main_app.root_path, alert: "Il n'y a aucun projet Apidae associé à votre compte."
22
+ end
23
+ end
5
24
  end
6
25
  end
@@ -3,11 +3,20 @@ require_dependency "apidae/application_controller"
3
3
  module Apidae
4
4
  class DashboardController < ApplicationController
5
5
  def index
6
- @objects = Obj.count
7
- @selections = Selection.count
8
- @projects = Project.count
6
+ if user_is_admin?
7
+ @objects = Obj.count
8
+ @selections = Selection.count
9
+ @projects = Project.count
10
+ @last_imports = FileImport.order(id: :desc).take(100)
11
+ else
12
+ projects = Project.where(apidae_id: apidae_user.apidae_projects_ids)
13
+ selections = Selection.where(apidae_project_id: projects.select(:id).map {|p| p.id})
14
+ @projects = projects.count
15
+ @selections = selections.uniq.count
16
+ @objects = SelectionObject.where(apidae_selection_id: selections.map {|s| s.id}.uniq).map {|so| so.apidae_object_id}.uniq.count
17
+ @last_imports = FileImport.where(apidae_id: apidae_user.apidae_projects_ids).order(id: :desc).take(100)
18
+ end
9
19
  @references = Reference.count
10
- @last_imports = FileImport.order(id: :desc).take(100)
11
20
  end
12
21
  end
13
22
  end
@@ -6,6 +6,7 @@ module Apidae
6
6
  class ImportController < ApplicationController
7
7
  skip_before_action :verify_authenticity_token
8
8
  skip_before_action Rails.application.config.apidae_auth
9
+ skip_before_action :check_user_data!
9
10
 
10
11
  # Callback endpoint for Apidae exports
11
12
  #
@@ -10,8 +10,13 @@ module Apidae
10
10
  if params[:selection_id]
11
11
  @selection = Selection.find(params[:selection_id])
12
12
  @objects = @selection.objects.select(:id, :apidae_id, :title_data, :apidae_type, :updated_at)
13
- else
13
+ elsif user_is_admin?
14
14
  @objects = Obj.all.select(:id, :apidae_id, :title_data, :apidae_type, :updated_at)
15
+ else
16
+ projects_ids = Project.where(apidae_id: apidae_user.apidae_projects_ids).map {|p| p.id}
17
+ @objects = Obj.joins(:selections).where("apidae_selections.apidae_project_id IN (?)", projects_ids)
18
+ .select("apidae_objs.id, apidae_objs.apidae_id, apidae_objs.title_data, apidae_objs.apidae_type, apidae_objs.updated_at")
19
+ .distinct("apidae_objs.apidae_id").to_a
15
20
  end
16
21
  end
17
22
 
@@ -5,7 +5,11 @@ module Apidae
5
5
  before_action :set_project, only: [:edit, :update, :destroy]
6
6
 
7
7
  def index
8
- @projects = Project.all
8
+ if user_is_admin?
9
+ @projects = Project.all
10
+ else
11
+ @projects = Project.where(apidae_id: apidae_user.apidae_projects_ids)
12
+ end
9
13
  end
10
14
 
11
15
  def new
@@ -5,7 +5,12 @@ module Apidae
5
5
  before_action :set_selection, only: [:show, :edit, :update, :destroy, :refresh]
6
6
 
7
7
  def index
8
- @selections = Selection.all
8
+ if user_is_admin?
9
+ @selections = Selection.all
10
+ else
11
+ projects_ids = Project.where(apidae_id: apidae_user.apidae_projects_ids).map {|p| p.id}
12
+ @selections = Selection.where(apidae_project_id: projects_ids)
13
+ end
9
14
  end
10
15
 
11
16
  def show
@@ -1,5 +1,9 @@
1
1
  module Apidae
2
2
  module ApplicationHelper
3
3
  include Apidae::ApidaeHelper
4
+
5
+ def apidae_user
6
+ send(Rails.application.config.apidae_user) if Rails.application.config.respond_to?(:apidae_user)
7
+ end
4
8
  end
5
9
  end
@@ -0,0 +1,398 @@
1
+ module Apidae
2
+ class ApidaeDataParser
3
+ PHONE = 201
4
+ ALT_PHONE = 206
5
+ EMAIL = 204
6
+ WEBSITE = 205
7
+ GOOGLE = 3789
8
+ FACEBOOK = 207
9
+ TWITTER = 3755
10
+ YELP = 4007
11
+ TRIP_ADVISOR = 4000
12
+
13
+ MODE_AUTO = 'auto'
14
+ MODE_MANUAL = 'manual'
15
+
16
+ MONDAY = 'MON'
17
+ TUESDAY = 'TUE'
18
+ WEDNESDAY = 'WED'
19
+ THURSDAY = 'THU'
20
+ FRIDAY = 'FRI'
21
+ SATURDAY = 'SAT'
22
+ SUNDAY = 'SUN'
23
+
24
+ ALL_DAYS = [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
25
+
26
+ WEEKDAYS_MAP = {
27
+ 'LUNDI' => MONDAY,
28
+ 'MARDI' => TUESDAY,
29
+ 'MERCREDI' => WEDNESDAY,
30
+ 'JEUD' => THURSDAY,
31
+ 'VENDREDI' => FRIDAY,
32
+ 'SAMEDI' => SATURDAY,
33
+ 'DIMANCHE' => SUNDAY
34
+ }
35
+
36
+ def self.parse_versioned_fields(data_hash)
37
+ version_fields = data_hash[:champsAspect] || []
38
+ matched_fields = []
39
+ version_fields.each do |f|
40
+ case f
41
+ when 'nom'
42
+ matched_fields << 'title'
43
+ when 'presentation.descriptifCourt'
44
+ matched_fields << 'short_desc'
45
+ when 'presentation.descriptifDetaille'
46
+ matched_fields << 'long_desc'
47
+ when 'illustrations'
48
+ matched_fields << 'pictures'
49
+ when 'multimedias'
50
+ matched_fields << 'attachments'
51
+ when 'informations.moyensCommunication'
52
+ matched_fields << 'contact'
53
+ when 'descriptifsThematises'
54
+ matched_fields << 'theme_desc'
55
+ when 'ouverture.periodesOuvertures', 'ouverture.periodeEnClair'
56
+ matched_fields << 'openings_desc'
57
+ matched_fields << 'openings'
58
+ when 'ouverture.periodeEnClairAutomatique'
59
+ matched_fields << 'openings_desc_mode'
60
+ when 'descriptionTarif.tarifsEnClair', 'descriptionTarif.periodes'
61
+ matched_fields << 'rates_desc'
62
+ matched_fields << 'rates'
63
+ when 'descriptionTarif.tarifsEnClairAutomatique'
64
+ matched_fields << 'rates_desc_mode'
65
+ when 'prestations.equipements'
66
+ matched_fields << 'equipments'
67
+ when 'prestations.activites'
68
+ matched_fields << 'activities'
69
+ when 'prestations.services'
70
+ matched_fields << 'services'
71
+ when 'localisation.environnements'
72
+ matched_fields << 'environments'
73
+ when 'prestations.complementAccueil'
74
+ matched_fields << 'extra'
75
+ when 'localisation.geolocalisation.complement'
76
+ matched_fields << 'access'
77
+ else
78
+ end
79
+ end
80
+ matched_fields.uniq
81
+ end
82
+
83
+ def self.parse_title(data_hash, *locales)
84
+ {title: node_value(data_hash, :nom, *locales)}
85
+ end
86
+
87
+ def self.parse_owner_data(data_hash)
88
+ unless data_hash.blank?
89
+ {owner_name: data_hash[:nom], owner_id: data_hash[:id]}
90
+ end
91
+ end
92
+
93
+ def self.parse_desc_data(data_hash, private_data, *locales)
94
+ unless data_hash.blank?
95
+ {
96
+ short_desc: node_value(data_hash, :descriptifCourt, *locales),
97
+ long_desc: node_value(data_hash, :descriptifDetaille, *locales),
98
+ theme_desc: data_hash[:descriptifsThematises].blank? ? {} : Hash[data_hash[:descriptifsThematises].map {|th| [node_id(th, :theme), node_value(th, :description, *locales)]}],
99
+ private_desc: private_data.blank? ? {} : Hash[private_data.map {|d| [d[:nomTechnique], node_value(d, :descriptif, *locales)]}]
100
+ }
101
+ end
102
+ end
103
+
104
+ def self.parse_pictures_data(pictures_array, *locales)
105
+ pics_data = {}
106
+ unless pictures_array.blank?
107
+ l = locales.blank? ? [DEFAULT_LOCALE] : locales
108
+ l.each do |locale|
109
+ pics_data[locale] = []
110
+ pictures_array.select { |p| p.is_a?(Hash) && !p[:traductionFichiers].blank? }.each do |pic|
111
+ pics_data[locale] << {
112
+ id: pic[:identifiant],
113
+ name: localized_value(pic, :nom, locale),
114
+ url: pic[:traductionFichiers][0][:url].gsub('http:', 'https:'),
115
+ description: localized_value(pic, :legende, locale),
116
+ credits: localized_value(pic, :copyright, locale),
117
+ expiration_date: pic[:dateLimiteDePublication]
118
+ }
119
+ end
120
+ end
121
+ end
122
+ {pictures: pics_data}
123
+ end
124
+
125
+ def self.parse_attachments_data(attachments_array, *locales)
126
+ atts_data = {}
127
+ unless attachments_array.blank?
128
+ l = locales.blank? ? [DEFAULT_LOCALE] : locales
129
+ l.each do |locale|
130
+ atts_data[locale] = []
131
+ attachments_array.select { |att| att.is_a?(Hash) && !att[:traductionFichiers].blank? }.each do |att|
132
+ atts_data[locale] << {
133
+ id: att[:identifiant],
134
+ name: localized_value(att, :nom, locale),
135
+ url: att[:traductionFichiers][0][:url].gsub('http:', 'https:'),
136
+ type: att[:type],
137
+ description: localized_value(att, :legende, locale)
138
+ }
139
+ end
140
+ end
141
+ end
142
+ {attachments: atts_data}
143
+ end
144
+
145
+ def self.parse_contact_data(information_hash, contacts_list)
146
+ contact_details = {contacts: contacts_list}
147
+ unless information_hash.blank?
148
+ contact_entries = information_hash[:moyensCommunication] || []
149
+ contact_entries.each do |c|
150
+ case c[:type][:id]
151
+ when PHONE, ALT_PHONE
152
+ contact_details[:telephone] ||= []
153
+ contact_details[:telephone] << c[:coordonnees][:fr]
154
+ when EMAIL
155
+ contact_details[:email] ||= []
156
+ contact_details[:email] << c[:coordonnees][:fr]
157
+ when WEBSITE
158
+ contact_details[:website] ||= []
159
+ contact_details[:website] << c[:coordonnees][:fr]
160
+ when GOOGLE
161
+ contact_details[:google] ||= []
162
+ contact_details[:google] << c[:coordonnees][:fr]
163
+ when FACEBOOK
164
+ contact_details[:facebook] ||= []
165
+ contact_details[:facebook] << c[:coordonnees][:fr]
166
+ when TWITTER
167
+ contact_details[:twitter] ||= []
168
+ contact_details[:twitter] << c[:coordonnees][:fr]
169
+ when YELP
170
+ contact_details[:yelp] ||= []
171
+ contact_details[:yelp] << c[:coordonnees][:fr]
172
+ when TRIP_ADVISOR
173
+ contact_details[:trip_advisor] ||= []
174
+ contact_details[:trip_advisor] << c[:coordonnees][:fr]
175
+ else
176
+ end
177
+ end
178
+ end
179
+ contact_details
180
+ end
181
+
182
+ def self.parse_location_data(location_hash, type_data_hash, territories)
183
+ loc_data = {}
184
+ unless location_hash.blank?
185
+ address_hash = location_hash[:adresse]
186
+ computed_address = []
187
+ unless address_hash.blank?
188
+ computed_address << address_hash[:adresse1] unless address_hash[:adresse1].blank?
189
+ computed_address << address_hash[:adresse2] unless address_hash[:adresse2].blank?
190
+ computed_address << address_hash[:adresse3] unless address_hash[:adresse3].blank?
191
+ end
192
+ loc_data.merge!({address: computed_address})
193
+ loc_data.merge!({place: type_data_hash[:nomLieu]}) if type_data_hash
194
+ geoloc_details = location_hash[:geolocalisation]
195
+ if geoloc_details && geoloc_details[:valide] && geoloc_details[:geoJson]
196
+ loc_data[:latitude] = geoloc_details[:geoJson][:coordinates][1]
197
+ loc_data[:longitude] = geoloc_details[:geoJson][:coordinates][0]
198
+ end
199
+ loc_data[:access] = node_value(geoloc_details, :complement) if geoloc_details
200
+ loc_data[:environments] = location_hash[:environnements].map {|e| e[:id]} if location_hash[:environnements]
201
+ end
202
+ loc_data[:territories] = territories.map {|t| t[:id]} unless territories.blank?
203
+ loc_data
204
+ end
205
+
206
+ # Note : use internal format for openings storage (ideally Apihours one, to merge data from both sources)
207
+ def self.parse_openings(openings_hash, *locales)
208
+ if openings_hash && openings_hash[:periodeEnClair]
209
+ {
210
+ openings_desc: node_value(openings_hash, :periodeEnClair, *locales),
211
+ openings_desc_mode: openings_hash[:periodeEnClairGenerationMode] == 'AUTOMATIQUE' ? MODE_AUTO : MODE_MANUAL,
212
+ openings: build_openings(openings_hash, *locales),
213
+ time_periods: lists_ids(openings_hash[:indicationsPeriode])
214
+ }
215
+ end
216
+ end
217
+
218
+ def self.parse_rates(rates_hash, *locales)
219
+ if rates_hash
220
+ desc = rates_hash[:gratuit] ? {DEFAULT_LOCALE => 'gratuit'} : node_value(rates_hash, :tarifsEnClair, *locales)
221
+ values = rates_hash[:periodes].blank? ? [] : rates_hash[:periodes].map {|p| build_rate(p)}
222
+ methods = rates_hash[:modesPaiement].blank? ? [] : rates_hash[:modesPaiement].map {|p| p[:id]}
223
+ {
224
+ rates_desc: desc, rates: values, payment_methods: methods,
225
+ rates_desc_mode: rates_hash[:tarifsEnClairGenerationMode] == 'AUTOMATIQUE' ? MODE_AUTO : MODE_MANUAL,
226
+ includes: node_value(rates_hash, :leTarifComprend, *locales),
227
+ excludes: node_value(rates_hash, :leTarifNeComprendPas, *locales)
228
+ }
229
+ end
230
+ end
231
+
232
+ def self.parse_type_data(apidae_obj, type_hash, presta_hash, business_hash, *locales)
233
+ data_hash = type_hash || {}
234
+ prestations_hash = presta_hash || {}
235
+ apidae_obj.apidae_subtype = lists_ids(data_hash[:typesManifestation]).first if apidae_obj.apidae_type == Obj::FEM
236
+ apidae_obj.apidae_subtype = node_id(data_hash, :rubrique) if apidae_obj.apidae_type == Obj::EQU
237
+ apidae_obj.apidae_subtype = lists_ids(data_hash[:typesHebergement]).first if apidae_obj.apidae_type == Obj::SPA
238
+ {
239
+ categories: lists_ids(data_hash[:categories], data_hash[:typesDetailles], data_hash[:activiteCategories]),
240
+ themes: lists_ids(data_hash[:themes]),
241
+ capacity: (data_hash[:capacite] || {})
242
+ .merge(presta_hash ? {group_min: presta_hash[:tailleGroupeMin], group_max: presta_hash[:tailleGroupeMax],
243
+ age_min: presta_hash[:ageMin], age_max: presta_hash[:ageMax]} : {}),
244
+ classification: nodes_ids(data_hash[:classement], data_hash[:classementPrefectoral], data_hash[:classification]) +
245
+ lists_ids(data_hash[:classementsGuides]) + lists_ids(data_hash[:classements]),
246
+ labels: lists_ids(data_hash[:labels], data_hash[:labelsChartesQualite], prestations_hash[:labelsTourismeHandicap]) +
247
+ (node_id(data_hash, :typeLabel) ? [node_id(data_hash, :typeLabel)] : []),
248
+ chains: lists_ids(data_hash[:chaines]) + nodes_ids(data_hash[:chaineEtLabel]),
249
+ area: apidae_obj.apidae_type == Obj::DOS ? data_hash.except(:classification) : node_value(data_hash, :lieuDePratique),
250
+ track: apidae_obj.apidae_type == Obj::EQU ? data_hash[:itineraire] : nil,
251
+ products: lists_ids(data_hash[:typesProduit], data_hash[:aopAocIgps], data_hash[:specialites]),
252
+ audience: lists_ids(prestations_hash[:typesClientele]),
253
+ animals: {allowed: prestations_hash[:animauxAcceptes] == 'ACCEPTES', desc: node_value(prestations_hash, :descriptifAnimauxAcceptes, *locales),
254
+ fee: prestations_hash[:animauxAcceptesSupplement] == 'AVEC_SUPPLEMENT'},
255
+ extra: apidae_obj.apidae_type == Obj::SPA ? node_value(data_hash, :formuleHebergement, *locales) : node_value(prestations_hash, :complementAccueil, *locales),
256
+ duration: apidae_obj.apidae_type == Obj::SPA ? {days: data_hash[:nombreJours], nights: data_hash[:nombreNuits]} : data_hash[:dureeSeance],
257
+ certifications: data_hash[:agrements].blank? ? [] : data_hash[:agrements].map {|a| {id: a[:type][:id], identifier: a[:numero]}},
258
+ business: business_hash
259
+ }
260
+ end
261
+
262
+ def self.parse_service_data(data_hash, type_data_hash)
263
+ if data_hash
264
+ {
265
+ services: lists_ids(data_hash[:services]),
266
+ equipments: lists_ids(data_hash[:equipements]),
267
+ comfort: lists_ids(data_hash[:conforts]),
268
+ activities: lists_ids(data_hash[:activites], type_data_hash ? type_data_hash[:activites] : [],
269
+ type_data_hash ? type_data_hash[:activitesSportives] : [],
270
+ type_data_hash ? type_data_hash[:activitesCulturelles] : []),
271
+ challenged: lists_ids(data_hash[:tourismesAdaptes]),
272
+ languages: lists_ids(data_hash[:languesParlees])
273
+ }
274
+ end
275
+ end
276
+
277
+ def self.parse_tags_data(pres_data_hash, crit_data_hash, linked_data_hash)
278
+ tags = {}
279
+ if pres_data_hash
280
+ tags[:promo] = lists_ids(pres_data_hash[:typologiesPromoSitra])
281
+ end
282
+ unless crit_data_hash.blank?
283
+ tags[:internal] = crit_data_hash.map {|c| c[:id]}
284
+ end
285
+ unless linked_data_hash.blank? || linked_data_hash[:liensObjetsTouristiquesTypes].blank?
286
+ tags[:linked] = linked_data_hash[:liensObjetsTouristiquesTypes]
287
+ .map {|l| {apidae_id: l[:objetTouristique][:id], apidae_type: l[:objetTouristique][:type], category: l[:type]}}
288
+ end
289
+ tags
290
+ end
291
+
292
+ def self.parse_booking(reservation_hash, *locales)
293
+ if reservation_hash
294
+ {
295
+ booking_desc: node_value(reservation_hash, :complement, *locales),
296
+ booking_entities: reservation_hash[:organismes]
297
+ }
298
+ end
299
+ end
300
+
301
+ def self.parse_town(location_hash)
302
+ if location_hash
303
+ address_hash = location_hash[:adresse]
304
+ (!address_hash.blank? && address_hash[:commune]) ? Town.find_by_apidae_id(address_hash[:commune][:id]) : nil
305
+ else
306
+ nil
307
+ end
308
+ end
309
+
310
+ def self.parse_entity_fields(information_hash, type_data_hash)
311
+ if information_hash && information_hash[:structureGestion]
312
+ {entity_id: information_hash[:structureGestion][:id], service_provider_id: node_id(type_data_hash, :prestataireActivites)}
313
+ end
314
+ end
315
+
316
+ def self.node_id(node, key)
317
+ node[key][:id] if node && node[key]
318
+ end
319
+
320
+ private
321
+
322
+ def self.build_rate(rate_period)
323
+ {
324
+ id: rate_period[:identifiant], start_date: rate_period[:dateDebut], end_date: rate_period[:dateFin],
325
+ values: rate_period[:tarifs].blank? ? [] : rate_period[:tarifs].map {|t| {min: t[:minimum], max: t[:maximum], type: t[:type][:id], details: node_value(t, :precisionTarif)}}
326
+ }
327
+ end
328
+
329
+ def self.build_openings(openings_data, *locales)
330
+ openings_list = openings_data[:periodesOuvertures]
331
+ closing_days = openings_data[:fermeturesExceptionnelles]
332
+ if openings_list.blank?
333
+ []
334
+ else
335
+ openings_list.map do |o|
336
+ {
337
+ id: o[:identifiant],
338
+ external_id: o[:identifiantTechnique],
339
+ start_date: o[:dateDebut],
340
+ end_date: o[:dateFin],
341
+ closing_days: closing_days.blank? ? [] : closing_days.map {|d| d[:dateSpeciale]},
342
+ details: node_value(o, :complementHoraire, *locales),
343
+ time_periods: [
344
+ {
345
+ type: 'opening',
346
+ weekdays: compute_weekdays(o),
347
+ time_frames: (o[:horaireOuverture].blank? && o[:horaireFermeture].blank?) ? [] : [{start_time: o[:horaireOuverture], end_time: o[:horaireFermeture], recurrence: nil}]
348
+ }
349
+ ]
350
+ }
351
+ end
352
+ end
353
+ end
354
+
355
+ def self.compute_weekdays(opening_data)
356
+ if opening_data[:type] == 'OUVERTURE_TOUS_LES_JOURS'
357
+ ALL_DAYS
358
+ elsif opening_data[:type] == 'OUVERTURE_SAUF' && opening_data[:ouverturesJournalieres]
359
+ closed_weekdays = opening_data[:ouverturesJournalieres].map {|d| WEEKDAYS_MAP[d[:jour]]}
360
+ ALL_DAYS - closed_weekdays
361
+ elsif opening_data[:type] == 'OUVERTURE_SEMAINE' && opening_data[:ouverturesJournalieres]
362
+ opening_data[:ouverturesJournalieres].map {|d| WEEKDAYS_MAP[d[:jour]]}
363
+ else
364
+ []
365
+ end
366
+ end
367
+
368
+ def self.node_value(node, key, *locales)
369
+ l = locales.blank? ? [DEFAULT_LOCALE] : locales
370
+ locales_map = Hash[l.map {|loc| [localized_key(loc), loc]}]
371
+ if node && node[key]
372
+ node[key].slice(*locales_map.keys).transform_keys {|k| locales_map[k]}
373
+ else
374
+ {}
375
+ end
376
+ end
377
+
378
+ def self.localized_value(node, key, loc)
379
+ if node && node[key]
380
+ node[key][localized_key(loc)]
381
+ else
382
+ ''
383
+ end
384
+ end
385
+
386
+ def self.lists_ids(*lists)
387
+ lists.blank? ? [] : lists.map {|l| l.blank? ? [] : l.map {|elt| elt[:id]}}.flatten.uniq
388
+ end
389
+
390
+ def self.nodes_ids(*nodes)
391
+ nodes.blank? ? [] : nodes.select {|n| !n.blank?}.map {|n| n[:id]}
392
+ end
393
+
394
+ def self.localized_key(loc = DEFAULT_LOCALE)
395
+ "libelle#{loc.camelize.gsub('-', '')}".to_sym
396
+ end
397
+ end
398
+ end