Tawk.To Live Chat - Version 0.7.0

Version Description

  • Enhanced URL pattern matching.
  • Supported version bump 5.9.
Download this release

Release Info

Developer alvinsotawk
Plugin Icon 128x128 Tawk.To Live Chat
Version 0.7.0
Comparing to
See all releases

Code changes from version 0.6.0 to 0.7.0

Files changed (49) hide show
  1. assets/css/tawk.admin.css +259 -126
  2. assets/js/tawk.admin.js +73 -64
  3. assets/js/tawk.selection.js +67 -59
  4. index.php +7 -0
  5. readme.txt +55 -28
  6. screenshot-1.png +0 -0
  7. screenshot-2.png +0 -0
  8. screenshot-3.png +0 -0
  9. screenshot-4.png +0 -0
  10. screenshot-5.png +0 -0
  11. screenshot-6.png +0 -0
  12. tawkto.php +402 -242
  13. templates/settings.php +438 -263
  14. templates/widget.php +21 -13
  15. upgrade.manager.php +113 -0
  16. upgrades/base.php +32 -0
  17. upgrades/version.070.php +72 -0
  18. vendor/autoload.php +7 -0
  19. vendor/composer/ClassLoader.php +572 -0
  20. vendor/composer/InstalledVersions.php +350 -0
  21. vendor/composer/LICENSE +21 -0
  22. vendor/composer/autoload_classmap.php +10 -0
  23. vendor/composer/autoload_namespaces.php +9 -0
  24. vendor/composer/autoload_psr4.php +11 -0
  25. vendor/composer/autoload_real.php +55 -0
  26. vendor/composer/autoload_static.php +41 -0
  27. vendor/composer/installed.json +44 -0
  28. vendor/composer/installed.php +32 -0
  29. vendor/tawk/url-utils/.gitattributes +1 -0
  30. vendor/tawk/url-utils/.gitignore +2 -0
  31. vendor/tawk/url-utils/CHANGELOG.md +18 -0
  32. vendor/tawk/url-utils/README.md +82 -0
  33. vendor/tawk/url-utils/composer.json +17 -0
  34. vendor/tawk/url-utils/composer.lock +2111 -0
  35. vendor/tawk/url-utils/lib/Enums/WildcardLocation.php +10 -0
  36. vendor/tawk/url-utils/lib/Helpers/Common.php +29 -0
  37. vendor/tawk/url-utils/lib/Helpers/PathHelper.php +108 -0
  38. vendor/tawk/url-utils/lib/Helpers/UrlHelper.php +60 -0
  39. vendor/tawk/url-utils/lib/Models/PathPattern.php +69 -0
  40. vendor/tawk/url-utils/lib/Modules/PathPatternMatcher.php +190 -0
  41. vendor/tawk/url-utils/lib/Modules/UrlPatternMatcher.php +58 -0
  42. vendor/tawk/url-utils/phpunit.xml +13 -0
  43. vendor/tawk/url-utils/tests/Enums/WildcardLocationTest.php +45 -0
  44. vendor/tawk/url-utils/tests/Helpers/CommonTest.php +58 -0
  45. vendor/tawk/url-utils/tests/Helpers/PathHelperTest.php +254 -0
  46. vendor/tawk/url-utils/tests/Helpers/UrlHelperTest.php +101 -0
  47. vendor/tawk/url-utils/tests/Models/PathPatternTest.php +120 -0
  48. vendor/tawk/url-utils/tests/Modules/PathPatternMatcherTest.php +543 -0
  49. vendor/tawk/url-utils/tests/Modules/UrlPatternMatcherTest.php +375 -0
assets/css/tawk.admin.css CHANGED
@@ -1,182 +1,315 @@
1
- .form-table th.tawksetting {
2
- width: 350px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  }
4
 
5
- .tawknotice{
6
- font-size:14px;
 
7
  }
8
 
9
- .tawkheader{
 
 
 
 
 
 
10
  overflow: hidden;
11
- border-style: solid;
12
- border-color: #ccc;
13
- border-width:1px 1px 0 1px;
14
- background-color: #ffffff;
15
- width:95%;
16
- margin-top:20px;
17
- padding: 6px 12px 0;
18
- font-size:2em;
19
  }
20
 
21
- div.tawkmel{
22
- float:left;
23
- width:10%;
24
- min-width: 75px;
25
- min-height: 80px;
26
- text-align: center;
27
  }
28
 
29
- div.tawkheadtext{
30
- float:left;
31
- line-height: 86px;
 
32
  }
33
 
34
- div.tawkfootaction{
35
- float:left;
36
- width:10%;
37
- min-width: 75px;
38
  }
39
 
40
- div.tawkfoottext{
41
- float:right;
42
- text-align: right;
 
 
 
 
 
 
 
 
 
 
43
  }
44
 
45
- a.tawklink{
46
- color:#7FB06F;
47
- text-decoration: none;
 
 
 
 
 
 
 
 
48
  }
49
 
50
- a.tawklink:hover{
51
- text-decoration: underline;
 
 
 
 
 
 
 
52
  }
53
 
 
 
 
 
54
 
55
- div.tawkaction{
56
- overflow: hidden;
57
- border: 1px solid #ccc;
58
- background-color: #ffffff;
59
- width:95%;
60
- padding: 6px 12px;
61
  }
62
 
63
- div.tawkaction p{
64
- margin:0;
65
- padding:0;
66
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
- .tawksettingsbody{
69
- overflow: hidden;
70
- border-style: solid;
71
- border-color: #ccc;
72
- border-width:0 1px 0 1px;
73
- background-color: #ffffff;
74
- width:95%;
75
- padding: 0 24px 0 0;
76
  }
77
 
78
- div.tawktabs {
79
- float:left;
80
- overflow: hidden;
81
- background-color: #ffffff;
82
- width:10%;
83
- min-width: 75px;
84
  }
85
 
 
 
 
86
 
87
- div.tawktabs button {
88
- background-color: inherit;
89
- float: left;
90
- border: none;
91
- outline: none;
92
- cursor: pointer;
93
- padding: 14px 0;
94
- transition: 0.3s;
95
- width:100%;
96
  }
97
 
98
- div.tawktabs button:hover {
99
- background-color: #ddd;
100
- color:#0085BA;
 
101
  }
102
 
103
- div.tawktabs button.active {
104
- background-color: #f1f1f1;
105
  }
106
 
107
- .tawktabcontent {
108
- float:left;
109
- display: none;
110
- padding: 6px 12px;
111
- background-color: #ffffff;
112
-
113
- border-style: solid;
114
- border-color: #ccc;
115
- border-width:0 0 0 1px;
116
 
117
- border-top: none;
118
- width:85%;
119
- min-width: 240px;
 
 
 
 
 
 
 
120
  }
121
 
 
 
 
122
 
123
- .switch {
124
- position: relative;
125
- display: inline-block;
126
- width: 60px;
127
- height: 34px;
 
 
 
 
 
128
  }
129
 
130
- .switch input {display:none;}
 
 
 
 
 
 
 
 
 
 
131
 
 
 
 
132
 
133
- .slider {
134
- position: absolute;
135
- cursor: pointer;
136
- top: 0;
137
- left: 0;
138
- right: 0;
139
- bottom: 0;
140
- background-color: #ccc;
141
- -webkit-transition: .4s;
142
- transition: .4s;
143
- }
144
-
145
- .slider:before {
146
- position: absolute;
147
- content: "";
148
- height: 26px;
149
- width: 26px;
150
- left: 4px;
151
- bottom: 4px;
152
- background-color: white;
153
- -webkit-transition: .4s;
154
- transition: .4s;
155
  }
156
 
157
  input:checked + .slider {
158
- background-color: #2196F3;
159
  }
160
 
161
  input:focus + .slider {
162
- box-shadow: 0 0 1px #2196F3;
163
  }
164
 
165
- input:checked + .slider:before {
166
- -webkit-transform: translateX(26px);
167
- -ms-transform: translateX(26px);
168
- transform: translateX(26px);
169
  }
170
 
171
- .slider.round {
172
- border-radius: 34px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  }
174
 
175
- .slider.round:before {
176
- border-radius: 50%;
177
  }
178
 
179
- #exlucded_urls_container,
180
- #included_urls_container{
181
- padding:15px;
182
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * #.# Header section
3
+ *
4
+ * Styles in the header section of the settings panel
5
+ */
6
+ #tawk-header {
7
+ background-color: #fff;
8
+ overflow: hidden;
9
+ width: 95%;
10
+ margin-top: 20px;
11
+ padding: 6px 12px 0;
12
+ border-style: solid;
13
+ border-color: #ccc;
14
+ border-width: 1px 1px 0 1px;
15
+ font-size: 2em;
16
+ }
17
+
18
+ div.tawk-mel {
19
+ float: left;
20
+ min-width: 75px;
21
+ min-height: 80px;
22
+ width: 10%;
23
+ text-align: center;
24
  }
25
 
26
+ div.tawk-header-text {
27
+ float: left;
28
+ line-height: 86px;
29
  }
30
 
31
+ /**
32
+ * #.# Form Action
33
+ *
34
+ * Styles for the form action button
35
+ */
36
+ .tawk-action {
37
+ background-color: #fff;
38
  overflow: hidden;
39
+ width: 95%;
40
+ padding: 6px 12px;
41
+ border: 1px solid #ccc;
 
 
 
 
 
42
  }
43
 
44
+ .tawk-action p {
45
+ margin: 0;
46
+ padding: 0;
 
 
 
47
  }
48
 
49
+ div.tawk-footer-action {
50
+ width: 10%;
51
+ min-width: 75px;
52
+ float: left;
53
  }
54
 
55
+ div.tawk-footer-text {
56
+ float: right;
57
+ text-align: right;
 
58
  }
59
 
60
+ /**
61
+ * #.# Settings Body
62
+ *
63
+ * Styles for the settings panel body container
64
+ */
65
+ #tawk-settings-body {
66
+ background-color: #fff;
67
+ overflow: hidden;
68
+ width: 95%;
69
+ padding: 0 24px 0 0;
70
+ border-style: solid;
71
+ border-color: #ccc;
72
+ border-width: 0 1px 0 1px;
73
  }
74
 
75
+ /**
76
+ * #.# Tabs
77
+ *
78
+ * Styles for the tabs section in the settings panel
79
+ */
80
+ #tawk-tabs {
81
+ background-color: #fff;
82
+ overflow: hidden;
83
+ float: left;
84
+ min-width: 75px;
85
+ width: 10%;
86
  }
87
 
88
+ #tawk-tabs button {
89
+ background-color: inherit;
90
+ float: left;
91
+ width: 100%;
92
+ border: none;
93
+ padding: 14px 0;
94
+ outline: none;
95
+ cursor: pointer;
96
+ transition: 0.3s;
97
  }
98
 
99
+ #tawk-tabs button:hover {
100
+ background-color: #ddd;
101
+ color: #0085ba;
102
+ }
103
 
104
+ #tawk-tabs button.active {
105
+ background-color: #f1f1f1;
 
 
 
 
106
  }
107
 
108
+ /**
109
+ * #.# Tab Content
110
+ *
111
+ * Styles for the tab content of the settings panel
112
+ */
113
+ .tawk-tab-content {
114
+ background-color: #fff;
115
+ display: none;
116
+ float: left;
117
+ min-width: 240px;
118
+ width: 85%;
119
+ padding: 6px 12px;
120
+ border-style: solid;
121
+ border-color: #ccc;
122
+ border-width: 0 0 0 1px;
123
+ border-top: none;
124
+ }
125
 
126
+ #tawk-iframe {
127
+ min-height: 295px;
128
+ width: 100%;
129
+ margin-top: 20px;
130
+ border: none;
 
 
 
131
  }
132
 
133
+ .tawk-notice {
134
+ font-size: 14px;
135
+ max-width: 578px;
 
 
 
136
  }
137
 
138
+ .form-table th.tawk-setting {
139
+ width: 350px;
140
+ }
141
 
142
+ #exlucded-urls-container,
143
+ #included-urls-container {
144
+ padding: 15px;
 
 
 
 
 
 
145
  }
146
 
147
+ #visibility-content {
148
+ display: flex;
149
+ justify-content: space-between;
150
+ flex-wrap: wrap;
151
  }
152
 
153
+ #visibility-content #visibility-info {
154
+ max-width: 250px;
155
  }
156
 
157
+ .list-type-bullet {
158
+ list-style: circle;
159
+ padding: 0 20px;
160
+ }
 
 
 
 
 
161
 
162
+ /**
163
+ * #.# Switch and Slider
164
+ *
165
+ * Styles for the switch/toggle/slider in the settings panel
166
+ */
167
+ .switch {
168
+ display: inline-block;
169
+ height: 34px;
170
+ width: 60px;
171
+ position: relative;
172
  }
173
 
174
+ .switch input {
175
+ display: none;
176
+ }
177
 
178
+ .slider {
179
+ background-color: #ccc;
180
+ position: absolute;
181
+ top: 0;
182
+ left: 0;
183
+ right: 0;
184
+ bottom: 0;
185
+ -webkit-transition: 0.4s;
186
+ transition: 0.4s;
187
+ cursor: pointer;
188
  }
189
 
190
+ .slider::before {
191
+ background-color: #fff;
192
+ height: 26px;
193
+ width: 26px;
194
+ position: absolute;
195
+ left: 4px;
196
+ bottom: 4px;
197
+ -webkit-transition: 0.4s;
198
+ transition: 0.4s;
199
+ content: "";
200
+ }
201
 
202
+ .slider.round {
203
+ border-radius: 34px;
204
+ }
205
 
206
+ .slider.round::before {
207
+ border-radius: 50%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  }
209
 
210
  input:checked + .slider {
211
+ background-color: #2196f3;
212
  }
213
 
214
  input:focus + .slider {
215
+ box-shadow: 0 0 1px #2196f3;
216
  }
217
 
218
+ input:checked + .slider::before {
219
+ -webkit-transform: translateX(26px);
220
+ -ms-transform: translateX(26px);
221
+ transform: translateX(26px);
222
  }
223
 
224
+ /**
225
+ * #.# Links
226
+ *
227
+ * Styles for links
228
+ */
229
+ a.tawk-link {
230
+ color: #7fb06f;
231
+ text-decoration: none;
232
+ }
233
+
234
+ a.tawk-link:hover {
235
+ text-decoration: underline;
236
+ }
237
+
238
+ /**
239
+ * #.# Tooltip
240
+ *
241
+ * Styles for tooltip
242
+ */
243
+ .tooltip {
244
+ position: relative;
245
+ display: inline;
246
+ color: #03a84e;
247
+ }
248
+
249
+ .tooltip .tooltiptext {
250
+ visibility: hidden;
251
+ background-color: #545454;
252
+ color: #fff;
253
+ text-align: center;
254
+ padding: 0.5rem;
255
+ max-width: 300px;
256
+ border-radius: 0.5rem;
257
+ font-size: 0.7rem;
258
+ font-weight: 600;
259
+ line-height: 0.8;
260
+
261
+ /* Position the tooltip text - see examples below! */
262
+ position: absolute;
263
+ z-index: 1000;
264
+ top: 5px;
265
+ }
266
+
267
+ .tooltip .tooltiptext::before {
268
+ content: "";
269
+ display: block;
270
+ width: 0;
271
+ height: 0;
272
+ position: absolute;
273
+
274
+ border-left: 5px solid transparent;
275
+ border-right: 5px solid transparent;
276
+ border-bottom: 5px solid #545454;
277
+ top: -5px;
278
+ left: 5px;
279
  }
280
 
281
+ .tooltip:hover .tooltiptext {
282
+ visibility: visible;
283
  }
284
 
285
+ /**
286
+ * #.# Media Queries
287
+ *
288
+ * Mobile view
289
+ */
290
+
291
+ @media only screen and (max-width: 712px) {
292
+
293
+ /**
294
+ * #.# Settings Body
295
+ *
296
+ * Styles for the settings panel body container
297
+ */
298
+ #tawk-settings-body {
299
+ max-width: 712px;
300
+ width: 100%;
301
+ padding: 0 0 0 0;
302
+ }
303
+
304
+ /**
305
+ * #.# Tabs
306
+ *
307
+ * Styles for the tabs section in the settings panel
308
+ */
309
+ #tawk-tabs {
310
+ background-color: #fff;
311
+ min-width: 75px;
312
+ width: 100%;
313
+ border-bottom: 1px solid #ccc;
314
+ }
315
+ }
assets/js/tawk.admin.js CHANGED
@@ -1,75 +1,84 @@
1
- jQuery(function() {
2
- document.getElementById("defaultOpen").click();
3
 
4
- if (jQuery("#always_display").prop("checked")) {
5
- jQuery('.twk_selected_display').hide();
6
- jQuery('#show_onfrontpage').prop('disabled', true);
7
- jQuery('#show_oncategory').prop('disabled', true);
8
- jQuery('#show_ontagpage').prop('disabled', true);
9
- jQuery('#show_onarticlepages').prop('disabled', true);
10
- jQuery('#include_url').prop('disabled', true);
11
- } else {
12
- jQuery('.twk_selected_display').show();
13
- }
14
 
15
- jQuery("#always_display").change(function() {
16
- if (this.checked) {
17
- jQuery('.twk_selected_display').fadeOut();
18
- jQuery('#show_onfrontpage').prop('disabled', true);
19
- jQuery('#show_oncategory').prop('disabled', true);
20
- jQuery('#show_ontagpage').prop('disabled', true);
21
- jQuery('#show_onarticlepages').prop('disabled', true);
22
- jQuery('#include_url').prop('disabled', true);
23
- } else {
24
- jQuery('.twk_selected_display').fadeIn();
25
- jQuery('#show_onfrontpage').prop('disabled', false);
26
- jQuery('#show_oncategory').prop('disabled', false);
27
- jQuery('#show_ontagpage').prop('disabled', false);
28
- jQuery('#show_onarticlepages').prop('disabled', false);
29
- jQuery('#include_url').prop('disabled', false);
30
- }
31
- });
32
 
33
- jQuery("#exclude_url").change(function() {
34
- if (this.checked) {
35
- jQuery("#exlucded_urls_container").fadeIn();
36
- } else {
37
- jQuery("#exlucded_urls_container").fadeOut();
38
- }
39
- });
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
- if (jQuery("#include_url").prop("checked")) {
42
- jQuery("#included_urls_container").show();
43
- }
 
 
 
 
 
 
44
 
45
- jQuery("#include_url").change(function() {
46
- if (this.checked) {
47
- jQuery("#included_urls_container").fadeIn();
48
- } else {
49
- jQuery("#included_urls_container").fadeOut();
50
- }
51
- });
52
 
53
- if (jQuery("#exclude_url").prop("checked")) {
54
- jQuery("#exlucded_urls_container").fadeIn();
55
- }
56
- });
 
 
 
 
 
57
 
 
 
 
 
 
58
 
59
- function opentab(evt, tabName) {
60
- // Declare all variables
61
- var i, tabcontent, tablinks;
62
 
63
- tabcontent = document.getElementsByClassName("tawktabcontent");
64
- for (i = 0; i < tabcontent.length; i++) {
65
- tabcontent[i].style.display = "none";
66
- }
67
 
68
- tablinks = document.getElementsByClassName("tawktablinks");
69
- for (i = 0; i < tablinks.length; i++) {
70
- tablinks[i].className = tablinks[i].className.replace(" active", "");
71
- }
72
 
73
- document.getElementById(tabName).style.display = "block";
74
- evt.currentTarget.className += " active";
75
- }
 
1
+ 'use strict';
 
2
 
3
+ jQuery(
4
+ function() {
5
+ document.getElementById( 'account-settings-tab' ).click();
 
 
 
 
 
 
 
6
 
7
+ if ( jQuery( '#always-display' ).prop( 'checked' ) ) {
8
+ jQuery( '.tawk-selected-display' ).hide();
9
+ jQuery( '#show-onfrontpage' ).prop( 'disabled', true );
10
+ jQuery( '#show-oncategory' ).prop( 'disabled', true );
11
+ jQuery( '#show-ontagpage' ).prop( 'disabled', true );
12
+ jQuery( '#show-onarticlepages' ).prop( 'disabled', true );
13
+ jQuery( '#include-url' ).prop( 'disabled', true );
14
+ } else {
15
+ jQuery( '.tawk-selected-display' ).show();
16
+ }
 
 
 
 
 
 
 
17
 
18
+ jQuery( '#always-display' ).change(
19
+ function() {
20
+ if ( this.checked ) {
21
+ jQuery( '.tawk-selected-display' ).fadeOut();
22
+ jQuery( '#show-onfrontpage' ).prop( 'disabled', true );
23
+ jQuery( '#show-oncategory' ).prop( 'disabled', true );
24
+ jQuery( '#show-ontagpage' ).prop( 'disabled', true );
25
+ jQuery( '#show-onarticlepages' ).prop( 'disabled', true );
26
+ jQuery( '#include-url' ).prop( 'disabled', true );
27
+ } else {
28
+ jQuery( '.tawk-selected-display' ).fadeIn();
29
+ jQuery( '#show-onfrontpage' ).prop( 'disabled', false );
30
+ jQuery( '#show-oncategory' ).prop( 'disabled', false );
31
+ jQuery( '#show-ontagpage' ).prop( 'disabled', false );
32
+ jQuery( '#show-onarticlepages' ).prop( 'disabled', false );
33
+ jQuery( '#include-url' ).prop( 'disabled', false );
34
+ }
35
+ }
36
+ );
37
 
38
+ jQuery( '#exclude-url' ).change(
39
+ function() {
40
+ if ( this.checked ) {
41
+ jQuery( '#exlucded-urls-container' ).fadeIn();
42
+ } else {
43
+ jQuery( '#exlucded-urls-container' ).fadeOut();
44
+ }
45
+ }
46
+ );
47
 
48
+ if ( jQuery( '#include-url' ).prop( 'checked' ) ) {
49
+ jQuery( '#included-urls-container' ).show();
50
+ }
 
 
 
 
51
 
52
+ jQuery( '#include-url' ).change(
53
+ function() {
54
+ if ( this.checked ) {
55
+ jQuery( '#included-urls-container' ).fadeIn();
56
+ } else {
57
+ jQuery( '#included-urls-container' ).fadeOut();
58
+ }
59
+ }
60
+ );
61
 
62
+ if ( jQuery( '#exclude-url' ).prop( 'checked' ) ) {
63
+ jQuery( '#exlucded-urls-container' ).fadeIn();
64
+ }
65
+ }
66
+ );
67
 
68
+ function opentab( evt, tabName ) {
69
+ var i, tabcontent, tablinks;
 
70
 
71
+ tabcontent = document.getElementsByClassName( 'tawk-tab-content' );
72
+ for ( i = 0; i < tabcontent.length; i++ ) {
73
+ tabcontent[i].style.display = 'none';
74
+ }
75
 
76
+ tablinks = document.getElementsByClassName( 'tawk-tab-links' );
77
+ for ( i = 0; i < tablinks.length; i++ ) {
78
+ tablinks[i].className = tablinks[i].className.replace( ' active', '' );
79
+ }
80
 
81
+ document.getElementById( tabName ).style.display = 'block';
82
+
83
+ evt.currentTarget.className += ' active';
84
+ }
assets/js/tawk.selection.js CHANGED
@@ -1,84 +1,92 @@
1
- // variables
 
2
  var currentHost = window.location.protocol + '//' + window.location.host;
3
- var iframeUrl = tawk_selection_data.url.iframe + '&parentDomain=' + currentHost;
4
- var baseUrl = tawk_selection_data.url.base;
5
 
6
- jQuery('#tawkIframe').attr('src', iframeUrl);
7
 
8
- window.addEventListener('message', function (e) {
9
- if(e.origin === baseUrl) {
 
 
10
 
11
- if(e.data.action === 'setWidget') {
12
- setWidget(e);
13
- }
14
 
15
- if(e.data.action === 'removeWidget') {
16
- removeWidget(e);
17
- }
18
 
19
- if(e.data.action === 'reloadHeight') {
20
- reloadIframeHeight(e.data.height);
 
21
  }
22
  }
23
- });
24
 
25
- function setWidget (e) {
26
- const data = {
27
- pageId : e.data.pageId,
28
- widgetId : e.data.widgetId,
29
- nonce : tawk_selection_data.nonce.setWidget
30
  };
31
 
32
- jQuery.ajax({
33
- type : 'POST',
34
- url : ajaxurl + '?action=tawkto_setwidget',
35
- contentType : 'application/json',
36
- dataType : 'json',
37
- data : JSON.stringify(data),
38
- success : function (r) {
39
- if (!r.success) {
40
- return e.source.postMessage({action: 'setFail'}, baseUrl);
 
 
 
 
 
 
41
  }
42
- e.source.postMessage({action: 'setDone'}, baseUrl);
43
- },
44
- error : function () {
45
- e.source.postMessage({action: 'setFail'}, baseUrl);
46
  }
47
- });
48
  }
49
 
50
- function removeWidget (e) {
51
- const data = {
52
- nonce : tawk_selection_data.nonce.removeWidget
53
- }
54
 
55
- jQuery.ajax({
56
- type : 'POST',
57
- url : ajaxurl + '?action=tawkto_removewidget',
58
- contentType : 'application/json',
59
- dataType : 'json',
60
- data : JSON.stringify(data),
61
- success : function (r) {
62
- if (!r.success) {
63
- return e.source.postMessage({action: 'removeFail'}, baseUrl);
 
 
 
 
 
 
64
  }
65
- e.source.postMessage({action: 'removeDone'}, baseUrl);
66
- },
67
- error : function () {
68
- e.source.postMessage({action: 'removeFail'}, baseUrl);
69
  }
70
- });
71
  }
72
 
73
- function reloadIframeHeight(height) {
74
- if (!height) {
 
 
75
  return;
76
  }
77
-
78
- var iframe = jQuery('#tawkIframe');
79
- if (height === iframe.height()) {
80
  return;
81
  }
82
 
83
- iframe.height(height);
84
- }
1
+ 'use strict';
2
+
3
  var currentHost = window.location.protocol + '//' + window.location.host;
4
+ var iframeUrl = tawkSelectionData.url.iframe + '&parentDomain=' + currentHost;
5
+ var baseUrl = tawkSelectionData.url.base;
6
 
7
+ jQuery( '#tawk-iframe' ).attr( 'src', iframeUrl );
8
 
9
+ window.addEventListener(
10
+ 'message',
11
+ function( e ) {
12
+ if ( baseUrl === e.origin ) {
13
 
14
+ if ( 'setWidget' === e.data.action ) {
15
+ setWidget( e );
16
+ }
17
 
18
+ if ( 'removeWidget' === e.data.action ) {
19
+ removeWidget( e );
20
+ }
21
 
22
+ if ( 'reloadHeight' === e.data.action ) {
23
+ reloadIframeHeight( e.data.height );
24
+ }
25
  }
26
  }
27
+ );
28
 
29
+ function setWidget( e ) {
30
+ var data = {
31
+ pageId: e.data.pageId,
32
+ widgetId: e.data.widgetId,
33
+ nonce: tawkSelectionData.nonce.setWidget
34
  };
35
 
36
+ jQuery.ajax(
37
+ {
38
+ type: 'POST',
39
+ url: ajaxurl + '?action=tawkto_setwidget',
40
+ contentType: 'application/json',
41
+ dataType: 'json',
42
+ data: JSON.stringify( data ),
43
+ success: function( r ) {
44
+ if ( ! r.success ) {
45
+ return e.source.postMessage({ action: 'setFail' }, baseUrl );
46
+ }
47
+ e.source.postMessage({ action: 'setDone' }, baseUrl );
48
+ },
49
+ error: function() {
50
+ e.source.postMessage({ action: 'setFail' }, baseUrl );
51
  }
 
 
 
 
52
  }
53
+ );
54
  }
55
 
56
+ function removeWidget( e ) {
57
+ var data = {
58
+ nonce: tawkSelectionData.nonce.removeWidget
59
+ };
60
 
61
+ jQuery.ajax(
62
+ {
63
+ type: 'POST',
64
+ url: ajaxurl + '?action=tawkto_removewidget',
65
+ contentType: 'application/json',
66
+ dataType: 'json',
67
+ data: JSON.stringify( data ),
68
+ success: function( r ) {
69
+ if ( ! r.success ) {
70
+ return e.source.postMessage({ action: 'removeFail' }, baseUrl );
71
+ }
72
+ e.source.postMessage({ action: 'removeDone' }, baseUrl );
73
+ },
74
+ error: function() {
75
+ e.source.postMessage({ action: 'removeFail' }, baseUrl );
76
  }
 
 
 
 
77
  }
78
+ );
79
  }
80
 
81
+ function reloadIframeHeight( height ) {
82
+ var iframe = jQuery( '#tawk-iframe' );
83
+
84
+ if ( ! height ) {
85
  return;
86
  }
87
+ if ( height === iframe.height() ) {
 
 
88
  return;
89
  }
90
 
91
+ iframe.height( height );
92
+ }
index.php CHANGED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package Tawk.to Widget for WordPress
4
+ * @author Tawk.to
5
+ * @copyright (C) 2014- Tawk.to
6
+ * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
7
+ **/
readme.txt CHANGED
@@ -3,59 +3,76 @@ Contributors: tawkto
3
  Tags: tawk,tawk.to,tawkto,chat,free chat,livechat,chat widget,plugin,chat for web,chat online,chat software,free live chat,IM Chat,,live chat,live support,live web chat,online chat,online support,snapengage,wordpress chat,wordpress live chat
4
  Requires at least: 2.7
5
  Requires PHP: 5.6
6
- Tested up to: 5.8
7
- Stable tag: 0.6.0
8
 
9
  (OFFICIAL tawk.to plugin) Instantly chat with visitors on your website with the free tawk.to chat widget.
