diff --git a/SampleFiles/Tags/Generated/Analytics+GenAllScript.swift b/SampleFiles/Tags/Generated/Analytics+GenAllScript.swift index 8742801..adcfb81 100644 --- a/SampleFiles/Tags/Generated/Analytics+GenAllScript.swift +++ b/SampleFiles/Tags/Generated/Analytics+GenAllScript.swift @@ -1,11 +1,12 @@ // Generated by ResgenSwift.Analytics 2.1.0 -import MatomoTracker +import Foundation import FirebaseAnalytics // MARK: - Protocol protocol AnalyticsManagerProtocol { + func logScreen( name: String, path: String, @@ -22,75 +23,12 @@ protocol AnalyticsManagerProtocol { func setEnable(_ enable: Bool) } -// MARK: - Matomo - -class MatomoAnalyticsManager: AnalyticsManagerProtocol { - - // MARK: - Properties - - private var tracker: MatomoTracker - - // MARK: - Init - - init(siteId: String, url: String) { - debugPrint("[Matomo service] Server URL: \(url)") - debugPrint("[Matomo service] Site ID: \(siteId)") - tracker = MatomoTracker( - siteId: siteId, - baseURL: URL(string: url)! - ) - - #if DEBUG - tracker.dispatchInterval = 5 - #endif - - #if DEBUG - tracker.logger = DefaultLogger(minLevel: .verbose) - #endif - - debugPrint("[Matomo service] Configured with content base: \(tracker.contentBase?.absoluteString ?? "-")") - debugPrint("[Matomo service] Opt out: \(tracker.isOptedOut)") - } - - // MARK: - Methods - - func logScreen( - name: String, - path: String, - params: [String: Any]? - ) { - guard let trackerUrl = tracker.contentBase?.absoluteString else { return } - - let urlString = URL(string: "\(trackerUrl)" + "/" + "\(path)" + "iOS") - tracker.track( - view: [name], - url: urlString - ) - } - - func logEvent( - name: String, - action: String, - category: String, - params: [String: Any]? - ) { - tracker.track( - eventWithCategory: category, - action: action, - name: name, - number: nil, - url: nil - ) - } - - func setEnable(_ enable: Bool) { - tracker.isOptedOut = !enable - } -} - // MARK: - Firebase class FirebaseAnalyticsManager: AnalyticsManagerProtocol { + + // MARK: - Methods + func logScreen( name: String, path: String, @@ -157,16 +95,16 @@ class FirebaseAnalyticsManager: AnalyticsManagerProtocol { parameters: parameters ) } + func setEnable(_ enable: Bool) { Analytics.setAnalyticsCollectionEnabled(enable) } } - // MARK: - Traker Type enum TrackerType: CaseIterable { - case matomo + case firebase } @@ -190,7 +128,7 @@ class AnalyticsManager { } } - // MARK: - Methods + // MARK: - Enable Methods private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) { managers.forEach { (key, value) in @@ -210,14 +148,12 @@ class AnalyticsManager { setAnalytics(enable: false, analytics) } - func configure(siteId: String, url: String) { - managers[TrackerType.matomo] = MatomoAnalyticsManager( - siteId: siteId, - url: url - ) + func configure() { managers[TrackerType.firebase] = FirebaseAnalyticsManager() } + // MARK: - Private Log Methods + private func logScreen( name: String, path: String, diff --git a/SampleFiles/genAllRessources.sh b/SampleFiles/genAllRessources.sh index 3de2c99..536a461 100755 --- a/SampleFiles/genAllRessources.sh +++ b/SampleFiles/genAllRessources.sh @@ -54,7 +54,7 @@ echo "\n-------------------------\n" # Analytics swift run -c release ResgenSwift analytics $FORCE_FLAG "./Tags/sampleTags.yml" \ - --target "firebase matomo" \ + --target "firebase" \ --extension-output-path "./Tags/Generated" \ --extension-name "Analytics" \ --extension-suffix "GenAllScript" \ diff --git a/Sources/ResgenSwift/Analytics/Generator/AnalyticsGenerator.swift b/Sources/ResgenSwift/Analytics/Generator/AnalyticsGenerator.swift index 0cff0cf..357a294 100644 --- a/Sources/ResgenSwift/Analytics/Generator/AnalyticsGenerator.swift +++ b/Sources/ResgenSwift/Analytics/Generator/AnalyticsGenerator.swift @@ -93,8 +93,8 @@ enum AnalyticsGenerator { \(Self.getImport(targets: targets)) \(Self.getAnalyticsProtocol(targets: targets)) - - \(Self.getTrackerTypeEnum()) + + \(Self.getTrackerTypeEnum(targets: targets)) // MARK: - Manager @@ -111,14 +111,14 @@ enum AnalyticsGenerator { \(Self.getEnabledContent()) \(Self.getAnalyticsProperties(targets: targets)) - + \(Self.getPrivateLogFunction()) """ } - private static func getTrackerTypeEnum() -> String { + private static func getTrackerTypeEnum(targets: [TrackerType]) -> String { var result: [String] = [] - TrackerType.allCases.forEach { type in + targets.forEach { type in result.append(" case \(type)") } @@ -126,6 +126,7 @@ enum AnalyticsGenerator { // MARK: - Traker Type enum TrackerType: CaseIterable { + \(result.joined(separator: "\n")) } """ @@ -141,7 +142,7 @@ enum AnalyticsGenerator { } } - // MARK: - Methods + // MARK: - Enable Methods private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) { managers.forEach { (key, value) in @@ -180,7 +181,9 @@ enum AnalyticsGenerator { private static func getPrivateLogFunction() -> String { """ - private func logScreen( + // MARK: - Private Log Methods + + private func logScreen( name: String, path: String, params: [String: Any]? @@ -252,6 +255,7 @@ enum AnalyticsGenerator { // MARK: - Protocol protocol AnalyticsManagerProtocol { + func logScreen( name: String, path: String, @@ -267,7 +271,6 @@ enum AnalyticsGenerator { func setEnable(_ enable: Bool) } - """ var result: [String] = [proto] @@ -280,7 +283,7 @@ enum AnalyticsGenerator { result.append(FirebaseGenerator.service) } - return result.joined(separator: "\n") + return result.joined(separator: "\n\n") } private static func getProperties( diff --git a/Sources/ResgenSwift/Analytics/Generator/FirebaseGenerator.swift b/Sources/ResgenSwift/Analytics/Generator/FirebaseGenerator.swift index 8d2d22d..168f944 100644 --- a/Sources/ResgenSwift/Analytics/Generator/FirebaseGenerator.swift +++ b/Sources/ResgenSwift/Analytics/Generator/FirebaseGenerator.swift @@ -29,6 +29,9 @@ enum FirebaseGenerator { // MARK: - Firebase class FirebaseAnalyticsManager: AnalyticsManagerProtocol { + + // MARK: - Methods + """ } @@ -54,7 +57,7 @@ enum FirebaseGenerator { }) { continue } - + parameters[newKey] = newValue as? NSObject } } @@ -83,11 +86,11 @@ enum FirebaseGenerator { if category.isEmpty == false { parameters["AnalyticsParameterItemCategory"] = category as NSObject } - + if action.isEmpty == false { parameters["action"] = action as NSObject } - + if let supplementaryParameters = params { for (newKey, newValue) in supplementaryParameters { if parameters.contains(where: { (key: String, value: NSObject) in @@ -105,6 +108,7 @@ enum FirebaseGenerator { parameters: parameters ) } + """ } @@ -119,7 +123,6 @@ enum FirebaseGenerator { private static var footer: String { """ } - """ } } diff --git a/Sources/ResgenSwift/Analytics/Generator/MatomoGenerator.swift b/Sources/ResgenSwift/Analytics/Generator/MatomoGenerator.swift index 0217328..50e3c1e 100644 --- a/Sources/ResgenSwift/Analytics/Generator/MatomoGenerator.swift +++ b/Sources/ResgenSwift/Analytics/Generator/MatomoGenerator.swift @@ -115,7 +115,6 @@ enum MatomoGenerator { private static var footer: String { """ } - """ } } diff --git a/Tests/ResgenSwiftTests/Analytics/AnalyticsDefinitionTests.swift b/Tests/ResgenSwiftTests/Analytics/AnalyticsDefinitionTests.swift index 4ed4bbe..cf824d1 100644 --- a/Tests/ResgenSwiftTests/Analytics/AnalyticsDefinitionTests.swift +++ b/Tests/ResgenSwiftTests/Analytics/AnalyticsDefinitionTests.swift @@ -62,7 +62,8 @@ final class AnalyticsDefinitionTests: XCTestCase { func logScreenDefinitionName() { logScreen( name: "Ecran un", - path: "ecran_un/" + path: "ecran_un/", + params: nil ) } """ @@ -84,7 +85,7 @@ final class AnalyticsDefinitionTests: XCTestCase { name: "Ecran un", action: "", category: "", - params: [:] + params: nil ) } """ @@ -103,9 +104,10 @@ final class AnalyticsDefinitionTests: XCTestCase { // Expect let expectScreen = """ static func logScreenDefinitionName() { - logScreen( + AnalyticsManager.shared.logScreen( name: "Ecran un", - path: "ecran_un/" + path: "ecran_un/", + params: nil ) } """ @@ -123,11 +125,11 @@ final class AnalyticsDefinitionTests: XCTestCase { // Expect let expectEvent = """ static func logEventDefinitionName() { - logEvent( + AnalyticsManager.shared.logEvent( name: "Ecran un", action: "", category: "", - params: [:] + params: nil ) } """ diff --git a/Tests/ResgenSwiftTests/Analytics/AnalyticsGeneratorTests.swift b/Tests/ResgenSwiftTests/Analytics/AnalyticsGeneratorTests.swift index 5b6e987..57f0016 100644 --- a/Tests/ResgenSwiftTests/Analytics/AnalyticsGeneratorTests.swift +++ b/Tests/ResgenSwiftTests/Analytics/AnalyticsGeneratorTests.swift @@ -1,6 +1,6 @@ // // AnalyticsGeneratorTests.swift -// +// // // Created by Thibaut Schmitt on 06/09/2022. // @@ -14,7 +14,7 @@ import ToolCore @testable import ResgenSwift final class AnalyticsGeneratorTests: XCTestCase { - + private func getAnalyticsDefinition( id: String, path: String = "", @@ -31,7 +31,183 @@ final class AnalyticsGeneratorTests: XCTestCase { definition.category = category return definition } - + + private func protocolString() -> String { + """ + // MARK: - Protocol + + protocol AnalyticsManagerProtocol { + + func logScreen( + name: String, + path: String, + params: [String: Any]? + ) + + func logEvent( + name: String, + action: String, + category: String, + params: [String: Any]? + ) + + func setEnable(_ enable: Bool) + } + """ + } + + private func firebaseString() -> String { + """ + // MARK: - Firebase + + class FirebaseAnalyticsManager: AnalyticsManagerProtocol { + + // MARK: - Methods + + func logScreen( + name: String, + path: String, + params: [String: Any]? + ) { + var parameters = [ + AnalyticsParameterScreenName: name as NSObject + ] + + if path.isEmpty == false { + parameters["path"] = path + "/iOS" as NSObject + } + + if let supplementaryParameters = params { + for (newKey, newValue) in supplementaryParameters { + if parameters.contains(where: { (key: String, value: NSObject) in + key == newKey + }) { + continue + } + + parameters[newKey] = newValue as? NSObject + } + } + + Analytics.logEvent( + AnalyticsEventScreenView, + parameters: parameters + ) + } + + func logEvent( + name: String, + action: String, + category: String, + params: [String: Any]? + ) { + var parameters: [String:NSObject] = [ + AnalyticsParameterItemName: name.replacingOccurrences(of: " ", with: "_") as NSObject + ] + + if category.isEmpty == false { + parameters["AnalyticsParameterItemCategory"] = category as NSObject + } + + if action.isEmpty == false { + parameters["action"] = action as NSObject + } + + if let supplementaryParameters = params { + for (newKey, newValue) in supplementaryParameters { + if parameters.contains(where: { (key: String, value: NSObject) in + key == newKey + }) { + continue + } + + parameters[newKey] = newValue as? NSObject + } + } + + Analytics.logEvent( + AnalyticsEventSelectContent, + parameters: parameters + ) + } + + func setEnable(_ enable: Bool) { + Analytics.setAnalyticsCollectionEnabled(enable) + } + } + """ + } + + private func matomoString() -> String { + """ + // MARK: - Matomo + + class MatomoAnalyticsManager: AnalyticsManagerProtocol { + + // MARK: - Properties + + private var tracker: MatomoTracker + + // MARK: - Init + + init(siteId: String, url: String) { + debugPrint("[Matomo service] Server URL: \\(url)") + debugPrint("[Matomo service] Site ID: \\(siteId)") + tracker = MatomoTracker( + siteId: siteId, + baseURL: URL(string: url)! + ) + + #if DEBUG + tracker.dispatchInterval = 5 + #endif + + #if DEBUG + tracker.logger = DefaultLogger(minLevel: .verbose) + #endif + + debugPrint("[Matomo service] Configured with content base: \\(tracker.contentBase?.absoluteString ?? "-")") + debugPrint("[Matomo service] Opt out: \\(tracker.isOptedOut)") + } + + // MARK: - Methods + + func logScreen( + name: String, + path: String, + params: [String: Any]? + ) { + guard let trackerUrl = tracker.contentBase?.absoluteString else { return } + + let urlString = URL(string: "\\(trackerUrl)" + "/" + "\\(path)" + "iOS") + tracker.track( + view: [name], + url: urlString + ) + } + + func logEvent( + name: String, + action: String, + category: String, + params: [String: Any]? + ) { + tracker.track( + eventWithCategory: category, + action: action, + name: name, + number: nil, + url: nil + ) + } + + func setEnable(_ enable: Bool) { + tracker.isOptedOut = !enable + } + } + """ + } + func testGeneratedExtensionContentFirebase() { // Given let sectionOne = AnalyticsCategory(id: "section_one") @@ -39,19 +215,19 @@ final class AnalyticsGeneratorTests: XCTestCase { getAnalyticsDefinition(id: "s1_def_one", name: "s1 def one", type: .screen, tags: ["ios", "iosonly"]), getAnalyticsDefinition(id: "s1_def_two", name: "s1 def two", type: .event, tags: ["ios", "iosonly"]), ] - + let sectionTwo = AnalyticsCategory(id: "section_two") sectionTwo.definitions = [ getAnalyticsDefinition(id: "s2_def_one", name: "s2 def one", type: .screen, tags: ["ios","iosonly"]), getAnalyticsDefinition(id: "s2_def_two", name: "s2 def two", type: .event, tags: ["droid","droidonly"]), ] - + let sectionThree = AnalyticsCategory(id: "section_three") sectionThree.definitions = [ getAnalyticsDefinition(id: "s3_def_one", name: "s3 def one", type: .screen, tags: ["droid","droidonly"]), getAnalyticsDefinition(id: "s3_def_two", name: "s3 def two", type: .event, tags: ["droid","droidonly"]), ] - + // When let extensionContent = AnalyticsGenerator.getExtensionContent( targets: [TrackerType.firebase], @@ -65,64 +241,18 @@ final class AnalyticsGeneratorTests: XCTestCase { let expect = """ // Generated by ResgenSwift.Analytics \(ResgenSwiftVersion) + import Foundation import FirebaseAnalytics - // MARK: - Protocol + \(protocolString()) - protocol AnalyticsManagerProtocol { + \(firebaseString()) - func logScreen(name: String, path: String) - func logEvent( - name: String, - action: String, - category: String, - params: [String: Any]? - ) - } + // MARK: - Traker Type - // MARK: - Firebase + enum TrackerType: CaseIterable { - class FirebaseAnalyticsManager: AnalyticsManagerProtocol { - - func logScreen(name: String, path: String) { - var parameters = [ - AnalyticsParameterScreenName: name as NSObject - ] - - Analytics.logEvent( - AnalyticsEventScreenView, - parameters: parameters - ) - } - - func logEvent( - name: String, - action: String, - category: String, - params: [String: Any]? - ) { - var parameters: [String:NSObject] = [ - "action": action as NSObject, - "category": category as NSObject, - ] - - if let supplementaryParameters = params { - for (newKey, newValue) in supplementaryParameters { - if parameters.contains(where: { (key: String, value: NSObject) in - key == newKey - }) { - continue - } - - parameters[newKey] = newValue as? NSObject - } - } - - Analytics.logEvent( - name.replacingOccurrences(of: [" "], with: "_"), - parameters: parameters - ) - } + case firebase } // MARK: - Manager @@ -131,27 +261,59 @@ final class AnalyticsGeneratorTests: XCTestCase { static var shared = AnalyticsManager() + private init() {} + // MARK: - Properties - var managers: [AnalyticsManagerProtocol] = [] + var managers: [TrackerType: AnalyticsManagerProtocol] = [:] - private var isEnabled: Bool = true + private var isEnabled: Bool { + if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" { + false + } else { + true + } + } - // MARK: - Methods + // MARK: - Enable Methods - func setAnalyticsEnabled(_ enable: Bool) { - isEnabled = enable + private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) { + managers.forEach { (key, value) in + if analytics.contains(where: { type in + type == key + }) { + value.setEnable(enable) + } + } + } + + func enableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) { + setAnalytics(enable: true, analytics) + } + + func disableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) { + setAnalytics(enable: false, analytics) } func configure() { - managers.append(FirebaseAnalyticsManager()) + managers[TrackerType.firebase] = FirebaseAnalyticsManager() } - private func logScreen(name: String, path: String) { + // MARK: - Private Log Methods + + private func logScreen( + name: String, + path: String, + params: [String: Any]? + ) { guard isEnabled else { return } - managers.forEach { manager in - manager.logScreen(name: name, path: path) + managers.values.forEach { manager in + manager.logScreen( + name: name, + path: path, + params: params + ) } } @@ -163,7 +325,7 @@ final class AnalyticsGeneratorTests: XCTestCase { ) { guard isEnabled else { return } - managers.forEach { manager in + managers.values.forEach { manager in manager.logEvent( name: name, action: action, @@ -178,7 +340,8 @@ final class AnalyticsGeneratorTests: XCTestCase { func logScreenS1DefOne() { logScreen( name: "s1 def one", - path: "" + path: "", + params: nil ) } @@ -187,7 +350,7 @@ final class AnalyticsGeneratorTests: XCTestCase { name: "s1 def two", action: "", category: "", - params: [:] + params: nil ) } @@ -196,19 +359,20 @@ final class AnalyticsGeneratorTests: XCTestCase { func logScreenS2DefOne() { logScreen( name: "s2 def one", - path: "" + path: "", + params: nil ) } } - + """ - + if extensionContent != expect { print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) } XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest()) } - + func testGeneratedExtensionContentMatomo() { // Given let sectionOne = AnalyticsCategory(id: "section_one") @@ -216,19 +380,19 @@ final class AnalyticsGeneratorTests: XCTestCase { getAnalyticsDefinition(id: "s1_def_one", path: "s1_def_one/", name: "s1 def one", type: .screen, tags: ["ios", "iosonly"]), getAnalyticsDefinition(id: "s1_def_two", action: "test", category: "test", name: "s1 def two", type: .event, tags: ["ios", "iosonly"]), ] - + let sectionTwo = AnalyticsCategory(id: "section_two") sectionTwo.definitions = [ getAnalyticsDefinition(id: "s2_def_one", path: "s2_def_one/", name: "s2 def one", type: .screen, tags: ["ios","iosonly"]), getAnalyticsDefinition(id: "s2_def_two", action: "test", category: "test", name: "s2 def two", type: .event, tags: ["droid","droidonly"]), ] - + let sectionThree = AnalyticsCategory(id: "section_three") sectionThree.definitions = [ getAnalyticsDefinition(id: "s3_def_one", path: "s3_def_one/", name: "s3 def one", type: .screen, tags: ["droid","droidonly"]), getAnalyticsDefinition(id: "s3_def_two", action: "test", category: "test", name: "s3 def two", type: .event, tags: ["droid","droidonly"]), ] - + // When let extensionContent = AnalyticsGenerator.getExtensionContent( targets: [TrackerType.matomo], @@ -241,80 +405,18 @@ final class AnalyticsGeneratorTests: XCTestCase { let expect = """ // Generated by ResgenSwift.Analytics \(ResgenSwiftVersion) + import Foundation import MatomoTracker - // MARK: - Protocol + \(protocolString()) - protocol AnalyticsManagerProtocol { + \(matomoString()) - func logScreen(name: String, path: String) - func logEvent( - name: String, - action: String, - category: String, - params: [String: Any]? - ) - } + // MARK: - Traker Type - // MARK: - Matomo + enum TrackerType: CaseIterable { - class MatomoAnalyticsManager: AnalyticsManagerProtocol { - - // MARK: - Properties - - private var tracker: MatomoTracker - - // MARK: - Init - - init(siteId: String, url: String) { - debugPrint("[Matomo service] Server URL: \\(url)") - debugPrint("[Matomo service] Site ID: \\(siteId)") - tracker = MatomoTracker( - siteId: siteId, - baseURL: URL(string: url)! - ) - - #if DEBUG - tracker.dispatchInterval = 5 - #endif - - #if DEBUG - tracker.logger = DefaultLogger(minLevel: .verbose) - #endif - - debugPrint("[Matomo service] Configured with content base: \\(tracker.contentBase?.absoluteString ?? "-")") - debugPrint("[Matomo service] Opt out: \\(tracker.isOptedOut)") - } - - // MARK: - Methods - - func logScreen(name: String, path: String) { - guard !tracker.isOptedOut else { return } - guard let trackerUrl = tracker.contentBase?.absoluteString else { return } - - let urlString = URL(string: "\\(trackerUrl)" + "/" + "\\(path)" + "iOS") - tracker.track( - view: [name], - url: urlString - ) - } - - func logEvent( - name: String, - action: String, - category: String, - params: [String: Any]? - ) { - guard !tracker.isOptedOut else { return } - - tracker.track( - eventWithCategory: category, - action: action, - name: name, - number: nil, - url: nil - ) - } + case matomo } // MARK: - Manager @@ -323,32 +425,62 @@ final class AnalyticsGeneratorTests: XCTestCase { static var shared = AnalyticsManager() + private init() {} + // MARK: - Properties - var managers: [AnalyticsManagerProtocol] = [] + var managers: [TrackerType: AnalyticsManagerProtocol] = [:] - private var isEnabled: Bool = true + private var isEnabled: Bool { + if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" { + false + } else { + true + } + } - // MARK: - Methods + // MARK: - Enable Methods - func setAnalyticsEnabled(_ enable: Bool) { - isEnabled = enable + private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) { + managers.forEach { (key, value) in + if analytics.contains(where: { type in + type == key + }) { + value.setEnable(enable) + } + } + } + + func enableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) { + setAnalytics(enable: true, analytics) + } + + func disableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) { + setAnalytics(enable: false, analytics) } func configure(siteId: String, url: String) { - managers.append( - MatomoAnalyticsManager( - siteId: siteId, - url: url - ) + managers[TrackerType.matomo] = MatomoAnalyticsManager( + siteId: siteId, + url: url ) } - private func logScreen(name: String, path: String) { + // MARK: - Private Log Methods + + private func logScreen( + name: String, + path: String, + params: [String: Any]? + ) { guard isEnabled else { return } - managers.forEach { manager in - manager.logScreen(name: name, path: path) + managers.values.forEach { manager in + manager.logScreen( + name: name, + path: path, + params: params + ) } } @@ -360,7 +492,7 @@ final class AnalyticsGeneratorTests: XCTestCase { ) { guard isEnabled else { return } - managers.forEach { manager in + managers.values.forEach { manager in manager.logEvent( name: name, action: action, @@ -375,7 +507,8 @@ final class AnalyticsGeneratorTests: XCTestCase { func logScreenS1DefOne() { logScreen( name: "s1 def one", - path: "s1_def_one/" + path: "s1_def_one/", + params: nil ) } @@ -384,7 +517,7 @@ final class AnalyticsGeneratorTests: XCTestCase { name: "s1 def two", action: "test", category: "test", - params: [:] + params: nil ) } @@ -393,19 +526,20 @@ final class AnalyticsGeneratorTests: XCTestCase { func logScreenS2DefOne() { logScreen( name: "s2 def one", - path: "s2_def_one/" + path: "s2_def_one/", + params: nil ) } } """ - + if extensionContent != expect { print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) } XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest()) } - + func testGeneratedExtensionContentMatomoAndFirebase() { // Given let sectionOne = AnalyticsCategory(id: "section_one") @@ -413,19 +547,19 @@ final class AnalyticsGeneratorTests: XCTestCase { getAnalyticsDefinition(id: "s1_def_one", path: "s1_def_one/", name: "s1 def one", type: .screen, tags: ["ios", "iosonly"]), getAnalyticsDefinition(id: "s1_def_two", action: "test", category: "test", name: "s1 def two", type: .event, tags: ["ios", "iosonly"]), ] - + let sectionTwo = AnalyticsCategory(id: "section_two") sectionTwo.definitions = [ getAnalyticsDefinition(id: "s2_def_one", path: "s2_def_one/", name: "s2 def one", type: .screen, tags: ["ios","iosonly"]), getAnalyticsDefinition(id: "s2_def_two", action: "test", category: "test", name: "s2 def two", type: .event, tags: ["droid","droidonly"]), ] - + let sectionThree = AnalyticsCategory(id: "section_three") sectionThree.definitions = [ getAnalyticsDefinition(id: "s3_def_one", path: "s3_def_one/", name: "s3 def one", type: .screen, tags: ["droid","droidonly"]), getAnalyticsDefinition(id: "s3_def_two", action: "test", category: "test", name: "s3 def two", type: .event, tags: ["droid","droidonly"]), ] - + // When let extensionContent = AnalyticsGenerator.getExtensionContent( targets: [TrackerType.matomo, TrackerType.firebase], @@ -439,125 +573,22 @@ final class AnalyticsGeneratorTests: XCTestCase { let expect = """ // Generated by ResgenSwift.Analytics \(ResgenSwiftVersion) + import Foundation import MatomoTracker import FirebaseAnalytics - // MARK: - Protocol + \(protocolString()) - protocol AnalyticsManagerProtocol { + \(matomoString()) - func logScreen(name: String, path: String) - func logEvent( - name: String, - action: String, - category: String, - params: [String: Any]? - ) - } + \(firebaseString()) - // MARK: - Matomo + // MARK: - Traker Type - class MatomoAnalyticsManager: AnalyticsManagerProtocol { + enum TrackerType: CaseIterable { - // MARK: - Properties - - private var tracker: MatomoTracker - - // MARK: - Init - - init(siteId: String, url: String) { - debugPrint("[Matomo service] Server URL: \\(url)") - debugPrint("[Matomo service] Site ID: \\(siteId)") - tracker = MatomoTracker( - siteId: siteId, - baseURL: URL(string: url)! - ) - - #if DEBUG - tracker.dispatchInterval = 5 - #endif - - #if DEBUG - tracker.logger = DefaultLogger(minLevel: .verbose) - #endif - - debugPrint("[Matomo service] Configured with content base: \\(tracker.contentBase?.absoluteString ?? "-")") - debugPrint("[Matomo service] Opt out: \\(tracker.isOptedOut)") - } - - // MARK: - Methods - - func logScreen(name: String, path: String) { - guard !tracker.isOptedOut else { return } - guard let trackerUrl = tracker.contentBase?.absoluteString else { return } - - let urlString = URL(string: "\\(trackerUrl)" + "/" + "\\(path)" + "iOS") - tracker.track( - view: [name], - url: urlString - ) - } - - func logEvent( - name: String, - action: String, - category: String, - params: [String: Any]? - ) { - guard !tracker.isOptedOut else { return } - - tracker.track( - eventWithCategory: category, - action: action, - name: name, - number: nil, - url: nil - ) - } - } - - // MARK: - Firebase - - class FirebaseAnalyticsManager: AnalyticsManagerProtocol { - func logScreen(name: String, path: String) { - var parameters = [ - AnalyticsParameterScreenName: name as NSObject - ] - - Analytics.logEvent( - AnalyticsEventScreenView, - parameters: parameters - ) - } - - func logEvent( - name: String, - action: String, - category: String, - params: [String: Any]? - ) { - var parameters: [String:NSObject] = [ - "action": action as NSObject, - "category": category as NSObject, - ] - - if let supplementaryParameters = params { - for (newKey, newValue) in supplementaryParameters { - if parameters.contains(where: { (key: String, value: NSObject) in - key == newKey - }) { - continue - } - - parameters[newKey] = newValue as? NSObject - } - } - - Analytics.logEvent( - name.replacingOccurrences(of: [" "], with: "_"), - parameters: parameters - ) - } + case matomo + case firebase } // MARK: - Manager @@ -566,33 +597,63 @@ final class AnalyticsGeneratorTests: XCTestCase { static var shared = AnalyticsManager() + private init() {} + // MARK: - Properties - var managers: [AnalyticsManagerProtocol] = [] + var managers: [TrackerType: AnalyticsManagerProtocol] = [:] - private var isEnabled: Bool = true + private var isEnabled: Bool { + if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" { + false + } else { + true + } + } - // MARK: - Methods + // MARK: - Enable Methods - func setAnalyticsEnabled(_ enable: Bool) { - isEnabled = enable + private func setAnalytics(enable: Bool, _ analytics: [TrackerType]) { + managers.forEach { (key, value) in + if analytics.contains(where: { type in + type == key + }) { + value.setEnable(enable) + } + } + } + + func enableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) { + setAnalytics(enable: true, analytics) + } + + func disableAnalytics(_ analytics: [TrackerType] = TrackerType.allCases) { + setAnalytics(enable: false, analytics) } func configure(siteId: String, url: String) { - managers.append( - MatomoAnalyticsManager( - siteId: siteId, - url: url - ) + managers[TrackerType.matomo] = MatomoAnalyticsManager( + siteId: siteId, + url: url ) - managers.append(FirebaseAnalyticsManager()) + managers[TrackerType.firebase] = FirebaseAnalyticsManager() } - private func logScreen(name: String, path: String) { + // MARK: - Private Log Methods + + private func logScreen( + name: String, + path: String, + params: [String: Any]? + ) { guard isEnabled else { return } - - managers.forEach { manager in - manager.logScreen(name: name, path: path) + + managers.values.forEach { manager in + manager.logScreen( + name: name, + path: path, + params: params + ) } } @@ -604,7 +665,7 @@ final class AnalyticsGeneratorTests: XCTestCase { ) { guard isEnabled else { return } - managers.forEach { manager in + managers.values.forEach { manager in manager.logEvent( name: name, action: action, @@ -619,7 +680,8 @@ final class AnalyticsGeneratorTests: XCTestCase { func logScreenS1DefOne() { logScreen( name: "s1 def one", - path: "s1_def_one/" + path: "s1_def_one/", + params: nil ) } @@ -628,7 +690,7 @@ final class AnalyticsGeneratorTests: XCTestCase { name: "s1 def two", action: "test", category: "test", - params: [:] + params: nil ) } @@ -637,13 +699,14 @@ final class AnalyticsGeneratorTests: XCTestCase { func logScreenS2DefOne() { logScreen( name: "s2 def one", - path: "s2_def_one/" + path: "s2_def_one/", + params: nil ) } } """ - + if extensionContent != expect { print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) }