zabbixapi 4.0.0 → 5.0.0.pre.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +20 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +30 -17
  5. data/lib/zabbixapi.rb +31 -1
  6. data/lib/zabbixapi/basic/basic_alias.rb +2 -2
  7. data/lib/zabbixapi/basic/basic_func.rb +13 -12
  8. data/lib/zabbixapi/basic/basic_init.rb +5 -5
  9. data/lib/zabbixapi/basic/basic_logic.rb +35 -34
  10. data/lib/zabbixapi/classes/actions.rb +25 -1
  11. data/lib/zabbixapi/classes/applications.rb +4 -4
  12. data/lib/zabbixapi/classes/configurations.rb +3 -3
  13. data/lib/zabbixapi/classes/drules.rb +55 -0
  14. data/lib/zabbixapi/classes/errors.rb +5 -2
  15. data/lib/zabbixapi/classes/events.rb +17 -0
  16. data/lib/zabbixapi/classes/graphs.rb +23 -33
  17. data/lib/zabbixapi/classes/hostgroups.rb +1 -1
  18. data/lib/zabbixapi/classes/hosts.rb +20 -20
  19. data/lib/zabbixapi/classes/httptests.rb +7 -7
  20. data/lib/zabbixapi/classes/items.rb +36 -36
  21. data/lib/zabbixapi/classes/maintenance.rb +1 -1
  22. data/lib/zabbixapi/classes/mediatypes.rb +86 -11
  23. data/lib/zabbixapi/classes/problems.rb +101 -0
  24. data/lib/zabbixapi/classes/proxies.rb +4 -4
  25. data/lib/zabbixapi/classes/roles.rb +114 -0
  26. data/lib/zabbixapi/classes/screens.rb +18 -17
  27. data/lib/zabbixapi/classes/scripts.rb +18 -10
  28. data/lib/zabbixapi/classes/server.rb +1 -1
  29. data/lib/zabbixapi/classes/templates.rb +19 -21
  30. data/lib/zabbixapi/classes/triggers.rb +14 -13
  31. data/lib/zabbixapi/classes/unusable.rb +1 -1
  32. data/lib/zabbixapi/classes/usergroups.rb +16 -19
  33. data/lib/zabbixapi/classes/usermacros.rb +24 -24
  34. data/lib/zabbixapi/classes/users.rb +16 -17
  35. data/lib/zabbixapi/classes/valuemaps.rb +4 -4
  36. data/lib/zabbixapi/client.rb +34 -16
  37. data/lib/zabbixapi/version.rb +1 -1
  38. data/zabbixapi.gemspec +2 -2
  39. metadata +16 -14
  40. data/.yardopts +0 -9
@@ -10,7 +10,7 @@ class ZabbixApi
10
10
  # @return [String] Zabbix API version number
11
11
  def initialize(client)
12
12
  @client = client
13
- @version = @client.api_request(:method => 'apiinfo.version', :params => {})
13
+ @version = @client.api_version()
14
14
  end
15
15
  end
16
16
  end
@@ -10,7 +10,7 @@ class ZabbixApi
10
10
  # The id field name used for identifying specific Template objects via Zabbix API
11
11
  #
12
12
  # @return [String]
13
- def indentify
13
+ def identify
14
14
  'host'
15
15
  end
16
16
 
@@ -21,7 +21,7 @@ class ZabbixApi
21
21
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
22
22
  # @return [Integer] The Template object id that was deleted
23
23
  def delete(data)
24
- result = @client.api_request(:method => 'template.delete', :params => [data])
24
+ result = @client.api_request(method: 'template.delete', params: [data])
25
25
  result.empty? ? nil : result['templateids'][0].to_i
26
26
  end
27
27
 
@@ -32,11 +32,9 @@ class ZabbixApi
32
32
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
33
33
  # @return [Array] Returns array of Template ids
34
34
  def get_ids_by_host(data)