10
  Website: [http://tawk.to](http://tawk.to)
11
  == Description ==
12
 
13
- Over 3,800,000+ business users use the tawk.to FREE live chat app that lets you monitor and chat with visitors on your Wordpress site. No catch. No spam. No Ads. It's truly free and always will be.
 
14
 
15
- tawk.to is the #1 most widely used chat applicationin the world.
16
 
17
- * Gain valuable insight when you monitor your website visitors in real time.
18
- * Stay connected anywhere, be in touch with your customers from your computer, or your mobile.
19
- * Live Chat is convenient for your customers, helping them through pain points and as a result helping you generate better customer support and higher conversions.
 
 
 
 
20
 
21
  [youtube https://www.youtube.com/watch?v=G7o8x5gj2ww]
22
 
23
- tawk.to is designed to increase the effectiveness in managing the online customer engagement experience, enabling multiple websites and agents in a single dashboard interface to chat with the visitors on your website.
 
 
24
 
25
- Compatible with all modern browsers, tawk.to is free live chat software created out of the growing need for businesses to respond in real time, with real people.
26
 
27
- Tawk.to offers free iOS, Android, Windows and Mac OSX apps to stay connected, or you can log in via any modern browser.
28
 
29
  = Why use tawk.to? =
30
 
31
- tawk.to is a free live chat app which integrates seamlessly with Wordpress! More than 250000 companies use tawk.to to provide real time support and service to their customers. Never lose another lead or sale again, with tawk.to you can monitor and chat with your website visitors when they need it most.
 
 
 
 
 
 
32
 
33
  = How much does this cost? =
34
 
35
- This tawk.to app is completely free.
36
 
37
- To learn why tawk.to is free visit [https://www.tawk.to/why-free/](https://www.tawk.to/why-free/)
38
 
39
  = Support =
40
 
41
  tawk.to offers 24x7-365 live support, visit https://www.tawk.to and initiate a chat or send us an email at support@tawk.to.
42
 
43
- Don't have a tawk.to account ? [Create one for free here!](https://www.tawk.to/?utm_source=wpdirectory&utm_medium=link&utm_campaign=signup)
44
-
45
  == Installation ==
46
 
47
- Adding tawk.to live chat widget to your Wordpress site is really easy, follow these steps :
48
 
49
- * Clone this repository into your plugins directory or download the zip file and unzip on your plugins directory
50
- * or Install the Free plugin from the WordPress directory and activate it.
51
- * Go to `Settings`, then to the `Tawk.to` sub menu, and login to your tawk.to account to select a widget.
52
- * Customize the chat widget from within the [tawk.to dashboard](https://dashboard.tawk.to) to your preference.
 
 
53
  * Start chatting with your visitors! :)
54
 
55
- Note: You will need a free tawk.to account : [Create one for free here!](https://tawk.to/?utm_source=wpdirectory&utm_medium=link&utm_campaign=signup)
56
 
57
  == Changelog ==
58
 
 
 
 
 
59
  = 0.6.0 =
60
  * **Security Update** Add CSRF tokens and specific action access checks.
61
  * **Security Update** Use `application/json` content type for ajax requests.
@@ -194,6 +211,17 @@ Note: You will need a free tawk.to account : [Create one for free here!](https:/
194
  = 0.1.1 =
195
  * No more manual embed code copying, choose desired widget and it will be inserted in your site
196
 
 
 
 
 
 
 
 
 
 
 
 
197
  ## Frequently Asked Questions
198
 
199
  = How much does this cost? =
@@ -202,15 +230,15 @@ This tawk.to app is completely free.
202
 
203
  = Do you provide support? =
204
 
205
- Yes, we provide 24x7-365 real time support via both live chat and email. We never close.
206
 
207
  = Can I choose which pages to put the widget on? =
208
 
209
- Yes, you can use the visibility options in the Plugin settings to select specific pages, or you can show the tawk.to widget on any page independent of the visibility options by simply using the [tawkto] shortcode in the post or page.
210
 
211
- = Can I customize the widget design =
212
 
213
- Yes, you can customize colors, content, border radius, position etc. You can even select one of 27 different languages, add Attention Grabbing bubbles etc.
214
 
215
  = Can I schedule when the widget will be shown? =
216
 
@@ -218,9 +246,8 @@ Yes, there is a complete widget scheduler.
218
 
219
  = Do you have any documentation or support articles? =
220
 
221
- Yes, we have a very detailed Knowledge Base, which includes videos & tutorials on all the features of tawk.to [https://www.tawk.to/knowledgebase/](https://www.tawk.to/knowledgebase/)
222
 
223
  = Can multiple users chat at one time? =
224
 
225
- Yes, you can add an unlimited number of Agents to your account so that your entire team can chat with your website visitors. Tawk.to also has a Departments feature, to group your agents. Eg: Sales, Support etc.
226
-
3
  Tags: tawk,tawk.to,tawkto,chat,free chat,livechat,chat widget,plugin,chat for web,chat online,chat software,free live chat,IM Chat,,live chat,live support,live web chat,online chat,online support,snapengage,wordpress chat,wordpress live chat
4
  Requires at least: 2.7
5
  Requires PHP: 5.6
6
+ Tested up to: 5.9
7
+ Stable tag: 0.7.0
8
 
9
  (OFFICIAL tawk.to plugin) Instantly chat with visitors on your website with the free tawk.to chat widget.
10
  Website: [http://tawk.to](http://tawk.to)
11
  == Description ==
12
 
13
+ Free messaging app to monitor and chat with site visitors
14
+ = Gain insight =
15
 
16
+ Gain valuable insights when you monitor and chat with website visitors in real time.
17
 
18
+ = Increase conversions =
19
+
20
+ Greet new and returning visitors, help them through pain points, and message before they leave your page.
21
+
22
+ = Stay connected =
23
+
24
+ Stay connected anywhere and respond to your customers from your computer or mobile device.
25
 
26
  [youtube https://www.youtube.com/watch?v=G7o8x5gj2ww]
27
 
28
+ = About tawk.to Live Chat =
29
+
30
+ The tawk.to Live Chat app makes it easy to monitor and chat with visitors on all your WordPress websites. Be there when they need you with unlimited messaging, ticketing and your own Knowledge Base — all 100% FREE.
31
 
32
+ Compatible with all modern browsers, tawk.to was created in response to the growing need for businesses to respond in real time, with real people.
33
 
34
+ Never lose another lead or sale again — tawk.to offers iOS, Android, Windows and Mac OSX apps to keep you connected wherever you go.
35
 
36
  = Why use tawk.to? =
37
 
38
+ tawk.to’s live chat app integrates seamlessly with WordPress. More than 5 million companies use tawk.to to provide real time support and service to their customers.
39
+
40
+ * *Save time and simplify* — monitor and chat with visitors on multiple websites from a single dashboard interface
41
+ * *Personalize greetings and share promos* with Trigger messages based on your visitor’s location, past visits, page views, and more
42
+ * *Easily share answers to FAQs* and provide self-help to customers with your own Knowledge Base — included in your free account
43
+ * *Create and assign tickets* in a built-in support desk and ticketing system, making it easy to follow up and create outstanding customer experiences every time
44
+ * See our [full list of features](https://www.tawk.to/features/) to learn more
45
 
46
  = How much does this cost? =
47
 
48
+ tawk.to is completely free — there are no limits to the number of agents, chat volumes or sites you can add widgets to.
49
 
50
+ Don't have a tawk.to account? [Create one for free here!](https://www.tawk.to/?utm_source=wpdirectory&utm_medium=link&utm_campaign=signup)
51
 
52
  = Support =
53
 
54
  tawk.to offers 24x7-365 live support, visit https://www.tawk.to and initiate a chat or send us an email at support@tawk.to.
55
 
 
 
56
  == Installation ==
57
 
58
+ Adding tawk.to live chat widget to your WordPress site is easy.
59
 
60
+ Follow these steps:
61
+
62
+ * Clone this repository into your plugins directory, download the zip file and unzip in your plugins directory, or install the free plugin from the WordPress directory and activate it.
63
+ * Go to `Settings` and select `Tawk.to` in the submenu. Then, log in to your tawk.to account to select a widget.
64
+ * Choose your visibility options and click the Save Changes button to update the settings.
65
+ * Customize the widget to suit your business from the tawk.to Dashboard.
66
  * Start chatting with your visitors! :)
67
 
68
+ Note: You will need a free tawk.to account: [Create one for free here!](https://tawk.to/?utm_source=wpdirectory&utm_medium=link&utm_campaign=signup)
69
 
70
  == Changelog ==
71
 
72
+ = 0.7.0 =
73
+ * Enhanced URL pattern matching.
74
+ * Supported version bump 5.9.
75
+
76
  = 0.6.0 =
77
  * **Security Update** Add CSRF tokens and specific action access checks.
78
  * **Security Update** Use `application/json` content type for ajax requests.
211
  = 0.1.1 =
212
  * No more manual embed code copying, choose desired widget and it will be inserted in your site
213
 
214
+ == Upgrade Notice ==
215
+
216
+ = 0.7.0 =
217
+ We have released an update for the URL include/exclude feature of our plugin. You can now enter either full URLs or paths with wildcards using any of the following placements:
218
+
219
+ * start of the path (ex. */to/somewhere)
220
+ * middle of the path (ex. /path/*/somewhere)
221
+ * end of the path (ex. /path/to/somewhere)
222
+ * start AND middle of the path (ex. */lead/*/somewhere)
223
+ * middle AND end of the path (ex. /path/*/to/*)
224
+
225
  ## Frequently Asked Questions
226
 
227
  = How much does this cost? =
230
 
231
  = Do you provide support? =
232
 
233
+ Yes, we provide 24x7-365 real-time support via both live chat and email. We never close.
234
 
235
  = Can I choose which pages to put the widget on? =
236
 
237
+ Yes, you can use the visibility options in the Plugin settings to select specific pages, or you can show the tawk.to widget on any page independent of the visibility options by simply using the [tawkto] shortcode in the post or page.
238
 
239
+ = Can I customize the widget design? =
240
 
241
+ Yes, you can customize colors, content, border radius, position and more. Select any of 45+ different languages. You can even customize your widget with an Attention Grabber — an image designed to catch your visitor’s attention so they know you’re ready to chat.
242
 
243
  = Can I schedule when the widget will be shown? =
244
 
246
 
247
  = Do you have any documentation or support articles? =
248
 
249
+ Yes, we have a detailed [Help Center](https://help.tawk.to/) and [Academy](https://www.tawk.to/academy/introduction/), which include videos and tutorials on all the features of tawk.to.
250
 
251
  = Can multiple users chat at one time? =
252
 
253
+ Yes, you can add an unlimited number of Agents to your account so that your entire team can chat with your website visitors. tawk.to also enables you to create Departments for grouping your agents. E.g., Sales, Support, etc.
 
screenshot-1.png CHANGED
Binary file
screenshot-2.png CHANGED
Binary file
screenshot-3.png CHANGED
Binary file
screenshot-4.png ADDED
Binary file
screenshot-5.png ADDED
Binary file
screenshot-6.png ADDED
Binary file
tawkto.php CHANGED
@@ -1,171 +1,236 @@
1
  <?php
2
- /*
3
- Plugin Name: Tawk.to Live Chat
4
- Plugin URI: https://www.tawk.to
5
- Description: Embeds Tawk.to live chat widget to your site
6
- Version: 0.6.0
7
- Author: Tawkto
8
- Text Domain: tawk-to-live-chat
9
- */
10
- if(!class_exists('TawkTo_Settings')){
11
-
12
- class TawkTo_Settings{
13
- const TAWK_WIDGET_ID_VARIABLE = 'tawkto-embed-widget-widget-id';
14
- const TAWK_PAGE_ID_VARIABLE = 'tawkto-embed-widget-page-id';
15
- const TAWK_VISIBILITY_OPTIONS = 'tawkto-visibility-options';
16
- const TAWK_ACTION_SET_WIDGET = 'tawkto-set-widget';
 
 
 
 
 
 
 
 
 
 
 
17
  const TAWK_ACTION_REMOVE_WIDGET = 'tawkto-remove-widget';
18
 
19
- public function __construct(){
20
-
21
- if(!get_option('tawkto-visibility-options',false))
22
- {
23
- $visibility = array (
24
- 'always_display' => 1,
25
- 'show_onfrontpage' => 0,
26
- 'show_oncategory' => 0,
27
- 'show_ontagpage' => 0,
28
- 'show_onarticlepages' => 0,
29
- 'exclude_url' => 0,
30
- 'excluded_url_list' => '',
31
- 'include_url' => 0,
32
- 'included_url_list' => '',
33
- 'display_on_shop' => 0,
34
- 'display_on_productcategory' => 0,
35
- 'display_on_productpage' => 0,
36
- 'display_on_producttag' => 0,
37
- 'enable_visitor_recognition' => 1
38
- );
39
- update_option( 'tawkto-visibility-options', $visibility);
 
 
 
40
  }
41
 
42
- add_action('admin_init', array(&$this, 'admin_init'));
43
- add_action('admin_menu', array(&$this, 'add_menu'));
44
- add_action('wp_ajax_tawkto_setwidget', array(&$this, 'action_setwidget'));
45
- add_action('wp_ajax_tawkto_removewidget', array(&$this, 'action_removewidget'));
46
- #add_action('admin_head', array(&$this,'tawk_custom_admin_style') );
 
47
 
48
- add_action('admin_enqueue_scripts', array($this,'tawk_settings_assets') );
49
- add_action( 'admin_notices', array($this,'tawk_admin_notice') );
 
 
 
 
 
 
 
50
  }
51
 
52
- public function tawk_settings_assets($hook)
53
- {
54
- if($hook != 'settings_page_tawkto_plugin')
 
 
 
 
 
55
  return;
 
56
 
57
- wp_register_style( 'tawk_admin_style', plugins_url( 'assets/css/tawk.admin.css' , __FILE__ ) );
 
 
 
 
 
58
  wp_enqueue_style( 'tawk_admin_style' );
59
 
60
- wp_enqueue_script( 'tawk_admin_script', plugins_url( 'assets/js/tawk.admin.js' , __FILE__ ) );
 
 
 
 
 
 
61
 
62
  }
63
 
64
- public function admin_init(){
65
- register_setting( 'tawk_options', 'tawkto-visibility-options', array(&$this,'validate_options') );
 
 
 
 
 
66
  }
67
 
 
 
 
68
  public function action_setwidget() {
69
- header('Content-Type: application/json');
70
 
71
- if (wp_is_json_request() === false) {
72
  $response['success'] = false;
73
  $response['message'] = 'Invalid request';
74
- wp_send_json($response);
75
  wp_die();
76
  };
77
 
78
- $postData = json_decode(file_get_contents('php://input'), true);
79
 
80
  $response = array(
81
- 'success' => true
82
  );
83
 
84
- if ($this->validate_request_auth($postData, self::TAWK_ACTION_SET_WIDGET) === false) {
85
  $response['success'] = false;
86
  $response['message'] = 'Unauthorized';
87
- wp_send_json($response);
88
  wp_die();
89
  };
90
 
91
- if (!isset($postData['pageId']) || !isset($postData['widgetId'])) {
92
  $response['success'] = false;
93
- wp_send_json($response);
94
  wp_die();
95
  }
96
 
97
- if (!self::ids_are_correct($postData['pageId'], $postData['widgetId'])) {
98
  $response['success'] = false;
99
- wp_send_json($response);
100
  wp_die();
101
  }
102
 
103
- update_option(self::TAWK_PAGE_ID_VARIABLE, $postData['pageId']);
104
- update_option(self::TAWK_WIDGET_ID_VARIABLE, $postData['widgetId']);
105
 
106
- wp_send_json($response);
107
  wp_die();
108
  }
109
 
110
- function tawk_admin_notice() {
111
-
112
- if( isset($_GET["settings-updated"]) )
113
- {
 
 
114
  ?>
115
  <div class="notice notice-warning is-dismissible">
116
- <p><?php _e( 'You might need to clear cache if your using a cache plugin to see your updates', 'tawk-to-live-chat' ); ?></p>
117
  </div>
118
  <?php
119
  }
120
  }
121
 
 
 
 
122
  public function action_removewidget() {
123
- header('Content-Type: application/json');
124
 
125
- if (wp_is_json_request() === false) {
126
  $response['success'] = false;
127
  $response['message'] = 'Invalid request';
128
- wp_send_json($response);
129
  wp_die();
130
  };
131
 
132
- $postData = json_decode(file_get_contents('php://input'), true);
133
 
134
  $response = array(
135
- 'success' => true
136
  );
137
 
138
- if ($this->validate_request_auth($postData, self::TAWK_ACTION_REMOVE_WIDGET) === false) {
139
  $response['success'] = false;
140
  $response['message'] = 'Unauthorized';
141
- wp_send_json($response);
142
  wp_die();
143
  };
144
 
145
- update_option(self::TAWK_PAGE_ID_VARIABLE, '');
146
- update_option(self::TAWK_WIDGET_ID_VARIABLE, '');
147
 
148
- wp_send_json($response);
149
  wp_die();
150
  }
151
 
152
- private function validate_request_auth($postData = array(), $action) {
153
- if (current_user_can('administrator') === false) {
 
 
 
 
 
 
 
154
  return false;
155
  }
156
 
157
- if (isset($postData['nonce']) === false) {
158
  return false;
159
  }
160
 
161
- if (wp_verify_nonce($postData['nonce'], $action) === false) {
162
  return false;
163
  }
164
 
165
  return true;
166
  }
167
 
168
- public function validate_options($input){
 
 
 
 
 
 
169
  $visibility_toggle_fields = array(
170
  'always_display',
171
  'show_onfrontpage',
@@ -178,310 +243,405 @@ if(!class_exists('TawkTo_Settings')){
178
  'display_on_productcategory',
179
  'display_on_productpage',
180
  'display_on_producttag',
181
- 'enable_visitor_recognition'
182
  );
183
- $visibility_text_fields = array('excluded_url_list', 'included_url_list');
184
 
185
- self::validate_visibility_toggle_fields($input, $visibility_toggle_fields);
186
- self::validate_text_fields($input, $visibility_text_fields);
 
 
 
 
 
187
 
188
  return $input;
189
  }
190
 
191
- public function add_menu(){
 
 
 
192
  add_options_page(
193
- __('Tawk.to Settings','tawk-to-live-chat'),
194
- __('Tawk.to','tawk-to-live-chat'),
195
  'manage_options',
196
  'tawkto_plugin',
197
- array(&$this, 'create_plugin_settings_page')
198
  );
199
  }
200
 
201
- public function tawk_custom_admin_style(){
202
- echo '<style>
203
- .form-table th.tawksetting {
204
- width: 350px;
205
- }
206
- .tawknotice{
207
- font-size:14px;
208
- }
209
- </style>';
210
- }
211
-
212
- public function create_plugin_settings_page(){
213
-
214
  global $wpdb;
215
 
216
- if(!current_user_can('manage_options')) {
217
- wp_die(__('You do not have sufficient permissions to access this page.'));
218
  }
219
 
220
- $page_id = get_option(self::TAWK_PAGE_ID_VARIABLE);
221
- $widget_id = get_option(self::TAWK_WIDGET_ID_VARIABLE);
222
- $base_url = 'https://plugins.tawk.to';
223
 
224
- $iframe_url = $base_url.'/generic/widgets'
225
- .'?currentWidgetId='.$widget_id
226
- .'&currentPageId='.$page_id
227
- .'&transparentBackground=1'
228
- .'&pltf=wordpress';
229
- $set_widget_nonce = wp_create_nonce(self::TAWK_ACTION_SET_WIDGET);
230
- $remove_widget_nonce = wp_create_nonce(self::TAWK_ACTION_REMOVE_WIDGET);
231
 
 
 
 
232
 
233
- include(sprintf("%s/templates/settings.php", dirname(__FILE__)));
234
  }
235
 
236
- public static function ids_are_correct($page_id, $widget_id) {
237
- return preg_match('/^[0-9A-Fa-f]{24}$/', $page_id) === 1 && preg_match('/^[a-z0-9]{1,50}$/i', $widget_id) === 1;
 
 
 
 
 
 
 
 
238
  }
239
 
240
- private static function validate_text_fields(&$fields, $field_names) {
241
- foreach ($field_names as $field_name) {
242
- if (isset($fields[$field_name])) {
243
- $fields[$field_name] = sanitize_text_field($fields[$field_name]);
 
 
 
 
 
 
 
244
  continue;
245
  }
246
 
247
- $fields[$field_name] = '';
248
  }
249
-
250
- return;
251
  }
252
 
253
- private static function validate_visibility_toggle_fields(&$fields, $field_names) {
254
- foreach ($field_names as $field_name) {
255
- if (isset($fields[$field_name]) && $fields[$field_name] == '1') {
256
- $fields[$field_name] = 1;
 
 
 
 
 
 
 
257
  continue;
258
  }
259
 
260
- $fields[$field_name] = 0;
261
  }
262
-
263
- return;
264
  }
265
  }
266
  }
267
 
268
- if(!class_exists('TawkTo')){
269
- class TawkTo{
270
- public function __construct(){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  $tawkto_settings = new TawkTo_Settings();
272
- add_shortcode( 'tawkto', array($this,'shortcode_print_embed_code') );
 
273
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  }
275
 
276
- public static function activate(){
277
-
278
- $visibility = array (
279
- 'always_display' => 1,
280
- 'show_onfrontpage' => 0,
281
- 'show_oncategory' => 0,
282
- 'show_ontagpage' => 0,
283
- 'show_onarticlepages' => 0,
284
- 'exclude_url' => 0,
285
- 'excluded_url_list' => '',
286
- 'include_url' => 0,
287
- 'included_url_list' => '',
288
- 'display_on_shop' => 0,
 
 
 
 
289
  'display_on_productcategory' => 0,
290
- 'display_on_productpage' => 0,
291
- 'display_on_producttag' => 0,
292
- 'enable_visitor_recognition' => 1
293
  );
294
 
295
- add_option(TawkTo_Settings::TAWK_PAGE_ID_VARIABLE, '', '', 'yes');
296
- add_option(TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE, '', '', 'yes');
297
- add_option(TawkTo_Settings::TAWK_VISIBILITY_OPTIONS, $visibility, '', 'yes');
 
298
  }
299
 
300
- public static function deactivate(){
301
- delete_option(TawkTo_Settings::TAWK_PAGE_ID_VARIABLE);
302
- delete_option(TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE);
303
- delete_option(TawkTo_Settings::TAWK_VISIBILITY_OPTIONS);
 
 
 
 
304
  }
305
 
306
- public function shortcode_print_embed_code(){
307
- add_action('wp_footer', array($this, 'embed_code'),100);
 
 
 
308
  }
309
 
310
- public function getCurrentCustomerDetails () {
311
- if(is_user_logged_in() ){
 
 
 
 
 
312
  $current_user = wp_get_current_user();
313
- $user_info = array(
314
- 'name' => $current_user->display_name,
315
- 'email' => $current_user->user_email
316
  );
317
- return json_encode($user_info);
318
  }
319
- return NULL;
320
  }
321
 
 
 
 
322
  public function embed_code() {
323
- $page_id = get_option('tawkto-embed-widget-page-id');
324
- $widget_id = get_option('tawkto-embed-widget-widget-id');
325
- $visibility = get_option('tawkto-visibility-options');
326
 
327
- $enable_visitor_recognition = true; // default value
 
328
 
329
- if (isset($visibility) && isset($visibility['enable_visitor_recognition'])) {
330
- $enable_visitor_recognition = $visibility['enable_visitor_recognition'] == 1;
331
  }
332
 
333
- if ($enable_visitor_recognition) {
334
- $customer_details = $this->getCurrentCustomerDetails();
335
  }
336
 
337
- if (!empty($page_id) && !empty($widget_id)) {
338
- include(sprintf("%s/templates/widget.php", dirname(__FILE__)));
339
  }
340
  }
341
 
 
 
 
 
 
342
  private function get_current_url() {
343
- $current_url = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
344
- $current_url = urldecode($current_url);
345
 
346
- $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://';
 
 
 
347
 
348
- return strtolower($protocol . $current_url);
349
- }
 
350
 
351
- private function match_url($url, $url_pattern) {
352
- // do partial match if wildcard character matched at the end pattern
353
- if (substr($url_pattern, -1) === '*') {
354
- $url_pattern = substr($url_pattern, 0, -1);
355
 
356
- return (strpos($url, $url_pattern) === 0);
357
- }
358
 
359
- // do extact match if wildcard character not matched at the end pattern
360
- return (strcmp($url, $url_pattern) === 0);
361
  }
362
 
 
 
 
 
 
363
  public function print_embed_code() {
364
- $vsibility = get_option('tawkto-visibility-options');
365
- $display = false;
366
 
367
- if ($vsibility['always_display'] == 1) {
368
  $display = true;
369
  }
370
 
371
- if (($vsibility['show_onfrontpage'] == 1) && (is_home() || is_front_page())) {
372
  $display = true;
373
  }
374
 
375
- if (($vsibility['show_oncategory'] == 1) && is_category()) {
376
  $display = true;
377
  }
378
 
379
- if (($vsibility['show_ontagpage'] == 1) && is_tag()) {
380
  $display = true;
381
  }
382
 
383
- if (($vsibility['show_onarticlepages'] == 1) && is_single()) {
384
  $display = true;
385
  }
386
 
387
- if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
388
- if (($vsibility['display_on_shop'] == 1) && is_shop()) {
389
  $display = true;
390
  }
391
 
392
- if (($vsibility['display_on_productcategory'] == 1) && is_product_category()) {
393
  $display = true;
394
  }
395
 
396
- if (($vsibility['display_on_productpage'] == 1) && is_product()) {
397
  $display = true;
398
  }
399
 
400
- if (($vsibility['display_on_producttag'] == 1) && is_product_tag()) {
401
  $display = true;
402
  }
403
  }
404
 
405
- if (isset($vsibility['include_url']) && $vsibility['include_url'] == 1) {
406
  $current_url = $this->get_current_url();
407
 
408
  $included_url_list = $vsibility['included_url_list'];
409
- $included_url_list = preg_split("/,/", $included_url_list);
410
 
411
- foreach ($included_url_list as $include_url) {
412
- $include_url = strtolower(urldecode(trim($include_url)));
413
-
414
- if (!empty($include_url) && $this->match_url($current_url, $include_url)) {
415
- $display = true;
416
- }
417
  }
418
  }
419
 
420
- if (isset($vsibility['exclude_url']) && ($vsibility['exclude_url'] == 1)) {
421
  $current_url = $this->get_current_url();
422
 
423
  $excluded_url_list = $vsibility['excluded_url_list'];
424
- $excluded_url_list = preg_split("/,/", $excluded_url_list);
425
-
426
- foreach ($excluded_url_list as $exclude_url) {
427
- $exclude_url = strtolower(urldecode(trim($exclude_url)));
428
 
429
- if (!empty($exclude_url) && $this->match_url($current_url, $exclude_url)) {
430
- $display = false;
431
- }
432
- }
433
  }
434
 
435
- if ($display) {
436
  $this->embed_code();
437
  }
438
  }
439
 
440
  /**
441
- * migrate old tawk to embed code to new version.
442
  *
443
- * old version contained embed code script, from that
444
  * markup we need only page id and widget id
445
  */
446
  public function migrate_embed_code() {
 
447
 
448
- $old_tawkto_embed_code = get_option('tawkto-embed-code');
449
-
450
- if(empty($old_tawkto_embed_code)) {
451
  return;
452
  }
453
 
454
  $matches = array();
455
- preg_match('/https:\/\/embed.tawk.to\/([0-9A-Fa-f]{24})\/([a-z0-9]{1,50})/', $old_tawkto_embed_code, $matches);
456
 
457
- if(isset($matches[1]) && isset($matches[2]) && TawkTo_Settings::ids_are_correct($matches[1], $matches[2])) {
458
- update_option(TawkTo_Settings::TAWK_PAGE_ID_VARIABLE, $matches[1]);
459
- update_option(TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE, $matches[2]);
460
  }
461
 
462
- delete_option('tawkto-embed-code');
463
  }
464
  }
465
  }
466
 
467
- if(class_exists('TawkTo')){
468
- register_activation_hook(__FILE__, array('TawkTo', 'activate'));
469
- register_deactivation_hook(__FILE__, array('TawkTo', 'deactivate'));
470
 
471
  $tawkto = new TawkTo();
472
 
473
- if(isset($tawkto)){
 
 
 
 
 
 
 
474
  $tawkto->migrate_embed_code();
475
 
476
- function tawkto_plugin_settings_link($links){
 
 
 
 
 
 
477
  $settings_link = '<a href="options-general.php?page=tawkto_plugin">Settings</a>';
478
- array_unshift($links, $settings_link);
479
  return $links;
480
  }
481
 
482
- $plugin = plugin_basename(__FILE__);
483
- add_filter("plugin_action_links_$plugin", 'tawkto_plugin_settings_link');
484
  }
485
 
486
- add_action('wp_footer', array($tawkto, 'print_embed_code'));
487
  }
1
  <?php
2
+ /**
3
+ * @package Tawk.to Widget for WordPress
4
+ * @copyright (C) 2014- Tawk.to
5
+ * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
6
+ * Plugin Name: Tawk.to Live Chat
7
+ * Plugin URI: https://www.tawk.to
8
+ * Description: Embeds Tawk.to live chat widget to your site
9
+ * Version: 0.7.0
10
+ * Author: Tawkto
11
+ * Text Domain: tawk-to-live-chat
12
+ **/
13
+
14
+ require_once dirname( __FILE__ ) . '/vendor/autoload.php';
15
+ require_once dirname( __FILE__ ) . '/upgrade.manager.php';
16
+
17
+ use Tawk\Modules\UrlPatternMatcher;
18
+
19
+ if ( ! class_exists( 'TawkTo_Settings' ) ) {
20
+ /**
21
+ * Admin settings module for the tawk.to plugin
22
+ */
23
+ class TawkTo_Settings {
24
+ const TAWK_WIDGET_ID_VARIABLE = 'tawkto-embed-widget-widget-id';
25
+ const TAWK_PAGE_ID_VARIABLE = 'tawkto-embed-widget-page-id';
26
+ const TAWK_VISIBILITY_OPTIONS = 'tawkto-visibility-options';
27
+ const TAWK_ACTION_SET_WIDGET = 'tawkto-set-widget';
28
  const TAWK_ACTION_REMOVE_WIDGET = 'tawkto-remove-widget';
29
 
30
+ /**
31
+ * __construct
32
+ *
33
+ * @return void
34
+ */
35
+ public function __construct() {
36
+ if ( ! get_option( 'tawkto-visibility-options', false ) ) {
37
+ $visibility = array(
38
+ 'always_display' => 1,
39
+ 'show_onfrontpage' => 0,
40
+ 'show_oncategory' => 0,
41
+ 'show_ontagpage' => 0,
42
+ 'show_onarticlepages' => 0,
43
+ 'exclude_url' => 0,
44
+ 'excluded_url_list' => '',
45
+ 'include_url' => 0,
46
+ 'included_url_list' => '',
47
+ 'display_on_shop' => 0,
48
+ 'display_on_productcategory' => 0,
49
+ 'display_on_productpage' => 0,
50
+ 'display_on_producttag' => 0,
51
+ 'enable_visitor_recognition' => 1,
52
+ );
53
+ update_option( 'tawkto-visibility-options', $visibility );
54
  }
55
 
56
+ add_action( 'admin_init', array( &$this, 'admin_init' ) );
57
+ add_action( 'admin_menu', array( &$this, 'add_menu' ) );
58
+ add_action( 'wp_ajax_tawkto_setwidget', array( &$this, 'action_setwidget' ) );
59
+ add_action( 'wp_ajax_tawkto_removewidget', array( &$this, 'action_removewidget' ) );
60
+ add_action( 'admin_enqueue_scripts', array( $this, 'tawk_settings_assets' ) );
61
+ add_action( 'admin_notices', array( $this, 'tawk_admin_notice' ) );
62
 
63
+ if ( is_admin() ) {
64
+ if ( false === function_exists( 'get_plugin_data' ) ) {
65
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
66
+ }
67
+
68
+ $plugin_data = get_plugin_data( __FILE__ );
69
+
70
+ $this->plugin_ver = $plugin_data['Version'];
71
+ }
72
  }
73
 
74
+ /**
75
+ * Retrieves tawk.to admin settings assets
76
+ *
77
+ * @param string $hook - hook name.
78
+ * @return void
79
+ */
80
+ public function tawk_settings_assets( $hook ) {
81
+ if ( 'settings_page_tawkto_plugin' !== $hook ) {
82
  return;
83
+ }
84
 
85
+ wp_register_style(
86
+ 'tawk_admin_style',
87
+ plugins_url( 'assets/css/tawk.admin.css', __FILE__ ),
88
+ array(),
89
+ $this->plugin_ver
90
+ );
91
  wp_enqueue_style( 'tawk_admin_style' );
92
 
93
+ wp_enqueue_script(
94
+ 'tawk_admin_script',
95
+ plugins_url( 'assets/js/tawk.admin.js', __FILE__ ),
96
+ array(),
97
+ $this->plugin_ver,
98
+ true
99
+ );
100
 
101
  }
102
 
103
+ /**
104
+ * Initialize plugin settings
105
+ *
106
+ * @return void
107
+ */
108
+ public function admin_init() {
109
+ register_setting( 'tawk_options', 'tawkto-visibility-options', array( &$this, 'validate_options' ) );
110
  }
111
 
112
+ /**
113
+ * Saves the selected property and widget to the database.
114
+ */
115
  public function action_setwidget() {
116
+ header( 'Content-Type: application/json' );
117
 
118
+ if ( false === wp_is_json_request() ) {
119
  $response['success'] = false;
120
  $response['message'] = 'Invalid request';
121
+ wp_send_json( $response );
122
  wp_die();
123
  };
124
 
125
+ $post_data = json_decode( file_get_contents( 'php://input' ), true );
126
 
127
  $response = array(
128
+ 'success' => true,
129
  );
130
 
131
+ if ( false === $this->validate_request_auth( self::TAWK_ACTION_SET_WIDGET, $post_data ) ) {
132
  $response['success'] = false;
133
  $response['message'] = 'Unauthorized';
134
+ wp_send_json( $response );
135
  wp_die();
136
  };
137
 
138
+ if ( ! isset( $post_data['pageId'] ) || ! isset( $post_data['widgetId'] ) ) {
139
  $response['success'] = false;
140
+ wp_send_json( $response );
141
  wp_die();
142
  }
143
 
144
+ if ( ! self::ids_are_correct( $post_data['pageId'], $post_data['widgetId'] ) ) {
145
  $response['success'] = false;
146
+ wp_send_json( $response );
147
  wp_die();
148
  }
149
 
150
+ update_option( self::TAWK_PAGE_ID_VARIABLE, $post_data['pageId'] );
151
+ update_option( self::TAWK_WIDGET_ID_VARIABLE, $post_data['widgetId'] );
152
 
153
+ wp_send_json( $response );
154
  wp_die();
155
  }
156
 
157
+ /**
158
+ * Plugin notice for tawk.to
159
+ */
160
+ public function tawk_admin_notice() {
161
+ $settings_updated = filter_input( INPUT_GET, 'settings-updated', FILTER_VALIDATE_BOOLEAN );
162
+ if ( true === $settings_updated ) {
163
  ?>
164
  <div class="notice notice-warning is-dismissible">
165
+ <p><?php esc_html_e( 'You might need to clear cache if your using a cache plugin to see your updates', 'tawk-to-live-chat' ); ?></p>
166
  </div>
167
  <?php
168
  }
169
  }
170
 
171
+ /**
172
+ * Removes the selected property and widget from the database.
173
+ */
174
  public function action_removewidget() {
175
+ header( 'Content-Type: application/json' );
176
 
177
+ if ( false === wp_is_json_request() ) {
178
  $response['success'] = false;
179
  $response['message'] = 'Invalid request';
180
+ wp_send_json( $response );
181
  wp_die();
182
  };
183
 
184
+ $post_data = json_decode( file_get_contents( 'php://input' ), true );
185
 
186
  $response = array(
187
+ 'success' => true,
188
  );
189
 
190
+ if ( false === $this->validate_request_auth( self::TAWK_ACTION_REMOVE_WIDGET, $post_data ) ) {
191
  $response['success'] = false;
192
  $response['message'] = 'Unauthorized';
193
+ wp_send_json( $response );
194
  wp_die();
195
  };
196
 
197
+ update_option( self::TAWK_PAGE_ID_VARIABLE, '' );
198
+ update_option( self::TAWK_WIDGET_ID_VARIABLE, '' );
199
 
200
+ wp_send_json( $response );
201
  wp_die();
202
  }
203
 
204
+ /**
205
+ * Validates action requests auth
206
+ *
207
+ * @param string $action - Action to be done.
208
+ * @param array $post_data - Parsed JSON payload for the action.
209
+ * @return boolean
210
+ */
211
+ private function validate_request_auth( $action, $post_data = array() ) {
212
+ if ( false === current_user_can( 'administrator' ) ) {
213
  return false;
214
  }
215
 
216
+ if ( false === isset( $post_data['nonce'] ) ) {
217
  return false;
218
  }
219
 
220
+ if ( false === wp_verify_nonce( $post_data['nonce'], $action ) ) {
221
  return false;
222
  }
223
 
224
  return true;
225
  }
226
 
227
+ /**
228
+ * Validates the selected visibility options
229
+ *
230
+ * @param array $input - Visibility option fields.
231
+ * @return boolean
232
+ */
233
+ public function validate_options( $input ) {
234
  $visibility_toggle_fields = array(
235
  'always_display',
236
  'show_onfrontpage',
243
  'display_on_productcategory',
244
  'display_on_productpage',
245
  'display_on_producttag',
246
+ 'enable_visitor_recognition',
247
  );
 
248
 
249
+ $visibility_text_fields = array(
250
+ 'excluded_url_list',
251
+ 'included_url_list',
252
+ );
253
+
254
+ self::validate_visibility_toggle_fields( $input, $visibility_toggle_fields );
255
+ self::validate_text_fields( $input, $visibility_text_fields );
256
 
257
  return $input;
258
  }
259
 
260
+ /**
261
+ * Adds the tawk.to plugin settings in the admin menu.
262
+ */
263
+ public function add_menu() {
264
  add_options_page(
265
+ __( 'Tawk.to Settings', 'tawk-to-live-chat' ),
266
+ __( 'Tawk.to', 'tawk-to-live-chat' ),
267
  'manage_options',
268
  'tawkto_plugin',
269
+ array( &$this, 'create_plugin_settings_page' )
270
  );
271
  }
272
 
273
+ /**
274
+ * Initializes the plugin settings page.
275
+ */
276
+ public function create_plugin_settings_page() {
 
 
 
 
 
 
 
 
 
277
  global $wpdb;
278
 
279
+ if ( ! current_user_can( 'manage_options' ) ) {
280
+ wp_die( esc_html_e( 'You do not have sufficient permissions to access this page.' ) );
281
  }
282
 
283
+ $page_id = get_option( self::TAWK_PAGE_ID_VARIABLE );
284
+ $widget_id = get_option( self::TAWK_WIDGET_ID_VARIABLE );
285
+ $base_url = 'https://plugins.tawk.to';
286
 
287
+ $iframe_url = $base_url . '/generic/widgets'
288
+ . '?currentWidgetId=' . $widget_id
289
+ . '&currentPageId=' . $page_id
290
+ . '&transparentBackground=1'
291
+ . '&pltf=WordPress';
 
 
292
 
293
+ $set_widget_nonce = wp_create_nonce( self::TAWK_ACTION_SET_WIDGET );
294
+ $remove_widget_nonce = wp_create_nonce( self::TAWK_ACTION_REMOVE_WIDGET );
295
+ $plugin_ver = $this->plugin_ver;
296
 
297
+ include sprintf( '%s/templates/settings.php', dirname( __FILE__ ) );
298
  }
299
 
300
+
301
+ /**
302
+ * Verifies if the provided property and widget ids are correct.
303
+ *
304
+ * @param string $page_id - Property Id.
305
+ * @param string $widget_id - Widget Id.
306
+ * @return boolean
307
+ */
308
+ public static function ids_are_correct( $page_id, $widget_id ) {
309
+ return 1 === preg_match( '/^[0-9A-Fa-f]{24}$/', $page_id ) && 1 === preg_match( '/^[a-z0-9]{1,50}$/i', $widget_id );
310
  }
311
 
312
+ /**
313
+ * Validates and sanitizes text fields
314
+ *
315
+ * @param array $fields - List of fields.
316
+ * @param array $field_names - List of field names to be validated.
317
+ * @return void
318
+ */
319
+ private static function validate_text_fields( &$fields, $field_names ) {
320
+ foreach ( $field_names as $field_name ) {
321
+ if ( isset( $fields[ $field_name ] ) ) {
322
+ $fields[ $field_name ] = sanitize_text_field( $fields[ $field_name ] );
323
  continue;
324
  }
325
 
326
+ $fields[ $field_name ] = '';
327
  }
 
 
328
  }
329
 
330
+ /**
331
+ * Validates and sanitizes visibility toggle fields
332
+ *
333
+ * @param array $fields - List of fields.
334
+ * @param array $field_names - List of field names to be validated.
335
+ * @return void
336
+ */
337
+ private static function validate_visibility_toggle_fields( &$fields, $field_names ) {
338
+ foreach ( $field_names as $field_name ) {
339
+ if ( isset( $fields[ $field_name ] ) && '1' === $fields[ $field_name ] ) {
340
+ $fields[ $field_name ] = 1;
341
  continue;
342
  }
343
 
344
+ $fields[ $field_name ] = 0;
345
  }
 
 
346
  }
347
  }
348
  }
349
 
350
+ if ( ! class_exists( 'TawkTo' ) ) {
351
+
352
+ $plugin_file_data = get_file_data(
353
+ __FILE__,
354
+ array(
355
+ 'Version' => 'Version',
356
+ ),
357
+ 'plugin'
358
+ );
359
+
360
+ /**
361
+ * Main tawk.to module
362
+ */
363
+ class TawkTo {
364
+ const PLUGIN_VERSION_VARIABLE = 'tawkto-version';
365
+
366
+ /**
367
+ * @var $plugin_version Plugin version
368
+ */
369
+ private static $plugin_version;
370
+
371
+ /**
372
+ * __construct
373
+ *
374
+ * @return void
375
+ */
376
+ public function __construct() {
377
  $tawkto_settings = new TawkTo_Settings();
378
+ add_shortcode( 'tawkto', array( $this, 'shortcode_print_embed_code' ) );
379
+ }
380
 
381
+ /**
382
+ * Retrieves plugin version
383
+ *
384
+ * @return string plugin version
385
+ */
386
+ public static function get_plugin_version() {
387
+ if ( false === isset( self::$plugin_version ) ) {
388
+ $plugin_file_data = get_file_data(
389
+ __FILE__,
390
+ array(
391
+ 'Version' => 'Version',
392
+ ),
393
+ 'plugin'
394
+ );
395
+
396
+ self::$plugin_version = $plugin_file_data['Version'];
397
+ }
398
+
399
+ return self::$plugin_version;
400
  }
401
 
402
+ /**
403
+ * Initializes plugin data on activation.
404
+ */
405
+ public static function activate() {
406
+ global $plugin_file_data;
407
+
408
+ $visibility = array(
409
+ 'always_display' => 1,
410
+ 'show_onfrontpage' => 0,
411
+ 'show_oncategory' => 0,
412
+ 'show_ontagpage' => 0,
413
+ 'show_onarticlepages' => 0,
414
+ 'exclude_url' => 0,
415
+ 'excluded_url_list' => '',
416
+ 'include_url' => 0,
417
+ 'included_url_list' => '',
418
+ 'display_on_shop' => 0,
419
  'display_on_productcategory' => 0,
420
+ 'display_on_productpage' => 0,
421
+ 'display_on_producttag' => 0,
422
+ 'enable_visitor_recognition' => 1,
423
  );
424
 
425
+ add_option( TawkTo_Settings::TAWK_PAGE_ID_VARIABLE, '', '', 'yes' );
426
+ add_option( TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE, '', '', 'yes' );
427
+ add_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS, $visibility, '', 'yes' );
428
+ add_option( self::PLUGIN_VERSION_VARIABLE, self::get_plugin_version(), '', 'yes' );
429
  }
430
 
431
+ /**
432
+ * Cleans up plugin data on deactivation
433
+ */
434
+ public static function deactivate() {
435
+ delete_option( TawkTo_Settings::TAWK_PAGE_ID_VARIABLE );
436
+ delete_option( TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE );
437
+ delete_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS );
438
+ delete_option( self::PLUGIN_VERSION_VARIABLE );
439
  }
440
 
441
+ /**
442
+ * Shortcode for tawk.to to inject the embed code.
443
+ */
444
+ public function shortcode_print_embed_code() {
445
+ add_action( 'wp_footer', array( $this, 'embed_code' ), 100 );
446
  }
447
 
448
+ /**
449
+ * Retrieves customer details
450
+ *
451
+ * @return array - Customer details
452
+ */
453
+ public function get_current_customer_details() {
454
+ if ( is_user_logged_in() ) {
455
  $current_user = wp_get_current_user();
456
+ $user_info = array(
457
+ 'name' => $current_user->display_name,
458
+ 'email' => $current_user->user_email,
459
  );
460
+ return wp_json_encode( $user_info );
461
  }
462
+ return null;
463
  }
464
 
465
+ /**
466
+ * Creates the embed code
467
+ */
468
  public function embed_code() {
469
+ $page_id = get_option( 'tawkto-embed-widget-page-id' );
470
+ $widget_id = get_option( 'tawkto-embed-widget-widget-id' );
471
+ $visibility = get_option( 'tawkto-visibility-options' );
472
 
473
+ // default value.
474
+ $enable_visitor_recognition = true;
475
 
476
+ if ( isset( $visibility ) && isset( $visibility['enable_visitor_recognition'] ) ) {
477
+ $enable_visitor_recognition = 1 === $visibility['enable_visitor_recognition'];
478
  }
479
 
480
+ if ( $enable_visitor_recognition ) {
481
+ $customer_details = $this->get_current_customer_details();
482
  }
483
 
484
+ if ( ! empty( $page_id ) && ! empty( $widget_id ) ) {
485
+ include sprintf( '%s/templates/widget.php', dirname( __FILE__ ) );
486
  }
487
  }
488
 
489
+ /**
490
+ * Retrieves current URL
491
+ *
492
+ * @return string
493
+ */
494
  private function get_current_url() {
495
+ $http_host = '';
496
+ $request_uri = '';
497
 
498
+ // sanitize and remove backslashes.
499
+ if ( true === isset( $_SERVER['HTTP_HOST'] ) ) {
500
+ $http_host = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) );
501
+ }
502
 
503
+ if ( true === isset( $_SERVER['REQUEST_URI'] ) ) {
504
+ $request_uri = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
505
+ }
506
 
507
+ $current_url = urldecode( $http_host . $request_uri );
 
 
 
508
 
509
+ $protocol = ( ! empty( $_SERVER['HTTPS'] ) && 'on' === $_SERVER['HTTPS'] ) ? 'https://' : 'http://';
 
510
 
511
+ return strtolower( $protocol . $current_url );
 
512
  }
513
 
514
+ /**
515
+ * Prints the embed code when it is allowed to be displayed.
516
+ *
517
+ * @return void
518
+ */
519
  public function print_embed_code() {
520
+ $vsibility = get_option( 'tawkto-visibility-options' );
521
+ $display = false;
522
 
523
+ if ( 1 === $vsibility['always_display'] ) {
524
  $display = true;
525
  }
526
 
527
+ if ( ( 1 === $vsibility['show_onfrontpage'] ) && ( is_home() || is_front_page() ) ) {
528
  $display = true;
529
  }
530
 
531
+ if ( ( 1 === $vsibility['show_oncategory'] ) && is_category() ) {
532
  $display = true;
533
  }
534
 
535
+ if ( ( 1 === $vsibility['show_ontagpage'] ) && is_tag() ) {
536
  $display = true;
537
  }
538
 
539
+ if ( ( 1 === $vsibility['show_onarticlepages'] ) && is_single() ) {
540
  $display = true;
541
  }
542
 
543
+ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ), true ) ) {
544
+ if ( ( 1 === $vsibility['display_on_shop'] ) && is_shop() ) {
545
  $display = true;
546
  }
547
 
548
+ if ( ( 1 === $vsibility['display_on_productcategory'] ) && is_product_category() ) {
549
  $display = true;
550
  }
551
 
552
+ if ( ( 1 === $vsibility['display_on_productpage'] ) && is_product() ) {
553
  $display = true;
554
  }
555
 
556
+ if ( ( 1 === $vsibility['display_on_producttag'] ) && is_product_tag() ) {
557
  $display = true;
558
  }
559
  }
560
 
561
+ if ( isset( $vsibility['include_url'] ) && 1 === $vsibility['include_url'] ) {
562
  $current_url = $this->get_current_url();
563
 
564
  $included_url_list = $vsibility['included_url_list'];
565
+ $included_url_list = array_map( 'trim', preg_split( '/,/', $included_url_list ) );
566
 
567
+ if ( UrlPatternMatcher::match( $current_url, $included_url_list ) ) {
568
+ $display = true;
 
 
 
 
569
  }
570
  }
571
 
572
+ if ( isset( $vsibility['exclude_url'] ) && ( 1 === $vsibility['exclude_url'] ) ) {
573
  $current_url = $this->get_current_url();
574
 
575
  $excluded_url_list = $vsibility['excluded_url_list'];
576
+ $excluded_url_list = array_map( 'trim', preg_split( '/,/', $excluded_url_list ) );
 
 
 
577
 
578
+ if ( UrlPatternMatcher::match( $current_url, $excluded_url_list ) ) {
579
+ $display = false;
580
+ };
 
581
  }
582
 
583
+ if ( $display ) {
584
  $this->embed_code();
585
  }
586
  }
587
 
588
  /**
589
+ * Migrate old tawk to embed code to new version.
590
  *
591
+ * Old version contained embed code script, from that
592
  * markup we need only page id and widget id
593
  */
594
  public function migrate_embed_code() {
595
+ $old_tawkto_embed_code = get_option( 'tawkto-embed-code' );
596
 
597
+ if ( empty( $old_tawkto_embed_code ) ) {
 
 
598
  return;
599
  }
600
 
601
  $matches = array();
602
+ preg_match( '/https:\/\/embed.tawk.to\/([0-9A-Fa-f]{24})\/([a-z0-9]{1,50})/', $old_tawkto_embed_code, $matches );
603
 
604
+ if ( isset( $matches[1] ) && isset( $matches[2] ) && TawkTo_Settings::ids_are_correct( $matches[1], $matches[2] ) ) {
605
+ update_option( TawkTo_Settings::TAWK_PAGE_ID_VARIABLE, $matches[1] );
606
+ update_option( TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE, $matches[2] );
607
  }
608
 
609
+ delete_option( 'tawkto-embed-code' );
610
  }
611
  }
612
  }
613
 
614
+ if ( class_exists( 'TawkTo' ) ) {
615
+ register_activation_hook( __FILE__, array( 'TawkTo', 'activate' ) );
616
+ register_deactivation_hook( __FILE__, array( 'TawkTo', 'deactivate' ) );
617
 
618
  $tawkto = new TawkTo();
619
 
620
+ $upgrade_manager = new TawkToUpgradeManager(
621
+ TawkTo::get_plugin_version(),
622
+ TawkTo::PLUGIN_VERSION_VARIABLE
623
+ );
624
+ $upgrade_manager->register_hooks();
625
+
626
+ if ( isset( $tawkto ) ) {
627
+ // these are called every page load.
628
  $tawkto->migrate_embed_code();
629
 
630
+ /**
631
+ * Adds plugin settings link
632
+ *
633
+ * @param array $links - List of links from WordPress admin.
634
+ * @return array Updated list of links
635
+ */
636
+ function tawkto_plugin_settings_link( $links ) {
637
  $settings_link = '<a href="options-general.php?page=tawkto_plugin">Settings</a>';
638
+ array_unshift( $links, $settings_link );
639
  return $links;
640
  }
641
 
642
+ $plugin_base_name = plugin_basename( __FILE__ );
643
+ add_filter( 'plugin_action_links_' . $plugin_base_name, 'tawkto_plugin_settings_link' );
644
  }
645
 
646
+ add_action( 'wp_footer', array( $tawkto, 'print_embed_code' ) );
647
  }
templates/settings.php CHANGED
@@ -1,286 +1,461 @@
1
  <?php
2
-
3
  /**
4
- * @package Tawk.to Widget for Wordpress
5
  * @author Tawk.to
6
  * @copyright (C) 2014- Tawk.to
7
  * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
8
- **/
 
9
  if ( ! defined( 'ABSPATH' ) ) {
10
- exit; // Exit if accessed directly
 
11
  }
 
 
 
 
 
 
 
 
12
  ?>
13
 
14
- <div class="tawkheader">
15
- <div class="tawkmel">
16
- <img src="<?php echo plugins_url( 'assets/tawky_big.png' , dirname(__FILE__) ) ?>">
17
- </div>
18
- <div class="tawkheadtext">
19
- <?php _e('tawk.to Plugin Settings','tawk-to-live-chat'); ?>
20
- </div>
21
  </div>
22
- <div class="tawkaction">
23
- <?php submit_button(); ?>
 
 
 
 
 
 
 
 
 
 
 
24
  </div>
25
- <div class="tawksettingsbody">
26
- <div class="tawktabs">
27
- <button class="tawktablinks" onclick="opentab(event, 'account')" id="defaultOpen">Account Settings</button>
28
- <button class="tawktablinks" onclick="opentab(event, 'visibility')">Visibility Options</button>
29
- <button class="tawktablinks" onclick="opentab(event, 'privacy')">Privacy Options</button>
30
- <?php
31
- if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) )
32
- {
33
- ?>
34
- <button class="tawktablinks" onclick="opentab(event, 'woocommerce')">Woocomerce Options</button>
35
- <?php } ?>
36
- </div>
37
 
38
- <div id="account" class="tawktabcontent" >
39
- <?php
40
- $page_id = get_option(self::TAWK_PAGE_ID_VARIABLE);
41
- $widget_id = get_option(self::TAWK_WIDGET_ID_VARIABLE);
42
- if(isset($_GET["override"]) && $_GET["override"] == 1){
43
- $override = TRUE;
44
- }else{
45
- $override = false;
46
- }
47
- $display_widgetsettings = false;
48
- if(($page_id == NULL) || ($widget_id == NULL)){
49
- $display_widgetsettings = true;
50
- }
51
- if($override == TRUE){
52
- $display_widgetsettings = true;
53
- }
54
- if ($display_widgetsettings == TRUE){
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
- wp_enqueue_script('tawk-selection', plugin_dir_url(__DIR__).'assets/js/tawk.selection.js');
57
- wp_localize_script('tawk-selection', 'tawk_selection_data', array(
58
- 'url' => array(
59
- 'base' => $base_url,
60
- 'iframe' => $iframe_url,
61
- ),
62
- 'nonce' => array(
63
- 'setWidget' => $set_widget_nonce,
64
- 'removeWidget' => $remove_widget_nonce
65
- )
66
- ));
67
- ?>
68
- <iframe
69
- id="tawkIframe"
70
- src=""
71
- style="min-height: 295px; width : 100%; border: none; margin-top: 20px">
72
- </iframe>
73
- <?php
74
- }else{
75
- echo "<h2>Property and widget is already set.</h2>";
76
- $tawk_admin_url = admin_url('options-general.php?page=tawkto_plugin&override=1');
77
- echo 'if you wish to reselect property or widget <a href="'.$tawk_admin_url.'">click here</a>';
78
- }
79
- ?>
80
- </div>
81
- </div>
82
- <form method="post" action="options.php">
83
- <?php
84
- settings_fields( 'tawk_options' );
85
- do_settings_sections( 'tawk_options' );
86
 
87
- $visibility = get_option( 'tawkto-visibility-options',FALSE );
88
- if($visibility == FALSE){
89
- $visibility = array (
90
- 'always_display' => 1,
91
- 'show_onfrontpage' => 0,
92
- 'show_oncategory' => 0,
93
- 'show_ontagpage' => 0,
94
- 'show_onarticlepages' => 0,
95
- 'exclude_url' => 0,
96
- 'excluded_url_list' => '',
97
- 'include_url' => 0,
98
- 'included_url_list' => '',
99
- 'display_on_shop' => 0,
100
- 'display_on_productcategory' => 0,
101
- 'display_on_productpage' => 0,
102
- 'display_on_producttag' => 0,
103
- 'enable_visitor_recognition' => 1
104
- );
105
- }
106
 
107
- if (!isset($visibility['enable_visitor_recognition'])) {
108
- $visibility['enable_visitor_recognition'] = 1; // default value
109
- }
110
- ?>
111
- <div id="visibility" class="tawktabcontent">
112
- <div id="tawkvisibilitysettings">
113
- <h2><?php _e('Visibility Options','tawk-to-live-chat'); ?></h2>
114
- <p class='tawknotice'>
115
- <?php _e('Please Note: that you can use the visibility options below, or you can show the tawk.to widget','tawk-to-live-chat'); ?>
116
- <BR>
117
- <?php _e('on any page independent of these visibility options by simply using the <b>[tawkto]</b> shortcode in','tawk-to-live-chat'); ?>
118
- <BR>
119
- <?php _e('the post or page.','tawk-to-live-chat'); ?>
120
- </p>
121
- <table class="form-table">
122
- <tr valign="top">
123
- <th class="tawksetting" scope="row"><?php _e('Always show Tawk.To widget on every page','tawk-to-live-chat'); ?></th>
124
- <td>
125
- <label class="switch">
126
- <input type="checkbox" class="slider round" id="always_display" name="tawkto-visibility-options[always_display]" value="1" <?php echo checked( 1, $visibility['always_display'], false ); ?> />
127
- <div class="slider round"></div>
128
- </label>
129
- </td>
130
- </tr>
131
- <tr valign="top" class="twk_selected_display">
132
- <th class="tawksetting" scope="row"><?php _e('Show on front page','tawk-to-live-chat'); ?></th>
133
- <td>
134
- <label class="switch">
135
- <input type="checkbox" class="slider round" id="show_onfrontpage" name="tawkto-visibility-options[show_onfrontpage]" value="1" <?php echo checked( 1, $visibility['show_onfrontpage'], false ); ?> />
136
- <div class="slider round"></div>
137
- </label>
138
- </td>
139
- </tr>
140
- <tr valign="top" class="twk_selected_display">
141
- <th class="tawksetting" scope="row"><?php _e('Show on Category pages','tawk-to-live-chat'); ?></th>
142
- <td>
143
- <label class="switch">
144
- <input type="checkbox" class="slider round" id="show_oncategory" name="tawkto-visibility-options[show_oncategory]" value="1" <?php echo checked( 1, $visibility['show_oncategory'], false ); ?> />
145
- <div class="slider round"></div>
146
- </label>
147
- </td>
148
- </tr>
149
- <tr valign="top" class="twk_selected_display">
150
- <th class="tawksetting" scope="row"><?php _e('Show on Tag pages','tawk-to-live-chat'); ?></th>
151
- <td>
152
- <label class="switch">
153
- <input type="checkbox" class="slider round" id="show_ontagpage" name="tawkto-visibility-options[show_ontagpage]" value="1" <?php echo checked( 1, $visibility['show_ontagpage'], false ); ?> />
154
- <div class="slider round"></div>
155
- </label>
156
- </td>
157
- </tr>
158
- <tr valign="top" class="twk_selected_display">
159
- <th class="tawksetting" scope="row"><?php _e('Show on Single Post Pages','tawk-to-live-chat'); ?></th>
160
- <td>
161
- <label class="switch">
162
- <input type="checkbox" class="slider round" id="show_onarticlepages" name="tawkto-visibility-options[show_onarticlepages]" value="1" <?php echo checked( 1, $visibility['show_onarticlepages'], false ); ?> />
163
- <div class="slider round"></div>
164
- </label>
165
- </td>
166
- </tr>
167
- <tr valign="top">
168
- <th class="tawksetting" scope="row"><?php _e('Exclude on specific url','tawk-to-live-chat'); ?></th>
169
- <td>
170
- <label class="switch">
171
- <input type="checkbox" class="slider round" id="exclude_url" name="tawkto-visibility-options[exclude_url]" value="1" <?php echo checked( 1, $visibility['exclude_url'], false ); ?> />
172
- <div class="slider round"></div>
173
- </label>
174
- <div id="exlucded_urls_container" style="display:none;">
175
- <textarea id="excluded_url_list" name="tawkto-visibility-options[excluded_url_list]" cols="50" rows="10"><?php echo $visibility['excluded_url_list']; ?></textarea><BR>
176
- <?php _e('Enter the url where you <b>DO NOT</b> want the widget to display.','tawk-to-live-chat'); ?><BR>
177
- <?php _e('Separate entries with comma','tawk-to-live-chat'); ?>(,).<BR>
178
- <?php _e('Add (*) at the end of the entry to match wildcard url.','tawk-to-live-chat'); ?><BR>
179
- </div>
180
- </td>
181
- </tr>
182
- <tr valign="top" class="twk_selected_display">
183
- <th class="tawksetting" scope="row"><?php _e('Include on specific url','tawk-to-live-chat'); ?></th>
184
- <td>
185
- <label class="switch">
186
- <input type="checkbox" class="slider round" id="include_url" name="tawkto-visibility-options[include_url]" value="1" <?php echo checked( 1, $visibility['include_url'], false ); ?> />
187
- <div class="slider round"></div>
188
- </label>
189
- <div id="included_urls_container" style="display:none;">
190
- <textarea id="included_url_list" name="tawkto-visibility-options[included_url_list]" cols="50" rows="10"><?php echo $visibility['included_url_list']; ?></textarea><BR>
191
- <?php _e('Enter the url where you <b>WANT</b> the widget to display.','tawk-to-live-chat'); ?><BR>
192
- <?php _e('Separate entries with comma ','tawk-to-live-chat'); ?>(,).<BR>
193
- <?php _e('Add (*) at the end of the entry to match wildcard url.','tawk-to-live-chat'); ?><BR>
194
- </div>
195
- </td>
196
- </tr>
197
- </table>
198
- </div>
199
  </div>
200
 
201
- <div id="woocommerce" class="tawktabcontent">
202
- <?php
203
- if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) )
204
- {
205
 
206
- if(!isset($visibility['display_on_shop']))
207
- {
208
- $visibility['display_on_shop'] = 0;
209
- $visibility['display_on_productcategory'] = 0;
210
- $visibility['display_on_productpage'] = 0;
211
- $visibility['display_on_producttag'] = 0;
212
- }
213
- ?>
214
- <div id="tawkvisibilitysettings woocommerce">
215
- <h2><?php _e('Woocommerce visibility Options','tawk-to-live-chat'); ?></h2>
216
- <table class="form-table">
217
- <tr valign="top">
218
- <th class="tawksetting" scope="row"><?php _e('Display on Shop main page','tawk-to-live-chat'); ?></th>
219
- <td>
220
- <label class="switch">
221
- <input type="checkbox" class="slider round" id="display_on_shop" name="tawkto-visibility-options[display_on_shop]" value="1" <?php echo checked( 1, $visibility['display_on_shop'], false ); ?> />
222
- <div class="slider round"></div>
223
- </label>
224
- </td>
225
- </tr>
226
- <tr valign="top">
227
- <th class="tawksetting" scope="row"><?php _e('Display on product category pages','tawk-to-live-chat'); ?></th>
228
- <td>
229
- <label class="switch">
230
- <input type="checkbox" class="slider round" id="display_on_productcategory" name="tawkto-visibility-options[display_on_productcategory]" value="1" <?php echo checked( 1, $visibility['display_on_productcategory'], false ); ?> />
231
- <div class="slider round"></div>
232
- </label>
233
- </td>
234
- </tr>
235
 
236
- <tr valign="top">
237
- <th class="tawksetting" scope="row"><?php _e('Display on single product page','tawk-to-live-chat'); ?></th>
238
- <td>
239
- <label class="switch">
240
- <input type="checkbox" class="slider round" id="display_on_productpage" name="tawkto-visibility-options[display_on_productpage]" value="1" <?php echo checked( 1, $visibility['display_on_productpage'], false ); ?> />
241
- <div class="slider round"></div>
242
- </label>
243
- </td>
244
- </tr>
245
- <tr valign="top">
246
- <th class="tawksetting" scope="row"><?php _e('Display on product tag pages','tawk-to-live-chat'); ?></th>
247
- <td>
248
- <label class="switch">
249
- <input type="checkbox" class="slider round" id="display_on_producttag" name="tawkto-visibility-options[display_on_producttag]" value="1" <?php echo checked( 1, $visibility['display_on_producttag'], false ); ?> />
250
- <div class="slider round"></div>
251
- </label>
252
- </td>
253
- </tr>
254
- </table>
255
- </div>
256
- <?php
257
  }
