mautic 2.3.9 → 2.6.0

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
  SHA256:
3
- metadata.gz: 59800fcfc64665ad1873fc20ef004bffe54edd38c2bb4da6263e702c0caba571
4
- data.tar.gz: e32ddec1e3707e5cf8fab1232de729a6c8df75d30f2520dc1620eec57bf857c7
3
+ metadata.gz: 8369fa0948409afca63ba594d3c630729dd160bc27fd9808dbaa941fab2e6a6e
4
+ data.tar.gz: 0cbc398f5515825575367d69866f176659713af2835df403901ee7321bdd0d85
5
5
  SHA512:
6
- metadata.gz: 0b8433f04ee7a96e9474a0f8b39a883637d68b5b2135203f150fc697d5a495e3a7447311c1d27171fe7545c74b979ee4b7727397ba279fde1ce9472b2ed29809
7
- data.tar.gz: 495c134933d712de9598cc618bf308f5b297e59bf86040d3e1c25b7ad636ee910932b08adc46c3a1a7144459b3f17e49dbb8cb57b167d28084715f8e19ed8197
6
+ metadata.gz: 623bedbe8dce28df4d92147ba646ff88506e1e2ddb883903ac687cfba6927164579279011307fbe53587d6940cd94a71feb55a31ef0a4642a7140a1e86f80253
7
+ data.tar.gz: e33d151ab4d0b44b4c978c347f6b56b1b4407520d814d9c62a2f0db1b363dab893cea944727158eab115ef17d9c9a0dec754c80ef25aaaf85bcfa3be5a556320
data/README.md CHANGED
@@ -94,11 +94,11 @@ end
94
94
  ```
95
95
  Get specify contact:
96
96
  ```ruby
97
- contact = m.contact.find(1) # => #<Mautic::Contact id=1 ...>
97
+ contact = m.contact.find(1) # => #<Mautic::Contact id=1 ...>
98
98
  ```
99
99
  Collections of contacts:
100
100
  ```ruby
101
- m.contacts.where("gmail").each do |contact|
101
+ m.contacts.where(search: "gmail").each do |contact|
102
102
  #<Mautic::Contact id=12 ...>
103
103
  #<Mautic::Contact id=21 ...>
104
104
  #<Mautic::Contact id=99 ...>
@@ -115,7 +115,7 @@ end
115
115
  contact.save # => false
116
116
  contact.errors # => [{"code"=>400, "message"=>"email: This field is required.", "details"=>{"email"=>["This field is required."]}}]
117
117
  ```
118
- Do not contact
118
+ #### Do not contact
119
119
  ```ruby
120
120
  contact.do_not_contact? # => false
121
121
  contact.do_not_contact! message: "Some reason"
@@ -127,6 +127,18 @@ end
127
127
  contact.remove_do_not_contact!
128
128
  contact.do_not_contact? # => false