35
- result = []
36
- @client.api_request(:method => 'template.get', :params => data).each do |tmpl|
37
- result << tmpl['templateid']
35
+ @client.api_request(method: 'template.get', params: data).map do |tmpl|
36
+ tmpl['templateid']
38
37
  end
39
- result
40
38
  end
41
39
 
42
40
  # Get or Create Template object using Zabbix API
@@ -46,7 +44,7 @@ class ZabbixApi
46
44
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
47
45
  # @return [Integer] Zabbix object id
48
46
  def get_or_create(data)
49
- unless (templateid = get_id(:host => data[:host]))
47
+ unless (templateid = get_id(host: data[:host]))
50
48
  templateid = create(data)
51
49
  end
52
50
  templateid
@@ -60,10 +58,10 @@ class ZabbixApi
60
58
  # @return [Boolean]
61
59
  def mass_update(data)
62
60
  result = @client.api_request(
63
- :method => 'template.massUpdate',
64
- :params => {
65
- :hosts => data[:hosts_id].map { |t| {:hostid => t} },
66
- :templates => data[:templates_id].map { |t| {:templateid => t} },
61
+ method: 'template.massUpdate',
62
+ params: {
63
+ hosts: data[:hosts_id].map { |t| { hostid: t } },
64
+ templates: data[:templates_id].map { |t| { templateid: t } }
67
65
  }
68
66
  )
69
67
  result.empty? ? false : true
@@ -77,10 +75,10 @@ class ZabbixApi
77
75
  # @return [Boolean]
78
76
  def mass_add(data)
79
77
  result = @client.api_request(
80
- :method => 'template.massAdd',
81
- :params => {
82
- :hosts => data[:hosts_id].map { |t| {:hostid => t} },
83
- :templates => data[:templates_id].map { |t| {:templateid => t} },
78
+ method: 'template.massAdd',
79
+ params: {
80
+ hosts: data[:hosts_id].map { |t| { hostid: t } },
81
+ templates: data[:templates_id].map { |t| { templateid: t } }
84
82
  }
85
83
  )
86
84
  result.empty? ? false : true
@@ -94,12 +92,12 @@ class ZabbixApi
94
92
  # @return [Boolean]
95
93
  def mass_remove(data)
96
94
  result = @client.api_request(
97
- :method => 'template.massRemove',
98
- :params => {
99
- :hostids => data[:hosts_id],
100
- :templateids => data[:templates_id],
101
- :groupids => data[:group_id],
102
- :force => 1,
95
+ method: 'template.massRemove',
96
+ params: {
97
+ hostids: data[:hosts_id],
98
+ templateids: data[:templates_id],
99
+ groupids: data[:group_id],
100
+ force: 1
103
101
  }
104
102
  )
105
103
  result.empty? ? false : true
@@ -10,7 +10,7 @@ class ZabbixApi
10
10
  # The id field name used for identifying specific Trigger objects via Zabbix API
11
11
  #
12
12
  # @return [String]
13
- def indentify
13
+ def identify
14
14
  'description'
15
15
  end
16
16
 
@@ -21,17 +21,17 @@ class ZabbixApi
21
21
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
22
22
  # @return [Hash]
23
23
  def dump_by_id(data)
24
- log "[DEBUG] Call dump_by_id with parametrs: #{data.inspect}"
24
+ log "[DEBUG] Call dump_by_id with parameters: #{data.inspect}"
25
25
 
26
26
  @client.api_request(
27
- :method => 'trigger.get',
28
- :params => {
29
- :filter => {
30
- key.to_sym => data[key.to_sym],
27
+ method: 'trigger.get',
28
+ params: {
29
+ filter: {
30
+ key.to_sym => data[key.to_sym]
31
31
  },
32
- :output => 'extend',
33
- :select_items => 'extend',
34
- :select_functions => 'extend',
32
+ output: 'extend',
33
+ select_items: 'extend',
34
+ select_functions: 'extend'
35
35
  }
36
36
  )
37
37
  end
@@ -68,7 +68,7 @@ class ZabbixApi
68
68
  else
69
69
  data[:expression] = old_expression
70
70
  # disable old trigger
71
- log '[DEBUG] disable :' + @client.api_request(:method => "#{method_name}.update", :params => [{:triggerid => data[:triggerid], :status => '1'}]).inspect
71
+ log '[DEBUG] disable :' + @client.api_request(method: "#{method_name}.update", params: [{ triggerid: data[:triggerid], status: '1' }]).inspect
72
72
  # create new trigger
73
73
  data.delete(:triggerid)
74
74
  create(data)
@@ -84,7 +84,7 @@ class ZabbixApi
84
84
  def get_or_create(data)
85
85
  log "[DEBUG] Call get_or_create with parameters: #{data.inspect}"
86
86
 
87
- unless (id = get_id(:description => data[:description], :hostid => data[:hostid]))
87
+ unless (id = get_id(description: data[:description], hostid: data[:hostid]))
88
88
  id = create(data)
89
89
  end
90
90
  id
@@ -97,8 +97,9 @@ class ZabbixApi
97
97
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
98
98
  # @return [Integer] Zabbix object id
99
99
  def create_or_update(data)
100
- triggerid = get_id(:description => data[:description], :hostid => data[:hostid])
101
- triggerid ? update(data.merge(:triggerid => triggerid)) : create(data)
100
+ triggerid = get_id(description: data[:description], hostid: data[:hostid])
101
+
102
+ triggerid ? update(data.merge(triggerid: triggerid)) : create(data)
102
103
  end
103
104
  end
104
105
  end
@@ -1,7 +1,7 @@
1
1
  class ZabbixApi
2
2
  class Triggers < Basic
3
3
  def create_or_update(data)
4
- log "[DEBUG] Call create_or_update with parametrs: #{data.inspect}"
4
+ log "[DEBUG] Call create_or_update with parameters: #{data.inspect}"
5
5
  get_or_create(data)
6
6
  end
7
7
  end
@@ -17,7 +17,7 @@ class ZabbixApi
17
17
  # The id field name used for identifying specific Usergroup objects via Zabbix API
18
18
  #
19
19
  # @return [String]
20
- def indentify
20
+ def identify
21
21
  'name'
22
22
  end
23
23
 
@@ -27,13 +27,13 @@ class ZabbixApi
27
27
  # @raise [ApiError] Error returned when there is a problem with the Zabbix API call.
28
28
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
29
29
  # @return [Integer] Zabbix object id (usergroup)
30
- def set_perms(data)
30
+ def permissions(data)
31
31
  permission = data[:permission] || 2
32
32
  result = @client.api_request(
33
- :method => 'usergroup.massAdd',
34
- :params => {
35
- :usrgrpids => [data[:usrgrpid]],
36
- :rights => data[:hostgroupids].map { |t| {:permission => permission, :id => t} },
33
+ method: 'usergroup.update',
34
+ params: {
35
+ usrgrpid: data[:usrgrpid],
36
+ rights: data[:hostgroupids].map { |t| { permission: permission, id: t } }
37
37
  }
38
38
  )
39
39
  result ? result['usrgrpids'][0].to_i : nil
@@ -41,19 +41,13 @@ class ZabbixApi
41
41
 
42
42
  # Add users to usergroup using Zabbix API
43
43
  #
44
+ # @deprecated Zabbix has removed massAdd in favor of update.
44
45
  # @param data [Hash] Needs to include userids and usrgrpids to mass add users to groups
45
46
  # @raise [ApiError] Error returned when there is a problem with the Zabbix API call.
46
47
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
47
48
  # @return [Integer] Zabbix object id (usergroup)
48
49
  def add_user(data)
49
- result = @client.api_request(
50
- :method => 'usergroup.massAdd',
51
- :params => {
52
- :usrgrpids => data[:usrgrpids],
53
- :userids => data[:userids],
54
- }
55
- )
56
- result ? result['usrgrpids'][0].to_i : nil
50
+ update_users(data)
57
51
  end
58
52
 
59
53
  # Update users in usergroups using Zabbix API
@@ -63,12 +57,15 @@ class ZabbixApi
63
57
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
64
58
  # @return [Integer] Zabbix object id (usergroup)
65
59
  def update_users(data)
66
- result = @client.api_request(
67
- :method => 'usergroup.massUpdate',
68
- :params => {
69
- :usrgrpids => data[:usrgrpids],
70
- :userids => data[:userids],
60
+ user_groups = data[:usrgrpids].map do |t|
61
+ {
62
+ usrgrpid: t,
63
+ userids: data[:userids],
71
64
  }
65
+ end
66
+ result = @client.api_request(
67
+ method: 'usergroup.update',
68
+ params: user_groups,
72
69
  )
73
70
  result ? result['usrgrpids'][0].to_i : nil
74
71
  end
@@ -3,7 +3,7 @@ class ZabbixApi
3
3
  # The id field name used for identifying specific User macro objects via Zabbix API
4
4
  #
5
5
  # @return [String]
6
- def indentify
6
+ def identify
7
7
  'macro'
8
8
  end
9
9
 
@@ -17,17 +17,17 @@ class ZabbixApi
17
17
  # Get User macro object id from Zabbix API based on provided data
18
18
  #
19
19
  # @param data [Hash] Needs to include macro to properly identify user macros via Zabbix API
20
- # @raise [ApiError] Error returned when there is a problem with the Zabbix API call or missing object's id field name (indentify).
20
+ # @raise [ApiError] Error returned when there is a problem with the Zabbix API call or missing object's id field name (identify).
21
21
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
22
22
  # @return [Integer] Zabbix object id
23
23
  def get_id(data)
24
24
  log "[DEBUG] Call get_id with parameters: #{data.inspect}"
25
25
 
26
26
  # symbolize keys if the user used string keys instead of symbols
27
- data = symbolize_keys(data) if data.key?(indentify)
28
- # raise an error if indentify name was not supplied
29
- name = data[indentify.to_sym]
30
- raise ApiError.new("#{indentify} not supplied in call to get_id") if name.nil?
27
+ data = symbolize_keys(data) if data.key?(identify)
28
+ # raise an error if identify name was not supplied
29
+ name = data[identify.to_sym]
30
+ raise ApiError.new("#{identify} not supplied in call to get_id") if name.nil?
31
31
 
32
32
  result = request(data, 'usermacro.get', 'hostmacroid')
33
33
 
@@ -37,17 +37,17 @@ class ZabbixApi
37
37
  # Get Global macro object id from Zabbix API based on provided data
38
38
  #
39
39
  # @param data [Hash] Needs to include macro to properly identify global macros via Zabbix API
40
- # @raise [ApiError] Error returned when there is a problem with the Zabbix API call or missing object's id field name (indentify).
40
+ # @raise [ApiError] Error returned when there is a problem with the Zabbix API call or missing object's id field name (identify).
41
41
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
42
42
  # @return [Integer] Zabbix object id
43
43
  def get_id_global(data)
44
44
  log "[DEBUG] Call get_id_global with parameters: #{data.inspect}"
45
45
 
46
46
  # symbolize keys if the user used string keys instead of symbols
47
- data = symbolize_keys(data) if data.key?(indentify)
48
- # raise an error if indentify name was not supplied
49
- name = data[indentify.to_sym]
50
- raise ApiError.new("#{indentify} not supplied in call to get_id") if name.nil?
47
+ data = symbolize_keys(data) if data.key?(identify)
48
+ # raise an error if identify name was not supplied
49
+ name = data[identify.to_sym]
50
+ raise ApiError.new("#{identify} not supplied in call to get_id_global") if name.nil?
51
51
 
52
52
  result = request(data, 'usermacro.get', 'globalmacroid')
53
53
 
@@ -56,7 +56,7 @@ class ZabbixApi
56
56
 
57
57
  # Get full/extended User macro data from Zabbix API
58
58
  #
59
- # @param data [Hash] Should include object's id field name (indentify) and id value
59
+ # @param data [Hash] Should include object's id field name (identify) and id value
60
60
  # @raise [ApiError] Error returned when there is a problem with the Zabbix API call.
61
61
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
62
62
  # @return [Hash]
@@ -68,7 +68,7 @@ class ZabbixApi
68
68
 
69
69
  # Get full/extended Global macro data from Zabbix API
70
70
  #
71
- # @param data [Hash] Should include object's id field name (indentify) and id value
71
+ # @param data [Hash] Should include object's id field name (identify) and id value
72
72
  # @raise [ApiError] Error returned when there is a problem with the Zabbix API call.
73
73
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
74
74
  # @return [Hash]
@@ -126,7 +126,7 @@ class ZabbixApi
126
126
 
127
127
  # Update User macro object using Zabbix API
128
128
  #
129
- # @param data [Hash] Should include object's id field name (indentify), id value, and fields to update
129
+ # @param data [Hash] Should include object's id field name (identify), id value, and fields to update
130
130
  # @param force [Boolean] Whether to force an object update even if provided data matches Zabbix
131
131
  # @raise [ApiError] Error returned when there is a problem with the Zabbix API call.
132
132
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
@@ -138,7 +138,7 @@ class ZabbixApi
138
138
 
139
139
  # Update Global macro object using Zabbix API
140
140
  #
141
- # @param data [Hash] Should include object's id field name (indentify), id value, and fields to update
141
+ # @param data [Hash] Should include object's id field name (identify), id value, and fields to update
142
142
  # @param force [Boolean] Whether to force an object update even if provided data matches Zabbix
143
143
  # @raise [ApiError] Error returned when there is a problem with the Zabbix API call.
144
144
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
@@ -157,7 +157,7 @@ class ZabbixApi
157
157
  def get_or_create(data)
158
158
  log "[DEBUG] Call get_or_create with parameters: #{data.inspect}"
159
159
 
160
- unless (id = get_id(:macro => data[:macro], :hostid => data[:hostid]))
160
+ unless (id = get_id(macro: data[:macro], hostid: data[:hostid]))
161
161
  id = create(data)
162
162
  end
163
163
  id
@@ -172,7 +172,7 @@ class ZabbixApi
172
172
  def get_or_create_global(data)
173
173
  log "[DEBUG] Call get_or_create_global with parameters: #{data.inspect}"
174
174
 
175
- unless (id = get_id_global(:macro => data[:macro], :hostid => data[:hostid]))
175
+ unless (id = get_id_global(macro: data[:macro], hostid: data[:hostid]))
176
176
  id = create_global(data)
177
177
  end
178
178
  id
@@ -185,8 +185,8 @@ class ZabbixApi
185
185
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
186
186
  # @return [Integer] Zabbix object id
187
187
  def create_or_update(data)
188
- hostmacroid = get_id(:macro => data[:macro], :hostid => data[:hostid])
189
- hostmacroid ? update(data.merge(:hostmacroid => hostmacroid)) : create(data)
188
+ hostmacroid = get_id(macro: data[:macro], hostid: data[:hostid])
189
+ hostmacroid ? update(data.merge(hostmacroid: hostmacroid)) : create(data)
190
190
  end
191
191
 
192
192
  # Create or update Global macro object using Zabbix API
@@ -196,8 +196,8 @@ class ZabbixApi
196
196
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
197
197
  # @return [Integer] Zabbix object id
198
198
  def create_or_update_global(data)
199
- hostmacroid = get_id_global(:macro => data[:macro], :hostid => data[:hostid])
200
- hostmacroid ? update_global(data.merge(:globalmacroid => globalmacroid)) : create_global(data)
199
+ globalmacroid = get_id_global(macro: data[:macro], hostid: data[:hostid])
200
+ globalmacroid ? update_global(data.merge(globalmacroid: globalmacroid)) : create_global(data)
201
201
  end
202
202
 
203
203
  private
@@ -214,12 +214,12 @@ class ZabbixApi
214
214
  # Zabbix has different result formats for gets vs updates
215
215
  if method.include?('.get')
216
216
  if result_key.include?('global')
217
- @client.api_request(:method => method, :params => {:globalmacro => true, :filter => data})
217
+ @client.api_request(method: method, params: { globalmacro: true, filter: data })
218
218
  else
219
- @client.api_request(:method => method, :params => {:filter => data})
219
+ @client.api_request(method: method, params: { filter: data })
220
220
  end
221
221
  else
222
- result = @client.api_request(:method => method, :params => data)
222
+ result = @client.api_request(method: method, params: data)
223
223
 
224
224
  result.key?(result_key) && !result[result_key].empty? ? result[result_key][0].to_i : nil
225
225
  end
@@ -24,10 +24,23 @@ class ZabbixApi
24
24
  # The id field name used for identifying specific User objects via Zabbix API
25
25
  #
26
26
  # @return [String]
27
- def indentify
27
+ def identify
28
28
  'alias'
29
29
  end
30
30
 
31
+ def medias_helper(data, action)
32
+ result = @client.api_request(
33
+ method: "user.#{action}",
34
+ params: data[:userids].map do |t|
35
+ {
36
+ userid: t,
37
+ user_medias: data[:media],
38
+ }
39
+ end,
40
+ )
41
+ result ? result['userids'][0].to_i : nil
42
+ end
43
+
31
44
  # Add media to users using Zabbix API
32
45
  #
33
46
  # @param data [Hash] Needs to include userids and media to mass add media to users
@@ -35,14 +48,7 @@ class ZabbixApi
35
48
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
36
49
  # @return [Integer] Zabbix object id (media)
37
50
  def add_medias(data)
38
- result = @client.api_request(
39
- :method => 'user.addMedia',
40
- :params => {
41
- :users => data[:userids].map { |t| {:userid => t} },
42
- :medias => data[:media],
43
- }
44
- )
45
- result ? result['mediaids'][0].to_i : nil
51
+ medias_helper(data, 'update')
46
52
  end
47
53
 
48
54
  # Update media for users using Zabbix API
@@ -52,14 +58,7 @@ class ZabbixApi
52
58
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
53
59
  # @return [Integer] Zabbix object id (user)
54
60
  def update_medias(data)
55
- result = @client.api_request(
56
- :method => 'user.updateMedia',
57
- :params => {
58
- :users => data[:userids].map { |t| {:userid => t} },
59
- :medias => data[:media],
60
- }
61
- )
62
- result ? result['userids'][0].to_i : nil
61
+ medias_helper(data, 'update')
63
62
  end
64
63
  end
65
64
  end
@@ -17,7 +17,7 @@ class ZabbixApi
17
17
  # The id field name used for identifying specific ValueMap objects via Zabbix API
18
18
  #
19
19
  # @return [String]
20
- def indentify
20
+ def identify
21
21
  'name'
22
22
  end
23
23
 
@@ -30,7 +30,7 @@ class ZabbixApi
30
30
  def get_or_create(data)
31
31
  log "[DEBUG] Call get_or_create with parameters: #{data.inspect}"
32
32
 
33
- unless (id = get_id(:valuemapids => data[:valuemapids]))
33
+ unless (id = get_id(valuemapids: data[:valuemapids]))
34
34
  id = create(data)
35
35
  end
36
36
  id
@@ -43,8 +43,8 @@ class ZabbixApi
43
43
  # @raise [HttpError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
44
44
  # @return [Integer] Zabbix object id
45
45
  def create_or_update(data)
46
- valuemapid = get_id(:name => data[:name])
47
- valuemapid ? update(data.merge(:valuemapids => [:valuemapid])) : create(data)
46
+ valuemapid = get_id(name: data[:name])
47
+ valuemapid ? update(data.merge(valuemapids: [:valuemapid])) : create(data)
48
48
  end
49
49
  end
50
50
  end