258
- ?>
259
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
 
261
- <div id="privacy" class="tawktabcontent">
262
- <h2><?php _e('Privacy Options','tawk-to-live-chat'); ?></h2>
263
- <table class="form-table">
264
- <tr valign="top">
265
- <th class="tawksetting" scope="row">
266
- <?php _e('Enable Visitor Recognition', 'tawk-to-live-chat'); ?>
267
- </th>
268
- <td>
269
- <label class="switch">
270
- <input type="checkbox" class="slider round" id="enable_visitor_recognition" name="tawkto-visibility-options[enable_visitor_recognition]" value="1" <?php echo checked( 1, $visibility['enable_visitor_recognition'], false ); ?> />
271
- <div class="slider round"></div>
272
- </label>
273
- </td>
274
- </tr>
275
- </table>
276
- </div>
277
- <div class="tawkaction">
278
- <div class="tawkfootaction">
279
- <?php submit_button(); ?>
280
- </div>
281
- <div class="tawkfoottext">
282
- Having trouble and need some help? Check out our <a class="tawklink" href="https://www.tawk.to/knowledgebase/" target="_blank">Knowledge Base</a>.
283
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  </div>
285
 
286
- </form>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
 
2
  /**
3
+ * @package Tawk.to Widget for WordPress
4
  * @author Tawk.to
5
  * @copyright (C) 2014- Tawk.to
6
  * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
7
+ **/
8
+
9
  if ( ! defined( 'ABSPATH' ) ) {
10
+ // Exit if accessed directly.
11
+ exit;
12
  }
13
+
14
+ $has_woocommerce = in_array(
15
+ 'woocommerce/woocommerce.php',
16
+ apply_filters( 'active_plugins', get_option( 'active_plugins' ) ),
17
+ true
18
+ );
19
+
20
+ $tawky_big_img_url = plugins_url( 'assets/tawky_big.png', dirname( __FILE__ ) );
21
  ?>
22
 
23
+ <div id="tawk-header">
24
+ <div class="tawk-mel">
25
+ <img <?php echo esc_attr( 'src=' . $tawky_big_img_url ); ?> />
26
+ </div>
27
+ <div class="tawk-header-text">
28
+ <?php esc_html_e( 'tawk.to Plugin Settings', 'tawk-to-live-chat' ); ?>
29
+ </div>
30
  </div>
31
+
32
+ <div class="tawk-action">
33
+ <?php
34
+ submit_button(
35
+ null,
36
+ 'primary',
37
+ 'submit-header',
38
+ true,
39
+ array(
40
+ 'form' => 'tawk-settings-form',
41
+ )
42
+ );
43
+ ?>
44
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
+ <div id="tawk-settings-body">
47
+ <div id="tawk-tabs">
48
+ <button class="tawk-tab-links"
49
+ onclick="opentab( event, 'account' )"
50
+ id="account-settings-tab">
51
+ Account Settings
52
+ </button>
53
+ <button class="tawk-tab-links"
54
+ onclick="opentab( event, 'visibility' )"
55
+ id="visibility-options-tab">
56
+ Visibility Options
57
+ </button>
58
+ <button class="tawk-tab-links"
59
+ onclick="opentab( event, 'privacy' )"
60
+ id="privacy-options-tab">
61
+ Privacy Options
62
+ </button>
63
+ <?php if ( $has_woocommerce ) { ?>
64
+ <button class="tawk-tab-links"
65
+ onclick="opentab( event, 'woocommerce' )"
66
+ id="woocommerce-options-tab">
67
+ Woocomerce Options
68
+ </button>
69
+ <?php } ?>
70
+ </div>
71
+
72
+ <div id="account" class="tawk-tab-content">
73
+ <?php
74
+ $page_id = get_option( self::TAWK_PAGE_ID_VARIABLE );
75
+ $widget_id = get_option( self::TAWK_WIDGET_ID_VARIABLE );
76
 