129
129
  ```
130
+ #### Campaigns
131
+ list of contacts campaigns (where contact is a member) and remove it from one
132
+ ```ruby
133
+ contact.campaigns #=> [Mautic::Campaign, ...]
134
+ campaign = contact.campaigns.find { |campaign| campaign.name == "Newsletter" }
135
+ campaign.remove_contact! contact.id
136
+ ```
137
+ or add contact back
138
+ ```ruby
139
+ campaign = connection.campaigns.where(search: "Newsletter").first
140
+ campaign.add_contact! contact.id
141
+ ```
130
142
  Of course you can use more than contact: `assets`, `emails`, `companies`, `forms`, `points` ...
131
143
  ### Gem provides simple Mautic form submit
132
144
  There are two options of usage:
@@ -0,0 +1,22 @@
1
+ module Mautic
2
+ class Campaign < Model
3
+
4
+ # @see https://developer.mautic.org/#add-contact-to-a-campaign
5
+ # @param [Integer] id of Mautic::Contact
6
+ def add_contact!(id)
7
+ json = @connection.request(:post, "api/campaigns/#{self.id}/contact/#{id}/add")
8
+ json["success"]
9
+ rescue RequestError => _e
10
+ false
11
+ end
12
+
13
+ # @see https://developer.mautic.org/#remove-contact-from-a-campaign
14
+ # @param [Integer] id of Mautic::Contact
15
+ def remove_contact!(id)
16
+ json = @connection.request(:post, "api/campaigns/#{self.id}/contact/#{id}/remove")
17
+ json["success"]
18
+ rescue RequestError => _e
19
+ false
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ module Mautic
2
+ class CompanyField < Model
3
+ def self.endpoint
4
+ "fields/company"
5
+ end
6
+
7
+ def self.in(connection)
8
+ Proxy.new(connection, endpoint, klass: name, data_name: "field")
9
+ end
10
+ end
11
+ end
@@ -1,6 +1,9 @@
1
1
  module Mautic
2
2
  class Contact < Model
3
3
 
4
+ around_create :ensure_stage, if: ->(contact) { contact.changes.has_key?(:stage_id) }
5
+ around_update :ensure_stage, if: ->(contact) { contact.changes.has_key?(:stage_id) }
6
+
4
7
  alias_attribute :first_name, :firstname
5
8
  alias_attribute :last_name, :lastname
6
9
 
@@ -41,17 +44,19 @@ module Mautic
41
44
 
42
45
  if source
43
46
  self.owner = source['owner'] || {}
47
+ self.stage = source['stage'] || {}
48
+ tags = (source['tags'] || []).map { |t| Mautic::Tag.new(self, t) }.sort_by(&:name)
44
49
  self.attributes = {
45
- tags: (source['tags'] || []).collect { |t| Mautic::Tag.new(@connection, t) }.sort_by(&:name),
50
+ tags: Tag::Collection.new(self, *tags),
46
51
  doNotContact: source['doNotContact'] || [],
47
52
  owner: owner['id'],
53
+ stage_id: stage&.id,
48
54
  }
49
55
  end
50
56
  end
51
57
 
52
58
  def to_mautic(data = @table)
53
59
  data.delete(:doNotContact)
54
- data.delete(:tags)
55
60
  super(data)
56
61
  end
57
62
 
@@ -96,7 +101,7 @@ module Mautic
96
101
  self.errors = e.errors
97
102
  end
98
103
 
99
- self.errors.blank?
104
+ errors.blank?
100
105
  end
101
106
 
102
107
  alias add_dnc do_not_contact!
@@ -117,11 +122,64 @@ module Mautic
117
122
 
118
123
  # !endgroup
119
124
 
125
+ # @!group Campaigns
126
+
127
+ # @return [Array<Mautic::Campaign>]
128
+ def campaigns
129
+ return @campaigns if @campaigns
130
+
131
+ json = @connection.request(:get, "api/contacts/#{id}/campaigns")
132
+
133
+ @campaigns = json["campaigns"].collect do |_campaign_id, campaign_attributes|
134
+ Mautic::Campaign.new @connection, campaign_attributes
135
+ end
136
+ rescue RequestError => _e
137
+ []
138
+ end
139
+
140
+ # !endgroup
141
+
142
+ # @!group Stage
143
+
144
+ # @return [Mautic::Stage, nil]
145
+ def stage
146
+ @stage
147
+ end
148
+
149
+ # @param [Mautic:::Stage,Hash, nil] hash
150
+ def stage=(object_or_hash)
151
+ @stage = case object_or_hash
152
+ when Mautic::Stage
153
+ object_or_hash
154
+ when Hash
155
+ Mautic::Stage.new(connection, object_or_hash)
156
+ end
157
+ @table[:stage_id] = @stage&.id
158
+ @stage
159
+ end
160
+
161
+ # !endgroup
162
+
120
163
  private
121
164
 
122
165
  def clear_change
123
166
  super
124
167
  remove_instance_variable :@do_not_contact
125
168
  end
169
+
170
+ # Add or Remove contact in stage after contact save
171
+ def ensure_stage
172
+ stage_id_change = changes[:stage_id]
173
+ yield
174
+ if stage_id_change
175
+ self.stage = Mautic::Stage.in(connection).find(stage_id_change)
176
+ stage.add_contact!(id)
177
+ @table[:stage_id] = stage.id
178
+ else
179
+ stage.remove_contact!(id)
180
+ @table.delete(:stage_id)
181
+ end
182
+ clear_changes
183
+ end
126
184
  end
127
- end
185
+ end
@@ -0,0 +1,11 @@
1
+ module Mautic
2
+ class ContactField < Model
3
+ def self.endpoint
4
+ "fields/contact"
5
+ end
6
+
7
+ def self.in(connection)
8
+ Proxy.new(connection, endpoint, klass: name, data_name: "field")
9
+ end
10
+ end
11
+ end
@@ -5,5 +5,34 @@ module Mautic
5
5
  self.attributes = { name: source['name'], fields: source['fields'] } if source.is_a? Hash
6
6
  end
7
7
 
8
+ # @param [Integer] submission_id
9
+ # @return Mautic::Submissions::Form
10
+ # @see https://developer.mautic.org/#get-form-submission
11
+ def submission(submission_id)
12
+ json = @connection.request(:get, "api/forms/#{id}/submissions/#{submission_id}")
13
+ Mautic::Submissions::Form.new @connection, json["submission"]
14
+ rescue Mautic::RecordNotFound => _e
15
+ nil
16
+ end
17
+
18
+ # @see https://developer.mautic.org/#list-form-submissions
19
+ # @param [Hash] options
20
+ # @option options [String] :search String or search command to filter entities by.
21
+ # @option options [String] :start Starting row for the entities returned. Defaults to 0.
22
+ # @option options [String] :limit Limit number of entities to return. Defaults to the system configuration for pagination (30).
23
+ # @option options [String] :orderBy Column to sort by. Can use any column listed in the response, also can use column of joined table with prefix. Sort by submitted date is s.date_submitted
24
+ # @option options [String] :orderByDir Sort direction: asc or desc.
25
+ # @option options [String] :publishedOnly Only return currently published entities.
26
+ # @option options [String] :minimal Return only array of entities without additional lists in it.
27
+ # @return Array[Mautic::Submissions::Form]
28
+ def submissions(**options)
29
+ json = @connection.request(:get, "api/forms/#{id}/submissions", params: options)
30
+ @submissions = json["submissions"].collect do |attributes|
31
+ Mautic::Submissions::Form.new @connection, attributes
32
+ end
33
+ rescue RequestError => _e
34
+ []
35
+ end
36
+
8
37
  end
9
- end
38
+ end
@@ -0,0 +1,22 @@
1
+ module Mautic
2
+ class Stage < Model
3
+
4
+ # @see https://developer.mautic.org/#add-contact-to-a-stage
5
+ # @param [Integer] id of Mautic::Contact
6
+ def add_contact!(id)
7
+ json = @connection.request(:post, "api/stages/#{self.id}/contact/#{id}/add")
8
+ json["success"]
9
+ rescue RequestError => _e
10
+ false
11
+ end
12
+
13
+ # @see https://developer.mautic.org/#remove-contact-from-a-stage
14
+ # @param [Integer] id of Mautic::Contact
15
+ def remove_contact!(id)
16
+ json = @connection.request(:post, "api/stages/#{self.id}/contact/#{id}/remove")
17
+ json["success"]
18
+ rescue RequestError => _e
19
+ false
20
+ end
21
+ end
22
+ end
@@ -1,6 +1,34 @@
1
1
  module Mautic
2
2
  class Tag < Model
3
3
 
4
+ class Collection < Array
5
+ attr_reader :model
6
+
7
+ # @param [Mautic::Model] model
8
+ def initialize(model, *several_variants)
9
+ @model = model
10
+ @tags_to_remove = []
11
+ super(several_variants)
12
+ end
13
+
14
+ def <<(item)
15
+ @model.changed = true
16
+ item = Tag.new(@model, { tag: item }) if item.is_a?(String)
17
+ super(item)
18
+ end
19
+
20
+ def remove(item)
21
+ @model.changed = true
22
+ item = detect { |t| t.name == item } if item.is_a?(String)
23
+ @tags_to_remove << "-#{item}"
24
+ delete item
25
+ end
26
+
27
+ def to_mautic
28
+ map(&:name) + @tags_to_remove
29
+ end
30
+ end
31
+
4
32
  # alias for attribute :tag
5
33
  def name
6
34
  tag
@@ -12,10 +12,10 @@ module Mautic
12
12
 
13
13
  def form_submissions
14
14
  @forms ||= Array.wrap(@params.require("mautic.form_on_submit")).collect do |data|
15
- p = data.permit(submission: [:id, form: {}, lead: {}, results: {}]).to_h
15
+ p = data.permit(submission: [:id, :referer, form: {}, lead: {}, results: {}]).to_h
16
16
  ::Mautic::Submissions::Form.new(@connection, p["submission"]) if p["submission"]
17
17
  end.compact
18
18
  end
19
19
 
20
20
  end
21
- end
21
+ end
@@ -2,8 +2,6 @@
2
2
  <html>
3
3
  <head>
4
4
  <title>Mautic</title>
5
- <%= stylesheet_link_tag "mautic/application", media: "all" %>
6
- <%= javascript_include_tag "mautic/application" %>
7
5
  <%= csrf_meta_tags %>
8
6
  </head>
9
7
  <body>
data/lib/mautic/model.rb CHANGED
@@ -2,6 +2,7 @@ module Mautic
2
2
  # Virtual model for Mautic endpoint
3
3
  # @see https://developer.mautic.org/#endpoints
4
4
  class Model < OpenStruct
5
+ extend ActiveModel::Callbacks
5
6
 
6
7
  class MauticHash < Hash
7
8
 
@@ -37,8 +38,11 @@ module Mautic
37
38
 
38
39
  end
39
40
 
41
+ define_model_callbacks :create, :update, :save
42
+
40
43
  attr_reader :connection
41
44
  attr_accessor :errors
45
+ attr_writer :changed
42
46
 
43
47
  # @param [Mautic::Connection] connection
44
48
  def initialize(connection, hash = nil)
@@ -54,21 +58,25 @@ module Mautic
54
58
  end
55
59
 
56
60
  def save(force = false)
57
- id.present? ? update(force) : create
61
+ run_callbacks :save do
62
+ id.present? ? update(force) : create
63
+ end
58
64
  end
59
65
 
60
66
  def update(force = false)
61
- return false if changes.blank?
67
+ return false unless changed?
62
68
 
63
69
  begin
64
- json = @connection.request((force && :put || :patch), "api/#{endpoint}/#{id}/edit", body: to_mautic)
65
- assign_attributes json[endpoint.singularize]
70
+ run_callbacks :create do
71
+ json = @connection.request((force && :put || :patch), "api/#{endpoint}/#{id}/edit", body: to_mautic)
72
+ assign_attributes json[endpoint.singularize]
73
+ end
66
74
  clear_changes
67
75
  rescue ValidationError => e
68
76
  self.errors = e.errors
69
77
  end
70
78
 
71
- self.errors.blank?
79
+ errors.blank?
72
80
  end
73
81
 
74
82
  def update_columns(attributes = {})
@@ -81,14 +89,16 @@ module Mautic
81
89
 
82
90
  def create
83
91
  begin
84
- json = @connection.request(:post, "api/#{endpoint}/#{id && "#{id}/"}new", body: to_mautic)
85
- assign_attributes json[endpoint.singularize]
92
+ run_callbacks :create do
93
+ json = @connection.request(:post, "api/#{endpoint}/#{id && "#{id}/"}new", body: to_mautic)
94
+ assign_attributes json[endpoint.singularize]
95
+ end
86
96
  clear_changes
87
97
  rescue ValidationError => e
88
98
  self.errors = e.errors
89
99
  end
90
100
 
91
- self.errors.blank?
101
+ errors.blank?
92
102
  end
93
103
 
94
104
  def destroy
@@ -105,6 +115,12 @@ module Mautic
105
115
  @table.changes
106
116
  end
107
117
 
118
+ def changed?
119
+ return @changed unless @changed.nil?
120
+
121
+ @changed = !changes.empty?
122
+ end
123
+
108
124
  def attributes
109
125
  @table.to_h
110
126
  end
@@ -117,14 +133,21 @@ module Mautic
117
133
  end
118
134
 
119
135
  def to_mautic(data = @table)
120
- data.each_with_object({}) do |(key, val), mem|
121
- mem[key] = val.is_a?(Array) ? val.join("|") : val
136
+ data.transform_values do |val|
137
+ if val.respond_to?(:to_mautic)
138
+ val.to_mautic
139
+ elsif val.is_a?(Array)
140
+ val.join("|")
141
+ else
142
+ val
143
+ end
122
144
  end
123
145
  end
124
146
 
125
147
  private
126
148
 
127
149
  def clear_changes
150
+ @changed = nil
128
151
  @table.instance_variable_set(:@changes, nil)
129
152
  end
130
153
 
data/lib/mautic/proxy.rb CHANGED
@@ -14,7 +14,7 @@ module Mautic
14
14
  end
15
15
 
16
16
  def data_name
17
- @endpoint.split("/").last
17
+ @options[:data_name] || @endpoint.split("/").last
18
18
  end
19
19
 
20
20
  def build_instance(data)
@@ -79,4 +79,4 @@ module Mautic
79
79
  end
80
80
 
81
81
  end
82
- end
82
+ end
@@ -1,5 +1,6 @@
1
1
  module Mautic
2
2
  module Submissions
3
+ # @see https://developer.mautic.org/#get-form-submissions
3
4
  class Form
4
5
  attr_reader :id
5
6
 
@@ -30,6 +31,17 @@ module Mautic
30
31
  def contact
31
32
  @contact ||= @connection.contacts.new(@raw["lead"])
32
33
  end
34
+
35
+ # @return [String]
36
+ def referer
37
+ @raw["referer"].to_s
38
+ end
39
+
40
+ # @return [Hash]
41
+ def results
42
+ @raw["results"]
43
+ end
44
+
33
45
  end
34
46
  end
35
- end
47
+ end
@@ -1,3 +1,3 @@
1
1
  module Mautic
2
- VERSION = '2.3.9'
2
+ VERSION = '2.6.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mautic
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.9
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lukáš Pokorný
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-07 00:00:00.000000000 Z
11
+ date: 2021-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -160,12 +160,6 @@ files:
160
160
  - MIT-LICENSE
161
161
  - README.md
162
162
  - Rakefile
163
- - app/assets/config/mautic_manifest.js
164
- - app/assets/javascripts/mautic/application.js
165
- - app/assets/javascripts/mautic/mautic_connections.js
166
- - app/assets/stylesheets/mautic/application.css
167
- - app/assets/stylesheets/mautic/mautic_connections.css
168
- - app/assets/stylesheets/scaffold.css
169
163
  - app/controllers/concerns/mautic/connections_controller_concern.rb
170
164
  - app/controllers/concerns/mautic/receive_web_hooks.rb
171
165
  - app/controllers/mautic/application_controller.rb
@@ -174,11 +168,15 @@ files:
174
168
  - app/jobs/mautic/application_job.rb
175
169
  - app/mailers/mautic/application_mailer.rb
176
170
  - app/models/mautic/application_record.rb
171
+ - app/models/mautic/campaign.rb
172
+ - app/models/mautic/company_field.rb
177
173
  - app/models/mautic/connection.rb
178
174
  - app/models/mautic/connections/oauth2.rb
179
175
  - app/models/mautic/contact.rb
176
+ - app/models/mautic/contact_field.rb
180
177
  - app/models/mautic/event.rb
181
178
  - app/models/mautic/form.rb
179
+ - app/models/mautic/stage.rb
182
180
  - app/models/mautic/tag.rb
183
181
  - app/models/mautic/web_hook.rb
184
182
  - app/views/layouts/mautic/application.html.erb
@@ -222,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
220
  - !ruby/object:Gem::Version
223
221
  version: '0'
224
222
  requirements: []
225
- rubygems_version: 3.0.6
223
+ rubygems_version: 3.0.8
226
224
  signing_key:
227
225
  specification_version: 4
228
226
  summary: Ruby on Rails Mautic integration
@@ -1,2 +0,0 @@
1
- //= link_directory ../javascripts/mautic .js
2
- //= link_directory ../stylesheets/mautic .css
@@ -1,14 +0,0 @@
1
- // This is a manifest file that'll be compiled into application.js, which will include all the files
2
- // listed below.
3
- //
4
- // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
- // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
- //
7
- // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
- // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
- //
10
- // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
- // about supported directives.
12
- //
13
- // require rails-ujs
14
- //= require_tree .
@@ -1,2 +0,0 @@
1
- // Place all the behaviors and hooks related to the matching controller here.
2
- // All this logic will automatically be available in application.js.
@@ -1,15 +0,0 @@
1
- /*
2
- * This is a manifest file that'll be compiled into application.css, which will include all the files
3
- * listed below.
4
- *
5
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
- * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
- *
8
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
- * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
- * files in this directory. Styles in this file should be added after the last require_* statement.
11
- * It is generally better to create a new file per style scope.
12
- *
13
- *= require_tree .
14
- *= require_self
15
- */
@@ -1,4 +0,0 @@
1
- /*
2
- Place all the styles related to the matching controller here.
3
- They will automatically be included in application.css.
4
- */
@@ -1,80 +0,0 @@
1
- body {
2
- background-color: #fff;
3
- color: #333;
4
- margin: 33px;
5
- }
6
-
7
- body, p, ol, ul, td {
8
- font-family: verdana, arial, helvetica, sans-serif;
9
- font-size: 13px;
10
- line-height: 18px;
11
- }
12
-
13
- pre {
14
- background-color: #eee;
15
- padding: 10px;
16
- font-size: 11px;
17
- }
18
-
19
- a {
20
- color: #000;
21
- }
22
-
23
- a:visited {
24
- color: #666;
25
- }
26
-
27
- a:hover {
28
- color: #fff;
29
- background-color: #000;
30
- }
31
-
32
- th {
33
- padding-bottom: 5px;
34
- }
35
-
36
- td {
37
- padding: 0 5px 7px;
38
- }
39
-
40
- div.field,
41
- div.actions {
42
- margin-bottom: 10px;
43
- }
44
-
45
- #notice {
46
- color: green;
47
- }
48
-
49
- .field_with_errors {
50
- padding: 2px;
51
- background-color: red;
52
- display: table;
53
- }
54
-
55
- #error_explanation {
56
- width: 450px;
57
- border: 2px solid red;
58
- padding: 7px 7px 0;
59
- margin-bottom: 20px;
60
- background-color: #f0f0f0;
61
- }
62
-
63
- #error_explanation h2 {
64
- text-align: left;
65
- font-weight: bold;
66
- padding: 5px 5px 5px 15px;
67
- font-size: 12px;
68
- margin: -7px -7px 0;
69
- background-color: #c00;
70
- color: #fff;
71
- }
72
-
73
- #error_explanation ul li {
74
- font-size: 12px;
75
- list-style: square;
76
- }
77
-
78
- label {
79
- display: block;
80
- }