added iOS source code
[wl-app.git] / iOS / Pods / MatomoTracker / MatomoTracker / EventSerializer.swift
1 //
2 //  EventSerializer.swift
3 //  PiwikTracker
4 //
5 //  Created by Cornelius Horstmann on 11.01.18.
6 //  Copyright © 2018 PIWIK. All rights reserved.
7 //
8
9 import Foundation
10
11 final class EventSerializer {
12     internal func jsonData(for events: [Event]) throws -> Data {
13         let eventsAsQueryItems = events.map({ $0.queryItems })
14         let serializedEvents = eventsAsQueryItems.map({ items in
15             items.flatMap({ item in
16                 guard let value = item.value,
17                     let encodedValue = value.addingPercentEncoding(withAllowedCharacters: .urlQueryParameterAllowed) else { return nil }
18                 return "\(item.name)=\(encodedValue)"
19             }).joined(separator: "&")
20         })
21         let body = ["requests": serializedEvents.map({ "?\($0)" })]
22         return try JSONSerialization.data(withJSONObject: body, options: [])
23     }
24 }
25
26 fileprivate extension Event {
27     
28     private func customVariableParameterValue() -> String {
29         let customVariableParameterValue: [String] = customVariables.map { "\"\($0.index)\":[\"\($0.name)\",\"\($0.value)\"]" }
30         return "{\(customVariableParameterValue.joined(separator: ","))}"
31     }
32
33     var queryItems: [URLQueryItem] {
34         get {
35             let items = [
36                 URLQueryItem(name: "idsite", value: siteId),
37                 URLQueryItem(name: "rec", value: "1"),
38                 // Visitor
39                 URLQueryItem(name: "_id", value: visitor.id),
40                 URLQueryItem(name: "uid", value: visitor.userId),
41                 
42                 // Session
43                 URLQueryItem(name: "_idvc", value: "\(session.sessionsCount)"),
44                 URLQueryItem(name: "_viewts", value: "\(Int(session.lastVisit.timeIntervalSince1970))"),
45                 URLQueryItem(name: "_idts", value: "\(Int(session.firstVisit.timeIntervalSince1970))"),
46                 
47                 URLQueryItem(name: "url", value:url?.absoluteString),
48                 URLQueryItem(name: "action_name", value: actionName.joined(separator: "/")),
49                 URLQueryItem(name: "lang", value: language),
50                 URLQueryItem(name: "urlref", value: referer?.absoluteString),
51                 URLQueryItem(name: "new_visit", value: isNewSession ? "1" : nil),
52                 
53                 URLQueryItem(name: "h", value: DateFormatter.hourDateFormatter.string(from: date)),
54                 URLQueryItem(name: "m", value: DateFormatter.minuteDateFormatter.string(from: date)),
55                 URLQueryItem(name: "s", value: DateFormatter.secondsDateFormatter.string(from: date)),
56                 
57                 //screen resolution
58                 URLQueryItem(name: "res", value:String(format: "%1.0fx%1.0f", screenResolution.width, screenResolution.height)),
59                 
60                 URLQueryItem(name: "e_c", value: eventCategory),
61                 URLQueryItem(name: "e_a", value: eventAction),
62                 URLQueryItem(name: "e_n", value: eventName),
63                 URLQueryItem(name: "e_v", value: eventValue != nil ? "\(eventValue!)" : nil),
64                 
65                 URLQueryItem(name: "_rcn", value: campaignName),
66                 URLQueryItem(name: "_rck", value: campaignKeyword),
67
68                 URLQueryItem(name: "search", value: searchQuery),
69                 URLQueryItem(name: "search_cat", value: searchCategory),
70                 URLQueryItem(name: "search_count", value: searchResultsCount != nil ? "\(searchResultsCount!)" : nil),
71                 
72                 URLQueryItem(name: "c_n", value: contentName),
73                 URLQueryItem(name: "c_p", value: contentPiece),
74                 URLQueryItem(name: "c_t", value: contentTarget),
75                 URLQueryItem(name: "c_i", value: contentInteraction),
76                 ].filter { $0.value != nil }
77
78             let dimensionItems = dimensions.map { URLQueryItem(name: "dimension\($0.index)", value: $0.value) }
79             let customItems = customTrackingParameters.map { return URLQueryItem(name: $0.key, value: $0.value) }
80             let customVariableItems = customVariables.count > 0 ? [URLQueryItem(name: "_cvar", value: customVariableParameterValue())] : []
81
82             return items + dimensionItems + customItems + customVariableItems
83         }
84     }
85 }
86
87 fileprivate extension DateFormatter {
88     static let hourDateFormatter: DateFormatter = {
89         let dateFormatter = DateFormatter()
90         dateFormatter.dateFormat = "HH"
91         return dateFormatter
92     }()
93     static let minuteDateFormatter: DateFormatter = {
94         let dateFormatter = DateFormatter()
95         dateFormatter.dateFormat = "mm"
96         return dateFormatter
97     }()
98     static let secondsDateFormatter: DateFormatter = {
99         let dateFormatter = DateFormatter()
100         dateFormatter.dateFormat = "ss"
101         return dateFormatter
102     }()
103 }
104
105 fileprivate extension CharacterSet {
106     
107     /// Returns the character set for characters allowed in a query parameter URL component.
108     fileprivate static var urlQueryParameterAllowed: CharacterSet {
109         return CharacterSet.urlQueryAllowed.subtracting(CharacterSet(charactersIn: "&/?"))
110     }
111 }