77
+ $override = filter_input( INPUT_GET, 'override', FILTER_VALIDATE_INT );
78
+ if ( 1 === $override ) {
79
+ $override = true;
80
+ } else {
81
+ $override = false;
82
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
+ $page_id_exist = true === isset( $page_id ) && false === empty( $page_id );
85
+ $widget_id_exist = true === isset( $widget_id ) && false === empty( $widget_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
87
+ $display_widget_settings = false;
88
+ if ( false === $page_id_exist || false === $widget_id_exist ) {
89
+ $display_widget_settings = true;
90
+ }
91
+
92
+ if ( true === $override ) {
93
+ $display_widget_settings = true;
94
+ }
95
+
96
+ if ( true === $display_widget_settings ) {
97
+ wp_enqueue_script( 'tawk-selection', plugin_dir_url( __DIR__ ) . 'assets/js/tawk.selection.js', array(), $plugin_ver, false );
98
+ wp_localize_script(
99
+ 'tawk-selection',
100
+ 'tawkSelectionData',
101
+ array(
102
+ 'url' => array(
103
+ 'base' => $base_url,
104
+ 'iframe' => $iframe_url,
105
+ ),
106
+ 'nonce' => array(
107
+ 'setWidget' => $set_widget_nonce,
108
+ 'removeWidget' => $remove_widget_nonce,
109
+ ),
110
+ )
111
+ );
112
+ ?>
113
+ <iframe id="tawk-iframe" src=""></iframe>
114
+ <?php
115
+ } else {
116
+ $tawk_admin_url = admin_url( 'options-general.php?page=tawkto_plugin&override=1' );
117
+ ?>
118
+ <h2><?php esc_html_e( 'Property and widget is already set.', 'tawk-to-live-chat' ); ?></h2>
119
+ <?php esc_html_e( 'if you wish to reselect property or widget', 'tawk-to-live-chat' ); ?>
120
+ <a id="reselect" href=<?php echo esc_html( $tawk_admin_url ); ?>>click here</a>
121
+ <?php } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  </div>
123
 
124
+ <form id='tawk-settings-form' method="post" action="options.php">
125
+ <?php
126
+ settings_fields( 'tawk_options' );
127
+ do_settings_sections( 'tawk_options' );
128
 
129
+ $visibility = get_option( 'tawkto-visibility-options', false );
130
+ if ( false === $visibility ) {
131
+ $visibility = array(
132
+ 'always_display' => 1,
133
+ 'show_onfrontpage' => 0,
134
+ 'show_oncategory' => 0,
135
+ 'show_ontagpage' => 0,
136
+ 'show_onarticlepages' => 0,
137
+ 'exclude_url' => 0,
138
+ 'excluded_url_list' => '',
139
+ 'include_url' => 0,
140
+ 'included_url_list' => '',
141
+ 'display_on_shop' => 0,
142
+ 'display_on_productcategory' => 0,
143
+ 'display_on_productpage' => 0,
144
+ 'display_on_producttag' => 0,
145
+ 'enable_visitor_recognition' => 1,
146
+ );
147
+ }
 
 
 
 
 
 
 
 
 
 
148
 
149
+ if ( ! isset( $visibility['enable_visitor_recognition'] ) ) {
150
+ // default value.
151
+ $visibility['enable_visitor_recognition'] = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  }
153
+ ?>
154
+ <div id="visibility" class="tawk-tab-content">
155
+ <div id="visibility-content">
156
+ <div id="tawk-visibility-settings">
157
+ <h2><?php esc_html_e( 'Visibility Options', 'tawk-to-live-chat' ); ?></h2>
158
+ <p class='tawk-notice'>
159
+ <?php esc_html_e( 'Please Note: that you can use the visibility options below, or you can show the tawk.to widget', 'tawk-to-live-chat' ); ?>
160
+ <?php esc_html_e( 'on any page independent of these visibility options by simply using the', 'tawk-to-live-chat' ); ?>
161
+ <b><?php esc_html_e( '[tawkto]', 'tawk-to-live-chat' ); ?></b>
162
+ <?php esc_html_e( 'shortcode in', 'tawk-to-live-chat' ); ?>
163
+ <?php esc_html_e( 'the post or page.', 'tawk-to-live-chat' ); ?>
164
+ </p>
165
+
166
+ <h2><?php esc_html_e( 'General Visibility', 'tawk-to-live-chat' ); ?></h2>
167
+ <table class="form-table">
168
+ <tr valign="top">
169
+ <th class="tawk-setting" scope="row">
170
+ <?php esc_html_e( 'Always show tawk.to widget on every page', 'tawk-to-live-chat' ); ?>
171
+ </th>
172
+ <td>
173
+ <label class="switch">
174
+ <input type="checkbox"
175
+ class="slider round"
176
+ id="always-display"
177
+ name="tawkto-visibility-options[always_display]"
178
+ value="1"
179
+ <?php echo checked( 1, $visibility['always_display'], false ); ?> />
180
+ <div class="slider round"></div>
181
+ </label>
182
+ </td>
183
+ </tr>
184
+ <tr valign="top" class="tawk-selected-display">
185
+ <th class="tawk-setting" scope="row">
186
+ <?php esc_html_e( 'Show on front page', 'tawk-to-live-chat' ); ?>
187
+ </th>
188
+ <td>
189
+ <label class="switch">
190
+ <input type="checkbox"
191
+ class="slider round"
192
+ id="show-onfrontpage"
193
+ name="tawkto-visibility-options[show_onfrontpage]"
194
+ value="1"
195
+ <?php echo checked( 1, $visibility['show_onfrontpage'], false ); ?> />
196
+ <div class="slider round"></div>
197
+ </label>
198
+ </td>
199
+ </tr>
200
+ <tr valign="top" class="tawk-selected-display">
201
+ <th class="tawk-setting" scope="row">
202
+ <?php esc_html_e( 'Show on category pages', 'tawk-to-live-chat' ); ?>
203
+ </th>
204
+ <td>
205
+ <label class="switch">
206
+ <input type="checkbox"
207
+ class="slider round"
208
+ id="show-oncategory"
209
+ name="tawkto-visibility-options[show_oncategory]"
210
+ value="1"
211
+ <?php echo checked( 1, $visibility['show_oncategory'], false ); ?> />
212
+ <div class="slider round"></div>
213
+ </label>
214
+ </td>
215
+ </tr>
216
+ <tr valign="top" class="tawk-selected-display">
217
+ <th class="tawk-setting" scope="row">
218
+ <?php esc_html_e( 'Show on tag pages', 'tawk-to-live-chat' ); ?>
219
+ </th>
220
+ <td>
221
+ <label class="switch">
222
+ <input type="checkbox"
223
+ class="slider round"
224
+ id="show-ontagpage"
225
+ name="tawkto-visibility-options[show_ontagpage]"
226
+ value="1"
227
+ <?php echo checked( 1, $visibility['show_ontagpage'], false ); ?> />
228
+ <div class="slider round"></div>
229
+ </label>
230
+ </td>
231
+ </tr>
232
+ <tr valign="top" class="tawk-selected-display">
233
+ <th class="tawk-setting" scope="row">
234
+ <?php esc_html_e( 'Show on single post pages', 'tawk-to-live-chat' ); ?>
235
+ </th>
236
+ <td>
237
+ <label class="switch">
238
+ <input type="checkbox"
239
+ class="slider round"
240
+ id="show-onarticlepages"
241
+ name="tawkto-visibility-options[show_onarticlepages]"
242
+ value="1"
243
+ <?php echo checked( 1, $visibility['show_onarticlepages'], false ); ?> />
244
+ <div class="slider round"></div>
245
+ </label>
246
+ </td>
247
+ </tr>
248
+ </table>
249
 
250
+ <h2><?php esc_html_e( 'URL Exclusion', 'tawk-to-live-chat' ); ?></h2>
251
+ <p class='tawk-notice'>
252
+ <?php esc_html_e( 'To show or hide the widget on one or more specific URLs or paths, enable this functionality and specify the rule. ', 'tawk-to-live-chat' ); ?>
253
+ <strong><?php esc_html_e( 'Separate entries with comma', 'tawk-to-live-chat' ); ?> (,)</strong>
254
+ <div class="tooltip">
255
+ <?php esc_html_e( 'Examples of accepted path patterns', 'tawk-to-live-chat' ); ?>
256
+ <ul class="tooltiptext">
257
+ <li>*</li>
258
+ <li>*/to/somewhere</li>
259
+ <li>/*/to/somewhere</li>
260
+ <li>/path/*/somewhere</li>
261
+ <li>/path/*/lead/*/somewhere</li>
262
+ <li>/path/*/*/somewhere</li>
263
+ <li>/path/to/*</li>
264
+ <li>/path/to/*/</li>
265
+ <li>*/to/*/page</li>
266
+ <li>/*/to/*/page</li>
267
+ <li>/path/*/other/*</li>
268
+ <li>/path/*/other/*/</li>
269
+ <li>http://www.example.com/</li>
270
+ <li>http://www.example.com/*</li>
271
+ <li>http://www.example.com/*/to/somewhere</li>
272
+ <li>http://www.example.com/path/*/somewhere</li>
273
+ <li>http://www.example.com/path/*/lead/*/somewhere</li>
274
+ <li>http://www.example.com/path/*/*/somewhere</li>
275
+ <li>http://www.example.com/path/to/*</li>
276
+ <li>http://www.example.com/path/to/*/</li>
277
+ <li>http://www.example.com/*/to/*/page</li>
278
+ <li>http://www.example.com/path/*/other/*</li>
279
+ <li>http://www.example.com/path/*/other/*/</li>
280
+ </ul>
281
+ </div>
282
+ </p>
283
+
284
+ <table class="form-table">
285
+ <tr valign="top">
286
+ <th class="tawk-setting" scope="row">
287
+ <?php esc_html_e( 'HIDE widget only on specific URLs or paths', 'tawk-to-live-chat' ); ?>
288
+ </th>
289
+ <td>
290
+ <label class="switch">
291
+ <input type="checkbox"
292
+ class="slider round"
293
+ id="exclude-url"
294
+ name="tawkto-visibility-options[exclude_url]"
295
+ value="1"
296
+ <?php echo checked( 1, $visibility['exclude_url'], false ); ?> />
297
+ <div class="slider round"></div>
298
+ </label>
299
+ <div id="exlucded-urls-container" style="display:none;">
300
+ <textarea id="excluded-url-list"
301
+ name="tawkto-visibility-options[excluded_url_list]"
302
+ cols="50"
303
+ rows="10"><?php echo esc_html( $visibility['excluded_url_list'] ); ?></textarea>
304
+ </div>
305
+ </td>
306
+ </tr>
307
+ <tr valign="top" class="tawk-selected-display">
308
+ <th class="tawk-setting" scope="row">
309
+ <?php esc_html_e( 'SHOW widget only on specific URLs or paths', 'tawk-to-live-chat' ); ?>
310
+ </th>
311
+ <td>
312
+ <label class="switch">
313
+ <input type="checkbox"
314
+ class="slider round"
315
+ id="include-url"
316
+ name="tawkto-visibility-options[include_url]"
317
+ value="1"
318
+ <?php echo checked( 1, $visibility['include_url'], false ); ?> />
319
+ <div class="slider round"></div>
320
+ </label>
321
+ <div id="included-urls-container" style="display:none;">
322
+ <textarea id="included-url-list"
323
+ name="tawkto-visibility-options[included_url_list]"
324
+ cols="50"
325
+ rows="10"><?php echo esc_html( $visibility['included_url_list'] ); ?></textarea>
326
+ </td>
327
+ </tr>
328
+ </table>
329
+ </div>
330
+ </div>
331
+ </div>
332
+
333
+ <div id="woocommerce" class="tawk-tab-content">
334
+ <?php
335
+ if ( $has_woocommerce ) {
336
+ if ( ! isset( $visibility['display_on_shop'] ) ) {
337
+ $visibility['display_on_shop'] = 0;
338
+ $visibility['display_on_productcategory'] = 0;
339
+ $visibility['display_on_productpage'] = 0;
340
+ $visibility['display_on_producttag'] = 0;
341
+ }
342
+ ?>
343
+ <div id="woocommerce">
344
+ <h2>
345
+ <?php esc_html_e( 'Woocommerce Visibility Options', 'tawk-to-live-chat' ); ?>
346
+ </h2>
347
+ <table class="form-table">
348
+ <tr valign="top">
349
+ <th class="tawk-setting" scope="row">
350
+ <?php esc_html_e( 'Display on shop main page', 'tawk-to-live-chat' ); ?>
351
+ </th>
352
+ <td>
353
+ <label class="switch">
354
+ <input type="checkbox"
355
+ class="slider round"
356
+ id="display-on-shop"
357
+ name="tawkto-visibility-options[display_on_shop]"
358
+ value="1"
359
+ <?php echo checked( 1, $visibility['display_on_shop'], false ); ?> />
360
+ <div class="slider round"></div>
361
+ </label>
362
+ </td>
363
+ </tr>
364
+ <tr valign="top">
365
+ <th class="tawk-setting" scope="row">
366
+ <?php esc_html_e( 'Display on product category pages', 'tawk-to-live-chat' ); ?>
367
+ </th>
368
+ <td>
369
+ <label class="switch">
370
+ <input type="checkbox"
371
+ class="slider round"
372
+ id="display-on-productcategory"
373
+ name="tawkto-visibility-options[display_on_productcategory]"
374
+ value="1"
375
+ <?php echo checked( 1, $visibility['display_on_productcategory'], false ); ?> />
376
+ <div class="slider round"></div>
377
+ </label>
378
+ </td>
379
+ </tr>
380
+
381
+ <tr valign="top">
382
+ <th class="tawk-setting" scope="row">
383
+ <?php esc_html_e( 'Display on single product page', 'tawk-to-live-chat' ); ?>
384
+ </th>
385
+ <td>
386
+ <label class="switch">
387
+ <input type="checkbox"
388
+ class="slider round"
389
+ id="display-on-productpage"
390
+ name="tawkto-visibility-options[display_on_productpage]"
391
+ value="1"
392
+ <?php echo checked( 1, $visibility['display_on_productpage'], false ); ?> />
393
+ <div class="slider round"></div>
394
+ </label>
395
+ </td>
396
+ </tr>
397
+ <tr valign="top">
398
+ <th class="tawk-setting" scope="row">
399
+ <?php esc_html_e( 'Display on product tag pages', 'tawk-to-live-chat' ); ?>
400
+ </th>
401
+ <td>
402
+ <label class="switch">
403
+ <input type="checkbox"
404
+ class="slider round"
405
+ id="display-on-producttag"
406
+ name="tawkto-visibility-options[display_on_producttag]"
407
+ value="1"
408
+ <?php echo checked( 1, $visibility['display_on_producttag'], false ); ?> />
409
+ <div class="slider round"></div>
410
+ </label>
411
+ </td>
412
+ </tr>
413
+ </table>
414
+ </div>
415
+ <?php } ?>
416
+ </div>
417
+
418
+ <div id="privacy" class="tawk-tab-content">
419
+ <h2>
420
+ <?php esc_html_e( 'Privacy Options', 'tawk-to-live-chat' ); ?>
421
+ </h2>
422
+ <table class="form-table">
423
+ <tr valign="top">
424
+ <th class="tawk-setting" scope="row">
425
+ <?php esc_html_e( 'Enable visitor recognition', 'tawk-to-live-chat' ); ?>
426
+ </th>
427
+ <td>
428
+ <label class="switch">
429
+ <input type="checkbox"
430
+ class="slider round"
431
+ id="enable-visitor-recognition"
432
+ name="tawkto-visibility-options[enable_visitor_recognition]"
433
+ value="1"
434
+ <?php echo checked( 1, $visibility['enable_visitor_recognition'], false ); ?> />
435
+ <div class="slider round"></div>
436
+ </label>
437
+ </td>
438
+ </tr>
439
+ </table>
440
+ </div>
441
+ </form>
442
  </div>
443
 
444
+ <div class="tawk-action">
445
+ <div class="tawk-footer-action">
446
+ <?php
447
+ submit_button(
448
+ null,
449
+ 'primary',
450
+ 'submit-footer',
451
+ true,
452
+ array(
453
+ 'form' => 'tawk-settings-form',
454
+ )
455
+ );
456
+ ?>
457
+ </div>
458
+ <div class="tawk-footer-text">
459
+ Having trouble and need some help? Check out our <a class="tawk-link" href="https://www.tawk.to/knowledgebase/" target="_blank">Knowledge Base</a>.
460
+ </div>
461
+ </div>
templates/widget.php CHANGED
@@ -1,19 +1,27 @@
1
- <!--Start of Tawk.to Script (0.6.0)-->
2
- <script type="text/javascript">
3
- var Tawk_API=Tawk_API||{};
4
  <?php
5
- if(isset($customer_details) && $enable_visitor_recognition) {
6
- echo 'Tawk_API.visitor = '. $customer_details.';';
7
- }
 
 
 
 
8
  ?>
 
 
 
 
 
 
 
9
  var Tawk_LoadStart=new Date();
10
  (function(){
11
- var s1=document.createElement("script"),s0=document.getElementsByTagName("script")[0];
12
- s1.async=true;
13
- s1.src='<?php echo esc_url('https://embed.tawk.to/'.$page_id.'/'.$widget_id); ?>';
14
- s1.charset='UTF-8';
15
- s1.setAttribute('crossorigin','*');
16
- s0.parentNode.insertBefore(s1,s0);
17
  })();
18
  </script>
19
- <!--End of Tawk.to Script (0.6.0)-->
 
 
 
1
  <?php
2
+ /**
3
+ * @package Tawk.to Widget for WordPress
4
+ * @author Tawk.to
5
+ * @copyright (C) 2014- Tawk.to
6
+ * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
7
+ */
8
+
9
  ?>
10
+
11
+ <!--Start of Tawk.to Script (0.7.0)-->
12
+ <script id="tawk-script" type="text/javascript">
13
+ var Tawk_API = Tawk_API || {};
14
+ <?php if ( isset( $customer_details ) && $enable_visitor_recognition ) : ?>
15
+ Tawk_API.visitor = JSON.parse(<?php echo wp_json_encode( $customer_details ); ?>);
16
+ <?php endif ?>
17
  var Tawk_LoadStart=new Date();
18
  (function(){
19
+ var s1 = document.createElement( 'script' ),s0=document.getElementsByTagName( 'script' )[0];
20
+ s1.async = true;
21
+ s1.src = '<?php echo esc_url( 'https://embed.tawk.to/' . $page_id . '/' . $widget_id ); ?>';
22
+ s1.charset = 'UTF-8';
23
+ s1.setAttribute( 'crossorigin','*' );
24
+ s0.parentNode.insertBefore( s1, s0 );
25
  })();
26
  </script>
27
+ <!--End of Tawk.to Script (0.7.0)-->
upgrade.manager.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once dirname( __FILE__ ) . '/upgrades/version.070.php';
4
+
5
+ /**
6
+ * Upgrade manager for tawk.to plugin
7
+ */
8
+ class TawkToUpgradeManager {
9
+ /**
10
+ * $upgrades
11
+ *
12
+ * @var array
13
+ */
14
+ protected $upgrades;
15
+ /**
16
+ * $prev_ver
17
+ *
18
+ * @var string
19
+ */
20
+ protected $prev_ver;
21
+ /**
22
+ * $curr_ver
23
+ *
24
+ * @var string
25
+ */
26
+ protected $curr_ver;
27
+ /**
28
+ * $version_var_name
29
+ *
30
+ * @var string
31
+ */
32
+ protected $version_var_name;
33
+
34
+ /**
35
+ * Constructor
36
+ *
37
+ * @param string $version Plugin version.
38
+ * @param string $version_var_name Version option variable name.
39
+ */
40
+ public function __construct( $version, $version_var_name ) {
41
+ $this->upgrades = array(
42
+ TawkToUpgradeVersion070::get_version() => TawkToUpgradeVersion070::class,
43
+ );
44
+
45
+ $this->version_var_name = $version_var_name;
46
+ $this->curr_ver = $version;
47
+ $this->prev_ver = get_option( $version_var_name, '' );
48
+ }
49
+
50
+ /**
51
+ * Start doing upgrades
52
+ */
53
+ public function start() {
54
+ if ( ! empty( $this->prev_ver ) && version_compare( $this->prev_ver, $this->curr_ver ) >= 0 ) {
55
+ // do not do anything.
56
+ return;
57
+ }
58
+
59
+ // special case: we've never set the version before.
60
+ // All plugins prior to the current version needs the upgrade.
61
+ if ( version_compare( $this->prev_ver, $this->curr_ver ) < 0 ) {
62
+ // are there upgrade steps depending on how out-of-date?
63
+ foreach ( $this->upgrades as $upgrade_ver => $upgrade ) {
64
+ // only run upgrades if upgrade version is lower than
65
+ // and equal to the current version.
66
+ if ( version_compare( $upgrade_ver, $this->curr_ver ) <= 0 ) {
67
+ $this->do_upgrade( $upgrade_ver );
68
+ }
69
+
70
+ update_option( $this->version_var_name, $upgrade_ver );
71
+ }
72
+ }
73
+
74
+ }
75
+
76
+ /**
77
+ * Gets upgrade class by provided version
78
+ *
79
+ * @param string $version Upgrade version.
80
+ *
81
+ * @return string|null Returns `upgrade class name` if version exists in the list. Otherwise, returns `null`.
82
+ */
83
+ protected function get_upgrade_class( $version ) {
84
+ if ( false === array_key_exists( $version, $this->upgrades ) ) {
85
+ return null;
86
+ }
87
+
88
+ return $this->upgrades[ $version ];
89
+ }
90
+
91
+ /**
92
+ * Does the version upgrade depending on the provided plugin version.
93
+ *
94
+ * @param string $version Plugin version.
95
+ * @return void
96
+ */
97
+ protected function do_upgrade( $version ) {
98
+ $upgrade_class = $this->get_upgrade_class( $version );
99
+
100
+ if ( true === is_null( $upgrade_class ) ) {
101
+ return;
102
+ }
103
+
104
+ $upgrade_class::upgrade();
105
+ }
106
+
107
+ /**
108
+ * Registers hooks for upgrade.
109
+ */
110
+ public function register_hooks() {
111
+ add_action( 'plugins_loaded', array( $this, 'start' ) );
112
+ }
113
+ }
upgrades/base.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Base class for upgrades
5
+ */
6
+ abstract class TawkToUpgradeBase {
7
+ const VERSION = null;
8
+
9
+ /**
10
+ * Gets current upgrade's release version
11
+ *
12
+ * @return string Release version
13
+ * @throws Exception Release version is not defined.
14
+ */
15
+ public static function get_version() {
16
+ if ( is_null( static::VERSION ) ) {
17
+ throw new Exception( 'Subclass must have const VERSION' );
18
+ }
19
+
20
+ return static::VERSION;
21
+ }
22
+
23
+ /**
24
+ * Upgrade script
25
+ *
26
+ * @return void
27
+ * @throws Exception Subclass has no upgrade implementation.
28
+ */
29
+ public static function upgrade() {
30
+ throw new Exception( 'Subclass must implement this!' );
31
+ }
32
+ }
upgrades/version.070.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! class_exists( 'TawkToUpgradeBase' ) ) {
4
+ require_once dirname( __FILE__ ) . '/base.php';
5
+ }
6
+
7
+ use Tawk\Helpers\PathHelper;
8
+ use Tawk\Helpers\Common as CommonHelper;
9
+
10
+ /**
11
+ * Upgrade for release version 0.7.0
12
+ */
13
+ class TawkToUpgradeVersion070 extends TawkToUpgradeBase {
14
+ const VERSION = '0.7.0';
15
+
16
+ /**
17
+ * Migration for url patterns with ending wildcards. (ex. https://www.example.com/path/to/somewhere/*)
18
+ *
19
+ * Adds the same url pattern without the ending wildcard (ex. https://www.example.com/path/to/somewhere)
20
+ * to adjust with the new pattern matching lib.
21
+ */
22
+ public static function upgrade() {
23
+ $visibility = get_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS );
24
+
25
+ $visibility['included_url_list'] = self::process_patterns( $visibility['included_url_list'] );
26
+ $visibility['excluded_url_list'] = self::process_patterns( $visibility['excluded_url_list'] );
27
+
28
+ update_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS, $visibility );
29
+ }
30
+
31
+ /**
32
+ * Processes the patterns with ending wildcards and adds
33
+ * a copy of it without the wildcard to the list.
34
+ *
35
+ * @param string $pattern_list Comma separated pattern list.
36
+ *
37
+ * @return string Updated pattern list.
38
+ */
39
+ protected static function process_patterns( $pattern_list ) {
40
+ $splitted_pattern_list = array_map( 'trim', preg_split( '/,/', $pattern_list ) );
41
+ $wildcard = PathHelper::get_wildcard();
42
+
43
+ $new_pattern_list = array();
44
+ $added_patterns = array();
45
+
46
+ foreach ( $splitted_pattern_list as $url ) {
47
+ if ( empty( $url ) ) {
48
+ continue;
49
+ }
50
+
51
+ $new_pattern_list[] = $url;
52
+
53
+ if ( false === CommonHelper::text_ends_with( $url, $wildcard ) ) {
54
+ continue;
55
+ }
56
+
57
+ $new_pattern = rtrim( $url, '/' . $wildcard );
58
+ if ( in_array( $new_pattern, $splitted_pattern_list, true ) ) {
59
+ continue;
60
+ }
61
+
62
+ if ( true === isset( $added_patterns[ $new_pattern ] ) ) {
63
+ continue;
64
+ }
65
+
66
+ $new_pattern_list[] = $new_pattern;
67
+ $added_patterns[ $new_pattern ] = true;
68
+ }
69
+
70
+ return join( ', ', $new_pattern_list );
71
+ }
72
+ }
vendor/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit3eb597ada59a4a18b26320b23bc7d0c2::getLoader();
vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,572 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
+ *
18
+ * $loader = new \Composer\Autoload\ClassLoader();
19
+ *
20
+ * // register classes with namespaces
21
+ * $loader->add('Symfony\Component', __DIR__.'/component');
22
+ * $loader->add('Symfony', __DIR__.'/framework');
23
+ *
24
+ * // activate the autoloader
25
+ * $loader->register();
26
+ *
27
+ * // to enable searching the include path (eg. for PEAR packages)
28
+ * $loader->setUseIncludePath(true);
29
+ *
30
+ * In this example, if you try to use a class in the Symfony\Component
31
+ * namespace or one of its children (Symfony\Component\Console for instance),
32
+ * the autoloader will first look for the class under the component/
33
+ * directory, and it will then fallback to the framework/ directory if not
34
+ * found before giving up.
35
+ *
36
+ * This class is loosely based on the Symfony UniversalClassLoader.
37
+ *
38
+ * @author Fabien Potencier <fabien@symfony.com>
39
+ * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see https://www.php-fig.org/psr/psr-0/
41
+ * @see https://www.php-fig.org/psr/psr-4/
42
+ */
43
+ class ClassLoader
44
+ {
45
+ /** @var ?string */
46
+ private $vendorDir;
47
+
48
+ // PSR-4
49
+ /**
50
+ * @var array[]
51
+ * @psalm-var array<string, array<string, int>>
52
+ */
53
+ private $prefixLengthsPsr4 = array();
54
+ /**
55
+ * @var array[]
56
+ * @psalm-var array<string, array<int, string>>
57
+ */
58
+ private $prefixDirsPsr4 = array();
59
+ /**
60
+ * @var array[]
61
+ * @psalm-var array<string, string>
62
+ */
63
+ private $fallbackDirsPsr4 = array();
64
+
65
+ // PSR-0
66
+ /**
67
+ * @var array[]
68
+ * @psalm-var array<string, array<string, string[]>>
69
+ */
70
+ private $prefixesPsr0 = array();
71
+ /**
72
+ * @var array[]
73
+ * @psalm-var array<string, string>
74
+ */
75
+ private $fallbackDirsPsr0 = array();
76
+
77
+ /** @var bool */
78
+ private $useIncludePath = false;
79
+
80
+ /**
81
+ * @var string[]
82
+ * @psalm-var array<string, string>
83
+ */
84
+ private $classMap = array();
85
+
86
+ /** @var bool */
87
+ private $classMapAuthoritative = false;
88
+
89
+ /**
90
+ * @var bool[]
91
+ * @psalm-var array<string, bool>
92
+ */
93
+ private $missingClasses = array();
94
+
95
+ /** @var ?string */
96
+ private $apcuPrefix;
97
+
98
+ /**
99
+ * @var self[]
100
+ */
101
+ private static $registeredLoaders = array();
102
+
103
+ /**
104
+ * @param ?string $vendorDir
105
+ */
106
+ public function __construct($vendorDir = null)
107
+ {
108
+ $this->vendorDir = $vendorDir;
109
+ }
110
+
111
+ /**
112
+ * @return string[]
113
+ */
114
+ public function getPrefixes()
115
+ {
116
+ if (!empty($this->prefixesPsr0)) {
117
+ return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
118
+ }
119
+
120
+ return array();
121
+ }
122
+
123
+ /**
124
+ * @return array[]
125
+ * @psalm-return array<string, array<int, string>>
126
+ */
127
+ public function getPrefixesPsr4()
128
+ {
129
+ return $this->prefixDirsPsr4;
130
+ }
131
+
132
+ /**
133
+ * @return array[]
134
+ * @psalm-return array<string, string>
135
+ */
136
+ public function getFallbackDirs()
137
+ {
138
+ return $this->fallbackDirsPsr0;
139
+ }
140
+
141
+ /**
142
+ * @return array[]
143
+ * @psalm-return array<string, string>
144
+ */
145
+ public function getFallbackDirsPsr4()
146
+ {
147
+ return $this->fallbackDirsPsr4;
148
+ }
149
+
150
+ /**
151
+ * @return string[] Array of classname => path
152
+ * @psalm-return array<string, string>
153
+ */
154
+ public function getClassMap()
155
+ {
156
+ return $this->classMap;
157
+ }
158
+
159
+ /**
160
+ * @param string[] $classMap Class to filename map
161
+ * @psalm-param array<string, string> $classMap
162
+ *
163
+ * @return void
164
+ */
165
+ public function addClassMap(array $classMap)
166
+ {
167
+ if ($this->classMap) {
168
+ $this->classMap = array_merge($this->classMap, $classMap);
169
+ } else {
170
+ $this->classMap = $classMap;
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Registers a set of PSR-0 directories for a given prefix, either
176
+ * appending or prepending to the ones previously set for this prefix.
177
+ *
178
+ * @param string $prefix The prefix
179
+ * @param string[]|string $paths The PSR-0 root directories
180
+ * @param bool $prepend Whether to prepend the directories
181
+ *
182
+ * @return void
183
+ */
184
+ public function add($prefix, $paths, $prepend = false)
185
+ {
186
+ if (!$prefix) {
187
+ if ($prepend) {
188
+ $this->fallbackDirsPsr0 = array_merge(
189
+ (array) $paths,
190
+ $this->fallbackDirsPsr0
191
+ );
192
+ } else {
193
+ $this->fallbackDirsPsr0 = array_merge(
194
+ $this->fallbackDirsPsr0,
195
+ (array) $paths
196
+ );
197
+ }
198
+
199
+ return;
200
+ }
201
+
202
+ $first = $prefix[0];
203
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
204
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
205
+
206
+ return;
207
+ }
208
+ if ($prepend) {
209
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
210
+ (array) $paths,
211
+ $this->prefixesPsr0[$first][$prefix]
212
+ );
213
+ } else {
214
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
215
+ $this->prefixesPsr0[$first][$prefix],
216
+ (array) $paths
217
+ );
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Registers a set of PSR-4 directories for a given namespace, either
223
+ * appending or prepending to the ones previously set for this namespace.
224
+ *
225
+ * @param string $prefix The prefix/namespace, with trailing '\\'
226
+ * @param string[]|string $paths The PSR-4 base directories
227
+ * @param bool $prepend Whether to prepend the directories
228
+ *
229
+ * @throws \InvalidArgumentException
230
+ *
231
+ * @return void
232
+ */
233
+ public function addPsr4($prefix, $paths, $prepend = false)
234
+ {
235
+ if (!$prefix) {
236
+ // Register directories for the root namespace.
237
+ if ($prepend) {
238
+ $this->fallbackDirsPsr4 = array_merge(
239
+ (array) $paths,
240
+ $this->fallbackDirsPsr4
241
+ );
242
+ } else {
243
+ $this->fallbackDirsPsr4 = array_merge(
244
+ $this->fallbackDirsPsr4,
245
+ (array) $paths
246
+ );
247
+ }
248
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
249
+ // Register directories for a new namespace.
250
+ $length = strlen($prefix);
251
+ if ('\\' !== $prefix[$length - 1]) {
252
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
253
+ }
254
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
255
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
256
+ } elseif ($prepend) {
257
+ // Prepend directories for an already registered namespace.
258
+ $this->prefixDirsPsr4[$prefix] = array_merge(
259
+ (array) $paths,
260
+ $this->prefixDirsPsr4[$prefix]
261
+ );
262
+ } else {
263
+ // Append directories for an already registered namespace.
264
+ $this->prefixDirsPsr4[$prefix] = array_merge(
265
+ $this->prefixDirsPsr4[$prefix],
266
+ (array) $paths
267
+ );
268
+ }
269
+ }
270
+
271
+ /**
272
+ * Registers a set of PSR-0 directories for a given prefix,
273
+ * replacing any others previously set for this prefix.
274
+ *
275
+ * @param string $prefix The prefix
276
+ * @param string[]|string $paths The PSR-0 base directories
277
+ *
278
+ * @return void
279
+ */
280
+ public function set($prefix, $paths)
281
+ {
282
+ if (!$prefix) {
283
+ $this->fallbackDirsPsr0 = (array) $paths;
284
+ } else {
285
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Registers a set of PSR-4 directories for a given namespace,
291
+ * replacing any others previously set for this namespace.
292
+ *
293
+ * @param string $prefix The prefix/namespace, with trailing '\\'
294
+ * @param string[]|string $paths The PSR-4 base directories
295
+ *
296
+ * @throws \InvalidArgumentException
297
+ *
298
+ * @return void
299
+ */
300
+ public function setPsr4($prefix, $paths)
301
+ {
302
+ if (!$prefix) {
303
+ $this->fallbackDirsPsr4 = (array) $paths;
304
+ } else {
305
+ $length = strlen($prefix);
306
+ if ('\\' !== $prefix[$length - 1]) {
307
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
308
+ }
309
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
310
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
311
+ }
312
+ }
313
+
314
+ /**
315
+ * Turns on searching the include path for class files.
316
+ *
317
+ * @param bool $useIncludePath
318
+ *
319
+ * @return void
320
+ */
321
+ public function setUseIncludePath($useIncludePath)
322
+ {
323
+ $this->useIncludePath = $useIncludePath;
324
+ }
325
+
326
+ /**
327
+ * Can be used to check if the autoloader uses the include path to check
328
+ * for classes.
329
+ *
330
+ * @return bool
331
+ */
332
+ public function getUseIncludePath()
333
+ {
334
+ return $this->useIncludePath;
335
+ }
336
+
337
+ /**
338
+ * Turns off searching the prefix and fallback directories for classes
339
+ * that have not been registered with the class map.
340
+ *
341
+ * @param bool $classMapAuthoritative
342
+ *
343
+ * @return void
344
+ */
345
+ public function setClassMapAuthoritative($classMapAuthoritative)
346
+ {
347
+ $this->classMapAuthoritative = $classMapAuthoritative;
348
+ }
349
+
350
+ /**
351
+ * Should class lookup fail if not found in the current class map?
352
+ *
353
+ * @return bool
354
+ */
355
+ public function isClassMapAuthoritative()
356
+ {
357
+ return $this->classMapAuthoritative;
358
+ }
359
+
360
+ /**
361
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
362
+ *
363
+ * @param string|null $apcuPrefix
364
+ *
365
+ * @return void
366
+ */
367
+ public function setApcuPrefix($apcuPrefix)
368
+ {
369
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
370
+ }
371
+
372
+ /**
373
+ * The APCu prefix in use, or null if APCu caching is not enabled.
374
+ *
375
+ * @return string|null
376
+ */
377
+ public function getApcuPrefix()
378
+ {
379
+ return $this->apcuPrefix;
380
+ }
381
+
382
+ /**
383
+ * Registers this instance as an autoloader.
384
+ *
385
+ * @param bool $prepend Whether to prepend the autoloader or not
386
+ *
387
+ * @return void
388
+ */
389
+ public function register($prepend = false)
390
+ {
391
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
392
+
393
+ if (null === $this->vendorDir) {
394
+ return;
395
+ }
396
+
397
+ if ($prepend) {
398
+ self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
399
+ } else {
400
+ unset(self::$registeredLoaders[$this->vendorDir]);
401
+ self::$registeredLoaders[$this->vendorDir] = $this;
402
+ }
403
+ }
404
+
405
+ /**
406
+ * Unregisters this instance as an autoloader.
407
+ *
408
+ * @return void
409
+ */
410
+ public function unregister()
411
+ {
412
+ spl_autoload_unregister(array($this, 'loadClass'));
413
+
414
+ if (null !== $this->vendorDir) {
415
+ unset(self::$registeredLoaders[$this->vendorDir]);
416
+ }
417
+ }
418
+
419
+ /**
420
+ * Loads the given class or interface.
421
+ *
422
+ * @param string $class The name of the class
423
+ * @return true|null True if loaded, null otherwise
424
+ */
425
+ public function loadClass($class)
426
+ {
427
+ if ($file = $this->findFile($class)) {
428
+ includeFile($file);
429
+
430
+ return true;
431
+ }
432
+
433
+ return null;
434
+ }
435
+
436
+ /**
437
+ * Finds the path to the file where the class is defined.
438
+ *
439
+ * @param string $class The name of the class
440
+ *
441
+ * @return string|false The path if found, false otherwise
442
+ */
443
+ public function findFile($class)
444
+ {
445
+ // class map lookup
446
+ if (isset($this->classMap[$class])) {
447
+ return $this->classMap[$class];
448
+ }
449
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
450
+ return false;
451
+ }
452
+ if (null !== $this->apcuPrefix) {
453
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
454
+ if ($hit) {
455
+ return $file;
456
+ }
457
+ }
458
+
459
+ $file = $this->findFileWithExtension($class, '.php');
460
+
461
+ // Search for Hack files if we are running on HHVM
462
+ if (false === $file && defined('HHVM_VERSION')) {
463
+ $file = $this->findFileWithExtension($class, '.hh');
464
+ }
465
+
466
+ if (null !== $this->apcuPrefix) {
467
+ apcu_add($this->apcuPrefix.$class, $file);
468
+ }
469
+
470
+ if (false === $file) {
471
+ // Remember that this class does not exist.
472
+ $this->missingClasses[$class] = true;
473
+ }
474
+
475
+ return $file;
476
+ }
477
+
478
+ /**
479
+ * Returns the currently registered loaders indexed by their corresponding vendor directories.
480
+ *
481
+ * @return self[]
482
+ */
483
+ public static function getRegisteredLoaders()
484
+ {
485
+ return self::$registeredLoaders;
486
+ }
487
+
488
+ /**
489
+ * @param string $class
490
+ * @param string $ext
491
+ * @return string|false
492
+ */
493
+ private function findFileWithExtension($class, $ext)
494
+ {
495
+ // PSR-4 lookup
496
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
497
+
498
+ $first = $class[0];
499
+ if (isset($this->prefixLengthsPsr4[$first])) {
500
+ $subPath = $class;
501
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
502
+ $subPath = substr($subPath, 0, $lastPos);
503
+ $search = $subPath . '\\';
504
+ if (isset($this->prefixDirsPsr4[$search])) {
505
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
506
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
507
+ if (file_exists($file = $dir . $pathEnd)) {
508
+ return $file;
509
+ }
510
+ }
511
+ }
512
+ }
513
+ }
514
+
515
+ // PSR-4 fallback dirs
516
+ foreach ($this->fallbackDirsPsr4 as $dir) {
517
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
518
+ return $file;
519
+ }
520
+ }
521
+
522
+ // PSR-0 lookup
523
+ if (false !== $pos = strrpos($class, '\\')) {
524
+ // namespaced class name
525
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
526
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
527
+ } else {
528
+ // PEAR-like class name
529
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
530
+ }
531
+
532
+ if (isset($this->prefixesPsr0[$first])) {
533
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
534
+ if (0 === strpos($class, $prefix)) {
535
+ foreach ($dirs as $dir) {
536
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
537
+ return $file;
538
+ }
539
+ }
540
+ }
541
+ }
542
+ }
543
+
544
+ // PSR-0 fallback dirs
545
+ foreach ($this->fallbackDirsPsr0 as $dir) {
546
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
547
+ return $file;
548
+ }
549
+ }
550
+
551
+ // PSR-0 include paths.
552
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
553
+ return $file;
554
+ }
555
+
556
+ return false;
557
+ }
558
+ }
559
+
560
+ /**
561
+ * Scope isolated include.
562
+ *
563
+ * Prevents access to $this/self from included files.
564
+ *
565
+ * @param string $file
566
+ * @return void
567
+ * @private
568
+ */
569
+ function includeFile($file)
570
+ {
571
+ include $file;
572
+ }
vendor/composer/InstalledVersions.php ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer;
14
+
15
+ use Composer\Autoload\ClassLoader;
16
+ use Composer\Semver\VersionParser;
17
+
18
+ /**
19
+ * This class is copied in every Composer installed project and available to all
20
+ *
21
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
22
+ *
23
+ * To require its presence, you can require `composer-runtime-api ^2.0`
24
+ */
25
+ class InstalledVersions
26
+ {
27
+ /**
28
+ * @var mixed[]|null
29
+ * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
30
+ */
31
+ private static $installed;
32
+
33
+ /**
34
+ * @var bool|null
35
+ */
36
+ private static $canGetVendors;
37
+
38
+ /**
39
+ * @var array[]
40
+ * @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
41
+ */
42
+ private static $installedByVendor = array();
43
+
44
+ /**
45
+ * Returns a list of all package names which are present, either by being installed, replaced or provided
46
+ *
47
+ * @return string[]
48
+ * @psalm-return list<string>
49
+ */
50
+ public static function getInstalledPackages()
51
+ {
52
+ $packages = array();
53
+ foreach (self::getInstalled() as $installed) {
54
+ $packages[] = array_keys($installed['versions']);
55
+ }
56
+
57
+ if (1 === \count($packages)) {
58
+ return $packages[0];
59
+ }
60
+
61
+ return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
62
+ }
63
+
64
+ /**
65
+ * Returns a list of all package names with a specific type e.g. 'library'
66
+ *
67
+ * @param string $type
68
+ * @return string[]
69
+ * @psalm-return list<string>
70
+ */
71
+ public static function getInstalledPackagesByType($type)
72
+ {
73
+ $packagesByType = array();
74
+
75
+ foreach (self::getInstalled() as $installed) {
76
+ foreach ($installed['versions'] as $name => $package) {
77
+ if (isset($package['type']) && $package['type'] === $type) {
78
+ $packagesByType[] = $name;
79
+ }
80
+ }
81
+ }
82
+
83
+ return $packagesByType;
84
+ }
85
+
86
+ /**
87
+ * Checks whether the given package is installed
88
+ *
89
+ * This also returns true if the package name is provided or replaced by another package
90
+ *
91
+ * @param string $packageName
92
+ * @param bool $includeDevRequirements
93
+ * @return bool
94
+ */
95
+ public static function isInstalled($packageName, $includeDevRequirements = true)
96
+ {
97
+ foreach (self::getInstalled() as $installed) {
98
+ if (isset($installed['versions'][$packageName])) {
99
+ return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
100
+ }
101
+ }
102
+
103
+ return false;
104
+ }
105
+
106
+ /**
107
+ * Checks whether the given package satisfies a version constraint
108
+ *
109
+ * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
110
+ *
111
+ * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
112
+ *
113
+ * @param VersionParser $parser Install composer/semver to have access to this class and functionality
114
+ * @param string $packageName
115
+ * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
116
+ * @return bool
117
+ */
118
+ public static function satisfies(VersionParser $parser, $packageName, $constraint)
119
+ {
120
+ $constraint = $parser->parseConstraints($constraint);
121
+ $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
122
+
123
+ return $provided->matches($constraint);
124
+ }
125
+
126
+ /**
127
+ * Returns a version constraint representing all the range(s) which are installed for a given package
128
+ *
129
+ * It is easier to use this via isInstalled() with the $constraint argument if you need to check
130
+ * whether a given version of a package is installed, and not just whether it exists
131
+ *
132
+ * @param string $packageName
133
+ * @return string Version constraint usable with composer/semver
134
+ */
135
+ public static function getVersionRanges($packageName)
136
+ {
137
+ foreach (self::getInstalled() as $installed) {
138
+ if (!isset($installed['versions'][$packageName])) {
139
+ continue;
140
+ }
141
+
142
+ $ranges = array();
143
+ if (isset($installed['versions'][$packageName]['pretty_version'])) {
144
+ $ranges[] = $installed['versions'][$packageName]['pretty_version'];
145
+ }
146
+ if (array_key_exists('aliases', $installed['versions'][$packageName])) {
147
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
148
+ }
149
+ if (array_key_exists('replaced', $installed['versions'][$packageName])) {
150
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
151
+ }
152
+ if (array_key_exists('provided', $installed['versions'][$packageName])) {
153
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
154
+ }
155
+
156
+ return implode(' || ', $ranges);
157
+ }
158
+
159
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
160
+ }
161
+
162
+ /**
163
+ * @param string $packageName
164
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
165
+ */
166
+ public static function getVersion($packageName)
167
+ {
168
+ foreach (self::getInstalled() as $installed) {
169
+ if (!isset($installed['versions'][$packageName])) {
170
+ continue;
171
+ }
172
+
173
+ if (!isset($installed['versions'][$packageName]['version'])) {
174
+ return null;
175
+ }
176
+
177
+ return $installed['versions'][$packageName]['version'];
178
+ }
179
+
180
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
181
+ }
182
+
183
+ /**
184
+ * @param string $packageName
185
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
186
+ */
187
+ public static function getPrettyVersion($packageName)
188
+ {
189
+ foreach (self::getInstalled() as $installed) {
190
+ if (!isset($installed['versions'][$packageName])) {
191
+ continue;
192
+ }
193
+
194
+ if (!isset($installed['versions'][$packageName]['pretty_version'])) {
195
+ return null;
196
+ }
197
+
198
+ return $installed['versions'][$packageName]['pretty_version'];
199
+ }
200
+
201
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
202
+ }
203
+
204
+ /**
205
+ * @param string $packageName
206
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
207
+ */
208
+ public static function getReference($packageName)
209
+ {
210
+ foreach (self::getInstalled() as $installed) {
211
+ if (!isset($installed['versions'][$packageName])) {
212
+ continue;
213
+ }
214
+
215
+ if (!isset($installed['versions'][$packageName]['reference'])) {
216
+ return null;
217
+ }
218
+
219
+ return $installed['versions'][$packageName]['reference'];
220
+ }
221
+
222
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
223
+ }
224
+
225
+ /**
226
+ * @param string $packageName
227
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
228
+ */
229
+ public static function getInstallPath($packageName)
230
+ {
231
+ foreach (self::getInstalled() as $installed) {
232
+ if (!isset($installed['versions'][$packageName])) {
233
+ continue;
234
+ }
235
+
236
+ return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
237
+ }
238
+
239
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
240
+ }
241
+
242
+ /**
243
+ * @return array
244
+ * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
245
+ */
246
+ public static function getRootPackage()
247
+ {
248
+ $installed = self::getInstalled();
249
+
250
+ return $installed[0]['root'];
251
+ }
252
+
253
+ /**
254
+ * Returns the raw installed.php data for custom implementations
255
+ *
256
+ * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
257
+ * @return array[]
258
+ * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
259
+ */
260
+ public static function getRawData()
261
+ {
262
+ @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
263
+
264
+ if (null === self::$installed) {
265
+ // only require the installed.php file if this file is loaded from its dumped location,
266
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
267
+ if (substr(__DIR__, -8, 1) !== 'C') {
268
+ self::$installed = include __DIR__ . '/installed.php';
269
+ } else {
270
+ self::$installed = array();
271
+ }
272
+ }
273
+
274
+ return self::$installed;
275
+ }
276
+
277
+ /**
278
+ * Returns the raw data of all installed.php which are currently loaded for custom implementations
279
+ *
280
+ * @return array[]
281
+ * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
282
+ */
283
+ public static function getAllRawData()
284
+ {
285
+ return self::getInstalled();
286
+ }
287
+
288
+ /**
289
+ * Lets you reload the static array from another file
290
+ *
291
+ * This is only useful for complex integrations in which a project needs to use
292
+ * this class but then also needs to execute another project's autoloader in process,
293
+ * and wants to ensure both projects have access to their version of installed.php.
294
+ *
295
+ * A typical case would be PHPUnit, where it would need to make sure it reads all
296
+ * the data it needs from this class, then call reload() with
297
+ * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
298
+ * the project in which it runs can then also use this class safely, without
299
+ * interference between PHPUnit's dependencies and the project's dependencies.
300
+ *
301
+ * @param array[] $data A vendor/composer/installed.php data set
302
+ * @return void
303
+ *
304
+ * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
305
+ */
306
+ public static function reload($data)
307
+ {
308
+ self::$installed = $data;
309
+ self::$installedByVendor = array();
310
+ }
311
+
312
+ /**
313
+ * @return array[]
314
+ * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
315
+ */
316
+ private static function getInstalled()
317
+ {
318
+ if (null === self::$canGetVendors) {
319
+ self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
320
+ }
321
+
322
+ $installed = array();
323
+
324
+ if (self::$canGetVendors) {
325
+ foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
326
+ if (isset(self::$installedByVendor[$vendorDir])) {
327
+ $installed[] = self::$installedByVendor[$vendorDir];
328
+ } elseif (is_file($vendorDir.'/composer/installed.php')) {
329
+ $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
330
+ if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
331
+ self::$installed = $installed[count($installed) - 1];
332
+ }
333
+ }
334
+ }
335
+ }
336
+
337
+ if (null === self::$installed) {
338
+ // only require the installed.php file if this file is loaded from its dumped location,
339
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
340
+ if (substr(__DIR__, -8, 1) !== 'C') {
341
+ self::$installed = require __DIR__ . '/installed.php';
342
+ } else {
343
+ self::$installed = array();
344
+ }
345
+ }
346
+ $installed[] = self::$installed;
347
+
348
+ return $installed;
349
+ }
350
+ }
vendor/composer/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copyright (c) Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname(dirname($vendorDir));
7
+
8
+ return array(
9
+ 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
10
+ );
vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname(dirname($vendorDir));
7
+
8
+ return array(
9
+ );
vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname(dirname($vendorDir));
7
+
8
+ return array(
9
+ 'Tawk\\Tests\\' => array($vendorDir . '/tawk/url-utils/tests'),
10
+ 'Tawk\\' => array($vendorDir . '/tawk/url-utils/lib'),
11
+ );
vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit3eb597ada59a4a18b26320b23bc7d0c2
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ /**
17
+ * @return \Composer\Autoload\ClassLoader
18
+ */
19
+ public static function getLoader()
20
+ {
21
+ if (null !== self::$loader) {
22
+ return self::$loader;
23
+ }
24
+
25
+ spl_autoload_register(array('ComposerAutoloaderInit3eb597ada59a4a18b26320b23bc7d0c2', 'loadClassLoader'), true, true);
26
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
27
+ spl_autoload_unregister(array('ComposerAutoloaderInit3eb597ada59a4a18b26320b23bc7d0c2', 'loadClassLoader'));
28
+
29
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
+ if ($useStaticLoader) {
31
+ require __DIR__ . '/autoload_static.php';
32
+
33
+ call_user_func(\Composer\Autoload\ComposerStaticInit3eb597ada59a4a18b26320b23bc7d0c2::getInitializer($loader));
34
+ } else {
35
+ $map = require __DIR__ . '/autoload_namespaces.php';
36
+ foreach ($map as $namespace => $path) {
37
+ $loader->set($namespace, $path);
38
+ }
39
+
40
+ $map = require __DIR__ . '/autoload_psr4.php';
41
+ foreach ($map as $namespace => $path) {
42
+ $loader->setPsr4($namespace, $path);
43
+ }
44
+
45
+ $classMap = require __DIR__ . '/autoload_classmap.php';
46
+ if ($classMap) {
47
+ $loader->addClassMap($classMap);
48
+ }
49
+ }
50
+
51
+ $loader->register(true);
52
+
53
+ return $loader;
54
+ }
55
+ }
vendor/composer/autoload_static.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInit3eb597ada59a4a18b26320b23bc7d0c2
8
+ {
9
+ public static $prefixLengthsPsr4 = array (
10
+ 'T' =>
11
+ array (
12
+ 'Tawk\\Tests\\' => 11,
13
+ 'Tawk\\' => 5,
14
+ ),
15
+ );
16
+
17
+ public static $prefixDirsPsr4 = array (
18
+ 'Tawk\\Tests\\' =>
19
+ array (
20
+ 0 => __DIR__ . '/..' . '/tawk/url-utils/tests',
21
+ ),
22
+ 'Tawk\\' =>
23
+ array (
24
+ 0 => __DIR__ . '/..' . '/tawk/url-utils/lib',
25
+ ),
26
+ );
27
+
28
+ public static $classMap = array (
29
+ 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
30
+ );
31
+
32
+ public static function getInitializer(ClassLoader $loader)
33
+ {
34
+ return \Closure::bind(function () use ($loader) {
35
+ $loader->prefixLengthsPsr4 = ComposerStaticInit3eb597ada59a4a18b26320b23bc7d0c2::$prefixLengthsPsr4;
36
+ $loader->prefixDirsPsr4 = ComposerStaticInit3eb597ada59a4a18b26320b23bc7d0c2::$prefixDirsPsr4;
37
+ $loader->classMap = ComposerStaticInit3eb597ada59a4a18b26320b23bc7d0c2::$classMap;
38
+
39
+ }, null, ClassLoader::class);
40
+ }
41
+ }
vendor/composer/installed.json ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "packages": [
3
+ {
4
+ "name": "tawk/url-utils",
5
+ "version": "2.0.0",
6
+ "version_normalized": "2.0.0.0",
7
+ "source": {
8
+ "type": "git",
9
+ "url": "https://github.com/tawk/tawk-url-utils.git",
10
+ "reference": "ec70275363ff0dac9d70c9a93399161e5e561a88"
11
+ },
12
+ "dist": {
13
+ "type": "zip",
14
+ "url": "https://api.github.com/repos/tawk/tawk-url-utils/zipball/ec70275363ff0dac9d70c9a93399161e5e561a88",
15
+ "reference": "ec70275363ff0dac9d70c9a93399161e5e561a88",
16
+ "shasum": ""
17
+ },
18
+ "require-dev": {
19
+ "phpunit/phpunit": "^9.5"
20
+ },
21
+ "time": "2021-12-29T08:42:47+00:00",
22
+ "type": "library",
23
+ "installation-source": "dist",
24
+ "autoload": {
25
+ "psr-4": {
26
+ "Tawk\\": "lib",
27
+ "Tawk\\Tests\\": "tests"
28
+ }
29
+ },
30
+ "scripts": {
31
+ "test": [
32
+ "phpunit"
33
+ ]
34
+ },
35
+ "support": {
36
+ "source": "https://github.com/tawk/tawk-url-utils/tree/2.0.0",
37
+ "issues": "https://github.com/tawk/tawk-url-utils/issues"
38
+ },
39
+ "install-path": "../tawk/url-utils"
40
+ }
41
+ ],
42
+ "dev": false,
43
+ "dev-package-names": []
44
+ }
vendor/composer/installed.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php return array(
2
+ 'root' => array(
3
+ 'pretty_version' => '0.7.0',
4
+ 'version' => '0.7.0.0',
5
+ 'type' => 'project',
6
+ 'install_path' => __DIR__ . '/../../../',
7
+ 'aliases' => array(),
8
+ 'reference' => NULL,
9
+ 'name' => 'tawk/tawk-wordpress',
10
+ 'dev' => false,
11
+ ),
12
+ 'versions' => array(
13
+ 'tawk/tawk-wordpress' => array(
14
+ 'pretty_version' => '0.7.0',
15
+ 'version' => '0.7.0.0',
16
+ 'type' => 'project',
17
+ 'install_path' => __DIR__ . '/../../../',
18
+ 'aliases' => array(),
19
+ 'reference' => NULL,
20
+ 'dev_requirement' => false,
21
+ ),
22
+ 'tawk/url-utils' => array(
23
+ 'pretty_version' => '2.0.0',
24
+ 'version' => '2.0.0.0',
25
+ 'type' => 'library',
26
+ 'install_path' => __DIR__ . '/../tawk/url-utils',
27
+ 'aliases' => array(),
28
+ 'reference' => 'ec70275363ff0dac9d70c9a93399161e5e561a88',
29
+ 'dev_requirement' => false,
30
+ ),
31
+ ),
32
+ );
vendor/tawk/url-utils/.gitattributes ADDED
@@ -0,0 +1 @@
 
1
+ /.github export-ignore
vendor/tawk/url-utils/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
1
+ /vendor/
2
+ .phpunit.*
vendor/tawk/url-utils/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 2.0.0
2
+
3
+ ## General changes
4
+
5
+ - [Breaking] Removed old matching modules.
6
+ - `Tawk\Match\Path`
7
+ - `Tawk\Match\Url`
8
+ - Added new modules for pattern matching.
9
+ - `Tawk\Modules\PathPatternMatcher`
10
+ - `Tawk\Modules\UrlPatternMatcher`
11
+ - Added new helpers for parsing URLs and paths.
12
+ - `Tawk\Helpers\PathHelper`
13
+ - `Tawk\Helpers\UrlHelper`
14
+ - Added new enum `Tawk\Enums\WildcardLocation`.
15
+
16
+ # 1.0.0
17
+
18
+ Initial Release
vendor/tawk/url-utils/README.md ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Tawk URL Utils Module
2
+
3
+ ## Overview
4
+
5
+ A tawk.to utility library for URLs.
6
+
7
+ ## Modules
8
+
9
+ ### Url Pattern Matcher
10
+
11
+ This module handles matching of the provided URL to the provided patterns.
12
+
13
+ #### match(string $current_url, array $patterns)
14
+
15
+ Matches the provided url and patterns. Returns `true` if it matches. Otherwise, `false`.
16
+
17
+ ##### Example
18
+
19
+ ```php
20
+ <?php
21
+ use Tawk\Modules\UrlPatternMatcher;
22
+
23
+ $current_url = 'http://www.example.com/path/to/somewhere';
24
+ $patterns = array('http://www.example.com/path/to/somewhere');
25
+
26
+ $match_result = UrlPatternMatcher::match($current_url, $patterns);
27
+ ```
28
+
29
+ ### Path Pattern Matcher
30
+
31
+ This module handles matching of the provided URL path to the provided patterns by matching them per chunk.
32
+
33
+ #### match(array $current_path_chunks, array $path_patterns)
34
+
35
+ Matches the provided url path and patterns. Returns `true` if it matches. Otherwise, `false`.
36
+
37
+ ```php
38
+ <?php
39
+ use Tawk\Helpers\PathHelper;
40
+ use Tawk\Models\PathPattern;
41
+ use Tawk\Modules\PathPatternMatcher;
42
+
43
+ $current_url = PathHelper::get_chunks('/path/to/somewhere');
44
+ $path_patterns = array(
45
+ PathPattern::create_instance_from_path('/path/to/somewhere'),
46
+ );
47
+
48
+ $match_result = PathPatternMatcher::match($current_url, $path_patterns);
49
+ ```
50
+
51
+ ### Additional Info
52
+
53
+ #### Valid Patterns for Pattern Matchers
54
+
55
+ - `*`
56
+ - `*/to/somewhere`
57
+ - `/*/to/somewhere`
58
+ - `/path/*/somewhere`
59
+ - `/path/*/lead/*/somewhere`
60
+ - `/path/*/*/somewhere`
61
+ - `/path/to/*`
62
+ - `/path/to/*/`
63
+ - `*/to/*/page`
64
+ - `/*/to/*/page`
65
+ - `/path/*/other/*`
66
+ - `/path/*/other/*/`
67
+ - `http://www.example.com/`
68
+ - `http://www.example.com/*`
69
+ - `http://www.example.com/*/to/somewhere`
70
+ - `http://www.example.com/path/*/somewhere`
71
+ - `http://www.example.com/path/*/lead/*/somewhere`
72
+ - `http://www.example.com/path/*/*/somewhere`
73
+ - `http://www.example.com/path/to/*`
74
+ - `http://www.example.com/path/to/*/`
75
+ - `http://www.example.com/*/to/*/page`
76
+ - `http://www.example.com/path/*/other/*`
77
+ - `http://www.example.com/path/*/other/*/`
78
+
79
+ #### Invalid Patterns for Pattern Matchers
80
+
81
+ - `path/*/somewhere` - "path" will be considered as a host and not a start of a path.
82
+ - `*/should/*/to/*` - This is currently not supported. Multiple wildcards on the pattern only supports either at `START and MIDDLE` or `MIDDLE and END` of the path.
vendor/tawk/url-utils/composer.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "tawk/url-utils",
3
+ "type": "library",
4
+ "require-dev": {
5
+ "phpunit/phpunit": "^9.5"
6
+ },
7
+ "version" : "2.0.0",
8
+ "autoload": {
9
+ "psr-4": {
10
+ "Tawk\\": "lib",
11
+ "Tawk\\Tests\\": "tests"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "test": "phpunit"
16
+ }
17
+ }
vendor/tawk/url-utils/composer.lock ADDED
@@ -0,0 +1,2111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_readme": [
3
+ "This file locks the dependencies of your project to a known state",
4
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
+ "This file is @generated automatically"
6
+ ],
7
+ "content-hash": "656998700722e65aa1bdc0601a62add9",
8
+ "packages": [],
9
+ "packages-dev": [
10
+ {
11
+ "name": "doctrine/instantiator",
12
+ "version": "1.4.0",
13
+ "source": {
14
+ "type": "git",
15
+ "url": "https://github.com/doctrine/instantiator.git",
16
+ "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b"
17
+ },
18
+ "dist": {
19
+ "type": "zip",
20
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b",
21
+ "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b",
22
+ "shasum": ""
23
+ },
24
+ "require": {
25
+ "php": "^7.1 || ^8.0"
26
+ },
27
+ "require-dev": {
28
+ "doctrine/coding-standard": "^8.0",
29
+ "ext-pdo": "*",
30
+ "ext-phar": "*",
31
+ "phpbench/phpbench": "^0.13 || 1.0.0-alpha2",
32
+ "phpstan/phpstan": "^0.12",
33
+ "phpstan/phpstan-phpunit": "^0.12",
34
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
35
+ },
36
+ "type": "library",
37
+ "autoload": {
38
+ "psr-4": {
39
+ "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
40
+ }
41
+ },
42
+ "notification-url": "https://packagist.org/downloads/",
43
+ "license": [
44
+ "MIT"
45
+ ],
46
+ "authors": [
47
+ {
48
+ "name": "Marco Pivetta",
49
+ "email": "ocramius@gmail.com",
50
+ "homepage": "https://ocramius.github.io/"
51
+ }
52
+ ],
53
+ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
54
+ "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
55
+ "keywords": [
56
+ "constructor",
57
+ "instantiate"
58
+ ],
59
+ "support": {
60
+ "issues": "https://github.com/doctrine/instantiator/issues",
61
+ "source": "https://github.com/doctrine/instantiator/tree/1.4.0"
62
+ },
63
+ "funding": [
64
+ {
65
+ "url": "https://www.doctrine-project.org/sponsorship.html",
66
+ "type": "custom"
67
+ },
68
+ {
69
+ "url": "https://www.patreon.com/phpdoctrine",
70
+ "type": "patreon"
71
+ },
72
+ {
73
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
74
+ "type": "tidelift"
75
+ }
76
+ ],
77
+ "time": "2020-11-10T18:47:58+00:00"
78
+ },
79
+ {
80
+ "name": "myclabs/deep-copy",
81
+ "version": "1.10.2",
82
+ "source": {
83
+ "type": "git",
84
+ "url": "https://github.com/myclabs/DeepCopy.git",
85
+ "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220"
86
+ },
87
+ "dist": {
88
+ "type": "zip",
89
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220",
90
+ "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220",
91
+ "shasum": ""
92
+ },
93
+ "require": {
94
+ "php": "^7.1 || ^8.0"
95
+ },
96
+ "replace": {
97
+ "myclabs/deep-copy": "self.version"
98
+ },
99
+ "require-dev": {
100
+ "doctrine/collections": "^1.0",
101
+ "doctrine/common": "^2.6",
102
+ "phpunit/phpunit": "^7.1"
103
+ },
104
+ "type": "library",
105
+ "autoload": {
106
+ "psr-4": {
107
+ "DeepCopy\\": "src/DeepCopy/"
108
+ },
109
+ "files": [
110
+ "src/DeepCopy/deep_copy.php"
111
+ ]
112
+ },
113
+ "notification-url": "https://packagist.org/downloads/",
114
+ "license": [
115
+ "MIT"
116
+ ],
117
+ "description": "Create deep copies (clones) of your objects",
118
+ "keywords": [
119
+ "clone",
120
+ "copy",
121
+ "duplicate",
122
+ "object",
123
+ "object graph"
124
+ ],
125
+ "support": {
126
+ "issues": "https://github.com/myclabs/DeepCopy/issues",
127
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2"
128
+ },
129
+ "funding": [
130
+ {
131
+ "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
132
+ "type": "tidelift"
133
+ }
134
+ ],
135
+ "time": "2020-11-13T09:40:50+00:00"
136
+ },
137
+ {
138
+ "name": "nikic/php-parser",
139
+ "version": "v4.13.0",
140
+ "source": {
141
+ "type": "git",
142
+ "url": "https://github.com/nikic/PHP-Parser.git",
143
+ "reference": "50953a2691a922aa1769461637869a0a2faa3f53"
144
+ },
145
+ "dist": {
146
+ "type": "zip",
147
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53",
148
+ "reference": "50953a2691a922aa1769461637869a0a2faa3f53",
149
+ "shasum": ""
150
+ },
151
+ "require": {
152
+ "ext-tokenizer": "*",
153
+ "php": ">=7.0"
154
+ },
155
+ "require-dev": {
156
+ "ircmaxell/php-yacc": "^0.0.7",
157
+ "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
158
+ },
159
+ "bin": [
160
+ "bin/php-parse"
161
+ ],
162
+ "type": "library",
163
+ "extra": {
164
+ "branch-alias": {
165
+ "dev-master": "4.9-dev"
166
+ }
167
+ },
168
+ "autoload": {
169
+ "psr-4": {
170
+ "PhpParser\\": "lib/PhpParser"
171
+ }
172
+ },
173
+ "notification-url": "https://packagist.org/downloads/",
174
+ "license": [
175
+ "BSD-3-Clause"
176
+ ],
177
+ "authors": [
178
+ {
179
+ "name": "Nikita Popov"
180
+ }
181
+ ],
182
+ "description": "A PHP parser written in PHP",
183
+ "keywords": [
184
+ "parser",
185
+ "php"
186
+ ],
187
+ "support": {
188
+ "issues": "https://github.com/nikic/PHP-Parser/issues",
189
+ "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.0"
190
+ },
191
+ "time": "2021-09-20T12:20:58+00:00"
192
+ },
193
+ {
194
+ "name": "phar-io/manifest",
195
+ "version": "2.0.3",
196
+ "source": {
197
+ "type": "git",
198
+ "url": "https://github.com/phar-io/manifest.git",
199
+ "reference": "97803eca37d319dfa7826cc2437fc020857acb53"
200
+ },
201
+ "dist": {
202
+ "type": "zip",
203
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
204
+ "reference": "97803eca37d319dfa7826cc2437fc020857acb53",
205
+ "shasum": ""
206
+ },
207
+ "require": {
208
+ "ext-dom": "*",
209
+ "ext-phar": "*",
210
+ "ext-xmlwriter": "*",
211
+ "phar-io/version": "^3.0.1",
212
+ "php": "^7.2 || ^8.0"
213
+ },
214
+ "type": "library",
215
+ "extra": {
216
+ "branch-alias": {
217
+ "dev-master": "2.0.x-dev"
218
+ }
219
+ },
220
+ "autoload": {
221
+ "classmap": [
222
+ "src/"
223
+ ]
224
+ },
225
+ "notification-url": "https://packagist.org/downloads/",
226
+ "license": [
227
+ "BSD-3-Clause"
228
+ ],
229
+ "authors": [
230
+ {
231
+ "name": "Arne Blankerts",
232
+ "email": "arne@blankerts.de",
233
+ "role": "Developer"
234
+ },
235
+ {
236
+ "name": "Sebastian Heuer",
237
+ "email": "sebastian@phpeople.de",
238
+ "role": "Developer"
239
+ },
240
+ {
241
+ "name": "Sebastian Bergmann",
242
+ "email": "sebastian@phpunit.de",
243
+ "role": "Developer"
244
+ }
245
+ ],
246
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
247
+ "support": {
248
+ "issues": "https://github.com/phar-io/manifest/issues",
249
+ "source": "https://github.com/phar-io/manifest/tree/2.0.3"
250
+ },
251
+ "time": "2021-07-20T11:28:43+00:00"
252
+ },
253
+ {
254
+ "name": "phar-io/version",
255
+ "version": "3.1.0",
256
+ "source": {
257
+ "type": "git",
258
+ "url": "https://github.com/phar-io/version.git",
259
+ "reference": "bae7c545bef187884426f042434e561ab1ddb182"
260
+ },
261
+ "dist": {
262
+ "type": "zip",
263
+ "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182",
264
+ "reference": "bae7c545bef187884426f042434e561ab1ddb182",
265
+ "shasum": ""
266
+ },
267
+ "require": {
268
+ "php": "^7.2 || ^8.0"
269
+ },
270
+ "type": "library",
271
+ "autoload": {
272
+ "classmap": [
273
+ "src/"
274
+ ]
275
+ },
276
+ "notification-url": "https://packagist.org/downloads/",
277
+ "license": [
278
+ "BSD-3-Clause"
279
+ ],
280
+ "authors": [
281
+ {
282
+ "name": "Arne Blankerts",
283
+ "email": "arne@blankerts.de",
284
+ "role": "Developer"
285
+ },
286
+ {
287
+ "name": "Sebastian Heuer",
288
+ "email": "sebastian@phpeople.de",
289
+ "role": "Developer"
290
+ },
291
+ {
292
+ "name": "Sebastian Bergmann",
293
+ "email": "sebastian@phpunit.de",
294
+ "role": "Developer"
295
+ }
296
+ ],
297
+ "description": "Library for handling version information and constraints",
298
+ "support": {
299
+ "issues": "https://github.com/phar-io/version/issues",
300
+ "source": "https://github.com/phar-io/version/tree/3.1.0"
301
+ },
302
+ "time": "2021-02-23T14:00:09+00:00"
303
+ },
304
+ {
305
+ "name": "phpdocumentor/reflection-common",
306
+ "version": "2.2.0",
307
+ "source": {
308
+ "type": "git",
309
+ "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
310
+ "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
311
+ },
312
+ "dist": {
313
+ "type": "zip",
314
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
315
+ "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
316
+ "shasum": ""
317
+ },
318
+ "require": {
319
+ "php": "^7.2 || ^8.0"
320
+ },
321
+ "type": "library",
322
+ "extra": {
323
+ "branch-alias": {
324
+ "dev-2.x": "2.x-dev"
325
+ }
326
+ },
327
+ "autoload": {
328
+ "psr-4": {
329
+ "phpDocumentor\\Reflection\\": "src/"
330
+ }
331
+ },
332
+ "notification-url": "https://packagist.org/downloads/",
333
+ "license": [
334
+ "MIT"
335
+ ],
336
+ "authors": [
337
+ {
338
+ "name": "Jaap van Otterdijk",
339
+ "email": "opensource@ijaap.nl"
340
+ }
341
+ ],
342
+ "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
343
+ "homepage": "http://www.phpdoc.org",
344
+ "keywords": [
345
+ "FQSEN",
346
+ "phpDocumentor",
347
+ "phpdoc",
348
+ "reflection",
349
+ "static analysis"
350
+ ],
351
+ "support": {
352
+ "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
353
+ "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
354
+ },
355
+ "time": "2020-06-27T09:03:43+00:00"
356
+ },
357
+ {
358
+ "name": "phpdocumentor/reflection-docblock",
359
+ "version": "5.2.2",
360
+ "source": {
361
+ "type": "git",
362
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
363
+ "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556"
364
+ },
365
+ "dist": {
366
+ "type": "zip",
367
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556",
368
+ "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556",
369
+ "shasum": ""
370
+ },
371
+ "require": {
372
+ "ext-filter": "*",
373
+ "php": "^7.2 || ^8.0",
374
+ "phpdocumentor/reflection-common": "^2.2",
375
+ "phpdocumentor/type-resolver": "^1.3",
376
+ "webmozart/assert": "^1.9.1"
377
+ },
378
+ "require-dev": {
379
+ "mockery/mockery": "~1.3.2"
380
+ },
381
+ "type": "library",
382
+ "extra": {
383
+ "branch-alias": {
384
+ "dev-master": "5.x-dev"
385
+ }
386
+ },
387
+ "autoload": {
388
+ "psr-4": {
389
+ "phpDocumentor\\Reflection\\": "src"
390
+ }
391
+ },
392
+ "notification-url": "https://packagist.org/downloads/",
393
+ "license": [
394
+ "MIT"
395
+ ],
396
+ "authors": [
397
+ {
398
+ "name": "Mike van Riel",
399
+ "email": "me@mikevanriel.com"
400
+ },
401
+ {
402
+ "name": "Jaap van Otterdijk",
403
+ "email": "account@ijaap.nl"
404
+ }
405
+ ],
406
+ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
407
+ "support": {
408
+ "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
409
+ "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master"
410
+ },
411
+ "time": "2020-09-03T19:13:55+00:00"
412
+ },
413
+ {
414
+ "name": "phpdocumentor/type-resolver",
415
+ "version": "1.5.1",
416
+ "source": {
417
+ "type": "git",
418
+ "url": "https://github.com/phpDocumentor/TypeResolver.git",
419
+ "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae"
420
+ },
421
+ "dist": {
422
+ "type": "zip",
423
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/a12f7e301eb7258bb68acd89d4aefa05c2906cae",
424
+ "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae",
425
+ "shasum": ""
426
+ },
427
+ "require": {
428
+ "php": "^7.2 || ^8.0",
429
+ "phpdocumentor/reflection-common": "^2.0"
430
+ },
431
+ "require-dev": {
432
+ "ext-tokenizer": "*",
433
+ "psalm/phar": "^4.8"
434
+ },
435
+ "type": "library",
436
+ "extra": {
437
+ "branch-alias": {
438
+ "dev-1.x": "1.x-dev"
439
+ }
440
+ },
441
+ "autoload": {
442
+ "psr-4": {
443
+ "phpDocumentor\\Reflection\\": "src"
444
+ }
445
+ },
446
+ "notification-url": "https://packagist.org/downloads/",
447
+ "license": [
448
+ "MIT"
449
+ ],
450
+ "authors": [
451
+ {
452
+ "name": "Mike van Riel",
453
+ "email": "me@mikevanriel.com"
454
+ }
455
+ ],
456
+ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
457
+ "support": {
458
+ "issues": "https://github.com/phpDocumentor/TypeResolver/issues",
459
+ "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.5.1"
460
+ },
461
+ "time": "2021-10-02T14:08:47+00:00"
462
+ },
463
+ {
464
+ "name": "phpspec/prophecy",
465
+ "version": "1.14.0",
466
+ "source": {
467
+ "type": "git",
468
+ "url": "https://github.com/phpspec/prophecy.git",
469
+ "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e"
470
+ },
471
+ "dist": {
472
+ "type": "zip",
473
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e",
474
+ "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e",
475
+ "shasum": ""
476
+ },
477
+ "require": {
478
+ "doctrine/instantiator": "^1.2",
479
+ "php": "^7.2 || ~8.0, <8.2",
480
+ "phpdocumentor/reflection-docblock": "^5.2",
481
+ "sebastian/comparator": "^3.0 || ^4.0",
482
+ "sebastian/recursion-context": "^3.0 || ^4.0"
483
+ },
484
+ "require-dev": {
485
+ "phpspec/phpspec": "^6.0 || ^7.0",
486
+ "phpunit/phpunit": "^8.0 || ^9.0"
487
+ },
488
+ "type": "library",
489
+ "extra": {
490
+ "branch-alias": {
491
+ "dev-master": "1.x-dev"
492
+ }
493
+ },
494
+ "autoload": {
495
+ "psr-4": {
496
+ "Prophecy\\": "src/Prophecy"
497
+ }
498
+ },
499
+ "notification-url": "https://packagist.org/downloads/",
500
+ "license": [
501
+ "MIT"
502
+ ],
503
+ "authors": [
504
+ {
505
+ "name": "Konstantin Kudryashov",
506
+ "email": "ever.zet@gmail.com",
507
+ "homepage": "http://everzet.com"
508
+ },
509
+ {
510
+ "name": "Marcello Duarte",
511
+ "email": "marcello.duarte@gmail.com"
512
+ }
513
+ ],
514
+ "description": "Highly opinionated mocking framework for PHP 5.3+",
515
+ "homepage": "https://github.com/phpspec/prophecy",
516
+ "keywords": [
517
+ "Double",
518
+ "Dummy",
519
+ "fake",
520
+ "mock",
521
+ "spy",
522
+ "stub"
523
+ ],
524
+ "support": {
525
+ "issues": "https://github.com/phpspec/prophecy/issues",
526
+ "source": "https://github.com/phpspec/prophecy/tree/1.14.0"
527
+ },
528
+ "time": "2021-09-10T09:02:12+00:00"
529
+ },
530
+ {
531
+ "name": "phpunit/php-code-coverage",
532
+ "version": "9.2.7",
533
+ "source": {
534
+ "type": "git",
535
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
536
+ "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218"
537
+ },
538
+ "dist": {
539
+ "type": "zip",
540
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d4c798ed8d51506800b441f7a13ecb0f76f12218",
541
+ "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218",
542
+ "shasum": ""
543
+ },
544
+ "require": {
545
+ "ext-dom": "*",
546
+ "ext-libxml": "*",
547
+ "ext-xmlwriter": "*",
548
+ "nikic/php-parser": "^4.12.0",
549
+ "php": ">=7.3",
550
+ "phpunit/php-file-iterator": "^3.0.3",
551
+ "phpunit/php-text-template": "^2.0.2",
552
+ "sebastian/code-unit-reverse-lookup": "^2.0.2",
553
+ "sebastian/complexity": "^2.0",
554
+ "sebastian/environment": "^5.1.2",
555
+ "sebastian/lines-of-code": "^1.0.3",
556
+ "sebastian/version": "^3.0.1",
557
+ "theseer/tokenizer": "^1.2.0"
558
+ },
559
+ "require-dev": {
560
+ "phpunit/phpunit": "^9.3"
561
+ },
562
+ "suggest": {
563
+ "ext-pcov": "*",
564
+ "ext-xdebug": "*"
565
+ },
566
+ "type": "library",
567
+ "extra": {
568
+ "branch-alias": {
569
+ "dev-master": "9.2-dev"
570
+ }
571
+ },
572
+ "autoload": {
573
+ "classmap": [
574
+ "src/"
575
+ ]
576
+ },
577
+ "notification-url": "https://packagist.org/downloads/",
578
+ "license": [
579
+ "BSD-3-Clause"
580
+ ],
581
+ "authors": [
582
+ {
583
+ "name": "Sebastian Bergmann",
584
+ "email": "sebastian@phpunit.de",
585
+ "role": "lead"
586
+ }
587
+ ],
588
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
589
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
590
+ "keywords": [
591
+ "coverage",
592
+ "testing",
593
+ "xunit"
594
+ ],
595
+ "support": {
596
+ "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
597
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.7"
598
+ },
599
+ "funding": [
600
+ {
601
+ "url": "https://github.com/sebastianbergmann",
602
+ "type": "github"
603
+ }
604
+ ],
605
+ "time": "2021-09-17T05:39:03+00:00"
606
+ },
607
+ {
608
+ "name": "phpunit/php-file-iterator",
609
+ "version": "3.0.5",
610
+ "source": {
611
+ "type": "git",
612
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
613
+ "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8"
614
+ },
615
+ "dist": {
616
+ "type": "zip",
617
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8",
618
+ "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8",
619
+ "shasum": ""
620
+ },
621
+ "require": {
622
+ "php": ">=7.3"
623
+ },
624
+ "require-dev": {
625
+ "phpunit/phpunit": "^9.3"
626
+ },
627
+ "type": "library",
628
+ "extra": {
629
+ "branch-alias": {
630
+ "dev-master": "3.0-dev"
631
+ }
632
+ },
633
+ "autoload": {
634
+ "classmap": [
635
+ "src/"
636
+ ]
637
+ },
638
+ "notification-url": "https://packagist.org/downloads/",
639
+ "license": [
640
+ "BSD-3-Clause"
641
+ ],
642
+ "authors": [
643
+ {
644
+ "name": "Sebastian Bergmann",
645
+ "email": "sebastian@phpunit.de",
646
+ "role": "lead"
647
+ }
648
+ ],
649
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
650
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
651
+ "keywords": [
652
+ "filesystem",
653
+ "iterator"
654
+ ],
655
+ "support": {
656
+ "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
657
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5"
658
+ },
659
+ "funding": [
660
+ {
661
+ "url": "https://github.com/sebastianbergmann",
662
+ "type": "github"
663
+ }
664
+ ],
665
+ "time": "2020-09-28T05:57:25+00:00"
666
+ },
667
+ {
668
+ "name": "phpunit/php-invoker",
669
+ "version": "3.1.1",
670
+ "source": {
671
+ "type": "git",
672
+ "url": "https://github.com/sebastianbergmann/php-invoker.git",
673
+ "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
674
+ },
675
+ "dist": {
676
+ "type": "zip",
677
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
678
+ "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
679
+ "shasum": ""
680
+ },
681
+ "require": {
682
+ "php": ">=7.3"
683
+ },
684
+ "require-dev": {
685
+ "ext-pcntl": "*",
686
+ "phpunit/phpunit": "^9.3"
687
+ },
688
+ "suggest": {
689
+ "ext-pcntl": "*"
690
+ },
691
+ "type": "library",
692
+ "extra": {
693
+ "branch-alias": {
694
+ "dev-master": "3.1-dev"
695
+ }
696
+ },
697
+ "autoload": {
698
+ "classmap": [
699
+ "src/"
700
+ ]
701
+ },
702
+ "notification-url": "https://packagist.org/downloads/",
703
+ "license": [
704
+ "BSD-3-Clause"
705
+ ],
706
+ "authors": [
707
+ {
708
+ "name": "Sebastian Bergmann",
709
+ "email": "sebastian@phpunit.de",
710
+ "role": "lead"
711
+ }
712
+ ],
713
+ "description": "Invoke callables with a timeout",
714
+ "homepage": "https://github.com/sebastianbergmann/php-invoker/",
715
+ "keywords": [
716
+ "process"
717
+ ],
718
+ "support": {
719
+ "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
720
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
721
+ },
722
+ "funding": [
723
+ {
724
+ "url": "https://github.com/sebastianbergmann",
725
+ "type": "github"
726
+ }
727
+ ],
728
+ "time": "2020-09-28T05:58:55+00:00"
729
+ },
730
+ {
731
+ "name": "phpunit/php-text-template",
732
+ "version": "2.0.4",
733
+ "source": {
734
+ "type": "git",
735
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
736
+ "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
737
+ },
738
+ "dist": {
739
+ "type": "zip",
740
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
741
+ "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
742
+ "shasum": ""
743
+ },
744
+ "require": {
745
+ "php": ">=7.3"
746
+ },
747
+ "require-dev": {
748
+ "phpunit/phpunit": "^9.3"
749
+ },
750
+ "type": "library",
751
+ "extra": {
752
+ "branch-alias": {
753
+ "dev-master": "2.0-dev"
754
+ }
755
+ },
756
+ "autoload": {
757
+ "classmap": [
758
+ "src/"
759
+ ]
760
+ },
761
+ "notification-url": "https://packagist.org/downloads/",
762
+ "license": [
763
+ "BSD-3-Clause"
764
+ ],
765
+ "authors": [
766
+ {
767
+ "name": "Sebastian Bergmann",
768
+ "email": "sebastian@phpunit.de",
769
+ "role": "lead"
770
+ }
771
+ ],
772
+ "description": "Simple template engine.",
773
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
774
+ "keywords": [
775
+ "template"
776
+ ],
777
+ "support": {
778
+ "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
779
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
780
+ },
781
+ "funding": [
782
+ {
783
+ "url": "https://github.com/sebastianbergmann",
784
+ "type": "github"
785
+ }
786
+ ],
787
+ "time": "2020-10-26T05:33:50+00:00"
788
+ },
789
+ {
790
+ "name": "phpunit/php-timer",
791
+ "version": "5.0.3",
792
+ "source": {
793
+ "type": "git",
794
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
795
+ "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
796
+ },
797
+ "dist": {
798
+ "type": "zip",
799
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
800
+ "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
801
+ "shasum": ""
802
+ },
803
+ "require": {
804
+ "php": ">=7.3"
805
+ },
806
+ "require-dev": {
807
+ "phpunit/phpunit": "^9.3"
808
+ },
809
+ "type": "library",
810
+ "extra": {
811
+ "branch-alias": {
812
+ "dev-master": "5.0-dev"
813
+ }
814
+ },
815
+ "autoload": {
816
+ "classmap": [
817
+ "src/"
818
+ ]
819
+ },
820
+ "notification-url": "https://packagist.org/downloads/",
821
+ "license": [
822
+ "BSD-3-Clause"
823
+ ],
824
+ "authors": [
825
+ {
826
+ "name": "Sebastian Bergmann",
827
+ "email": "sebastian@phpunit.de",
828
+ "role": "lead"
829
+ }
830
+ ],
831
+ "description": "Utility class for timing",
832
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
833
+ "keywords": [
834
+ "timer"
835
+ ],
836
+ "support": {
837
+ "issues": "https://github.com/sebastianbergmann/php-timer/issues",
838
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
839
+ },
840
+ "funding": [
841
+ {
842
+ "url": "https://github.com/sebastianbergmann",
843
+ "type": "github"
844
+ }
845
+ ],
846
+ "time": "2020-10-26T13:16:10+00:00"
847
+ },
848
+ {
849
+ "name": "phpunit/phpunit",
850
+ "version": "9.5.10",
851
+ "source": {
852
+ "type": "git",
853
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
854
+ "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a"
855
+ },
856
+ "dist": {
857
+ "type": "zip",
858
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c814a05837f2edb0d1471d6e3f4ab3501ca3899a",
859
+ "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a",
860
+ "shasum": ""
861
+ },
862
+ "require": {
863
+ "doctrine/instantiator": "^1.3.1",
864
+ "ext-dom": "*",
865
+ "ext-json": "*",
866
+ "ext-libxml": "*",
867
+ "ext-mbstring": "*",
868
+ "ext-xml": "*",
869
+ "ext-xmlwriter": "*",
870
+ "myclabs/deep-copy": "^1.10.1",
871
+ "phar-io/manifest": "^2.0.3",
872
+ "phar-io/version": "^3.0.2",
873
+ "php": ">=7.3",
874
+ "phpspec/prophecy": "^1.12.1",
875
+ "phpunit/php-code-coverage": "^9.2.7",
876
+ "phpunit/php-file-iterator": "^3.0.5",
877
+ "phpunit/php-invoker": "^3.1.1",
878
+ "phpunit/php-text-template": "^2.0.3",
879
+ "phpunit/php-timer": "^5.0.2",
880
+ "sebastian/cli-parser": "^1.0.1",
881
+ "sebastian/code-unit": "^1.0.6",
882
+ "sebastian/comparator": "^4.0.5",
883
+ "sebastian/diff": "^4.0.3",
884
+ "sebastian/environment": "^5.1.3",
885
+ "sebastian/exporter": "^4.0.3",
886
+ "sebastian/global-state": "^5.0.1",
887
+ "sebastian/object-enumerator": "^4.0.3",
888
+ "sebastian/resource-operations": "^3.0.3",
889
+ "sebastian/type": "^2.3.4",
890
+ "sebastian/version": "^3.0.2"
891
+ },
892
+ "require-dev": {
893
+ "ext-pdo": "*",
894
+ "phpspec/prophecy-phpunit": "^2.0.1"
895
+ },
896
+ "suggest": {
897
+ "ext-soap": "*",
898
+ "ext-xdebug": "*"
899
+ },
900
+ "bin": [
901
+ "phpunit"
902
+ ],
903
+ "type": "library",
904
+ "extra": {
905
+ "branch-alias": {
906
+ "dev-master": "9.5-dev"
907
+ }
908
+ },
909
+ "autoload": {
910
+ "classmap": [
911
+ "src/"
912
+ ],
913
+ "files": [
914
+ "src/Framework/Assert/Functions.php"
915
+ ]
916
+ },
917
+ "notification-url": "https://packagist.org/downloads/",
918
+ "license": [
919
+ "BSD-3-Clause"
920
+ ],
921
+ "authors": [
922
+ {
923
+ "name": "Sebastian Bergmann",
924
+ "email": "sebastian@phpunit.de",
925
+ "role": "lead"
926
+ }
927
+ ],
928
+ "description": "The PHP Unit Testing framework.",
929
+ "homepage": "https://phpunit.de/",
930
+ "keywords": [
931
+ "phpunit",
932
+ "testing",
933
+ "xunit"
934
+ ],
935
+ "support": {
936
+ "issues": "https://github.com/sebastianbergmann/phpunit/issues",
937
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.10"
938
+ },
939
+ "funding": [
940
+ {
941
+ "url": "https://phpunit.de/donate.html",
942
+ "type": "custom"
943
+ },
944
+ {
945
+ "url": "https://github.com/sebastianbergmann",
946
+ "type": "github"
947
+ }
948
+ ],
949
+ "time": "2021-09-25T07:38:51+00:00"
950
+ },
951
+ {
952
+ "name": "sebastian/cli-parser",
953
+ "version": "1.0.1",
954
+ "source": {
955
+ "type": "git",
956
+ "url": "https://github.com/sebastianbergmann/cli-parser.git",
957
+ "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
958
+ },
959
+ "dist": {
960
+ "type": "zip",
961
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
962
+ "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
963
+ "shasum": ""
964
+ },
965
+ "require": {
966
+ "php": ">=7.3"
967
+ },
968
+ "require-dev": {
969
+ "phpunit/phpunit": "^9.3"
970
+ },
971
+ "type": "library",
972
+ "extra": {
973
+ "branch-alias": {
974
+ "dev-master": "1.0-dev"
975
+ }
976
+ },
977
+ "autoload": {
978
+ "classmap": [
979
+ "src/"
980
+ ]
981
+ },
982
+ "notification-url": "https://packagist.org/downloads/",
983
+ "license": [
984
+ "BSD-3-Clause"
985
+ ],
986
+ "authors": [
987
+ {
988
+ "name": "Sebastian Bergmann",
989
+ "email": "sebastian@phpunit.de",
990
+ "role": "lead"
991
+ }
992
+ ],
993
+ "description": "Library for parsing CLI options",
994
+ "homepage": "https://github.com/sebastianbergmann/cli-parser",
995
+ "support": {
996
+ "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
997
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
998
+ },
999
+ "funding": [
1000
+ {
1001
+ "url": "https://github.com/sebastianbergmann",
1002
+ "type": "github"
1003
+ }
1004
+ ],
1005
+ "time": "2020-09-28T06:08:49+00:00"
1006
+ },
1007
+ {
1008
+ "name": "sebastian/code-unit",
1009
+ "version": "1.0.8",
1010
+ "source": {
1011
+ "type": "git",
1012
+ "url": "https://github.com/sebastianbergmann/code-unit.git",
1013
+ "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
1014
+ },
1015
+ "dist": {
1016
+ "type": "zip",
1017
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
1018
+ "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
1019
+ "shasum": ""
1020
+ },
1021
+ "require": {
1022
+ "php": ">=7.3"
1023
+ },
1024
+ "require-dev": {
1025
+ "phpunit/phpunit": "^9.3"
1026
+ },
1027
+ "type": "library",
1028
+ "extra": {
1029
+ "branch-alias": {
1030
+ "dev-master": "1.0-dev"
1031
+ }
1032
+ },
1033
+ "autoload": {
1034
+ "classmap": [
1035
+ "src/"
1036
+ ]
1037
+ },
1038
+ "notification-url": "https://packagist.org/downloads/",
1039
+ "license": [
1040
+ "BSD-3-Clause"
1041
+ ],
1042
+ "authors": [
1043
+ {
1044
+ "name": "Sebastian Bergmann",
1045
+ "email": "sebastian@phpunit.de",
1046
+ "role": "lead"
1047
+ }
1048
+ ],
1049
+ "description": "Collection of value objects that represent the PHP code units",
1050
+ "homepage": "https://github.com/sebastianbergmann/code-unit",
1051
+ "support": {
1052
+ "issues": "https://github.com/sebastianbergmann/code-unit/issues",
1053
+ "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
1054
+ },
1055
+ "funding": [
1056
+ {
1057
+ "url": "https://github.com/sebastianbergmann",
1058
+ "type": "github"
1059
+ }
1060
+ ],
1061
+ "time": "2020-10-26T13:08:54+00:00"
1062
+ },
1063
+ {
1064
+ "name": "sebastian/code-unit-reverse-lookup",
1065
+ "version": "2.0.3",
1066
+ "source": {
1067
+ "type": "git",
1068
+ "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
1069
+ "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
1070
+ },
1071
+ "dist": {
1072
+ "type": "zip",
1073
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
1074
+ "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
1075
+ "shasum": ""
1076
+ },
1077
+ "require": {
1078
+ "php": ">=7.3"
1079
+ },
1080
+ "require-dev": {
1081
+ "phpunit/phpunit": "^9.3"
1082
+ },
1083
+ "type": "library",
1084
+ "extra": {
1085
+ "branch-alias": {
1086
+ "dev-master": "2.0-dev"
1087
+ }
1088
+ },
1089
+ "autoload": {
1090
+ "classmap": [
1091
+ "src/"
1092
+ ]
1093
+ },
1094
+ "notification-url": "https://packagist.org/downloads/",
1095
+ "license": [
1096
+ "BSD-3-Clause"
1097
+ ],
1098
+ "authors": [
1099
+ {
1100
+ "name": "Sebastian Bergmann",
1101
+ "email": "sebastian@phpunit.de"
1102
+ }
1103
+ ],
1104
+ "description": "Looks up which function or method a line of code belongs to",
1105
+ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
1106
+ "support": {
1107
+ "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
1108
+ "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
1109
+ },
1110
+ "funding": [
1111
+ {
1112
+ "url": "https://github.com/sebastianbergmann",
1113
+ "type": "github"
1114
+ }
1115
+ ],
1116
+ "time": "2020-09-28T05:30:19+00:00"
1117
+ },
1118
+ {
1119
+ "name": "sebastian/comparator",
1120
+ "version": "4.0.6",
1121
+ "source": {
1122
+ "type": "git",
1123
+ "url": "https://github.com/sebastianbergmann/comparator.git",
1124
+ "reference": "55f4261989e546dc112258c7a75935a81a7ce382"
1125
+ },
1126
+ "dist": {
1127
+ "type": "zip",
1128
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382",
1129
+ "reference": "55f4261989e546dc112258c7a75935a81a7ce382",
1130
+ "shasum": ""
1131
+ },
1132
+ "require": {
1133
+ "php": ">=7.3",
1134
+ "sebastian/diff": "^4.0",
1135
+ "sebastian/exporter": "^4.0"
1136
+ },
1137
+ "require-dev": {
1138
+ "phpunit/phpunit": "^9.3"
1139
+ },
1140
+ "type": "library",
1141
+ "extra": {
1142
+ "branch-alias": {
1143
+ "dev-master": "4.0-dev"
1144
+ }
1145
+ },
1146
+ "autoload": {
1147
+ "classmap": [
1148
+ "src/"
1149
+ ]
1150
+ },
1151
+ "notification-url": "https://packagist.org/downloads/",
1152
+ "license": [
1153
+ "BSD-3-Clause"
1154
+ ],
1155
+ "authors": [
1156
+ {
1157
+ "name": "Sebastian Bergmann",
1158
+ "email": "sebastian@phpunit.de"
1159
+ },
1160
+ {
1161
+ "name": "Jeff Welch",
1162
+ "email": "whatthejeff@gmail.com"
1163
+ },
1164
+ {
1165
+ "name": "Volker Dusch",
1166
+ "email": "github@wallbash.com"
1167
+ },
1168
+ {
1169
+ "name": "Bernhard Schussek",
1170
+ "email": "bschussek@2bepublished.at"
1171
+ }
1172
+ ],
1173
+ "description": "Provides the functionality to compare PHP values for equality",
1174
+ "homepage": "https://github.com/sebastianbergmann/comparator",
1175
+ "keywords": [
1176
+ "comparator",
1177
+ "compare",
1178
+ "equality"
1179
+ ],
1180
+ "support": {
1181
+ "issues": "https://github.com/sebastianbergmann/comparator/issues",
1182
+ "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6"
1183
+ },
1184
+ "funding": [
1185
+ {
1186
+ "url": "https://github.com/sebastianbergmann",
1187
+ "type": "github"
1188
+ }
1189
+ ],
1190
+ "time": "2020-10-26T15:49:45+00:00"
1191
+ },
1192
+ {
1193
+ "name": "sebastian/complexity",
1194
+ "version": "2.0.2",
1195
+ "source": {
1196
+ "type": "git",
1197
+ "url": "https://github.com/sebastianbergmann/complexity.git",
1198
+ "reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
1199
+ },
1200
+ "dist": {
1201
+ "type": "zip",
1202
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
1203
+ "reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
1204
+ "shasum": ""
1205
+ },
1206
+ "require": {
1207
+ "nikic/php-parser": "^4.7",
1208
+ "php": ">=7.3"
1209
+ },
1210
+ "require-dev": {
1211
+ "phpunit/phpunit": "^9.3"
1212
+ },
1213
+ "type": "library",
1214
+ "extra": {
1215
+ "branch-alias": {
1216
+ "dev-master": "2.0-dev"
1217
+ }
1218
+ },
1219
+ "autoload": {
1220
+ "classmap": [
1221
+ "src/"
1222
+ ]
1223
+ },
1224
+ "notification-url": "https://packagist.org/downloads/",
1225
+ "license": [
1226
+ "BSD-3-Clause"
1227
+ ],
1228
+ "authors": [
1229
+ {
1230
+ "name": "Sebastian Bergmann",
1231
+ "email": "sebastian@phpunit.de",
1232
+ "role": "lead"
1233
+ }
1234
+ ],
1235
+ "description": "Library for calculating the complexity of PHP code units",
1236
+ "homepage": "https://github.com/sebastianbergmann/complexity",
1237
+ "support": {
1238
+ "issues": "https://github.com/sebastianbergmann/complexity/issues",
1239
+ "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
1240
+ },
1241
+ "funding": [
1242
+ {
1243
+ "url": "https://github.com/sebastianbergmann",
1244
+ "type": "github"
1245
+ }
1246
+ ],
1247
+ "time": "2020-10-26T15:52:27+00:00"
1248
+ },
1249
+ {
1250
+ "name": "sebastian/diff",
1251
+ "version": "4.0.4",
1252
+ "source": {
1253
+ "type": "git",
1254
+ "url": "https://github.com/sebastianbergmann/diff.git",
1255
+ "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
1256
+ },
1257
+ "dist": {
1258
+ "type": "zip",
1259
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
1260
+ "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
1261
+ "shasum": ""
1262
+ },
1263
+ "require": {
1264
+ "php": ">=7.3"
1265
+ },
1266
+ "require-dev": {
1267
+ "phpunit/phpunit": "^9.3",
1268
+ "symfony/process": "^4.2 || ^5"
1269
+ },
1270
+ "type": "library",
1271
+ "extra": {
1272
+ "branch-alias": {
1273
+ "dev-master": "4.0-dev"
1274
+ }
1275
+ },
1276
+ "autoload": {
1277
+ "classmap": [
1278
+ "src/"
1279
+ ]
1280
+ },
1281
+ "notification-url": "https://packagist.org/downloads/",
1282
+ "license": [
1283
+ "BSD-3-Clause"
1284
+ ],
1285
+ "authors": [
1286
+ {
1287
+ "name": "Sebastian Bergmann",
1288
+ "email": "sebastian@phpunit.de"
1289
+ },
1290
+ {
1291
+ "name": "Kore Nordmann",
1292
+ "email": "mail@kore-nordmann.de"
1293
+ }
1294
+ ],
1295
+ "description": "Diff implementation",
1296
+ "homepage": "https://github.com/sebastianbergmann/diff",
1297
+ "keywords": [
1298
+ "diff",
1299
+ "udiff",
1300
+ "unidiff",
1301
+ "unified diff"
1302
+ ],
1303
+ "support": {
1304
+ "issues": "https://github.com/sebastianbergmann/diff/issues",
1305
+ "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
1306
+ },
1307
+ "funding": [
1308
+ {
1309
+ "url": "https://github.com/sebastianbergmann",
1310
+ "type": "github"
1311
+ }
1312
+ ],
1313
+ "time": "2020-10-26T13:10:38+00:00"
1314
+ },
1315
+ {
1316
+ "name": "sebastian/environment",
1317
+ "version": "5.1.3",
1318
+ "source": {
1319
+ "type": "git",
1320
+ "url": "https://github.com/sebastianbergmann/environment.git",
1321
+ "reference": "388b6ced16caa751030f6a69e588299fa09200ac"
1322
+ },
1323
+ "dist": {
1324
+ "type": "zip",
1325
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac",
1326
+ "reference": "388b6ced16caa751030f6a69e588299fa09200ac",
1327
+ "shasum": ""
1328
+ },
1329
+ "require": {
1330
+ "php": ">=7.3"
1331
+ },
1332
+ "require-dev": {
1333
+ "phpunit/phpunit": "^9.3"
1334
+ },
1335
+ "suggest": {
1336
+ "ext-posix": "*"
1337
+ },
1338
+ "type": "library",
1339
+ "extra": {
1340
+ "branch-alias": {
1341
+ "dev-master": "5.1-dev"
1342
+ }
1343
+ },
1344
+ "autoload": {
1345
+ "classmap": [
1346
+ "src/"
1347
+ ]
1348
+ },
1349
+ "notification-url": "https://packagist.org/downloads/",
1350
+ "license": [
1351
+ "BSD-3-Clause"
1352
+ ],
1353
+ "authors": [
1354
+ {
1355
+ "name": "Sebastian Bergmann",
1356
+ "email": "sebastian@phpunit.de"
1357
+ }
1358
+ ],
1359
+ "description": "Provides functionality to handle HHVM/PHP environments",
1360
+ "homepage": "http://www.github.com/sebastianbergmann/environment",
1361
+ "keywords": [
1362
+ "Xdebug",
1363
+ "environment",
1364
+ "hhvm"
1365
+ ],
1366
+ "support": {
1367
+ "issues": "https://github.com/sebastianbergmann/environment/issues",
1368
+ "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3"
1369
+ },
1370
+ "funding": [
1371
+ {
1372
+ "url": "https://github.com/sebastianbergmann",
1373
+ "type": "github"
1374
+ }
1375
+ ],
1376
+ "time": "2020-09-28T05:52:38+00:00"
1377
+ },
1378
+ {
1379
+ "name": "sebastian/exporter",
1380
+ "version": "4.0.3",
1381
+ "source": {
1382
+ "type": "git",
1383
+ "url": "https://github.com/sebastianbergmann/exporter.git",
1384
+ "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65"
1385
+ },
1386
+ "dist": {
1387
+ "type": "zip",
1388
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65",
1389
+ "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65",
1390
+ "shasum": ""
1391
+ },
1392
+ "require": {
1393
+ "php": ">=7.3",
1394
+ "sebastian/recursion-context": "^4.0"
1395
+ },
1396
+ "require-dev": {
1397
+ "ext-mbstring": "*",
1398
+ "phpunit/phpunit": "^9.3"
1399
+ },
1400
+ "type": "library",
1401
+ "extra": {
1402
+ "branch-alias": {
1403
+ "dev-master": "4.0-dev"
1404
+ }
1405
+ },
1406
+ "autoload": {
1407
+ "classmap": [
1408
+ "src/"
1409
+ ]
1410
+ },
1411
+ "notification-url": "https://packagist.org/downloads/",
1412
+ "license": [
1413
+ "BSD-3-Clause"
1414
+ ],
1415
+ "authors": [
1416
+ {
1417
+ "name": "Sebastian Bergmann",
1418
+ "email": "sebastian@phpunit.de"
1419
+ },
1420
+ {
1421
+ "name": "Jeff Welch",
1422
+ "email": "whatthejeff@gmail.com"
1423
+ },
1424
+ {
1425
+ "name": "Volker Dusch",
1426
+ "email": "github@wallbash.com"
1427
+ },
1428
+ {
1429
+ "name": "Adam Harvey",
1430
+ "email": "aharvey@php.net"
1431
+ },
1432
+ {
1433
+ "name": "Bernhard Schussek",
1434
+ "email": "bschussek@gmail.com"
1435
+ }
1436
+ ],
1437
+ "description": "Provides the functionality to export PHP variables for visualization",
1438
+ "homepage": "http://www.github.com/sebastianbergmann/exporter",
1439
+ "keywords": [
1440
+ "export",
1441
+ "exporter"
1442
+ ],
1443
+ "support": {
1444
+ "issues": "https://github.com/sebastianbergmann/exporter/issues",
1445
+ "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.3"
1446
+ },
1447
+ "funding": [
1448
+ {
1449
+ "url": "https://github.com/sebastianbergmann",
1450
+ "type": "github"
1451
+ }
1452
+ ],
1453
+ "time": "2020-09-28T05:24:23+00:00"
1454
+ },
1455
+ {
1456
+ "name": "sebastian/global-state",
1457
+ "version": "5.0.3",
1458
+ "source": {
1459
+ "type": "git",
1460
+ "url": "https://github.com/sebastianbergmann/global-state.git",
1461
+ "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49"
1462
+ },
1463
+ "dist": {
1464
+ "type": "zip",
1465
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49",
1466
+ "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49",
1467
+ "shasum": ""
1468
+ },
1469
+ "require": {
1470
+ "php": ">=7.3",
1471
+ "sebastian/object-reflector": "^2.0",
1472
+ "sebastian/recursion-context": "^4.0"
1473
+ },
1474
+ "require-dev": {
1475
+ "ext-dom": "*",
1476
+ "phpunit/phpunit": "^9.3"
1477
+ },
1478
+ "suggest": {
1479
+ "ext-uopz": "*"
1480
+ },
1481
+ "type": "library",
1482
+ "extra": {
1483
+ "branch-alias": {
1484
+ "dev-master": "5.0-dev"
1485
+ }
1486
+ },
1487
+ "autoload": {
1488
+ "classmap": [
1489
+ "src/"
1490
+ ]
1491
+ },
1492
+ "notification-url": "https://packagist.org/downloads/",
1493
+ "license": [
1494
+ "BSD-3-Clause"
1495
+ ],
1496
+ "authors": [
1497
+ {
1498
+ "name": "Sebastian Bergmann",
1499
+ "email": "sebastian@phpunit.de"
1500
+ }
1501
+ ],
1502
+ "description": "Snapshotting of global state",
1503
+ "homepage": "http://www.github.com/sebastianbergmann/global-state",
1504
+ "keywords": [
1505
+ "global state"
1506
+ ],
1507
+ "support": {
1508
+ "issues": "https://github.com/sebastianbergmann/global-state/issues",
1509
+ "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3"
1510
+ },
1511
+ "funding": [
1512
+ {
1513
+ "url": "https://github.com/sebastianbergmann",
1514
+ "type": "github"
1515
+ }
1516
+ ],
1517
+ "time": "2021-06-11T13:31:12+00:00"
1518
+ },
1519
+ {
1520
+ "name": "sebastian/lines-of-code",
1521
+ "version": "1.0.3",
1522
+ "source": {
1523
+ "type": "git",
1524
+ "url": "https://github.com/sebastianbergmann/lines-of-code.git",
1525
+ "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
1526
+ },
1527
+ "dist": {
1528
+ "type": "zip",
1529
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
1530
+ "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
1531
+ "shasum": ""
1532
+ },
1533
+ "require": {
1534
+ "nikic/php-parser": "^4.6",
1535
+ "php": ">=7.3"
1536
+ },
1537
+ "require-dev": {
1538
+ "phpunit/phpunit": "^9.3"
1539
+ },
1540
+ "type": "library",
1541
+ "extra": {
1542
+ "branch-alias": {
1543
+ "dev-master": "1.0-dev"
1544
+ }
1545
+ },
1546
+ "autoload": {
1547
+ "classmap": [
1548
+ "src/"
1549
+ ]
1550
+ },
1551
+ "notification-url": "https://packagist.org/downloads/",
1552
+ "license": [
1553
+ "BSD-3-Clause"
1554
+ ],
1555
+ "authors": [
1556
+ {
1557
+ "name": "Sebastian Bergmann",
1558
+ "email": "sebastian@phpunit.de",
1559
+ "role": "lead"
1560
+ }
1561
+ ],
1562
+ "description": "Library for counting the lines of code in PHP source code",
1563
+ "homepage": "https://github.com/sebastianbergmann/lines-of-code",
1564
+ "support": {
1565
+ "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
1566
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
1567
+ },
1568
+ "funding": [
1569
+ {
1570
+ "url": "https://github.com/sebastianbergmann",
1571
+ "type": "github"
1572
+ }
1573
+ ],
1574
+ "time": "2020-11-28T06:42:11+00:00"
1575
+ },
1576
+ {
1577
+ "name": "sebastian/object-enumerator",
1578
+ "version": "4.0.4",
1579
+ "source": {
1580
+ "type": "git",
1581
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
1582
+ "reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
1583
+ },
1584
+ "dist": {
1585
+ "type": "zip",
1586
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
1587
+ "reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
1588
+ "shasum": ""
1589
+ },
1590
+ "require": {
1591
+ "php": ">=7.3",
1592
+ "sebastian/object-reflector": "^2.0",
1593
+ "sebastian/recursion-context": "^4.0"
1594
+ },
1595
+ "require-dev": {
1596
+ "phpunit/phpunit": "^9.3"
1597
+ },
1598
+ "type": "library",
1599
+ "extra": {
1600
+ "branch-alias": {
1601
+ "dev-master": "4.0-dev"
1602
+ }
1603
+ },
1604
+ "autoload": {
1605
+ "classmap": [
1606
+ "src/"
1607
+ ]
1608
+ },
1609
+ "notification-url": "https://packagist.org/downloads/",
1610
+ "license": [
1611
+ "BSD-3-Clause"
1612
+ ],
1613
+ "authors": [
1614
+ {
1615
+ "name": "Sebastian Bergmann",
1616
+ "email": "sebastian@phpunit.de"
1617
+ }
1618
+ ],
1619
+ "description": "Traverses array structures and object graphs to enumerate all referenced objects",
1620
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
1621
+ "support": {
1622
+ "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
1623
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
1624
+ },
1625
+ "funding": [
1626
+ {
1627
+ "url": "https://github.com/sebastianbergmann",
1628
+ "type": "github"
1629
+ }
1630
+ ],
1631
+ "time": "2020-10-26T13:12:34+00:00"
1632
+ },
1633
+ {
1634
+ "name": "sebastian/object-reflector",
1635
+ "version": "2.0.4",
1636
+ "source": {
1637
+ "type": "git",
1638
+ "url": "https://github.com/sebastianbergmann/object-reflector.git",
1639
+ "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
1640
+ },
1641
+ "dist": {
1642
+ "type": "zip",
1643
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
1644
+ "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
1645
+ "shasum": ""
1646
+ },
1647
+ "require": {
1648
+ "php": ">=7.3"
1649
+ },
1650
+ "require-dev": {
1651
+ "phpunit/phpunit": "^9.3"
1652
+ },
1653
+ "type": "library",
1654
+ "extra": {
1655
+ "branch-alias": {
1656
+ "dev-master": "2.0-dev"
1657
+ }
1658
+ },
1659
+ "autoload": {
1660
+ "classmap": [
1661
+ "src/"
1662
+ ]
1663
+ },
1664
+ "notification-url": "https://packagist.org/downloads/",
1665
+ "license": [
1666
+ "BSD-3-Clause"
1667
+ ],
1668
+ "authors": [
1669
+ {
1670
+ "name": "Sebastian Bergmann",
1671
+ "email": "sebastian@phpunit.de"
1672
+ }
1673
+ ],
1674
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
1675
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
1676
+ "support": {
1677
+ "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
1678
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
1679
+ },
1680
+ "funding": [
1681
+ {
1682
+ "url": "https://github.com/sebastianbergmann",
1683
+ "type": "github"
1684
+ }
1685
+ ],
1686
+ "time": "2020-10-26T13:14:26+00:00"
1687
+ },
1688
+ {
1689
+ "name": "sebastian/recursion-context",
1690
+ "version": "4.0.4",
1691
+ "source": {
1692
+ "type": "git",
1693
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
1694
+ "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
1695
+ },
1696
+ "dist": {
1697
+ "type": "zip",
1698
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
1699
+ "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
1700
+ "shasum": ""
1701
+ },
1702
+ "require": {
1703
+ "php": ">=7.3"
1704
+ },
1705
+ "require-dev": {
1706
+ "phpunit/phpunit": "^9.3"
1707
+ },
1708
+ "type": "library",
1709
+ "extra": {
1710
+ "branch-alias": {
1711
+ "dev-master": "4.0-dev"
1712
+ }
1713
+ },
1714
+ "autoload": {
1715
+ "classmap": [
1716
+ "src/"
1717
+ ]
1718
+ },
1719
+ "notification-url": "https://packagist.org/downloads/",
1720
+ "license": [
1721
+ "BSD-3-Clause"
1722
+ ],
1723
+ "authors": [
1724
+ {
1725
+ "name": "Sebastian Bergmann",
1726
+ "email": "sebastian@phpunit.de"
1727
+ },
1728
+ {
1729
+ "name": "Jeff Welch",
1730
+ "email": "whatthejeff@gmail.com"
1731
+ },
1732
+ {
1733
+ "name": "Adam Harvey",
1734
+ "email": "aharvey@php.net"
1735
+ }
1736
+ ],
1737
+ "description": "Provides functionality to recursively process PHP variables",
1738
+ "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
1739
+ "support": {
1740
+ "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
1741
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
1742
+ },
1743
+ "funding": [
1744
+ {
1745
+ "url": "https://github.com/sebastianbergmann",
1746
+ "type": "github"
1747
+ }
1748
+ ],
1749
+ "time": "2020-10-26T13:17:30+00:00"
1750
+ },
1751
+ {
1752
+ "name": "sebastian/resource-operations",
1753
+ "version": "3.0.3",
1754
+ "source": {
1755
+ "type": "git",
1756
+ "url": "https://github.com/sebastianbergmann/resource-operations.git",
1757
+ "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
1758
+ },
1759
+ "dist": {
1760
+ "type": "zip",
1761
+ "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
1762
+ "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
1763
+ "shasum": ""
1764
+ },
1765
+ "require": {
1766
+ "php": ">=7.3"
1767
+ },
1768
+ "require-dev": {
1769
+ "phpunit/phpunit": "^9.0"
1770
+ },
1771
+ "type": "library",
1772
+ "extra": {
1773
+ "branch-alias": {
1774
+ "dev-master": "3.0-dev"
1775
+ }
1776
+ },
1777
+ "autoload": {
1778
+ "classmap": [
1779
+ "src/"
1780
+ ]
1781
+ },
1782
+ "notification-url": "https://packagist.org/downloads/",
1783
+ "license": [
1784
+ "BSD-3-Clause"
1785
+ ],
1786
+ "authors": [
1787
+ {
1788
+ "name": "Sebastian Bergmann",
1789
+ "email": "sebastian@phpunit.de"
1790
+ }
1791
+ ],
1792
+ "description": "Provides a list of PHP built-in functions that operate on resources",
1793
+ "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
1794
+ "support": {
1795
+ "issues": "https://github.com/sebastianbergmann/resource-operations/issues",
1796
+ "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
1797
+ },
1798
+ "funding": [
1799
+ {
1800
+ "url": "https://github.com/sebastianbergmann",
1801
+ "type": "github"
1802
+ }
1803
+ ],
1804
+ "time": "2020-09-28T06:45:17+00:00"
1805
+ },
1806
+ {
1807
+ "name": "sebastian/type",
1808
+ "version": "2.3.4",
1809
+ "source": {
1810
+ "type": "git",
1811
+ "url": "https://github.com/sebastianbergmann/type.git",
1812
+ "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914"
1813
+ },
1814
+ "dist": {
1815
+ "type": "zip",
1816
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914",
1817
+ "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914",
1818
+ "shasum": ""
1819
+ },
1820
+ "require": {
1821
+ "php": ">=7.3"
1822
+ },
1823
+ "require-dev": {
1824
+ "phpunit/phpunit": "^9.3"
1825
+ },
1826
+ "type": "library",
1827
+ "extra": {
1828
+ "branch-alias": {
1829
+ "dev-master": "2.3-dev"
1830
+ }
1831
+ },
1832
+ "autoload": {
1833
+ "classmap": [
1834
+ "src/"
1835
+ ]
1836
+ },
1837
+ "notification-url": "https://packagist.org/downloads/",
1838
+ "license": [
1839
+ "BSD-3-Clause"
1840
+ ],
1841
+ "authors": [
1842
+ {
1843
+ "name": "Sebastian Bergmann",
1844
+ "email": "sebastian@phpunit.de",
1845
+ "role": "lead"
1846
+ }
1847
+ ],
1848
+ "description": "Collection of value objects that represent the types of the PHP type system",
1849
+ "homepage": "https://github.com/sebastianbergmann/type",
1850
+ "support": {
1851
+ "issues": "https://github.com/sebastianbergmann/type/issues",
1852
+ "source": "https://github.com/sebastianbergmann/type/tree/2.3.4"
1853
+ },
1854
+ "funding": [
1855
+ {
1856
+ "url": "https://github.com/sebastianbergmann",
1857
+ "type": "github"
1858
+ }
1859
+ ],
1860
+ "time": "2021-06-15T12:49:02+00:00"
1861
+ },
1862
+ {
1863
+ "name": "sebastian/version",
1864
+ "version": "3.0.2",
1865
+ "source": {
1866
+ "type": "git",
1867
+ "url": "https://github.com/sebastianbergmann/version.git",
1868
+ "reference": "c6c1022351a901512170118436c764e473f6de8c"
1869
+ },
1870
+ "dist": {
1871
+ "type": "zip",
1872
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
1873
+ "reference": "c6c1022351a901512170118436c764e473f6de8c",
1874
+ "shasum": ""
1875
+ },
1876
+ "require": {
1877
+ "php": ">=7.3"
1878
+ },
1879
+ "type": "library",
1880
+ "extra": {
1881
+ "branch-alias": {
1882
+ "dev-master": "3.0-dev"
1883
+ }
1884
+ },
1885
+ "autoload": {
1886
+ "classmap": [
1887
+ "src/"
1888
+ ]
1889
+ },
1890
+ "notification-url": "https://packagist.org/downloads/",
1891
+ "license": [
1892
+ "BSD-3-Clause"
1893
+ ],
1894
+ "authors": [
1895
+ {
1896
+ "name": "Sebastian Bergmann",
1897
+ "email": "sebastian@phpunit.de",
1898
+ "role": "lead"
1899
+ }
1900
+ ],
1901
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1902
+ "homepage": "https://github.com/sebastianbergmann/version",
1903
+ "support": {
1904
+ "issues": "https://github.com/sebastianbergmann/version/issues",
1905
+ "source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
1906
+ },
1907
+ "funding": [
1908
+ {
1909
+ "url": "https://github.com/sebastianbergmann",
1910
+ "type": "github"
1911
+ }
1912
+ ],
1913
+ "time": "2020-09-28T06:39:44+00:00"
1914
+ },
1915
+ {
1916
+ "name": "symfony/polyfill-ctype",
1917
+ "version": "v1.23.0",
1918
+ "source": {
1919
+ "type": "git",
1920
+ "url": "https://github.com/symfony/polyfill-ctype.git",
1921
+ "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
1922
+ },
1923
+ "dist": {
1924
+ "type": "zip",
1925
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
1926
+ "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
1927
+ "shasum": ""
1928
+ },
1929
+ "require": {
1930
+ "php": ">=7.1"
1931
+ },
1932
+ "suggest": {
1933
+ "ext-ctype": "For best performance"
1934
+ },
1935
+ "type": "library",
1936
+ "extra": {
1937
+ "branch-alias": {
1938
+ "dev-main": "1.23-dev"
1939
+ },
1940
+ "thanks": {
1941
+ "name": "symfony/polyfill",
1942
+ "url": "https://github.com/symfony/polyfill"
1943
+ }
1944
+ },
1945
+ "autoload": {
1946
+ "psr-4": {
1947
+ "Symfony\\Polyfill\\Ctype\\": ""
1948
+ },
1949
+ "files": [
1950
+ "bootstrap.php"
1951
+ ]
1952
+ },
1953
+ "notification-url": "https://packagist.org/downloads/",
1954
+ "license": [
1955
+ "MIT"
1956
+ ],
1957
+ "authors": [
1958
+ {
1959
+ "name": "Gert de Pagter",
1960
+ "email": "BackEndTea@gmail.com"
1961
+ },
1962
+ {
1963
+ "name": "Symfony Community",
1964
+ "homepage": "https://symfony.com/contributors"
1965
+ }
1966
+ ],
1967
+ "description": "Symfony polyfill for ctype functions",
1968
+ "homepage": "https://symfony.com",
1969
+ "keywords": [
1970
+ "compatibility",
1971
+ "ctype",
1972
+ "polyfill",
1973
+ "portable"
1974
+ ],
1975
+ "support": {
1976
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0"
1977
+ },
1978
+ "funding": [
1979
+ {
1980
+ "url": "https://symfony.com/sponsor",
1981
+ "type": "custom"
1982
+ },
1983
+ {
1984
+ "url": "https://github.com/fabpot",
1985
+ "type": "github"
1986
+ },
1987
+ {
1988
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1989
+ "type": "tidelift"
1990
+ }
1991
+ ],
1992
+ "time": "2021-02-19T12:13:01+00:00"
1993
+ },
1994
+ {
1995
+ "name": "theseer/tokenizer",
1996
+ "version": "1.2.1",
1997
+ "source": {
1998
+ "type": "git",
1999
+ "url": "https://github.com/theseer/tokenizer.git",
2000
+ "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
2001
+ },
2002
+ "dist": {
2003
+ "type": "zip",
2004
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
2005
+ "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
2006
+ "shasum": ""
2007
+ },
2008
+ "require": {
2009
+ "ext-dom": "*",
2010
+ "ext-tokenizer": "*",
2011
+ "ext-xmlwriter": "*",
2012
+ "php": "^7.2 || ^8.0"
2013
+ },
2014
+ "type": "library",
2015
+ "autoload": {
2016
+ "classmap": [
2017
+ "src/"
2018
+ ]
2019
+ },
2020
+ "notification-url": "https://packagist.org/downloads/",
2021
+ "license": [
2022
+ "BSD-3-Clause"
2023
+ ],
2024
+ "authors": [
2025
+ {
2026
+ "name": "Arne Blankerts",
2027
+ "email": "arne@blankerts.de",
2028
+ "role": "Developer"
2029
+ }
2030
+ ],
2031
+ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
2032
+ "support": {
2033
+ "issues": "https://github.com/theseer/tokenizer/issues",
2034
+ "source": "https://github.com/theseer/tokenizer/tree/1.2.1"
2035
+ },
2036
+ "funding": [
2037
+ {
2038
+ "url": "https://github.com/theseer",
2039
+ "type": "github"
2040
+ }
2041
+ ],
2042
+ "time": "2021-07-28T10:34:58+00:00"
2043
+ },
2044
+ {
2045
+ "name": "webmozart/assert",
2046
+ "version": "1.10.0",
2047
+ "source": {
2048
+ "type": "git",
2049
+ "url": "https://github.com/webmozarts/assert.git",
2050
+ "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
2051
+ },
2052
+ "dist": {
2053
+ "type": "zip",
2054
+ "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
2055
+ "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
2056
+ "shasum": ""
2057
+ },
2058
+ "require": {
2059
+ "php": "^7.2 || ^8.0",
2060
+ "symfony/polyfill-ctype": "^1.8"
2061
+ },
2062
+ "conflict": {
2063
+ "phpstan/phpstan": "<0.12.20",
2064
+ "vimeo/psalm": "<4.6.1 || 4.6.2"
2065
+ },
2066
+ "require-dev": {
2067
+ "phpunit/phpunit": "^8.5.13"
2068
+ },
2069
+ "type": "library",
2070
+ "extra": {
2071
+ "branch-alias": {
2072
+ "dev-master": "1.10-dev"
2073
+ }
2074
+ },
2075
+ "autoload": {
2076
+ "psr-4": {
2077
+ "Webmozart\\Assert\\": "src/"
2078
+ }
2079
+ },
2080
+ "notification-url": "https://packagist.org/downloads/",
2081
+ "license": [
2082
+ "MIT"
2083
+ ],
2084
+ "authors": [
2085
+ {
2086
+ "name": "Bernhard Schussek",
2087
+ "email": "bschussek@gmail.com"
2088
+ }
2089
+ ],
2090
+ "description": "Assertions to validate method input/output with nice error messages.",
2091
+ "keywords": [
2092
+ "assert",
2093
+ "check",
2094
+ "validate"
2095
+ ],
2096
+ "support": {
2097
+ "issues": "https://github.com/webmozarts/assert/issues",
2098
+ "source": "https://github.com/webmozarts/assert/tree/1.10.0"
2099
+ },
2100
+ "time": "2021-03-09T10:59:23+00:00"
2101
+ }
2102
+ ],
2103
+ "aliases": [],
2104
+ "minimum-stability": "stable",
2105
+ "stability-flags": [],
2106
+ "prefer-stable": false,
2107
+ "prefer-lowest": false,
2108
+ "platform": [],
2109
+ "platform-dev": [],
2110
+ "plugin-api-version": "2.1.0"
2111
+ }
vendor/tawk/url-utils/lib/Enums/WildcardLocation.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Enums;
4
+
5
+ class WildcardLocation {
6
+ const START = 'start';
7
+ const MIDDLE = 'middle';
8
+ const END = 'end';
9
+ const NONE = 'none';
10
+ }
vendor/tawk/url-utils/lib/Helpers/Common.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Helpers;
4
+
5
+ class Common {
6
+ /**
7
+ * Checks the provided text starts with.
8
+ *
9
+ * @param string $text The text to be checked
10
+ * @param string $start_with The text to match from the provided text to start with.
11
+ * @return void
12
+ */
13
+ public static function text_starts_with($text, $start_with) {
14
+ $length = strlen($start_with);
15
+ return substr($text, 0, $length) === $start_with;
16
+ }
17
+
18
+ /**
19
+ * Checks the provided text ends with.
20
+ *
21
+ * @param string $text The text to be checked
22
+ * @param string $ends_with The text to match from the provided text to start with.
23
+ * @return void
24
+ */
25
+ public static function text_ends_with($text, $ends_with) {
26
+ $length = strlen($ends_with);
27
+ return substr($text, -$length) === $ends_with;
28
+ }
29
+ }
vendor/tawk/url-utils/lib/Helpers/PathHelper.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Helpers;
4
+
5
+ use Tawk\Enums\WildcardLocation;
6
+
7
+ define('WILDCARD', '*');
8
+
9
+ class PathHelper {
10
+ /**
11
+ * Gets the WILDCARD constant.
12
+ *
13
+ * @return string Wildcard
14
+ */
15
+ public static function get_wildcard() {
16
+ return WILDCARD;
17
+ }
18
+
19
+ /**
20
+ * Checks if provided path starts with the WILDCARD or /.
21
+ * If it is, it is considered as a path.
22
+ *
23
+ * @param string $path URL Path.
24
+ * @return bool Returns `true` if the provided path either has a leading `/` or WILDCARD. Otherwise, returns `false`.
25
+ */
26
+ public static function is_path($path) {
27
+ return strpos($path, WILDCARD) === 0 || strpos($path, '/') === 0;
28
+ }
29
+
30
+ /**
31
+ * Checks if the pattern chunks provided has a wildcard
32
+ *
33
+ * @param string[] $path_chunks URL Path in chunks.
34
+ * @return bool Returns `true` if there's a WILDCARD in the provided path chunks. Otherwise, returns `false`.
35
+ */
36
+ public static function path_chunks_has_wildcard($path_chunks) {
37
+ return in_array(WILDCARD, $path_chunks, true);
38
+ }
39
+
40
+ /**
41
+ * Checks if the pattern chunk provided is a wildcard.
42
+ *
43
+ * @param string $path_chunk URL Path chunk.
44
+ * @return bool Returns `true` if the chunk is a WILDCARD. Otherwise, returns `false`.
45
+ */
46
+ public static function is_wildcard($path_chunk) {
47
+ return $path_chunk === WILDCARD;
48
+ }
49
+
50
+ /**
51
+ * Gets the path chunks from the provided path.
52
+ *
53
+ * @param string $path URL Path.
54
+ * @return string[] URL Path in chunks.
55
+ */
56
+ public static function get_chunks($path) {
57
+ $chunks = explode('/', $path);
58
+ $filtered_chunks = array_filter($chunks, function ($item) {
59
+ return empty($item) !== true;
60
+ });
61
+ return array_values($filtered_chunks);
62
+ }
63
+
64
+ /**
65
+ * Identifies where the wildcard is located in the provided chunks.
66
+ *
67
+ * @param string[] $path_chunks URL Path in chunks.
68
+ * @return string Wildcard Location.
69
+ */
70
+ public static function get_wildcard_location_by_chunks($path_chunks) {
71
+ if (is_array($path_chunks) === false) {
72
+ return WildcardLocation::NONE;
73
+ }
74
+
75
+ if (self::path_chunks_has_wildcard($path_chunks) === false) {
76
+ return WildcardLocation::NONE;
77
+ }
78
+
79
+ if (self::is_wildcard(end($path_chunks))) {
80
+ return WildcardLocation::END;
81
+ }
82
+
83
+ if (self::is_wildcard($path_chunks[0])) {
84
+ return WildcardLocation::START;
85
+ }
86
+
87
+ return WildcardLocation::MIDDLE;
88
+ }
89
+
90
+ /**
91
+ * Check if path has strict length.
92
+ *
93
+ * @param string $path URL Path.
94
+ * @param string $wildcard_location Wildcard Location.
95
+ * @return bool Returns `true` if path has strict length. Otherwise, returns `false`.
96
+ */
97
+ public static function path_has_strict_length($path, $wildcard_location) {
98
+ if ($wildcard_location === WildcardLocation::START && Common::text_starts_with($path, '/' . WILDCARD) === true) {
99
+ return true;
100
+ }
101
+
102
+ if ($wildcard_location === WildcardLocation::END && Common::text_ends_with($path, WILDCARD . '/') === true) {
103
+ return true;
104
+ }
105
+
106
+ return false;
107
+ }
108
+ }
vendor/tawk/url-utils/lib/Helpers/UrlHelper.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Helpers;
4
+
5
+ use Tawk\Helpers\PathHelper;
6
+
7
+ define('PROTOCOL_REGEX', '/^(http|https):\/\//');
8
+
9
+ class UrlHelper {
10
+ /**
11
+ * Parses url
12
+ *
13
+ * @param string $url
14
+ *
15
+ * @return array {
16
+ * path: string,
17
+ * host: string?,
18
+ * port: string?,
19
+ * scheme: string?
20
+ * }
21
+ */
22
+ public static function parse_url($url) {
23
+ $is_path = PathHelper::is_path($url);
24
+ $has_protocol = preg_match(PROTOCOL_REGEX, $url) === 1;
25
+
26
+ if ($is_path === false && $has_protocol === false) {
27
+ // Add http:// in front of the string to properly parse the provided url.
28
+ // The reason is if the url provided only consists of the following example:
29
+ //
30
+ // www.example.com/path/to/somewhere
31
+ //
32
+ // parse_url function will treat the whole url as a path.
33
+ $url = 'http://'.$url;
34
+ }
35
+
36
+ $parsed_url = parse_url($url);
37
+
38
+ $url_data = array(
39
+ 'path' => '/'
40
+ );
41
+
42
+ if (isset($parsed_url['path'])) {
43
+ $url_data['path'] = $parsed_url['path'];
44
+ }
45
+
46
+ if (isset($parsed_url['host'])) {
47
+ $url_data['host'] = $parsed_url['host'];
48
+ }
49
+
50
+ if (isset($parsed_url['port'])) {
51
+ $url_data['port'] = $parsed_url['port'];
52
+ }
53
+
54
+ if ($is_path === false && $has_protocol === true) {
55
+ $url_data['scheme'] = $parsed_url['scheme'];
56
+ }
57
+
58
+ return $url_data;
59
+ }
60
+ }
vendor/tawk/url-utils/lib/Models/PathPattern.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Models;
4
+
5
+ use Tawk\Enums\WildcardLocation;
6
+ use Tawk\Helpers\PathHelper;
7
+
8
+ class PathPattern {
9
+ protected array $path_chunks;
10
+ protected string $wildcard_location;
11
+ protected bool $strict_length_flag;
12
+
13
+ /**
14
+ * Constructor
15
+ *
16
+ * @param string $path URL Path
17
+ */
18
+ protected function __construct($path) {
19
+ $this->path_chunks = PathHelper::get_chunks($path);
20
+ $this->wildcard_location = PathHelper::get_wildcard_location_by_chunks($this->path_chunks);
21
+ $this->strict_length_flag = PathHelper::path_has_strict_length($path, $this->wildcard_location);
22
+ }
23
+
24
+ /**
25
+ * Creates an instance of PathPattern class from the provided path.
26
+ *
27
+ * @param string $path URL Path.
28
+ * @return PathPattern instance of PathPattern Model.
29
+ */
30
+ public static function create_instance_from_path($path) {
31
+ return new PathPattern($path);
32
+ }
33
+
34
+ /**
35
+ * Checks if path has wildcard.
36
+ *
37
+ * @return bool Returns `true` if path has wildcard. Otherwise, `false`.
38
+ */
39
+ public function has_wildcard() {
40
+ return $this->wildcard_location !== WildcardLocation::NONE;
41
+ }
42
+
43
+ /**
44
+ * Checks if path should have strict length.
45
+ *
46
+ * @return bool Returns `true` if path should have strict length. Otherwise, `false`.
47
+ */
48
+ public function has_strict_length() {
49
+ return $this->strict_length_flag;
50
+ }
51
+
52
+ /**
53
+ * Provides the path in chunks.
54
+ *
55
+ * @return string[] Path chunks.
56
+ */
57
+ public function get_chunks() {
58
+ return $this->path_chunks;
59
+ }
60
+
61
+ /**
62
+ * Provides the wildcard location.
63
+ *
64
+ * @return string Wildcard location.
65
+ */
66
+ public function get_wildcard_location() {
67
+ return $this->wildcard_location;
68
+ }
69
+ }
vendor/tawk/url-utils/lib/Modules/PathPatternMatcher.php ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Modules;
4
+
5
+ use Tawk\Enums\WildcardLocation;
6
+ use Tawk\Helpers\PathHelper;
7
+ use Tawk\Models\PathPattern;
8
+
9
+ class PathPatternMatcher {
10
+ /**
11
+ * Matches current path to multiple patterns
12
+ *
13
+ * @param string[] $current_path_chunks Current path in chunks
14
+ * @param PathPattern[] $path_patterns List of path pattern instances
15
+ * @return bool Returns `true` if current path chunks matches with one of the provided patterns. Otherwise, returns `false`.
16
+ */
17
+ public static function match($current_path_chunks, $path_patterns) {
18
+ foreach($path_patterns as $path_pattern) {
19
+ $path_pattern_chunks = $path_pattern->get_chunks();
20
+ $has_strict_length = $path_pattern->has_strict_length();
21
+
22
+ if ($path_pattern->has_wildcard() === false) {
23
+ if (join('/', $current_path_chunks) === join('/', $path_pattern_chunks)) {
24
+ return true;
25
+ };
26
+ } else if ($path_pattern->get_wildcard_location() === WildcardLocation::START) {
27
+ // if wildcard is at the start, match in reverse order so that the wildcard is at the end
28
+ if (self::match_chunks_reverse($current_path_chunks, $path_pattern_chunks, $has_strict_length) === true) {
29
+ return true;
30
+ }
31
+ } else {
32
+ if (self::match_chunks($current_path_chunks, $path_pattern_chunks, $has_strict_length) === true) {
33
+ return true;
34
+ }
35
+ }
36
+ }
37
+
38
+ return false;
39
+ }
40
+
41
+ /**
42
+ * Iterates over the current and pattern path chunks and matches them
43
+ *
44
+ * @param string[] $current_path_chunks Current path in chunks
45
+ * @param string[] $pattern_path_chunks Pattern path in chunks
46
+ * @return boolean Returns `true` if current path matches with the pattern. Otherwise, `false`.
47
+ */
48
+ private static function match_chunks($current_path_chunks, $pattern_path_chunks, $has_strict_length) {
49
+ $current_path_len = count($current_path_chunks);
50
+ $pattern_path_len = count($pattern_path_chunks);
51
+
52
+ // do not proceed on matching if pattern path has strict length
53
+ // and if it differs to the current path length.
54
+ if ($has_strict_length === true && $current_path_len !== $pattern_path_len) {
55
+ return false;
56
+ }
57
+
58
+ // handles empty current path
59
+ if ($current_path_len === 0) {
60
+ // match if pattern path is also empty
61
+ if ($pattern_path_len === 0) {
62
+ return true;
63
+ }
64
+
65
+ // match if pattern path is only a wildcard
66
+ if ($pattern_path_len === 1 && PathHelper::is_wildcard($pattern_path_chunks[0])) {
67
+ return true;
68
+ }
69
+
70
+ // else, do not match since there's nothing to match with
71
+ return false;
72
+ }
73
+
74
+ // do not proceed on matching if pattern path is longer than the current path.
75
+ if ($pattern_path_len > $current_path_len) {
76
+ return false;
77
+ }
78
+
79
+ for ($i = 0; $i < $current_path_len; $i++) {
80
+ $current_path_chunk = $current_path_chunks[$i];
81
+
82
+ // handles current paths that are longer than the pattern
83
+ // ex.
84
+ // path - /path/to/somewhere/longer
85
+ // pattern - /path/*/somewhere
86
+ if (isset($pattern_path_chunks[$i]) === false) {
87
+ return false;
88
+ }
89
+
90
+ $pattern_path_chunk = $pattern_path_chunks[$i];
91
+
92
+ if (PathHelper::is_wildcard($pattern_path_chunk)) {
93
+ // if current pattern chunk is the last chunk
94
+ if ($i === $pattern_path_len - 1) {
95
+ // if pattern does not have strict length
96
+ // stop matching and true
97
+ if ($has_strict_length === false) {
98
+ return true;
99
+ }
100
+ }
101
+
102
+ // otherwise, continue on matching
103
+ continue;
104
+ }
105
+
106
+ // stop matching if one of the chunks doesn't match.
107
+ if ($pattern_path_chunk !== $current_path_chunk) {
108
+ return false;
109
+ }
110
+ }
111
+
112
+ return true;
113
+ }
114
+
115
+ /**
116
+ * Iterates over the current and pattern path chunks and matches them in reverse
117
+ *
118
+ * @param string[] $current_path_chunks Current path in chunks
119
+ * @param string[] $pattern_path_chunks Pattern path in chunks
120
+ * @return boolean Returns `true` if current path matches with the pattern. Otherwise, `false`.
121
+ */
122
+ private static function match_chunks_reverse($current_path_chunks, $pattern_path_chunks, $has_strict_length) {
123
+ $current_path_len = count($current_path_chunks);
124
+ $pattern_path_len = count($pattern_path_chunks);
125
+
126
+ // do not proceed on matching if pattern path has strict length
127
+ // and if it differs to the current path length.
128
+ if ($has_strict_length === true && $current_path_len !== $pattern_path_len) {
129
+ return false;
130
+ }
131
+
132
+ // handles empty current path
133
+ if ($current_path_len === 0) {
134
+ // match if pattern path is also empty
135
+ if ($pattern_path_len === 0) {
136
+ return true;
137
+ }
138
+
139
+ // match if pattern path is only a wildcard
140
+ if ($pattern_path_len === 1 && PathHelper::is_wildcard($pattern_path_chunks[0])) {
141
+ return true;
142
+ }
143
+
144
+ // else, do not match since there's nothing to match with
145
+ return false;
146
+ }
147
+
148
+ // do not proceed on matching if pattern path is longer than the current path.
149
+ if ($pattern_path_len > $current_path_len) {
150
+ return false;
151
+ }
152
+
153
+ $offset = $current_path_len - $pattern_path_len;
154
+ for ($i = $current_path_len - 1; $i >= 0; $i--) {
155
+ $current_path_chunk = $current_path_chunks[$i];
156
+
157
+ // handles current paths that are longer than the pattern
158
+ // ex.
159
+ // path - /path/to/somewhere/longer
160
+ // pattern - */somewhere
161
+ $pattern_index = $i - $offset;
162
+ if (isset($pattern_path_chunks[$pattern_index]) === false) {
163
+ return false;
164
+ }
165
+
166
+ $pattern_path_chunk = $pattern_path_chunks[$pattern_index];
167
+
168
+ if (PathHelper::is_wildcard($pattern_path_chunk)) {
169
+ // if current pattern chunk is the first chunk
170
+ if ($pattern_index === 0) {
171
+ // if pattern does not have strict length
172
+ // stop matching and true
173
+ if ($has_strict_length === false) {
174
+ return true;
175
+ }
176
+ }
177
+
178
+ // otherwise, continue on matching
179
+ continue;
180
+ }
181
+
182
+ // stop matching if one of the chunks doesn't match.
183
+ if ($pattern_path_chunk !== $current_path_chunk) {
184
+ return false;
185
+ }
186
+ }
187
+
188
+ return true;
189
+ }
190
+ }
vendor/tawk/url-utils/lib/Modules/UrlPatternMatcher.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Modules;
4
+
5
+ use Tawk\Helpers\PathHelper;
6
+ use Tawk\Helpers\UrlHelper;
7
+ use Tawk\Models\PathPattern;
8
+ use Tawk\Modules\PathPatternMatcher;
9
+
10
+ class UrlPatternMatcher {
11
+ /**
12
+ * Matches current url to multiple patterns
13
+ *
14
+ * @param string $current_url Current URL
15
+ * @param string[] $patterns List of URL/Path patterns
16
+ * @return bool - Returns `true` if current url matches to one of the provided patterns. Otherwise, returns `false`.
17
+ */
18
+ public static function match($current_url, $patterns) {
19
+ $parsed_current_url = UrlHelper::parse_url($current_url);
20
+ $current_path_chunks = PathHelper::get_chunks($parsed_current_url['path']);
21
+
22
+ foreach($patterns as $pattern) {
23
+ $parsed_pattern = UrlHelper::parse_url($pattern);
24
+
25
+ // checks if the provided pattern has scheme (http/https)
26
+ // and matches with current url if it has the same scheme
27
+ if (isset($parsed_current_url['scheme']) && isset($parsed_pattern['scheme'])) {
28
+ if ($parsed_current_url['scheme'] !== $parsed_pattern['scheme']) {
29
+ continue;
30
+ }
31
+ }
32
+
33
+ // checks if the provided pattern has host
34
+ // and matches with current url if it has the same host
35
+ if (isset($parsed_current_url['host']) && isset($parsed_pattern['host'])) {
36
+ if ($parsed_current_url['host'] !== $parsed_pattern['host']) {
37
+ continue;
38
+ }
39
+ }
40
+
41
+ // checks if the provided pattern has port
42
+ // and matches with current url if it has the same port
43
+ if (isset($parsed_current_url['port']) && isset($parsed_pattern['port'])) {
44
+ if ($parsed_current_url['port'] !== $parsed_pattern['port']) {
45
+ continue;
46
+ }
47
+ }
48
+
49
+ $path_pattern_instance = PathPattern::create_instance_from_path($parsed_pattern['path']);
50
+
51
+ if (PathPatternMatcher::match($current_path_chunks, array($path_pattern_instance)) === true) {
52
+ return true;
53
+ }
54
+ }
55
+
56
+ return false;
57
+ }
58
+ }
vendor/tawk/url-utils/phpunit.xml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+
3
+ <phpunit bootstrap="vendor/autoload.php"
4
+ colors="true"
5
+ verbose="true"
6
+ stopOnFailure="false"
7
+ testdox="true">
8
+ <testsuites>
9
+ <testsuite name="match">
10
+ <directory>tests</directory>
11
+ </testsuite>
12
+ </testsuites>
13
+ </phpunit>
vendor/tawk/url-utils/tests/Enums/WildcardLocationTest.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Tests\Enums;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use Tawk\Enums\WildcardLocation;
7
+
8
+ class WildcardLocationTest extends TestCase {
9
+ /**
10
+ * @test
11
+ * @group enum_wildcard_location
12
+ * @covers ::START
13
+ * @small
14
+ */
15
+ public function check_wildcard_location_start() {
16
+ $this->assertEquals(WildcardLocation::START, 'start');
17
+ }
18
+ /**
19
+ * @test
20
+ * @group enum_wildcard_location
21
+ * @covers ::END
22
+ * @small
23
+ */
24
+ public function check_wildcard_location_end() {
25
+ $this->assertEquals(WildcardLocation::END, 'end');
26
+ }
27
+ /**
28
+ * @test
29
+ * @group enum_wildcard_location
30
+ * @covers ::MIDDLE
31
+ * @small
32
+ */
33
+ public function check_wildcard_location_middle() {
34
+ $this->assertEquals(WildcardLocation::MIDDLE, 'middle');
35
+ }
36
+ /**
37
+ * @test
38
+ * @group enum_wildcard_location
39
+ * @covers ::NONE
40
+ * @small
41
+ */
42
+ public function check_wildcard_location_none() {
43
+ $this->assertEquals(WildcardLocation::NONE, 'none');
44
+ }
45
+ }
vendor/tawk/url-utils/tests/Helpers/CommonTest.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Tests\Helpers\CommonTest;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use Tawk\Helpers\Common;
7
+
8
+ /**
9
+ * @coversDefaultClass \Tawk\Helpers\Common
10
+ */
11
+ class StrStartsWith extends TestCase {
12
+ /**
13
+ * @test
14
+ * @group text_starts_with
15
+ * @covers ::text_starts_with
16
+ * @small
17
+ */
18
+ public function should_be_true_if_provided_text_starts_with() {
19
+ $this->assertTrue(Common::text_starts_with('something', 'some'));
20
+ }
21
+
22
+ /**
23
+ * @test
24
+ * @group text_starts_with
25
+ * @covers ::text_starts_with
26
+ * @small
27
+ */
28
+ public function should_be_false_if_provided_text_does_not_starts_with() {
29
+ $this->assertFalse(Common::text_starts_with('something', 'none'));
30
+ }
31
+ }
32
+
33
+
34
+ /**
35
+ * @coversDefaultClass \Tawk\Helpers\Common
36
+ */
37
+ class StrEndsWith extends TestCase {
38
+ /**
39
+ * @test
40
+ * @group text_ends_with
41
+ * @covers ::text_ends_with
42
+ * @small
43
+ */
44
+ public function should_be_true_if_provided_text_ends_with() {
45
+ $this->assertTrue(Common::text_ends_with('something', 'thing'));
46
+ }
47
+
48
+ /**
49
+ * @test
50
+ * @group text_ends_with
51
+ * @covers ::text_ends_with
52
+ * @small
53
+ */
54
+ public function should_be_false_if_provided_text_does_not_ends_with() {
55
+ $this->assertFalse(Common::text_ends_with('something', 'none'));
56
+ }
57
+ }
58
+
vendor/tawk/url-utils/tests/Helpers/PathHelperTest.php ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Tests\Helpers\PathHelperTest;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use Tawk\Enums\WildcardLocation;
7
+ use Tawk\Helpers\PathHelper;
8
+
9
+ /**
10
+ * @coversDefaultClass \Tawk\Helpers\PathHelper
11
+ */
12
+ class GetWildcardTest extends TestCase {
13
+ /**
14
+ * @test
15
+ * @group get_wildcard
16
+ * @covers ::get_wildcard
17
+ * @small
18
+ */
19
+ public function should_return_wildcard_constant() {
20
+ $this->assertEquals(PathHelper::get_wildcard(), '*');
21
+ }
22
+ }
23
+
24
+ /**
25
+ * @coversDefaultClass \Tawk\Helpers\PathHelper
26
+ */
27
+ class IsPathTest extends TestCase {
28
+ /**
29
+ * @test
30
+ * @group is_path
31
+ * @covers ::is_path
32
+ * @small
33
+ */
34
+ public function should_return_true_if_path_has_leading_slash() {
35
+ $this->assertTrue(PathHelper::is_path('/path/to/somewhere'));
36
+ }
37
+
38
+ /**
39
+ * @test
40
+ * @group is_path
41
+ * @covers ::is_path
42
+ * @small
43
+ */
44
+ public function should_return_true_if_path_has_leading_wildcard() {
45
+ $this->assertTrue(PathHelper::is_path('*/to/somewhere'));
46
+ }
47
+
48
+ /**
49
+ * @test
50
+ * @group is_path
51
+ * @covers ::is_path
52
+ * @small
53
+ */
54
+ public function should_return_false_if_path_has_no_leading_slash_and_wildcard() {
55
+ $this->assertFalse(PathHelper::is_path('path/to/somewhere'));
56
+ }
57
+ }
58
+
59
+ /**
60
+ * @coversDefaultClass \Tawk\Helpers\PathHelper
61
+ */
62
+ class PathChunksHasWildcardTest extends TestCase {
63
+ /**
64
+ * @test
65
+ * @group path_chunks_has_wildcard
66
+ * @covers ::path_chunks_has_wildcard
67
+ * @small
68
+ */
69
+ public function should_return_true_if_path_chunks_contains_wildcard() {
70
+ $path_chunks = array('*', 'to', 'somewhere');
71
+ $this->assertTrue(PathHelper::path_chunks_has_wildcard($path_chunks));
72
+ }
73
+
74
+ /**
75
+ * @test
76
+ * @group path_chunks_has_wildcard
77
+ * @covers ::path_chunks_has_wildcard
78
+ * @small
79
+ */
80
+ public function should_return_false_if_path_chunks_does_not_contain_wildcard() {
81
+ $path_chunks = array('path', 'to', 'somewhere');
82
+ $this->assertFalse(PathHelper::path_chunks_has_wildcard($path_chunks));
83
+ }
84
+ }
85
+
86
+ /**
87
+ * @coversDefaultClass \Tawk\Helpers\PathHelper
88
+ */
89
+ class IsWildcardTest extends TestCase {
90
+ /**
91
+ * @test
92
+ * @group is_wildcard
93
+ * @covers ::is_wildcard
94
+ * @small
95
+ */
96
+ public function should_return_true_if_wildcard() {
97
+ $this->assertTrue(PathHelper::is_wildcard('*'));
98
+ }
99
+
100
+ /**
101
+ * @test
102
+ * @group is_wildcard
103
+ * @covers ::is_wildcard
104
+ * @small
105
+ */
106
+ public function should_return_false_if_not_wildcard() {
107
+ $this->assertFalse(PathHelper::is_wildcard('not-wildcard'));
108
+ }
109
+ }
110
+
111
+ /**
112
+ * @coversDefaultClass \Tawk\Helpers\PathHelper
113
+ */
114
+ class GetChunksTest extends TestCase {
115
+ /**
116
+ * @test
117
+ * @group get_chunks
118
+ * @covers ::get_chunks
119
+ * @small
120
+ */
121
+ public function should_get_chunks_from_provided_path() {
122
+ $this->assertEquals(PathHelper::get_chunks('/path/to/somewhere'), array('path', 'to', 'somewhere'));
123
+ }
124
+
125
+ /**
126
+ * @test
127
+ * @group get_chunks
128
+ * @covers ::get_chunks
129
+ * @small
130
+ */
131
+ public function should_get_empty_string_array_if_only_provided_with_single_slash() {
132
+ $this->assertEquals(PathHelper::get_chunks('/'), array());
133
+ }
134
+ }
135
+
136
+ /**
137
+ * @coversDefaultClass \Tawk\Helpers\PathHelper
138
+ */
139
+ class GetWildcardLocationByChunks extends TestCase {
140
+ /**
141
+ * @test
142
+ * @group get_wildcard_location_by_chunks
143
+ * @covers ::get_wildcard_location_by_chunks
144
+ * @small
145
+ */
146
+ public function should_return_start_if_provided_chunks_has_leading_wildcard() {
147
+ $path_chunks = array('*', 'to', 'somewhere');
148
+ $this->assertEquals(PathHelper::get_wildcard_location_by_chunks($path_chunks), WildcardLocation::START);
149
+ }
150
+
151
+ /**
152
+ * @test
153
+ * @group get_wildcard_location_by_chunks
154
+ * @covers ::get_wildcard_location_by_chunks
155
+ * @small
156
+ */
157
+ public function should_return_middle_if_provided_chunks_has_wildcard_at_the_middle() {
158
+ $path_chunks = array('path', '*', 'somewhere');
159
+ $this->assertEquals(PathHelper::get_wildcard_location_by_chunks($path_chunks), WildcardLocation::MIDDLE);
160
+ }
161
+
162
+ /**
163
+ * @test
164
+ * @group get_wildcard_location_by_chunks
165
+ * @covers ::get_wildcard_location_by_chunks
166
+ * @small
167
+ */
168
+ public function should_return_end_if_provided_chunks_has_trailing_wildcard() {
169
+ $path_chunks = array('path', 'to', '*');
170
+ $this->assertEquals(PathHelper::get_wildcard_location_by_chunks($path_chunks), WildcardLocation::END);
171
+ }
172
+
173
+ /**
174
+ * @test
175
+ * @group get_wildcard_location_by_chunks
176
+ * @covers ::get_wildcard_location_by_chunks
177
+ * @small
178
+ */
179
+ public function should_return_none_if_provided_chunks_has_no_wildcard() {
180
+ $path_chunks = array('path', 'to', 'somewhere');
181
+ $this->assertEquals(PathHelper::get_wildcard_location_by_chunks($path_chunks), WildcardLocation::NONE);
182
+ }
183
+ }
184
+
185
+ /**
186
+ * @coversDefaultClass \Tawk\Helpers\PathHelper
187
+ */
188
+ class CheckStrictLength extends TestCase {
189
+ /**
190
+ * @test
191
+ * @group path_has_strict_length
192
+ * @covers ::path_has_strict_length
193
+ * @small
194
+ */
195
+ public function should_be_true_if_provided_path_has_leading_slash_and_wildcard() {
196
+ $path = '/*/to/somewhere';
197
+ $this->assertTrue(PathHelper::path_has_strict_length($path, WildcardLocation::START));
198
+ }
199
+
200
+ /**
201
+ * @test
202
+ * @group path_has_strict_length
203
+ * @covers ::path_has_strict_length
204
+ * @small
205
+ */
206
+ public function should_be_true_if_provided_path_has_trailing_wildcard_and_slash() {
207
+ $path = '/path/to/*/';
208
+ $this->assertTrue(PathHelper::path_has_strict_length($path, WildcardLocation::END));
209
+ }
210
+
211
+ /**
212
+ * @test
213
+ * @group path_has_strict_length
214
+ * @covers ::path_has_strict_length
215
+ * @small
216
+ */
217
+ public function should_be_false_if_provided_path_has_leading_wildcard_and_slash() {
218
+ $path = '*/to/somewhere';
219
+ $this->assertFalse(PathHelper::path_has_strict_length($path, WildcardLocation::START));
220
+ }
221
+
222
+ /**
223
+ * @test
224
+ * @group path_has_strict_length
225
+ * @covers ::path_has_strict_length
226
+ * @small
227
+ */
228
+ public function should_be_false_if_provided_path_has_trailing_slash_and_wildcard() {
229
+ $path = '/path/to/*';
230
+ $this->assertFalse(PathHelper::path_has_strict_length($path, WildcardLocation::END));
231
+ }
232
+
233
+ /**
234
+ * @test
235
+ * @group path_has_strict_length
236
+ * @covers ::path_has_strict_length
237
+ * @small
238
+ */
239
+ public function should_be_false_if_provided_path_has_no_leading_or_trailing_slash_and_wildcard() {
240
+ $path = '/path/*/somewhere';
241
+ $this->assertFalse(PathHelper::path_has_strict_length($path, WildcardLocation::MIDDLE));
242
+ }
243
+
244
+ /**
245
+ * @test
246
+ * @group path_has_strict_length
247
+ * @covers ::path_has_strict_length
248
+ * @small
249
+ */
250
+ public function should_be_false_if_provided_path_has_different_wildcard_location_on_path() {
251
+ $path = '/path/somewhere/*/';
252
+ $this->assertFalse(PathHelper::path_has_strict_length($path, WildcardLocation::START));
253
+ }
254
+ }
vendor/tawk/url-utils/tests/Helpers/UrlHelperTest.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Tests\Helpers\UrlHelperTest;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+
7
+ use Tawk\Helpers\UrlHelper;
8
+
9
+ /**
10
+ * @coversDefaultClass \Tawk\Helpers\UrlHelper
11
+ */
12
+ class ParsePatternUrl extends Testcase {
13
+ /**
14
+ * @test
15
+ * @group parse_url
16
+ * @covers ::parse_url
17
+ * @small
18
+ */
19
+ public function should_parse_provided_pattern_url() {
20
+ $pattern_url = 'http://www.example.com:80/path/to/somewhere';
21
+ $this->assertEquals(UrlHelper::parse_url($pattern_url), array(
22
+ 'scheme' => 'http',
23
+ 'host' => 'www.example.com',
24
+ 'port' => '80',
25
+ 'path' => '/path/to/somewhere'
26
+ ));
27
+ }
28
+
29
+ /**
30
+ * @test
31
+ * @group parse_url
32
+ * @covers ::parse_url
33
+ * @small
34
+ */
35
+ public function should_parse_provided_pattern_url_without_scheme() {
36
+ $pattern_url = 'www.example.com:80/path/to/somewhere';
37
+ $this->assertEquals(UrlHelper::parse_url($pattern_url), array(
38
+ 'host' => 'www.example.com',
39
+ 'port' => '80',
40
+ 'path' => '/path/to/somewhere'
41
+ ));
42
+ }
43
+
44
+ /**
45
+ * @test
46
+ * @group parse_url
47
+ * @covers ::parse_url
48
+ * @small
49
+ */
50
+ public function should_parse_provided_pattern_url_without_port() {
51
+ $pattern_url = 'http://www.example.com/path/to/somewhere';
52
+ $this->assertEquals(UrlHelper::parse_url($pattern_url), array(
53
+ 'scheme' => 'http',
54
+ 'host' => 'www.example.com',
55
+ 'path' => '/path/to/somewhere'
56
+ ));
57
+ }
58
+
59
+ /**
60
+ * @test
61
+ * @group parse_url
62
+ * @covers ::parse_url
63
+ * @small
64
+ */
65
+ public function should_parse_provided_pattern_url_without_path() {
66
+ $pattern_url = 'http://www.example.com:80';
67
+ $this->assertEquals(UrlHelper::parse_url($pattern_url), array(
68
+ 'scheme' => 'http',
69
+ 'host' => 'www.example.com',
70
+ 'port' => '80',
71
+ 'path' => '/'
72
+ ));
73
+ }
74
+
75
+ /**
76
+ * @test
77
+ * @group parse_url
78
+ * @covers ::parse_url
79
+ * @small
80
+ */
81
+ public function should_parse_provided_pattern_path() {
82
+ $pattern_path = '/path/to/somewhere';
83
+ $this->assertEquals(UrlHelper::parse_url($pattern_path), array(
84
+ 'path' => '/path/to/somewhere'
85
+ ));
86
+ }
87
+
88
+ /**
89
+ * @test
90
+ * @group parse_url
91
+ * @covers ::parse_url
92
+ * @small
93
+ */
94
+ public function should_parse_set_host_if_provided_pattern_path_has_no_leading_slash() {
95
+ $pattern_path = 'path/to/somewhere';
96
+ $this->assertEquals(UrlHelper::parse_url($pattern_path), array(
97
+ 'host' => 'path',
98
+ 'path' => '/to/somewhere'
99
+ ));
100
+ }
101
+ }
vendor/tawk/url-utils/tests/Models/PathPatternTest.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Tests\Models\PathPatternTest;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use Tawk\Enums\WildcardLocation;
7
+ use Tawk\Models\PathPattern;
8
+
9
+ /**
10
+ * @coversDefaultClass \Tawk\Models\PathPatternTest
11
+ */
12
+ class CreateInstanceFromPath extends TestCase {
13
+ /**
14
+ * @test
15
+ * @group create_instance_from_path
16
+ * @covers ::create_instance_from_path
17
+ * @small
18
+ */
19
+ public function should_create_path_pattern_instance_from_provided_path() {
20
+ $path_pattern = PathPattern::create_instance_from_path('/path/to/somewhere');
21
+ $this->assertInstanceOf(PathPattern::class, $path_pattern);
22
+ }
23
+ }
24
+
25
+ /**
26
+ * @coversDefaultClass \Tawk\Models\PathPatternTest
27
+ */
28
+ class HasWildcard extends TestCase {
29
+ /**
30
+ * @test
31
+ * @group has_wildcard
32
+ * @covers ::has_wildcard
33
+ * @small
34
+ */
35
+ public function should_be_true_if_path_provided_has_wildcard() {
36
+ $path_pattern = PathPattern::create_instance_from_path('/path/to/*');
37
+ $this->assertTrue($path_pattern->has_wildcard());
38
+ }
39
+
40
+ /**
41
+ * @test
42
+ * @group has_wildcard
43
+ * @covers ::has_wildcard
44
+ * @small
45
+ */
46
+ public function should_be_false_if_path_provided_does_not_have_wildcard() {
47
+ $path_pattern = PathPattern::create_instance_from_path('/path/to/somewhere');
48
+ $this->assertFalse($path_pattern->has_wildcard());
49
+ }
50
+ }
51
+
52
+ /**
53
+ * @coversDefaultClass \Tawk\Models\PathPatternTest
54
+ */
55
+ class HasStrictLength extends TestCase {
56
+ /**
57
+ * @test
58
+ * @group has_strict_length
59
+ * @covers ::has_strict_length
60
+ * @small
61
+ */
62
+ public function should_be_true_if_pattern_provided_has_leading_slash_and_wildcard() {
63
+ $path_pattern = PathPattern::create_instance_from_path('/*/to/somewhere');
64
+ $this->assertTrue($path_pattern->has_strict_length());
65
+ }
66
+
67
+ /**
68
+ * @test
69
+ * @group has_strict_length
70
+ * @covers ::has_strict_length
71
+ * @small
72
+ */
73
+ public function should_be_true_if_pattern_provided_has_trailing_wildcard_and_slash() {
74
+ $path_pattern = PathPattern::create_instance_from_path('/path/to/*/');
75
+ $this->assertTrue($path_pattern->has_strict_length());
76
+ }
77
+
78
+ /**
79
+ * @test
80
+ * @group has_strict_length
81
+ * @covers ::has_strict_length
82
+ * @small
83
+ */
84
+ public function should_be_false_if_pattern_provided_has_no_leading_or_trailing_slash_and_wildcard() {
85
+ $path_pattern = PathPattern::create_instance_from_path('/path/to/somewhere');
86
+ $this->assertFalse($path_pattern->has_strict_length());
87
+ }
88
+ }
89
+
90
+ /**
91
+ * @coversDefaultClass \Tawk\Models\PathPatternTest
92
+ */
93
+ class GetChunks extends TestCase {
94
+ /**
95
+ * @test
96
+ * @group get_chunks
97
+ * @covers ::get_chunks
98
+ * @small
99
+ */
100
+ public function should_provide_path_in_chunks() {
101
+ $path_pattern = PathPattern::create_instance_from_path('/path/to/somewhere');
102
+ $this->assertEquals($path_pattern->get_chunks(), array('path', 'to', 'somewhere'));
103
+ }
104
+ }
105
+
106
+ /**
107
+ * @coversDefaultClass \Tawk\Models\PathPatternTest
108
+ */
109
+ class GetWildcardLocation extends TestCase {
110
+ /**
111
+ * @test
112
+ * @group get_wildcard_location
113
+ * @covers ::get_wildcard_location
114
+ * @small
115
+ */
116
+ public function should_provide_wildcard_location() {
117
+ $path_pattern = PathPattern::create_instance_from_path('/path/*/somewhere');
118
+ $this->assertEquals($path_pattern->get_wildcard_location(), WildcardLocation::MIDDLE);
119
+ }
120
+ }
vendor/tawk/url-utils/tests/Modules/PathPatternMatcherTest.php ADDED
@@ -0,0 +1,543 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Tests\Modules;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use Tawk\Models\PathPattern;
7
+ use Tawk\Modules\PathPatternMatcher;
8
+
9
+ /**
10
+ * @coversDefaultClass \Tawk\Modules\PathPatternMatcher
11
+ */
12
+ class PathMatchTest extends TestCase {
13
+ /**
14
+ * @test
15
+ * @group match_path_no_wildcard
16
+ * @covers ::match
17
+ * @small
18
+ */
19
+ public function should_match_similar_path_and_pattern() {
20
+ $path_chunks = array('path', 'to', 'somewhere');
21
+ $pattern_chunks = array(
22
+ PathPattern::create_instance_from_path('/path/to/somewhere')
23
+ );
24
+
25
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
26
+ }
27
+
28
+ /**
29
+ * @test
30
+ * @group match_path_no_wildcard
31
+ * @covers ::match
32
+ * @small
33
+ */
34
+ public function should_match_both_empty_path_and_pattern() {
35
+ $path_chunks = array();
36
+ $pattern_chunks = array(
37
+ PathPattern::create_instance_from_path('')
38
+ );
39
+
40
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
41
+ }
42
+
43
+ /**
44
+ * @test
45
+ * @group match_path_no_wildcard
46
+ * @covers ::match
47
+ * @small
48
+ */
49
+ public function should_not_match_different_path_and_pattern() {
50
+ $path_chunks = array('path', 'to', 'somewhere');
51
+ $pattern_chunks = array(
52
+ PathPattern::create_instance_from_path('/path/different/path')
53
+ );
54
+
55
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
56
+ }
57
+
58
+ /**
59
+ * @test
60
+ * @group match_path_no_wildcard
61
+ * @covers ::match
62
+ * @small
63
+ */
64
+ public function should_not_match_path_longer_than_pattern() {
65
+ $path_chunks = array('path', 'to', 'somewhere', 'longer');
66
+ $pattern_chunks = array(
67
+ PathPattern::create_instance_from_path('/path/to/somewhere')
68
+ );
69
+
70
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
71
+ }
72
+
73
+ /**
74
+ * @test
75
+ * @group match_path_no_wildcard
76
+ * @covers ::match
77
+ * @small
78
+ */
79
+ public function should_not_match_path_shorter_than_pattern() {
80
+ $path_chunks = array('path', 'to', 'somewhere');
81
+ $pattern_chunks = array(
82
+ PathPattern::create_instance_from_path('/path/to/somewhere/longer')
83
+ );
84
+
85
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
86
+ }
87
+
88
+ /**
89
+ * @test
90
+ * @group match_path_single_wildcard
91
+ * @covers ::match
92
+ * @small
93
+ */
94
+ public function should_match_path_with_single_wildcard_pattern() {
95
+ $path_chunks = array('path', 'to', 'somewhere');
96
+ $pattern_chunks = array(
97
+ PathPattern::create_instance_from_path('*')
98
+ );
99
+
100
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
101
+ }
102
+
103
+ /**
104
+ * @test
105
+ * @group test
106
+ * @covers ::match
107
+ * @small
108
+ */
109
+ public function should_match_empty_path_with_single_wildcard_pattern() {
110
+ $path_chunks = array();
111
+ $pattern_chunks = array(
112
+ PathPattern::create_instance_from_path('*')
113
+ );
114
+
115
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
116
+ }
117
+
118
+ /**
119
+ * @test
120
+ * @group match_path_wildcard_start
121
+ * @covers ::match
122
+ * @small
123
+ */
124
+ public function should_match_path_with_leading_wildcard_pattern() {
125
+ $path_chunks = array('path', 'to', 'somewhere');
126
+ $pattern_chunks = array(
127
+ PathPattern::create_instance_from_path('*/to/somewhere')
128
+ );
129
+
130
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
131
+ }
132
+
133
+ /**
134
+ * @test
135
+ * @group match_path_wildcard_start
136
+ * @covers ::match
137
+ * @small
138
+ */
139
+ public function should_match_path_with_leading_wildcard_pattern_that_covers_multiple_path_chunks() {
140
+ $path_chunks = array('path', 'to', 'somewhere', 'longer');
141
+ $pattern_chunks = array(
142
+ PathPattern::create_instance_from_path('*/longer')
143
+ );
144
+
145
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
146
+ }
147
+
148
+ /**
149
+ * @test
150
+ * @group match_path_wildcard_start
151
+ * @covers ::match
152
+ * @small
153
+ */
154
+ public function should_not_match_path_longer_than_the_pattern_with_leading_wildcard() {
155
+ $path_chunks = array('path', 'to', 'somewhere', 'longer');
156
+ $pattern_chunks = array(
157
+ PathPattern::create_instance_from_path('*/to/somewhere')
158
+ );
159
+
160
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
161
+ }
162
+
163
+ /**
164
+ * @test
165
+ * @group match_path_wildcard_start
166
+ * @covers ::match
167
+ * @small
168
+ */
169
+ public function should_not_match_shorter_path_with_leading_wildcard_pattern_that_has_different_ending_path() {
170
+ $path_chunks = array('path', 'to', 'somewhere');
171
+ $pattern_chunks = array(
172
+ PathPattern::create_instance_from_path('*/to/somewhere/longer')
173
+ );
174
+
175
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
176
+ }
177
+
178
+ /**
179
+ * @test
180
+ * @group match_path_wildcard_start
181
+ * @covers ::match
182
+ * @small
183
+ */
184
+ public function should_not_match_different_ending_path_with_leading_wildcard_pattern_that_covers_multiple_path_chunks() {
185
+ $path_chunks = array('path', 'to', 'somewhere', 'longer', 'and', 'different');
186
+ $pattern_chunks = array(
187
+ PathPattern::create_instance_from_path('*/longer')
188
+ );
189
+
190
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
191
+ }
192
+
193
+ /**
194
+ * @test
195
+ * @group match_path_wildcard_start
196
+ * @covers ::match
197
+ * @small
198
+ */
199
+ public function should_not_match_path_with_leading_wildcard_pattern_that_covers_multiple_path_chunks_and_has_different_ending_path() {
200
+ $path_chunks = array('path', 'to', 'somewhere', 'longer');
201
+ $pattern_chunks = array(
202
+ PathPattern::create_instance_from_path('*/longer/and/different')
203
+ );
204
+
205
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
206
+ }
207
+
208
+ /**
209
+ * @test
210
+ * @group match_path_wildcard_start
211
+ * @covers ::match
212
+ * @small
213
+ */
214
+ public function should_not_match_path_with_leading_wildcard_pattern_that_has_no_similarities() {
215
+ $path_chunks = array('path', 'to', 'somewhere', 'longer', 'and', 'different');
216
+ $pattern_chunks = array(
217
+ PathPattern::create_instance_from_path('*/longer')
218
+ );
219
+
220
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
221
+ }
222
+
223
+ /**
224
+ * @test
225
+ * @group match_path_wildcard_start
226
+ * @covers ::match
227
+ * @small
228
+ */
229
+ public function should_not_match_empty_path_with_leading_wildcard_pattern() {
230
+ $path_chunks = array();
231
+ $pattern_chunks = array(
232
+ PathPattern::create_instance_from_path('*/to/somewhere')
233
+ );
234
+
235
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
236
+ }
237
+
238
+ /**
239
+ * @test
240
+ * @group match_path_wildcard_end
241
+ * @covers ::match
242
+ * @small
243
+ */
244
+ public function should_match_path_and_trailing_wildcard_pattern() {
245
+ $path_chunks = array('path', 'to', 'somewhere');
246
+ $pattern_chunks = array(
247
+ PathPattern::create_instance_from_path('/path/to/*')
248
+ );
249
+
250
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
251
+ }
252
+
253
+ /**
254
+ * @test
255
+ * @group match_path_wildcard_end
256
+ * @covers ::match
257
+ * @small
258
+ */
259
+ public function should_match_path_and_trailing_wildcard_pattern_that_covers_multiple_path_chunks() {
260
+ $path_chunks = array('path', 'to', 'somewhere');
261
+ $pattern_chunks = array(
262
+ PathPattern::create_instance_from_path('/path/*')
263
+ );
264
+
265
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
266
+ }
267
+
268
+ /**
269
+ * @test
270
+ * @group match_path_wildcard_end
271
+ * @covers ::match
272
+ * @small
273
+ */
274
+ public function should_not_match_path_and_trailing_wildcard_pattern_that_contains_the_full_path() {
275
+ $path_chunks = array('path', 'to', 'somewhere');
276
+ $pattern_chunks = array(
277
+ PathPattern::create_instance_from_path('/path/to/somewhere/*')
278
+ );
279
+
280
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
281
+ }
282
+
283
+ /**
284
+ * @test
285
+ * @group match_path_wildcard_end
286
+ * @covers ::match
287
+ * @small
288
+ */
289
+ public function should_not_match_path_with_trailing_wildcard_pattern_that_has_different_starting_path() {
290
+ $path_chunks = array('path', 'to', 'somewhere');
291
+ $pattern_chunks = array(
292
+ PathPattern::create_instance_from_path('/different/path/*')
293
+ );
294
+
295
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
296
+ }
297
+
298
+ /**
299
+ * @test
300
+ * @group match_path_wildcard_end
301
+ * @covers ::match
302
+ * @small
303
+ */
304
+ public function should_not_match_empty_path_with_trailing_wildcard_pattern() {
305
+ $path_chunks = array();
306
+ $pattern_chunks = array(
307
+ PathPattern::create_instance_from_path('/different/path/*')
308
+ );
309
+
310
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
311
+ }
312
+
313
+ /**
314
+ * @test
315
+ * @group match_path_wildcard_end
316
+ * @covers ::match
317
+ * @small
318
+ */
319
+ public function should_not_match_path_with_trailing_wildcard_pattern_that_contains_the_full_path_but_has_additional_path() {
320
+ $path_chunks = array('path', 'to', 'somewhere');
321
+ $pattern_chunks = array(
322
+ PathPattern::create_instance_from_path('/path/to/somewhere/longer/*')
323
+ );
324
+
325
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
326
+ }
327
+
328
+ /**
329
+ * @test
330
+ * @group match_path_wildcard_middle
331
+ * @covers ::match
332
+ * @small
333
+ */
334
+ public function should_match_path_with_middle_wildcard_pattern() {
335
+ $path_chunks = array('path', 'to', 'somewhere');
336
+ $pattern_chunks = array(
337
+ PathPattern::create_instance_from_path('/path/*/somewhere')
338
+ );
339
+
340
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
341
+ }
342
+
343
+ /**
344
+ * @test
345
+ * @group match_path_wildcard_middle
346
+ * @covers ::match
347
+ * @small
348
+ */
349
+ public function should_match_path_with_multiple_middle_wildcard_pattern() {
350
+ $path_chunks = array('path', 'to', 'some', 'different', 'place');
351
+ $pattern_chunks = array(
352
+ PathPattern::create_instance_from_path('/path/*/some/*/place')
353
+ );
354
+
355
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
356
+ }
357
+
358
+ /**
359
+ * @test
360
+ * @group match_path_wildcard_middle
361
+ * @covers ::match
362
+ * @small
363
+ */
364
+ public function should_match_path_with_multiple_succeeding_middle_wildcard_pattern() {
365
+ $path_chunks = array('path', 'to', 'somewhere', 'different');
366
+ $pattern_chunks = array(
367
+ PathPattern::create_instance_from_path('/path/*/*/different')
368
+ );
369
+
370
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
371
+ }
372
+
373
+ /**
374
+ * @test
375
+ * @group match_path_wildcard_middle
376
+ * @covers ::match
377
+ * @small
378
+ */
379
+ public function should_not_match_path_with_middle_wildcard_pattern_that_has_different_start_and_end_paths() {
380
+ $path_chunks = array('path', 'to', 'somewhere');
381
+ $pattern_chunks = array(
382
+ PathPattern::create_instance_from_path('/different/*/path')
383
+ );
384
+
385
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
386
+ }
387
+
388
+ /**
389
+ * @test
390
+ * @group match_path_with_leading_slash_and_wildcard
391
+ * @covers ::match()
392
+ * @small
393
+ */
394
+ public function should_match_path_with_leading_slash_and_wildcard_pattern() {
395
+ $path_chunks = array('path', 'to', 'somewhere');
396
+ $pattern_chunks = array(
397
+ PathPattern::create_instance_from_path('/*/to/somewhere')
398
+ );
399
+
400
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
401
+ }
402
+
403
+ /**
404
+ * @test
405
+ * @group match_path_with_leading_slash_and_wildcard
406
+ * @covers ::match()
407
+ * @small
408
+ */
409
+ public function should_not_match_multiple_leading_path_with_leading_slash_and_wildcard_pattern() {
410
+ $path_chunks = array('more', 'path', 'to', 'somewhere');
411
+ $pattern_chunks = array(
412
+ PathPattern::create_instance_from_path('/*/to/somewhere')
413
+ );
414
+
415
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
416
+ }
417
+
418
+ /**
419
+ * @test
420
+ * @group match_path_with_trailing_slash_and_wildcard
421
+ * @covers ::match()
422
+ * @small
423
+ */
424
+ public function should_match_path_with_trailing_slash_and_wildcard_pattern() {
425
+ $path_chunks = array('path', 'to', 'somewhere');
426
+ $pattern_chunks = array(
427
+ PathPattern::create_instance_from_path('/path/to/*/')
428
+ );
429
+
430
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
431
+ }
432
+
433
+ /**
434
+ * @test
435
+ * @group match_path_with_trailing_slash_and_wildcard
436
+ * @covers ::match()
437
+ * @small
438
+ */
439
+ public function should_not_match_multiple_trailing_path_with_trailing_slash_and_wildcard_pattern() {
440
+ $path_chunks = array('path', 'to', 'somewhere', 'safe');
441
+ $pattern_chunks = array(
442
+ PathPattern::create_instance_from_path('/path/to/*/')
443
+ );
444
+
445
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
446
+ }
447
+
448
+
449
+ /**
450
+ * @test
451
+ * @group match_path_with_leading_and_middle_wildcard
452
+ * @covers ::match()
453
+ * @small
454
+ */
455
+ public function should_match_path_with_leading_and_middle_wildcard_pattern() {
456
+ $path_chunks = array('some', 'other', 'path', 'to', 'somewhere');
457
+ $pattern_chunks = array(
458
+ PathPattern::create_instance_from_path('*/path/*/somewhere')
459
+ );
460
+
461
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
462
+ }
463
+
464
+ /**
465
+ * @test
466
+ * @group match_path_with_leading_and_middle_wildcard
467
+ * @covers ::match()
468
+ * @small
469
+ */
470
+ public function should_not_match_multiple_middle_path_with_leading_and_middle_wildcard_pattern() {
471
+ $path_chunks = array('some', 'other', 'path', 'leads', 'to', 'somewhere');
472
+ $pattern_chunks = array(
473
+ PathPattern::create_instance_from_path('*/path/*/somewhere')
474
+ );
475
+
476
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
477
+ }
478
+
479
+
480
+ /**
481
+ * @test
482
+ * @group match_path_with_trailing_and_middle_wildcard
483
+ * @covers ::match()
484
+ * @small
485
+ */
486
+ public function should_match_path_with_trailing_and_middle_wildcard_pattern() {
487
+ $path_chunks = array('path', 'to', 'another', 'place');
488
+ $pattern_chunks = array(
489
+ PathPattern::create_instance_from_path('/path/*/another/*')
490
+ );
491
+
492
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
493
+ }
494
+
495
+ /**
496
+ * @test
497
+ * @group match_path_with_trailing_and_middle_wildcard
498
+ * @covers ::match()
499
+ * @small
500
+ */
501
+ public function should_not_match_multiple_middle_path_with_trailing_and_middle_wildcard_pattern() {
502
+ $path_chunks = array('path', 'leads', 'to', 'another', 'place');
503
+ $pattern_chunks = array(
504
+ PathPattern::create_instance_from_path('/path/*/another/*')
505
+ );
506
+
507
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
508
+ }
509
+
510
+ /**
511
+ * @test
512
+ * @group match_path_multiple
513
+ * @covers ::match
514
+ * @small
515
+ */
516
+ public function should_match_path_with_one_of_the_provided_patterns() {
517
+ $path_chunks = array('path', 'to', 'somewhere');
518
+ $pattern_chunks = array(
519
+ PathPattern::create_instance_from_path('/path/*/elsewhere'),
520
+ PathPattern::create_instance_from_path('/path/on/*'),
521
+ PathPattern::create_instance_from_path('*/to/somewhere')
522
+ );
523
+
524
+ $this->assertTrue(PathPatternMatcher::match($path_chunks, $pattern_chunks));
525
+ }
526
+
527
+ /**
528
+ * @test
529
+ * @group match_path_multiple
530
+ * @covers ::match
531
+ * @small
532
+ */
533
+ public function should_not_match_path_with_any_of_the_provided_patterns_that_are_different() {
534
+ $path_chunks = array('path', 'to', 'somewhere');
535
+ $pattern_chunks = array(
536
+ PathPattern::create_instance_from_path('/path/to/elsewhere'),
537
+ PathPattern::create_instance_from_path('/path/is/somewhere'),
538
+ PathPattern::create_instance_from_path('*/others')
539
+ );
540
+
541
+ $this->assertFalse(PathPatternMatcher::match($path_chunks, $pattern_chunks));
542
+ }
543
+ }
vendor/tawk/url-utils/tests/Modules/UrlPatternMatcherTest.php ADDED
@@ -0,0 +1,375 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Tawk\Tests\Modules;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use Tawk\Modules\UrlPatternMatcher;
7
+
8
+ /**
9
+ * @coversDefaultClass \Tawk\Modules\UrlPatternMatcher
10
+ */
11
+ class UrlMatchTest extends TestCase {
12
+ /**
13
+ * @test
14
+ * @group match_url
15
+ * @covers ::match
16
+ * @small
17
+ */
18
+ public function should_match_similar_url() {
19
+ $url = 'http://www.example.com';
20
+ $pattern = array('http://www.example.com');
21
+ $result = UrlPatternMatcher::match($url, $pattern);
22
+
23
+ $this->assertTrue($result);
24
+ }
25
+
26
+ /**
27
+ * @test
28
+ * @group match_url_scheme
29
+ * @covers ::match
30
+ * @small
31
+ */
32
+ public function should_match_url_with_pattern_that_has_no_scheme() {
33
+ $url = 'http://www.example.com';
34
+ $pattern = array('www.example.com');
35
+ $result = UrlPatternMatcher::match($url, $pattern);
36
+
37
+ $this->assertTrue($result);
38
+ }
39
+
40
+ /**
41
+ * @test
42
+ * @group match_url_scheme
43
+ * @covers ::match
44
+ * @small
45
+ */
46
+ public function should_not_match_url_with_different_pattern_scheme() {
47
+ $url = 'http://www.example.com';
48
+ $pattern = array('https://www.example.com');
49
+ $result = UrlPatternMatcher::match($url, $pattern);
50
+
51
+ $this->assertFalse($result);
52
+ }
53
+
54
+ /**
55
+ * @test
56
+ * @group match_url_host
57
+ * @covers ::match
58
+ * @small
59
+ */
60
+ public function should_not_match_different_url_host() {
61
+ $url = 'http://www.example.com';
62
+ $pattern = array('http://www.tawk.to');
63
+ $result = UrlPatternMatcher::match($url, $pattern);
64
+
65
+ $this->assertFalse($result);
66
+ }
67
+
68
+ /**
69
+ * @test
70
+ * @group match_url_host
71
+ * @covers ::match
72
+ */
73
+ public function should_match_url_with_ip_address_as_host() {
74
+ $url = 'http://192.168.0.1/path/to/somewhere';
75
+ $pattern = array('http://192.168.0.1/path/to/somewhere');
76
+ $result = UrlPatternMatcher::match($url, $pattern);
77
+
78
+ $this->assertTrue($result);
79
+ }
80
+
81
+ /**
82
+ * @test
83
+ * @group match_url_host
84
+ * @covers ::match
85
+ * @small
86
+ */
87
+ public function should_match_localhost() {
88
+ $url = 'http://localhost';
89
+ $pattern = array('http://localhost');
90
+ $result = UrlPatternMatcher::match($url, $pattern);
91
+
92
+ $this->assertTrue($result);
93
+ }
94
+
95
+ /**
96
+ * @test
97
+ * @group match_url_host
98
+ * @covers ::match
99
+ * @small
100
+ */
101
+ public function should_match_localhost_without_scheme() {
102
+ $url = 'http://localhost';
103
+ $pattern = array('localhost');
104
+ $result = UrlPatternMatcher::match($url, $pattern);
105
+
106
+ $this->assertTrue($result);
107
+ }
108
+
109
+ /**
110
+ * @test
111
+ * @group match_url_port
112
+ * @covers ::match
113
+ * @small
114
+ */
115
+ public function should_match_similar_url_port() {
116
+ $url = 'http://www.example.com:80';
117
+ $pattern = array('http://www.example.com:80');
118
+ $result = UrlPatternMatcher::match($url, $pattern);
119
+
120
+ $this->assertTrue($result);
121
+ }
122
+
123
+ /**
124
+ * @test
125
+ * @group match_url_port
126
+ * @covers ::match
127
+ * @small
128
+ */
129
+ public function should_not_match_different_url_port() {
130
+ $url = 'http://www.example.com:80';
131
+ $pattern = array('http://www.example.com:8000');
132
+ $result = UrlPatternMatcher::match($url, $pattern);
133
+
134
+ $this->assertFalse($result);
135
+ }
136
+
137
+ /**
138
+ * @test
139
+ * @group match_url_with_full_url_and_path
140
+ * @covers ::match
141
+ * @small
142
+ */
143
+ public function should_match_similar_url_and_pattern() {
144
+ $url = 'http://www.example.com/path/to/somewhere';
145
+ $pattern = array('http://www.example.com/path/to/somewhere');
146
+ $result = UrlPatternMatcher::match($url, $pattern);
147
+
148
+ $this->assertTrue($result);
149
+ }
150
+
151
+ /**
152
+ * @test
153
+ * @group match_url_with_full_url_and_path
154
+ * @covers ::match
155
+ * @small
156
+ */
157
+ public function should_match_url_with_full_url_and_leading_wildcard_path_pattern() {
158
+ $url = 'http://www.example.com/path/to/somewhere';
159
+ $pattern = array('http://www.example.com/*/to/somewhere');
160
+ $result = UrlPatternMatcher::match($url, $pattern);
161
+
162
+ $this->assertTrue($result);
163
+ }
164
+
165
+ /**
166
+ * @test
167
+ * @group match_url_with_full_url_and_path
168
+ * @covers ::match
169
+ * @small
170
+ */
171
+ public function should_match_url_with_full_url_and_trailing_wildcard_path_pattern() {
172
+ $url = 'http://www.example.com/path/to/somewhere';
173
+ $pattern = array('http://www.example.com/path/to/*');
174
+ $result = UrlPatternMatcher::match($url, $pattern);
175
+
176
+ $this->assertTrue($result);
177
+ }
178
+
179
+ /**
180
+ * @test
181
+ * @group match_url_with_full_url_and_path
182
+ * @covers ::match
183
+ * @small
184
+ */
185
+ public function should_match_url_with_full_url_and_middle_wildcard_path_pattern() {
186
+ $url = 'http://www.example.com/path/to/somewhere';
187
+ $pattern = array('http://www.example.com/path/*/somewhere');
188
+ $result = UrlPatternMatcher::match($url, $pattern);
189
+
190
+ $this->assertTrue($result);
191
+ }
192
+
193
+ /**
194
+ * @test
195
+ * @group match_url_with_full_url_and_path
196
+ * @covers ::match
197
+ * @small
198
+ */
199
+ public function should_match_url_with_full_url_and_only_wildcard_path_pattern() {
200
+ $url = 'http://www.example.com/path/to/somewhere';
201
+ $pattern = array('http://www.example.com/*');
202
+ $result = UrlPatternMatcher::match($url, $pattern);
203
+
204
+ $this->assertTrue($result);
205
+ }
206
+
207
+ /**
208
+ * @test
209
+ * @group match_url_with_full_url_and_path
210
+ * @covers ::match
211
+ * @small
212
+ */
213
+ public function should_match_url_and_empty_path_with_full_url_and_only_wildcard_path_pattern() {
214
+ $url = 'http://www.example.com/';
215
+ $pattern = array('http://www.example.com/*');
216
+ $result = UrlPatternMatcher::match($url, $pattern);
217
+
218
+ $this->assertTrue($result);
219
+ }
220
+
221
+ /**
222
+ * @test
223
+ * @group match_url_with_path_only
224
+ * @covers ::match
225
+ * @small
226
+ */
227
+ public function should_match_url_with_path_only_pattern() {
228
+ $url = 'http://www.example.com/path/to/somewhere';
229
+ $pattern = array('/path/to/somewhere');
230
+ $result = UrlPatternMatcher::match($url, $pattern);
231
+
232
+ $this->assertTrue($result);
233
+ }
234
+
235
+ /**
236
+ * @test
237
+ * @group match_url_with_path_only
238
+ * @covers ::match
239
+ * @small
240
+ */
241
+ public function should_match_url_with_leading_wildcard_pattern_path() {
242
+ $url = 'http://www.example.com/path/to/somewhere';
243
+ $pattern = array('*/to/somewhere');
244
+ $result = UrlPatternMatcher::match($url, $pattern);
245
+
246
+ $this->assertTrue($result);
247
+ }
248
+
249
+ /**
250
+ * @test
251
+ * @group match_url_with_path_only
252
+ * @covers ::match
253
+ * @small
254
+ */
255
+ public function should_match_url_with_trailing_wildcard_pattern_path() {
256
+ $url = 'http://www.example.com/path/to/somewhere';
257
+ $pattern = array('/path/to/*');
258
+ $result = UrlPatternMatcher::match($url, $pattern);
259
+
260
+ $this->assertTrue($result);
261
+ }
262
+
263
+ /**
264
+ * @test
265
+ * @group match_url_with_path_only
266
+ * @covers ::match
267
+ * @small
268
+ */
269
+ public function should_match_url_with_middle_wildcard_pattern_path() {
270
+ $url = 'http://www.example.com/path/to/somewhere';
271
+ $pattern = array('/path/*/somewhere');
272
+ $result = UrlPatternMatcher::match($url, $pattern);
273
+
274
+ $this->assertTrue($result);
275
+ }
276
+
277
+ /**
278
+ * @test
279
+ * @group match_url_with_path_only
280
+ * @covers ::match
281
+ * @small
282
+ */
283
+ public function should_match_url_and_empty_path_with_wildcard_only_pattern_path() {
284
+ $url = 'http://www.example.com';
285
+ $pattern = array('*');
286
+ $result = UrlPatternMatcher::match($url, $pattern);
287
+
288
+ $this->assertTrue($result);
289
+ }
290
+
291
+ /**
292
+ * @test
293
+ * @group match_url_with_path_only
294
+ * @covers ::match
295
+ * @small
296
+ */
297
+ public function should_match_url_with_wildcard_only_pattern_path() {
298
+ $url = 'http://www.example.com/path/to/somewhere';
299
+ $pattern = array('*');
300
+ $result = UrlPatternMatcher::match($url, $pattern);
301
+
302
+ $this->assertTrue($result);
303
+ }
304
+
305
+ /**
306
+ * @test
307
+ * @group match_url_with_path_only
308
+ * @covers ::match
309
+ * @small
310
+ */
311
+ public function should_not_match_url_with_pattern_not_having_leading_slash_or_wildcard() {
312
+ $url = 'http://www.example.com/path/to/somewhere';
313
+ $pattern = array('path/to/somewhere');
314
+ $result = UrlPatternMatcher::match($url, $pattern);
315
+
316
+ $this->assertFalse($result);
317
+ }
318
+
319
+ /**
320
+ * @test
321
+ * @group match_url_multiple
322
+ * @covers ::match
323
+ * @small
324
+ */
325
+ public function should_match_url_with_multiple_patterns() {
326
+ $url = 'http://www.example.com/path/to/somewhere';
327
+ $pattern = array(
328
+ 'path/to/somewhere',
329
+ 'http://www.example.com/path/to/*',
330
+ 'http://www.example.com/*/path/should/lead/to/somewhere',
331
+ 'this/*/should/lead/to/somewhere'
332
+ );
333
+ $result = UrlPatternMatcher::match($url, $pattern);
334
+
335
+ $this->assertTrue($result);
336
+ }
337
+
338
+ /**
339
+ * @test
340
+ * @group match_url_multiple
341
+ * @covers ::match
342
+ * @small
343
+ */
344
+ public function should_match_url_with_multiple_patterns_that_has_one_similar_pattern() {
345
+ $url = 'http://www.example.com/path/to/somewhere';
346
+ $pattern = array(
347
+ '/this/path/should/lead/to/elsewhere',
348
+ 'http://www.example.com/this/path/should/lead/in/*',
349
+ 'http://www.example.com/*/path/should/lead/to/me',
350
+ '/path/*/somewhere' // valid
351
+ );
352
+ $result = UrlPatternMatcher::match($url, $pattern);
353
+
354
+ $this->assertTrue($result);
355
+ }
356
+
357
+ /**
358
+ * @test
359
+ * @group match_url_multiple
360
+ * @covers ::match
361
+ * @small
362
+ */
363
+ public function should_not_match_url_with_multiple_patterns_that_are_all_different() {
364
+ $url = 'http://www.example.com/path/to/somewhere';
365
+ $pattern = array(
366
+ 'this/path/should/lead/to/elsewhere',
367
+ 'http://www.example.com/this/path/should/lead/in/*',
368
+ 'http://www.example.com/*/path/should/lead/to/me',
369
+ 'this/*/shouldnot/lead/to/somewhere'
370
+ );
371
+ $result = UrlPatternMatcher::match($url, $pattern);
372
+
373
+ $this->assertFalse($result);
374
+ }
375
+ }