Printful Integration for WooCommerce - Version 2.1.20

Version Description

Woocommerce compatibility raised to 5.0

Download this release

Release Info

Developer printful
Plugin Icon 128x128 Printful Integration for WooCommerce
Version 2.1.20
Comparing to
See all releases

Code changes from version 2.1.19 to 2.1.20

assets/css/dashboard.css CHANGED
@@ -1,181 +1,181 @@
1
- .printful-connect {
2
- position: relative;
3
- height: 100%;
4
- }
5
-
6
- .printful-connect-inner {
7
- max-width: 600px;
8
- margin: 100px auto 0 auto;
9
- text-align: center;
10
- position: relative;
11
- }
12
- .printful-connect .connect-image {
13
- max-width: 100%;
14
- }
15
- .printful-connect h1 {
16
- margin-bottom: 30px;
17
- font-size: 34px;
18
- }
19
- .printful-connect .connect-description {
20
- margin: 20px 0 30px 0;
21
- }
22
-
23
- /*noinspection CssUnusedSymbol*/
24
- .printful-connect .printful-connect-button {
25
- height: 53px;
26
- line-height: 53px;
27
- padding: 0 40px;
28
- font-size: 18px;
29
- }
30
-
31
- .printful-stats {
32
- position: relative;
33
- margin: 20px 0 50px 0;
34
- background-color: #fff;
35
- padding: 30px 20px;
36
- box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
37
- border-left: #0073aa 4px solid;
38
- }
39
- .printful-stats .printful-stats-item {
40
- width: 49%;
41
- display: inline-block;
42
- margin-bottom: 25px;
43
- box-sizing: border-box;
44
- vertical-align: top;
45
- padding: 0 8px;
46
- }
47
-
48
- .printful-stats .printful-stats-item h4 {
49
- margin: 0 0 10px 0;
50
- font-size: 24px;
51
- line-height: 26px;
52
- }
53
- .printful-stats .printful-stats-item h4 .dashicons {
54
- font-size: 26px;
55
- width: 26px;
56
- height: 26px;
57
- }
58
-
59
- /*noinspection ALL*/
60
- .printful-stats .printful-stats-item h4 .dashicons-arrow-up-alt {
61
- color: green;
62
- }
63
- .printful-stats .printful-stats-item h4 .dashicons-arrow-down-alt {
64
- color: #d54e21;
65
- }
66
-
67
- @media (min-width: 768px) {
68
- .printful-stats .printful-stats-item {
69
- width: 24%;
70
- margin-bottom: 0;
71
- padding: 0 25px;
72
- }
73
- .printful-stats .printful-stats-item h4 {
74
- font-size: 32px;
75
- line-height: 36px;
76
- }
77
- .printful-stats .printful-stats-item h4 .dashicons {
78
- padding-top: 4px;
79
- font-size: 30px;
80
- width: 30px;
81
- height: 30px;
82
- }
83
- }
84
-
85
- .printful-latest-orders {
86
- display: table;
87
- width: 100%;
88
- margin-bottom: 50px;
89
- }
90
- .printful-latest-orders .row {
91
- display: table-row;
92
- }
93
- .printful-latest-orders .row .cell {
94
- display: table-cell;
95
- }
96
-
97
- .wrap h2.nav-tab-wrapper.printful-tabs {
98
- margin-bottom: 15px;
99
- }
100
-
101
-
102
- .printful-quick-links {
103
- position: relative;
104
- margin-bottom: 30px;
105
- }
106
- .printful-quick-links .printful-quick-links-item {
107
- width: 120px;
108
- background: #fff;
109
- border: solid 1px #e1e1e1;
110
- float: left;
111
- padding: 20px;
112
- margin-right: 25px;
113
- margin-bottom: 25px;
114
- text-align: center;
115
- text-decoration: none;
116
- }
117
- .printful-quick-links .printful-quick-links-item .dashicons {
118
- font-size: 40px;
119
- width: 40px;
120
- height: 40px;
121
- text-decoration: none;
122
- color: #444;
123
- }
124
- .printful-quick-links .printful-quick-links-item h4 {
125
- text-decoration: none;
126
- color: #444;
127
- margin: 5px 0 0 0;
128
- }
129
- .printful-quick-links .printful-quick-links-item:hover {
130
- cursor: pointer;
131
- }
132
- .printful-quick-links .printful-quick-links-item:hover .dashicons,
133
- .printful-quick-links .printful-quick-links-item:hover h4 {
134
- color: #0D72B2;
135
- }
136
-
137
- .printful-error {
138
- margin-top: 20px;
139
- }
140
-
141
- .printful-notice {
142
- background: #fff;
143
- border-left: 4px solid #dc3232;
144
- padding: 1px 12px;
145
- margin: 10px 0 20px 0;
146
- box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
147
- text-align: left;
148
- }
149
- .printful-notice li {
150
- font-weight: bold;
151
- margin-left: 20px;
152
- list-style: disc;
153
- }
154
-
155
- .block-loader {
156
- text-align: center;
157
- padding: 20px 0;
158
- line-height: 20px;
159
- }
160
- .block-loader .message {
161
- padding-left: 10px;
162
- line-height: 20px;
163
- display: inline-block;
164
- font-size: 16px;
165
- }
166
- .block-loader .loader {
167
- vertical-align: top;
168
- }
169
-
170
- #wpfooter::after {
171
- box-sizing: border-box;
172
- content: "";
173
- width: 64px;
174
- left: 50%;
175
- margin-left: -32px;
176
- height: 28px;
177
- position: absolute;
178
- bottom: 0;
179
- background: url("../images/printful-logo-footer.png") no-repeat bottom center;
180
- background-size: 64px;
181
  }
1
+ .printful-connect {
2
+ position: relative;
3
+ height: 100%;
4
+ }
5
+
6
+ .printful-connect-inner {
7
+ max-width: 600px;
8
+ margin: 100px auto 0 auto;
9
+ text-align: center;
10
+ position: relative;
11
+ }
12
+ .printful-connect .connect-image {
13
+ max-width: 100%;
14
+ }
15
+ .printful-connect h1 {
16
+ margin-bottom: 30px;
17
+ font-size: 34px;
18
+ }
19
+ .printful-connect .connect-description {
20
+ margin: 20px 0 30px 0;
21
+ }
22
+
23
+ /*noinspection CssUnusedSymbol*/
24
+ .printful-connect .printful-connect-button {
25
+ height: 53px;
26
+ line-height: 53px;
27
+ padding: 0 40px;
28
+ font-size: 18px;
29
+ }
30
+
31
+ .printful-stats {
32
+ position: relative;
33
+ margin: 20px 0 50px 0;
34
+ background-color: #fff;
35
+ padding: 30px 20px;
36
+ box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
37
+ border-left: #0073aa 4px solid;
38
+ }
39
+ .printful-stats .printful-stats-item {
40
+ width: 49%;
41
+ display: inline-block;
42
+ margin-bottom: 25px;
43
+ box-sizing: border-box;
44
+ vertical-align: top;
45
+ padding: 0 8px;
46
+ }
47
+
48
+ .printful-stats .printful-stats-item h4 {
49
+ margin: 0 0 10px 0;
50
+ font-size: 24px;
51
+ line-height: 26px;
52
+ }
53
+ .printful-stats .printful-stats-item h4 .dashicons {
54
+ font-size: 26px;
55
+ width: 26px;
56
+ height: 26px;
57
+ }
58
+
59
+ /*noinspection ALL*/
60
+ .printful-stats .printful-stats-item h4 .dashicons-arrow-up-alt {
61
+ color: green;
62
+ }
63
+ .printful-stats .printful-stats-item h4 .dashicons-arrow-down-alt {
64
+ color: #d54e21;
65
+ }
66
+
67
+ @media (min-width: 768px) {
68
+ .printful-stats .printful-stats-item {
69
+ width: 24%;
70
+ margin-bottom: 0;
71
+ padding: 0 25px;
72
+ }
73
+ .printful-stats .printful-stats-item h4 {
74
+ font-size: 32px;
75
+ line-height: 36px;
76
+ }
77
+ .printful-stats .printful-stats-item h4 .dashicons {
78
+ padding-top: 4px;
79
+ font-size: 30px;
80
+ width: 30px;
81
+ height: 30px;
82
+ }
83
+ }
84
+
85
+ .printful-latest-orders {
86
+ display: table;
87
+ width: 100%;
88
+ margin-bottom: 50px;
89
+ }
90
+ .printful-latest-orders .row {
91
+ display: table-row;
92
+ }
93
+ .printful-latest-orders .row .cell {
94
+ display: table-cell;
95
+ }
96
+
97
+ .wrap h2.nav-tab-wrapper.printful-tabs {
98
+ margin-bottom: 15px;
99
+ }
100
+
101
+
102
+ .printful-quick-links {
103
+ position: relative;
104
+ margin-bottom: 30px;
105
+ }
106
+ .printful-quick-links .printful-quick-links-item {
107
+ width: 120px;
108
+ background: #fff;
109
+ border: solid 1px #e1e1e1;
110
+ float: left;
111
+ padding: 20px;
112
+ margin-right: 25px;
113
+ margin-bottom: 25px;
114
+ text-align: center;
115
+ text-decoration: none;
116
+ }
117
+ .printful-quick-links .printful-quick-links-item .dashicons {
118
+ font-size: 40px;
119
+ width: 40px;
120
+ height: 40px;
121
+ text-decoration: none;
122
+ color: #444;
123
+ }
124
+ .printful-quick-links .printful-quick-links-item h4 {
125
+ text-decoration: none;
126
+ color: #444;
127
+ margin: 5px 0 0 0;
128
+ }
129
+ .printful-quick-links .printful-quick-links-item:hover {
130
+ cursor: pointer;
131
+ }
132
+ .printful-quick-links .printful-quick-links-item:hover .dashicons,
133
+ .printful-quick-links .printful-quick-links-item:hover h4 {
134
+ color: #0D72B2;
135
+ }
136
+
137
+ .printful-error {
138
+ margin-top: 20px;
139
+ }
140
+
141
+ .printful-notice {
142
+ background: #fff;
143
+ border-left: 4px solid #dc3232;
144
+ padding: 1px 12px;
145
+ margin: 10px 0 20px 0;
146
+ box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
147
+ text-align: left;
148
+ }
149
+ .printful-notice li {
150
+ font-weight: bold;
151
+ margin-left: 20px;
152
+ list-style: disc;
153
+ }
154
+
155
+ .block-loader {
156
+ text-align: center;
157
+ padding: 20px 0;
158
+ line-height: 20px;
159
+ }
160
+ .block-loader .message {
161
+ padding-left: 10px;
162
+ line-height: 20px;
163
+ display: inline-block;
164
+ font-size: 16px;
165
+ }
166
+ .block-loader .loader {
167
+ vertical-align: top;
168
+ }
169
+
170
+ #wpfooter::after {
171
+ box-sizing: border-box;
172
+ content: "";
173
+ width: 64px;
174
+ left: 50%;
175
+ margin-left: -32px;
176
+ height: 28px;
177
+ position: absolute;
178
+ bottom: 0;
179
+ background: url("../images/printful-logo-footer.png") no-repeat bottom center;
180
+ background-size: 64px;
181
  }
assets/css/global.css CHANGED
@@ -1,19 +1,19 @@
1
- .printful-toolbar .printful-toolbar-issues {
2
- background-color: #d54e21;
3
- display: inline-block;
4
- padding: 0 5px !important;
5
- border-radius: 10px !important;
6
- line-height: 16px !important;
7
- font-size: 11px !important;
8
- color: #fff !important;
9
- }
10
- .printful-toolbar:hover .printful-toolbar-issues,
11
- .printful-toolbar:active .printful-toolbar-issues,
12
- .printful-toolbar.hover .printful-toolbar-issues
13
- {
14
- color: #fff !important;
15
- }
16
-
17
- #adminmenu .toplevel_page_printful-dashboard img {
18
- width: 28px;
19
  }
1
+ .printful-toolbar .printful-toolbar-issues {
2
+ background-color: #d54e21;
3
+ display: inline-block;
4
+ padding: 0 5px !important;
5
+ border-radius: 10px !important;
6
+ line-height: 16px !important;
7
+ font-size: 11px !important;
8
+ color: #fff !important;
9
+ }
10
+ .printful-toolbar:hover .printful-toolbar-issues,
11
+ .printful-toolbar:active .printful-toolbar-issues,
12
+ .printful-toolbar.hover .printful-toolbar-issues
13
+ {
14
+ color: #fff !important;
15
+ }
16
+
17
+ #adminmenu .toplevel_page_printful-dashboard img {
18
+ width: 28px;
19
  }
assets/css/settings.css CHANGED
@@ -1,46 +1,46 @@
1
- .printful-setting-group {
2
- overflow: hidden;
3
- margin-bottom: 20px;
4
- }
5
-
6
- .printful-setting-group .input-text {
7
- width: 400px;
8
- }
9
-
10
- .printful-setting-group .checkbox-group-item i {
11
- color: #777;
12
- }
13
-
14
- .printful-submit .woocommerce-save-button {
15
- float: left;
16
- }
17
-
18
- .printful-submit .loader-wrap {
19
- display: inline-block;
20
- padding: 4px 10px;
21
- float: left;
22
- }
23
-
24
- .printful-submit .loader-wrap .loader {
25
- display: none;
26
- float: left;
27
- }
28
-
29
- .printful-submit .loader-wrap .dashicons {
30
- font-size: 24px;
31
- width: 24px;
32
- height: 24px;
33
- }
34
-
35
- .printful-submit .loader-wrap .pass,
36
- .printful-submit .loader-wrap .fail {
37
- display: none;
38
- float: left;
39
- line-height: 24px;
40
- }
41
-
42
- .printful-setting-group .carrier-type {
43
- font-weight: bold;
44
- padding: 20px 0;
45
- display: block;
46
  }
1
+ .printful-setting-group {
2
+ overflow: hidden;
3
+ margin-bottom: 20px;
4
+ }
5
+
6
+ .printful-setting-group .input-text {
7
+ width: 400px;
8
+ }
9
+
10
+ .printful-setting-group .checkbox-group-item i {
11
+ color: #777;
12
+ }
13
+
14
+ .printful-submit .woocommerce-save-button {
15
+ float: left;
16
+ }
17
+
18
+ .printful-submit .loader-wrap {
19
+ display: inline-block;
20
+ padding: 4px 10px;
21
+ float: left;
22
+ }
23
+
24
+ .printful-submit .loader-wrap .loader {
25
+ display: none;
26
+ float: left;
27
+ }
28
+
29
+ .printful-submit .loader-wrap .dashicons {
30
+ font-size: 24px;
31
+ width: 24px;
32
+ height: 24px;
33
+ }
34
+
35
+ .printful-submit .loader-wrap .pass,
36
+ .printful-submit .loader-wrap .fail {
37
+ display: none;
38
+ float: left;
39
+ line-height: 24px;
40
+ }
41
+
42
+ .printful-setting-group .carrier-type {
43
+ font-weight: bold;
44
+ padding: 20px 0;
45
+ display: block;
46
  }
assets/css/status.css CHANGED
@@ -1,21 +1,21 @@
1
- .pass {
2
- font-weight: bold;
3
- color: green;
4
- }
5
- .fail {
6
- font-weight: bold;
7
- color: red;
8
- }
9
- .warning {
10
- font-weight: bold;
11
- color: #cab827;
12
- }
13
- .printful-status .col-status {
14
- width: 10%;
15
- }
16
- .printful-status .col-desc {
17
- width: 57%;
18
- }
19
- .printful-status tbody tr:first-child td {
20
- font-weight: bold;
21
  }
1
+ .pass {
2
+ font-weight: bold;
3
+ color: green;
4
+ }
5
+ .fail {
6
+ font-weight: bold;
7
+ color: red;
8
+ }
9
+ .warning {
10
+ font-weight: bold;
11
+ color: #cab827;
12
+ }
13
+ .printful-status .col-status {
14
+ width: 10%;
15
+ }
16
+ .printful-status .col-desc {
17
+ width: 57%;
18
+ }
19
+ .printful-status tbody tr:first-child td {
20
+ font-weight: bold;
21
  }
assets/css/support.css CHANGED
@@ -1,62 +1,62 @@
1
- .support-report-wrap {
2
- background-color: #fff;
3
- padding: 20px;
4
- margin: 20px 0;
5
- box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
6
- border-left: #0073aa 4px solid;
7
- }
8
-
9
- .support-report-wrap p {
10
- margin-top: 0;
11
- }
12
-
13
- .support-report-wrap .support-report {
14
- width: 100%;
15
- height: 100px;
16
- font-family: monospace;
17
- margin-bottom: 10px;
18
- background: #efefef;
19
- }
20
-
21
- .support-info-wrap {
22
- margin-top: 40px;
23
- box-sizing: border-box;
24
-
25
- }
26
-
27
- .support-info-wrap .support-info-block {
28
- box-sizing: border-box;
29
- padding: 20px;
30
- background: #fff;
31
- box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
32
- margin-bottom: 20px;
33
- }
34
-
35
- .support-info-wrap .support-info-block h3 {
36
- text-align: center;
37
- margin-top: 10px;
38
- }
39
-
40
- .support-info-wrap .support-info-block .btn-wrap {
41
- margin-top: 20px;
42
- text-align: center;
43
- }
44
-
45
- @media (min-width: 768px) {
46
-
47
- .support-info-wrap {
48
- justify-content: space-between;
49
- display: flex;
50
- }
51
-
52
- .support-info-wrap .support-info-block {
53
- width: 32%;
54
- }
55
-
56
- .support-info-wrap .support-info-block:first-child {
57
-
58
- }
59
- .support-info-wrap .support-info-block:last-child {
60
-
61
- }
62
  }
1
+ .support-report-wrap {
2
+ background-color: #fff;
3
+ padding: 20px;
4
+ margin: 20px 0;
5
+ box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
6
+ border-left: #0073aa 4px solid;
7
+ }
8
+
9
+ .support-report-wrap p {
10
+ margin-top: 0;
11
+ }
12
+
13
+ .support-report-wrap .support-report {
14
+ width: 100%;
15
+ height: 100px;
16
+ font-family: monospace;
17
+ margin-bottom: 10px;
18
+ background: #efefef;
19
+ }
20
+
21
+ .support-info-wrap {
22
+ margin-top: 40px;
23
+ box-sizing: border-box;
24
+
25
+ }
26
+
27
+ .support-info-wrap .support-info-block {
28
+ box-sizing: border-box;
29
+ padding: 20px;
30
+ background: #fff;
31
+ box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
32
+ margin-bottom: 20px;
33
+ }
34
+
35
+ .support-info-wrap .support-info-block h3 {
36
+ text-align: center;
37
+ margin-top: 10px;
38
+ }
39
+
40
+ .support-info-wrap .support-info-block .btn-wrap {
41
+ margin-top: 20px;
42
+ text-align: center;
43
+ }
44
+
45
+ @media (min-width: 768px) {
46
+
47
+ .support-info-wrap {
48
+ justify-content: space-between;
49
+ display: flex;
50
+ }
51
+
52
+ .support-info-wrap .support-info-block {
53
+ width: 32%;
54
+ }
55
+
56
+ .support-info-wrap .support-info-block:first-child {
57
+
58
+ }
59
+ .support-info-wrap .support-info-block:last-child {
60
+
61
+ }
62
  }
assets/images/connect.svg CHANGED
@@ -1,74 +1,74 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="408" height="177" viewBox="0 0 408 177">
2
- <g fill="none" fill-rule="evenodd" transform="translate(1 1)">
3
- <path fill="#FFF" fill-rule="nonzero" stroke="#231F20" stroke-width="2" d="M299 120h107v8H299zM0 120h107v8H0z"/>
4
- <path stroke="#D1D3D4" d="M197.5 21V10.2c0-5.5-4.1-9.8-9.6-9.8h-124c-5.5 0-10.4 4.2-10.4 9.8V87M208.5 21V10.2c0-5.5 4.9-9.8 10.4-9.8h124c5.5 0 9.6 4.2 9.6 9.8V87"/>
5
- <path fill="#FFF" fill-rule="nonzero" stroke="#231F20" stroke-width="2" d="M5 48h97v72H5z"/>
6
- <g fill-rule="nonzero">
7
- <path fill="#9B5C8F" d="M27.104 70h44.77C74.706 70 77 72.312 77 75.168v17.225c0 2.856-2.293 5.168-5.127 5.168H55.82L58.022 103l-9.691-5.44H27.127C24.294 97.56 22 95.25 22 92.394V75.168C21.978 72.334 24.27 70 27.104 70z"/>
8
- <path fill="#FFF" d="M25.389 74.664c.316-.431.79-.658 1.422-.703 1.152-.091 1.807.453 1.965 1.633.7 4.743 1.468 8.76 2.28 12.05l4.946-9.463c.451-.862 1.016-1.316 1.693-1.361.994-.068 1.603.567 1.852 1.906.565 3.017 1.287 5.582 2.145 7.76.587-5.763 1.58-9.916 2.98-12.48.34-.635.836-.953 1.491-.998.52-.046.994.113 1.423.453.429.34.655.772.7 1.294.022.408-.045.749-.226 1.09-.88 1.633-1.603 4.378-2.19 8.19-.565 3.699-.768 6.58-.633 8.646.046.567-.045 1.066-.27 1.497-.272.5-.678.772-1.197.817-.588.046-1.197-.227-1.784-.84-2.1-2.155-3.771-5.377-4.99-9.666a425.409 425.409 0 0 0-3.252 6.535c-1.333 2.564-2.462 3.88-3.41 3.948-.61.046-1.13-.476-1.58-1.565-1.152-2.973-2.394-8.714-3.726-17.223-.09-.59.044-1.112.36-1.52zm48.526 3.563c-.813-1.43-2.01-2.292-3.613-2.633a5.904 5.904 0 0 0-1.22-.136c-2.167 0-3.928 1.135-5.306 3.404-1.174 1.929-1.76 4.062-1.76 6.399 0 1.747.36 3.244 1.083 4.493.813 1.43 2.01 2.291 3.613 2.632.429.09.835.136 1.22.136 2.19 0 3.95-1.135 5.306-3.404 1.174-1.951 1.761-4.084 1.761-6.421.023-1.77-.361-3.245-1.084-4.47zm-2.845 6.285c-.316 1.498-.88 2.61-1.716 3.358-.655.59-1.265.84-1.83.726-.541-.113-.993-.59-1.331-1.475a5.778 5.778 0 0 1-.407-2.065c0-.567.045-1.134.158-1.656a7.357 7.357 0 0 1 1.197-2.7c.745-1.112 1.535-1.566 2.348-1.407.542.113.994.59 1.333 1.475.27.703.406 1.407.406 2.065 0 .59-.045 1.157-.158 1.679zm-11.29-6.285c-.813-1.43-2.033-2.292-3.613-2.633a5.902 5.902 0 0 0-1.22-.136c-2.168 0-3.929 1.135-5.306 3.404-1.174 1.929-1.762 4.062-1.762 6.399 0 1.747.362 3.244 1.084 4.493.813 1.43 2.01 2.291 3.613 2.632.43.09.835.136 1.22.136 2.19 0 3.951-1.135 5.306-3.404 1.174-1.951 1.761-4.084 1.761-6.421 0-1.77-.361-3.245-1.084-4.47zm-2.868 6.285c-.316 1.498-.881 2.61-1.716 3.358-.655.59-1.265.84-1.83.726-.541-.113-.993-.59-1.332-1.475a5.787 5.787 0 0 1-.406-2.065c0-.567.045-1.134.158-1.656a7.354 7.354 0 0 1 1.197-2.7c.745-1.112 1.535-1.566 2.348-1.407.542.113.994.59 1.332 1.475.272.703.407 1.407.407 2.065a6.726 6.726 0 0 1-.158 1.679z"/>
9
- </g>
10
- <path fill="#FFF" fill-rule="nonzero" stroke="#231F20" stroke-width="2" d="M304 48h97v72h-97z"/>
11
- <g fill-rule="nonzero">
12
- <path fill="#F2C994" d="M320 98l17.5-30L355 98z"/>
13
- <path fill="#ED4642" d="M336 98l17.5-30L371 98z"/>
14
- <path fill="#17BCB5" d="M352 98l17.5-30L387 98z"/>
15
- <path fill="#16342F" d="M352 98h19l-9.5-16z"/>
16
- <path fill="#DF392F" d="M336 98h19l-9.5-16z"/>
17
- <path fill="#15291B" d="M352 98h3l-1.5-3z"/>
18
- </g>
19
- <path fill="#FFF" fill-rule="nonzero" stroke="#231F20" stroke-width="2" d="M155 21h97v124h-97z"/>
20
- <path fill="#FFF" fill-rule="nonzero" stroke="#231F20" stroke-width="2" d="M150 142h107v33H150z"/>
21
- <path stroke="#D1D3D4" d="M162.5 161.8l1.3-3.4 2 3.6 5.3-9.2 4 9.2 2.7-4.6 3.3 2.6"/>
22
- <path stroke="#231F20" d="M161.5 148.5h20v20h-20zM187.5 148.5h61v20h-61z"/>
23
- <circle cx="191.2" cy="33.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
24
- <path stroke="#FFF" d="M191.2 33.8l.7-3.8"/>
25
- <circle cx="191.2" cy="44.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
26
- <path stroke="#FFF" d="M191.2 44.8l2.3 3"/>
27
- <circle cx="191.2" cy="55.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
28
- <path stroke="#FFF" d="M191.2 55.8l-3 2.3"/>
29
- <circle cx="191.2" cy="66.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
30
- <path stroke="#FFF" d="M191.2 66.8l2.3 3"/>
31
- <circle cx="191.2" cy="77.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
32
- <path stroke="#FFF" d="M191.2 77.8l3.6 1.2"/>
33
- <path fill="#F1F2F2" fill-rule="nonzero" stroke="#231F20" d="M183.5 87.5h7v3h-7zM193.5 87.5h7v3h-7zM203.5 87.5h7v3h-7zM213.5 87.5h7v3h-7zM223.5 87.5h7v3h-7z"/>
34
- <path fill="#F2C994" fill-rule="nonzero" stroke="#231F20" d="M233.5 87.5h7v3h-7z"/>
35
- <path stroke="#231F20" stroke-width="2" d="M184 30v52"/>
36
- <circle cx="214.2" cy="33.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
37
- <path stroke="#FFF" d="M214.2 33.8l2.3 3"/>
38
- <circle cx="214.2" cy="44.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
39
- <path stroke="#FFF" d="M214.2 44.8l3-2.4"/>
40
- <circle cx="214.2" cy="55.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
41
- <path stroke="#FFF" d="M214.2 55.8l2.3 3"/>
42
- <circle cx="214.2" cy="66.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
43
- <path stroke="#FFF" d="M214.2 66.8l-3 2.3"/>
44
- <circle cx="214.2" cy="77.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
45
- <path stroke="#FFF" d="M214.2 77.8l2.3 3"/>
46
- <path stroke="#231F20" stroke-width="2" d="M207 30v52"/>
47
- <circle cx="237.2" cy="33.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
48
- <path stroke="#FFF" d="M237.2 33.8l3.7.8"/>
49
- <circle cx="237.2" cy="44.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
50
- <path stroke="#FFF" d="M237.2 44.8l2.3 3"/>
51
- <circle cx="237.2" cy="55.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
52
- <path stroke="#FFF" d="M237.2 55.8l.3 3.8"/>
53
- <circle cx="237.2" cy="66.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
54
- <path stroke="#FFF" d="M237.2 66.8l3.4-1.7"/>
55
- <circle cx="237.2" cy="77.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
56
- <path stroke="#FFF" d="M237.2 77.8l2.3 3"/>
57
- <path stroke="#231F20" stroke-width="2" d="M230 30v52M184 96v34M207 96v34"/>
58
- <path fill="#F1F2F2" fill-rule="nonzero" stroke="#231F20" d="M179.5 109.5h9v3h-9zM202.5 125.5h9v4h-9z"/>
59
- <path stroke="#231F20" stroke-width="2" d="M230 96v34"/>
60
- <path fill="#F1F2F2" fill-rule="nonzero" stroke="#231F20" d="M225.5 114.5h9v4h-9z"/>
61
- <circle cx="169.5" cy="35.8" r="5" fill="#F2C994" fill-rule="nonzero" stroke="#231F20" stroke-width="2"/>
62
- <circle cx="169.5" cy="48.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
63
- <circle cx="169.5" cy="59.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
64
- <circle cx="169.5" cy="70.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
65
- <circle cx="169.5" cy="81.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
66
- <circle cx="169.5" cy="99.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
67
- <circle cx="169.5" cy="113.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
68
- <circle cx="169.5" cy="127.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
69
- <circle cx="194.2" cy="152.8" r="2" fill="#F2C994" fill-rule="nonzero"/>
70
- <circle cx="210.2" cy="162.8" r="2" fill="#F2C994" fill-rule="nonzero"/>
71
- <path stroke="#231F20" d="M187 156.5h61"/>
72
- <circle cx="239.2" cy="159.8" r="2" fill="#F2C994" fill-rule="nonzero"/>
73
- </g>
74
- </svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="408" height="177" viewBox="0 0 408 177">
2
+ <g fill="none" fill-rule="evenodd" transform="translate(1 1)">
3
+ <path fill="#FFF" fill-rule="nonzero" stroke="#231F20" stroke-width="2" d="M299 120h107v8H299zM0 120h107v8H0z"/>
4
+ <path stroke="#D1D3D4" d="M197.5 21V10.2c0-5.5-4.1-9.8-9.6-9.8h-124c-5.5 0-10.4 4.2-10.4 9.8V87M208.5 21V10.2c0-5.5 4.9-9.8 10.4-9.8h124c5.5 0 9.6 4.2 9.6 9.8V87"/>
5
+ <path fill="#FFF" fill-rule="nonzero" stroke="#231F20" stroke-width="2" d="M5 48h97v72H5z"/>
6
+ <g fill-rule="nonzero">
7
+ <path fill="#9B5C8F" d="M27.104 70h44.77C74.706 70 77 72.312 77 75.168v17.225c0 2.856-2.293 5.168-5.127 5.168H55.82L58.022 103l-9.691-5.44H27.127C24.294 97.56 22 95.25 22 92.394V75.168C21.978 72.334 24.27 70 27.104 70z"/>
8
+ <path fill="#FFF" d="M25.389 74.664c.316-.431.79-.658 1.422-.703 1.152-.091 1.807.453 1.965 1.633.7 4.743 1.468 8.76 2.28 12.05l4.946-9.463c.451-.862 1.016-1.316 1.693-1.361.994-.068 1.603.567 1.852 1.906.565 3.017 1.287 5.582 2.145 7.76.587-5.763 1.58-9.916 2.98-12.48.34-.635.836-.953 1.491-.998.52-.046.994.113 1.423.453.429.34.655.772.7 1.294.022.408-.045.749-.226 1.09-.88 1.633-1.603 4.378-2.19 8.19-.565 3.699-.768 6.58-.633 8.646.046.567-.045 1.066-.27 1.497-.272.5-.678.772-1.197.817-.588.046-1.197-.227-1.784-.84-2.1-2.155-3.771-5.377-4.99-9.666a425.409 425.409 0 0 0-3.252 6.535c-1.333 2.564-2.462 3.88-3.41 3.948-.61.046-1.13-.476-1.58-1.565-1.152-2.973-2.394-8.714-3.726-17.223-.09-.59.044-1.112.36-1.52zm48.526 3.563c-.813-1.43-2.01-2.292-3.613-2.633a5.904 5.904 0 0 0-1.22-.136c-2.167 0-3.928 1.135-5.306 3.404-1.174 1.929-1.76 4.062-1.76 6.399 0 1.747.36 3.244 1.083 4.493.813 1.43 2.01 2.291 3.613 2.632.429.09.835.136 1.22.136 2.19 0 3.95-1.135 5.306-3.404 1.174-1.951 1.761-4.084 1.761-6.421.023-1.77-.361-3.245-1.084-4.47zm-2.845 6.285c-.316 1.498-.88 2.61-1.716 3.358-.655.59-1.265.84-1.83.726-.541-.113-.993-.59-1.331-1.475a5.778 5.778 0 0 1-.407-2.065c0-.567.045-1.134.158-1.656a7.357 7.357 0 0 1 1.197-2.7c.745-1.112 1.535-1.566 2.348-1.407.542.113.994.59 1.333 1.475.27.703.406 1.407.406 2.065 0 .59-.045 1.157-.158 1.679zm-11.29-6.285c-.813-1.43-2.033-2.292-3.613-2.633a5.902 5.902 0 0 0-1.22-.136c-2.168 0-3.929 1.135-5.306 3.404-1.174 1.929-1.762 4.062-1.762 6.399 0 1.747.362 3.244 1.084 4.493.813 1.43 2.01 2.291 3.613 2.632.43.09.835.136 1.22.136 2.19 0 3.951-1.135 5.306-3.404 1.174-1.951 1.761-4.084 1.761-6.421 0-1.77-.361-3.245-1.084-4.47zm-2.868 6.285c-.316 1.498-.881 2.61-1.716 3.358-.655.59-1.265.84-1.83.726-.541-.113-.993-.59-1.332-1.475a5.787 5.787 0 0 1-.406-2.065c0-.567.045-1.134.158-1.656a7.354 7.354 0 0 1 1.197-2.7c.745-1.112 1.535-1.566 2.348-1.407.542.113.994.59 1.332 1.475.272.703.407 1.407.407 2.065a6.726 6.726 0 0 1-.158 1.679z"/>
9
+ </g>
10
+ <path fill="#FFF" fill-rule="nonzero" stroke="#231F20" stroke-width="2" d="M304 48h97v72h-97z"/>
11
+ <g fill-rule="nonzero">
12
+ <path fill="#F2C994" d="M320 98l17.5-30L355 98z"/>
13
+ <path fill="#ED4642" d="M336 98l17.5-30L371 98z"/>
14
+ <path fill="#17BCB5" d="M352 98l17.5-30L387 98z"/>
15
+ <path fill="#16342F" d="M352 98h19l-9.5-16z"/>
16
+ <path fill="#DF392F" d="M336 98h19l-9.5-16z"/>
17
+ <path fill="#15291B" d="M352 98h3l-1.5-3z"/>
18
+ </g>
19
+ <path fill="#FFF" fill-rule="nonzero" stroke="#231F20" stroke-width="2" d="M155 21h97v124h-97z"/>
20
+ <path fill="#FFF" fill-rule="nonzero" stroke="#231F20" stroke-width="2" d="M150 142h107v33H150z"/>
21
+ <path stroke="#D1D3D4" d="M162.5 161.8l1.3-3.4 2 3.6 5.3-9.2 4 9.2 2.7-4.6 3.3 2.6"/>
22
+ <path stroke="#231F20" d="M161.5 148.5h20v20h-20zM187.5 148.5h61v20h-61z"/>
23
+ <circle cx="191.2" cy="33.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
24
+ <path stroke="#FFF" d="M191.2 33.8l.7-3.8"/>
25
+ <circle cx="191.2" cy="44.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
26
+ <path stroke="#FFF" d="M191.2 44.8l2.3 3"/>
27
+ <circle cx="191.2" cy="55.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
28
+ <path stroke="#FFF" d="M191.2 55.8l-3 2.3"/>
29
+ <circle cx="191.2" cy="66.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
30
+ <path stroke="#FFF" d="M191.2 66.8l2.3 3"/>
31
+ <circle cx="191.2" cy="77.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
32
+ <path stroke="#FFF" d="M191.2 77.8l3.6 1.2"/>
33
+ <path fill="#F1F2F2" fill-rule="nonzero" stroke="#231F20" d="M183.5 87.5h7v3h-7zM193.5 87.5h7v3h-7zM203.5 87.5h7v3h-7zM213.5 87.5h7v3h-7zM223.5 87.5h7v3h-7z"/>
34
+ <path fill="#F2C994" fill-rule="nonzero" stroke="#231F20" d="M233.5 87.5h7v3h-7z"/>
35
+ <path stroke="#231F20" stroke-width="2" d="M184 30v52"/>
36
+ <circle cx="214.2" cy="33.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
37
+ <path stroke="#FFF" d="M214.2 33.8l2.3 3"/>
38
+ <circle cx="214.2" cy="44.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
39
+ <path stroke="#FFF" d="M214.2 44.8l3-2.4"/>
40
+ <circle cx="214.2" cy="55.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
41
+ <path stroke="#FFF" d="M214.2 55.8l2.3 3"/>
42
+ <circle cx="214.2" cy="66.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
43
+ <path stroke="#FFF" d="M214.2 66.8l-3 2.3"/>
44
+ <circle cx="214.2" cy="77.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
45
+ <path stroke="#FFF" d="M214.2 77.8l2.3 3"/>
46
+ <path stroke="#231F20" stroke-width="2" d="M207 30v52"/>
47
+ <circle cx="237.2" cy="33.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
48
+ <path stroke="#FFF" d="M237.2 33.8l3.7.8"/>
49
+ <circle cx="237.2" cy="44.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
50
+ <path stroke="#FFF" d="M237.2 44.8l2.3 3"/>
51
+ <circle cx="237.2" cy="55.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
52
+ <path stroke="#FFF" d="M237.2 55.8l.3 3.8"/>
53
+ <circle cx="237.2" cy="66.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
54
+ <path stroke="#FFF" d="M237.2 66.8l3.4-1.7"/>
55
+ <circle cx="237.2" cy="77.8" r="4" fill="#D1D3D4" fill-rule="nonzero"/>
56
+ <path stroke="#FFF" d="M237.2 77.8l2.3 3"/>
57
+ <path stroke="#231F20" stroke-width="2" d="M230 30v52M184 96v34M207 96v34"/>
58
+ <path fill="#F1F2F2" fill-rule="nonzero" stroke="#231F20" d="M179.5 109.5h9v3h-9zM202.5 125.5h9v4h-9z"/>
59
+ <path stroke="#231F20" stroke-width="2" d="M230 96v34"/>
60
+ <path fill="#F1F2F2" fill-rule="nonzero" stroke="#231F20" d="M225.5 114.5h9v4h-9z"/>
61
+ <circle cx="169.5" cy="35.8" r="5" fill="#F2C994" fill-rule="nonzero" stroke="#231F20" stroke-width="2"/>
62
+ <circle cx="169.5" cy="48.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
63
+ <circle cx="169.5" cy="59.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
64
+ <circle cx="169.5" cy="70.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
65
+ <circle cx="169.5" cy="81.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
66
+ <circle cx="169.5" cy="99.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
67
+ <circle cx="169.5" cy="113.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
68
+ <circle cx="169.5" cy="127.8" r="3" fill="#D1D3D4" fill-rule="nonzero"/>
69
+ <circle cx="194.2" cy="152.8" r="2" fill="#F2C994" fill-rule="nonzero"/>
70
+ <circle cx="210.2" cy="162.8" r="2" fill="#F2C994" fill-rule="nonzero"/>
71
+ <path stroke="#231F20" d="M187 156.5h61"/>
72
+ <circle cx="239.2" cy="159.8" r="2" fill="#F2C994" fill-rule="nonzero"/>
73
+ </g>
74
+ </svg>
assets/js/block-loader.js CHANGED
@@ -1,22 +1,22 @@
1
- var Printful_Block_Loader;
2
-
3
- (function () {
4
- 'use strict';
5
-
6
- Printful_Block_Loader = {
7
- load: function (ajax_url, block) {
8
-
9
- block = jQuery('#' + block);
10
- if (block.length > 0) {
11
-
12
- jQuery.ajax({
13
- type: "GET",
14
- url: ajax_url,
15
- success: function (response) {
16
- block.html(response);
17
- }
18
- });
19
- }
20
- }
21
- };
22
  })();
1
+ var Printful_Block_Loader;
2
+
3
+ (function () {
4
+ 'use strict';
5
+
6
+ Printful_Block_Loader = {
7
+ load: function (ajax_url, block) {
8
+
9
+ block = jQuery('#' + block);
10
+ if (block.length > 0) {
11
+
12
+ jQuery.ajax({
13
+ type: "GET",
14
+ url: ajax_url,
15
+ success: function (response) {
16
+ block.html(response);
17
+ }
18
+ });
19
+ }
20
+ }
21
+ };
22
  })();
assets/js/connect.js CHANGED
@@ -1,60 +1,60 @@
1
- var Printful_Connect;
2
-
3
- (function () {
4
- 'use strict';
5
-
6
- Printful_Connect = {
7
- interval: 0,
8
- ajax_url: '',
9
- init: function (ajax_url) {
10
- this.ajax_url = ajax_url;
11
- this.loader();
12
- this.listen_status();
13
- this.listen_auth_return();
14
- },
15
- loader: function () {
16
- jQuery('.printful-connect-button').click(function () {
17
- jQuery(this).hide();
18
- jQuery(this).siblings('.loader').removeClass('hidden');
19
-
20
- setTimeout(function() {
21
- Printful_Connect.hide_loader();
22
- }, 60000); //hide the loader after a minute, assume failure
23
- });
24
- },
25
- hide_loader: function() {
26
- var button = jQuery('.printful-connect-button');
27
- button.show();
28
- button.siblings('.loader').addClass('hidden');
29
- },
30
- listen_status: function () {
31
- this.interval = setInterval(this.get_status.bind(this), 10000); //check status every 10 secs
32
- },
33
- get_status: function () {
34
- var interval = this.interval;
35
- jQuery.ajax( {
36
- type: "GET",
37
- url: this.ajax_url,
38
- success: function( response ) {
39
- if (response === 'OK') {
40
- clearInterval(interval);
41
- Printful_Connect.send_return_message();
42
- }
43
- }
44
- });
45
- },
46
- listen_auth_return: function () {
47
- var intercom = Intercom.getInstance();
48
- intercom.on('printful-auth', function (data) {
49
- if (data.success === true) {
50
- location.reload();
51
- }
52
- });
53
- },
54
- send_return_message: function () {
55
- var intercom = Intercom.getInstance();
56
- intercom.emit('printful-auth', {success: true});
57
- window.top.close();
58
- }
59
- };
60
  })();
1
+ var Printful_Connect;
2
+
3
+ (function () {
4
+ 'use strict';
5
+
6
+ Printful_Connect = {
7
+ interval: 0,
8
+ ajax_url: '',
9
+ init: function (ajax_url) {
10
+ this.ajax_url = ajax_url;
11
+ this.loader();
12
+ this.listen_status();
13
+ this.listen_auth_return();
14
+ },
15
+ loader: function () {
16
+ jQuery('.printful-connect-button').click(function () {
17
+ jQuery(this).hide();
18
+ jQuery(this).siblings('.loader').removeClass('hidden');
19
+
20
+ setTimeout(function() {
21
+ Printful_Connect.hide_loader();
22
+ }, 60000); //hide the loader after a minute, assume failure
23
+ });
24
+ },
25
+ hide_loader: function() {
26
+ var button = jQuery('.printful-connect-button');
27
+ button.show();
28
+ button.siblings('.loader').addClass('hidden');
29
+ },
30
+ listen_status: function () {
31
+ this.interval = setInterval(this.get_status.bind(this), 10000); //check status every 10 secs
32
+ },
33
+ get_status: function () {
34
+ var interval = this.interval;
35
+ jQuery.ajax( {
36
+ type: "GET",
37
+ url: this.ajax_url,
38
+ success: function( response ) {
39
+ if (response === 'OK') {
40
+ clearInterval(interval);
41
+ Printful_Connect.send_return_message();
42
+ }
43
+ }
44
+ });
45
+ },
46
+ listen_auth_return: function () {
47
+ var intercom = Intercom.getInstance();
48
+ intercom.on('printful-auth', function (data) {
49
+ if (data.success === true) {
50
+ location.reload();
51
+ }
52
+ });
53
+ },
54
+ send_return_message: function () {
55
+ var intercom = Intercom.getInstance();
56
+ intercom.emit('printful-auth', {success: true});
57
+ window.top.close();
58
+ }
59
+ };
60
  })();
assets/js/intercom.min.js CHANGED
@@ -1,12 +1,12 @@
1
- /*! intercom.js | https://github.com/diy/intercom.js | Apache License (v2) */
2
- var Intercom=function(){var g=function(){};g.createInterface=function(b){return{on:function(a,c){"undefined"===typeof this[b]&&(this[b]={});this[b].hasOwnProperty(a)||(this[b][a]=[]);this[b][a].push(c)},off:function(a,c){"undefined"!==typeof this[b]&&this[b].hasOwnProperty(a)&&i.removeItem(c,this[b][a])},trigger:function(a){if("undefined"!==typeof this[b]&&this[b].hasOwnProperty(a))for(var c=Array.prototype.slice.call(arguments,1),e=0;e<this[b][a].length;e++)this[b][a][e].apply(this[b][a][e],c)}}};
3
- var m=g.createInterface("_handlers");g.prototype._on=m.on;g.prototype._off=m.off;g.prototype._trigger=m.trigger;var n=g.createInterface("handlers");g.prototype.on=function(){n.on.apply(this,arguments);Array.prototype.unshift.call(arguments,"on");this._trigger.apply(this,arguments)};g.prototype.off=n.off;g.prototype.trigger=n.trigger;var f=window.localStorage;"undefined"===typeof f&&(f={getItem:function(){},setItem:function(){},removeItem:function(){}});var i={},h=function(){return(65536*(1+Math.random())|
4
- 0).toString(16).substring(1)};i.guid=function(){return h()+h()+"-"+h()+"-"+h()+"-"+h()+"-"+h()+h()+h()};i.throttle=function(b,a){var c=0;return function(){var e=(new Date).getTime();e-c>b&&(c=e,a.apply(this,arguments))}};i.extend=function(b,a){if("undefined"===typeof b||!b)b={};if("object"===typeof a)for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b};i.removeItem=function(b,a){for(var c=a.length-1;0<=c;c--)a[c]===b&&a.splice(c,1);return a};var d=function(){var b=this,a=(new Date).getTime();
5
- this.origin=i.guid();this.lastMessage=a;this.bindings=[];this.receivedIDs={};this.previousValues={};a=function(){b._onStorageEvent.apply(b,arguments)};window.attachEvent?document.attachEvent("onstorage",a):window.addEventListener("storage",a,!1)};d.prototype._transaction=function(b){var a=this,c=!1,e=!1,p=null,d=function(){if(!c){var g=(new Date).getTime(),s=parseInt(f.getItem(l)||0);s&&1E3>g-s?(e||(a._on("storage",d),e=!0),p=window.setTimeout(d,20)):(c=!0,f.setItem(l,g),b(),e&&a._off("storage",d),
6
- p&&window.clearTimeout(p),f.removeItem(l))}};d()};d.prototype._cleanup_emit=i.throttle(100,function(){this._transaction(function(){for(var b=(new Date).getTime()-t,a=0,c=JSON.parse(f.getItem(j)||"[]"),e=c.length-1;0<=e;e--)c[e].timestamp<b&&(c.splice(e,1),a++);0<a&&f.setItem(j,JSON.stringify(c))})});d.prototype._cleanup_once=i.throttle(100,function(){var b=this;this._transaction(function(){var a,c=JSON.parse(f.getItem(k)||"{}");(new Date).getTime();var e=0;for(a in c)b._once_expired(a,c)&&(delete c[a],
7
- e++);0<e&&f.setItem(k,JSON.stringify(c))})});d.prototype._once_expired=function(b,a){if(!a||!a.hasOwnProperty(b)||"object"!==typeof a[b])return!0;var c=a[b].ttl||u,e=(new Date).getTime();return a[b].timestamp<e-c};d.prototype._localStorageChanged=function(b,a){if(b&&b.key)return b.key===a;var c=f.getItem(a);if(c===this.previousValues[a])return!1;this.previousValues[a]=c;return!0};d.prototype._onStorageEvent=function(b){var b=b||window.event,a=this;this._localStorageChanged(b,j)&&this._transaction(function(){for(var b=
8
- (new Date).getTime(),e=f.getItem(j),e=JSON.parse(e||"[]"),d=0;d<e.length;d++)if(e[d].origin!==a.origin&&!(e[d].timestamp<a.lastMessage)){if(e[d].id){if(a.receivedIDs.hasOwnProperty(e[d].id))continue;a.receivedIDs[e[d].id]=!0}a.trigger(e[d].name,e[d].payload)}a.lastMessage=b});this._trigger("storage",b)};d.prototype._emit=function(b,a,c){if((c="string"===typeof c||"number"===typeof c?String(c):null)&&c.length){if(this.receivedIDs.hasOwnProperty(c))return;this.receivedIDs[c]=!0}var e={id:c,name:b,origin:this.origin,
9
- timestamp:(new Date).getTime(),payload:a},d=this;this._transaction(function(){var c=f.getItem(j)||"[]",c=[c.substring(0,c.length-1),"[]"===c?"":",",JSON.stringify(e),"]"].join("");f.setItem(j,c);d.trigger(b,a);window.setTimeout(function(){d._cleanup_emit()},50)})};d.prototype.bind=function(b,a){for(var c=0;c<d.bindings.length;c++){var e=d.bindings[c].factory(b,a||null,this);e&&this.bindings.push(e)}};d.prototype.emit=function(b,a){this._emit.apply(this,arguments);this._trigger("emit",b,a)};d.prototype.once=
10
- function(b,a,c){if(d.supported){var e=this;this._transaction(function(){var d=JSON.parse(f.getItem(k)||"{}");e._once_expired(b,d)&&(d[b]={},d[b].timestamp=(new Date).getTime(),"number"===typeof c&&(d[b].ttl=1E3*c),f.setItem(k,JSON.stringify(d)),a(),window.setTimeout(function(){e._cleanup_once()},50))})}};i.extend(d.prototype,g.prototype);d.bindings=[];d.supported="undefined"!==typeof f;var j="intercom",k="intercom_once",l="intercom_lock",t=5E4,u=36E5;d.destroy=function(){f.removeItem(l);f.removeItem(j);
11
- f.removeItem(k)};var q=null;d.getInstance=function(){q||(q=new d);return q};var r=function(b,a,c){a=i.extend({id:null,send:!0,receive:!0},a);if(a.receive){var d=[],f=function(f){-1===d.indexOf(f)&&(d.push(f),b.on(f,function(b){var d="function"===typeof a.id?a.id(f,b):null,e="function"===typeof a.receive?a.receive(f,b):!0;(e||"boolean"!==typeof e)&&c._emit(f,b,d)}))},g;for(g in c.handlers)for(var h=0;h<c.handlers[g].length;h++)f(g,c.handlers[g][h]);c._on("on",f)}a.send&&c._on("emit",function(c,d){var e=
12
  "function"===typeof a.send?a.send(c,d):!0;(e||"boolean"!==typeof e)&&b.emit(c,d)})};r.factory=function(b,a,c){return"undefined"===typeof b.socket?!1:new r(b,a,c)};d.bindings.push(r);return d}();
1
+ /*! intercom.js | https://github.com/diy/intercom.js | Apache License (v2) */
2
+ var Intercom=function(){var g=function(){};g.createInterface=function(b){return{on:function(a,c){"undefined"===typeof this[b]&&(this[b]={});this[b].hasOwnProperty(a)||(this[b][a]=[]);this[b][a].push(c)},off:function(a,c){"undefined"!==typeof this[b]&&this[b].hasOwnProperty(a)&&i.removeItem(c,this[b][a])},trigger:function(a){if("undefined"!==typeof this[b]&&this[b].hasOwnProperty(a))for(var c=Array.prototype.slice.call(arguments,1),e=0;e<this[b][a].length;e++)this[b][a][e].apply(this[b][a][e],c)}}};
3
+ var m=g.createInterface("_handlers");g.prototype._on=m.on;g.prototype._off=m.off;g.prototype._trigger=m.trigger;var n=g.createInterface("handlers");g.prototype.on=function(){n.on.apply(this,arguments);Array.prototype.unshift.call(arguments,"on");this._trigger.apply(this,arguments)};g.prototype.off=n.off;g.prototype.trigger=n.trigger;var f=window.localStorage;"undefined"===typeof f&&(f={getItem:function(){},setItem:function(){},removeItem:function(){}});var i={},h=function(){return(65536*(1+Math.random())|
4
+ 0).toString(16).substring(1)};i.guid=function(){return h()+h()+"-"+h()+"-"+h()+"-"+h()+"-"+h()+h()+h()};i.throttle=function(b,a){var c=0;return function(){var e=(new Date).getTime();e-c>b&&(c=e,a.apply(this,arguments))}};i.extend=function(b,a){if("undefined"===typeof b||!b)b={};if("object"===typeof a)for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b};i.removeItem=function(b,a){for(var c=a.length-1;0<=c;c--)a[c]===b&&a.splice(c,1);return a};var d=function(){var b=this,a=(new Date).getTime();
5
+ this.origin=i.guid();this.lastMessage=a;this.bindings=[];this.receivedIDs={};this.previousValues={};a=function(){b._onStorageEvent.apply(b,arguments)};window.attachEvent?document.attachEvent("onstorage",a):window.addEventListener("storage",a,!1)};d.prototype._transaction=function(b){var a=this,c=!1,e=!1,p=null,d=function(){if(!c){var g=(new Date).getTime(),s=parseInt(f.getItem(l)||0);s&&1E3>g-s?(e||(a._on("storage",d),e=!0),p=window.setTimeout(d,20)):(c=!0,f.setItem(l,g),b(),e&&a._off("storage",d),
6
+ p&&window.clearTimeout(p),f.removeItem(l))}};d()};d.prototype._cleanup_emit=i.throttle(100,function(){this._transaction(function(){for(var b=(new Date).getTime()-t,a=0,c=JSON.parse(f.getItem(j)||"[]"),e=c.length-1;0<=e;e--)c[e].timestamp<b&&(c.splice(e,1),a++);0<a&&f.setItem(j,JSON.stringify(c))})});d.prototype._cleanup_once=i.throttle(100,function(){var b=this;this._transaction(function(){var a,c=JSON.parse(f.getItem(k)||"{}");(new Date).getTime();var e=0;for(a in c)b._once_expired(a,c)&&(delete c[a],
7
+ e++);0<e&&f.setItem(k,JSON.stringify(c))})});d.prototype._once_expired=function(b,a){if(!a||!a.hasOwnProperty(b)||"object"!==typeof a[b])return!0;var c=a[b].ttl||u,e=(new Date).getTime();return a[b].timestamp<e-c};d.prototype._localStorageChanged=function(b,a){if(b&&b.key)return b.key===a;var c=f.getItem(a);if(c===this.previousValues[a])return!1;this.previousValues[a]=c;return!0};d.prototype._onStorageEvent=function(b){var b=b||window.event,a=this;this._localStorageChanged(b,j)&&this._transaction(function(){for(var b=
8
+ (new Date).getTime(),e=f.getItem(j),e=JSON.parse(e||"[]"),d=0;d<e.length;d++)if(e[d].origin!==a.origin&&!(e[d].timestamp<a.lastMessage)){if(e[d].id){if(a.receivedIDs.hasOwnProperty(e[d].id))continue;a.receivedIDs[e[d].id]=!0}a.trigger(e[d].name,e[d].payload)}a.lastMessage=b});this._trigger("storage",b)};d.prototype._emit=function(b,a,c){if((c="string"===typeof c||"number"===typeof c?String(c):null)&&c.length){if(this.receivedIDs.hasOwnProperty(c))return;this.receivedIDs[c]=!0}var e={id:c,name:b,origin:this.origin,
9
+ timestamp:(new Date).getTime(),payload:a},d=this;this._transaction(function(){var c=f.getItem(j)||"[]",c=[c.substring(0,c.length-1),"[]"===c?"":",",JSON.stringify(e),"]"].join("");f.setItem(j,c);d.trigger(b,a);window.setTimeout(function(){d._cleanup_emit()},50)})};d.prototype.bind=function(b,a){for(var c=0;c<d.bindings.length;c++){var e=d.bindings[c].factory(b,a||null,this);e&&this.bindings.push(e)}};d.prototype.emit=function(b,a){this._emit.apply(this,arguments);this._trigger("emit",b,a)};d.prototype.once=
10
+ function(b,a,c){if(d.supported){var e=this;this._transaction(function(){var d=JSON.parse(f.getItem(k)||"{}");e._once_expired(b,d)&&(d[b]={},d[b].timestamp=(new Date).getTime(),"number"===typeof c&&(d[b].ttl=1E3*c),f.setItem(k,JSON.stringify(d)),a(),window.setTimeout(function(){e._cleanup_once()},50))})}};i.extend(d.prototype,g.prototype);d.bindings=[];d.supported="undefined"!==typeof f;var j="intercom",k="intercom_once",l="intercom_lock",t=5E4,u=36E5;d.destroy=function(){f.removeItem(l);f.removeItem(j);
11
+ f.removeItem(k)};var q=null;d.getInstance=function(){q||(q=new d);return q};var r=function(b,a,c){a=i.extend({id:null,send:!0,receive:!0},a);if(a.receive){var d=[],f=function(f){-1===d.indexOf(f)&&(d.push(f),b.on(f,function(b){var d="function"===typeof a.id?a.id(f,b):null,e="function"===typeof a.receive?a.receive(f,b):!0;(e||"boolean"!==typeof e)&&c._emit(f,b,d)}))},g;for(g in c.handlers)for(var h=0;h<c.handlers[g].length;h++)f(g,c.handlers[g][h]);c._on("on",f)}a.send&&c._on("emit",function(c,d){var e=
12
  "function"===typeof a.send?a.send(c,d):!0;(e||"boolean"!==typeof e)&&b.emit(c,d)})};r.factory=function(b,a,c){return"undefined"===typeof b.socket?!1:new r(b,a,c)};d.bindings.push(r);return d}();
assets/js/settings.js CHANGED
@@ -1,44 +1,44 @@
1
- var Printful_Settings;
2
-
3
- (function () {
4
- 'use strict';
5
-
6
- Printful_Settings = {
7
- init_submit: function () {
8
-
9
- var form = jQuery('form[name=printful_settings]');
10
- var submit_button = form.find('.woocommerce-save-button');
11
- var loader = form.find('.loader');
12
- var pass = form.find('.loader-wrap .pass');
13
- var fail = form.find('.loader-wrap .fail');
14
-
15
- submit_button.click(function (e) {
16
-
17
- e.preventDefault();
18
- submit_button.attr('disabled', 'disabled');
19
- loader.show();
20
-
21
- jQuery.ajax({
22
- type: "POST",
23
- url: form.attr('action'),
24
- data: form.serialize(),
25
- success: function (response) {
26
- submit_button.removeAttr('disabled');
27
- loader.hide();
28
-
29
- if (response === 'OK') {
30
- pass.show(0).delay(3000).hide(0);
31
- } else {
32
- fail.empty();
33
- fail.append('<span class="dashicons dashicons-no"></span>' + response);
34
- fail.show(0).delay(3000).hide(0);
35
- }
36
- }
37
- });
38
- });
39
- },
40
- enable_submit_btn: function () {
41
- jQuery('.printful-submit input[type=submit]').removeClass('disabled').prop('disabled', false);
42
- }
43
- };
44
  })();
1
+ var Printful_Settings;
2
+
3
+ (function () {
4
+ 'use strict';
5
+
6
+ Printful_Settings = {
7
+ init_submit: function () {
8
+
9
+ var form = jQuery('form[name=printful_settings]');
10
+ var submit_button = form.find('.woocommerce-save-button');
11
+ var loader = form.find('.loader');
12
+ var pass = form.find('.loader-wrap .pass');
13
+ var fail = form.find('.loader-wrap .fail');
14
+
15
+ submit_button.click(function (e) {
16
+
17
+ e.preventDefault();
18
+ submit_button.attr('disabled', 'disabled');
19
+ loader.show();
20
+
21
+ jQuery.ajax({
22
+ type: "POST",
23
+ url: form.attr('action'),
24
+ data: form.serialize(),
25
+ success: function (response) {
26
+ submit_button.removeAttr('disabled');
27
+ loader.hide();
28
+
29
+ if (response === 'OK') {
30
+ pass.show(0).delay(3000).hide(0);
31
+ } else {
32
+ fail.empty();
33
+ fail.append('<span class="dashicons dashicons-no"></span>' + response);
34
+ fail.show(0).delay(3000).hide(0);
35
+ }
36
+ }
37
+ });
38
+ });
39
+ },
40
+ enable_submit_btn: function () {
41
+ jQuery('.printful-submit input[type=submit]').removeClass('disabled').prop('disabled', false);
42
+ }
43
+ };
44
  })();
includes/class-printful-admin.php CHANGED
@@ -1,172 +1,172 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) exit;
3
-
4
- class Printful_Admin {
5
-
6
- const MENU_TITLE_TOP = 'Printful';
7
- const PAGE_TITLE_DASHBOARD = 'Dashboard';
8
- const MENU_TITLE_DASHBOARD = 'Dashboard';
9
- const MENU_SLUG_DASHBOARD = 'printful-dashboard';
10
- const CAPABILITY = 'manage_options';
11
-
12
- public static function init() {
13
- $admin = new self;
14
- $admin->register_admin();
15
- }
16
-
17
- /**
18
- * Register admin scripts
19
- */
20
- public function register_admin() {
21
-
22
- add_action( 'admin_menu', array( $this, 'register_admin_menu_page' ) );
23
- add_action( 'admin_enqueue_scripts', array( $this, 'add_admin_styles' ) );
24
- add_action( 'admin_enqueue_scripts', array( $this, 'add_admin_scripts' ) );
25
- add_action( 'wp_enqueue_scripts', array( $this, 'add_global_style' ) );
26
- add_action( 'admin_bar_menu', array( $this, 'add_printful_status_toolbar' ), 999 );
27
- }
28
-
29
- /**
30
- * Loads stylesheets used in printful admin pages
31
- * @param $hook
32
- */
33
- public function add_admin_styles($hook) {
34
-
35
- wp_enqueue_style( 'printful-global', plugins_url( '../assets/css/global.css', __FILE__ ) );
36
-
37
- if ( strpos( $hook, 'printful-dashboard' ) !== false ) {
38
- wp_enqueue_style( 'wp-color-picker' );
39
- wp_enqueue_style( 'printful-dashboard', plugins_url( '../assets/css/dashboard.css', __FILE__ ) );
40
- wp_enqueue_style( 'printful-status', plugins_url( '../assets/css/status.css', __FILE__ ) );
41
- wp_enqueue_style( 'printful-support', plugins_url( '../assets/css/support.css', __FILE__ ) );
42
- wp_enqueue_style( 'printful-settings', plugins_url( '../assets/css/settings.css', __FILE__ ) );
43
- }
44
- }
45
-
46
- /**
47
- * Loads stylesheet for printful toolbar element
48
- */
49
- public function add_global_style() {
50
- if ( is_user_logged_in() ) {
51
- wp_enqueue_style( 'printful-global', plugins_url( '../assets/css/global.css', __FILE__ ) );
52
- }
53
- }
54
-
55
- /**
56
- * Loads scripts used in printful admin pages
57
- * @param $hook
58
- */
59
- public function add_admin_scripts($hook) {
60
- if ( strpos( $hook, 'printful-dashboard' ) !== false ) {
61
- wp_enqueue_script( 'wp-color-picker' );
62
- wp_enqueue_script( 'printful-settings', plugins_url( '../assets/js/settings.js', __FILE__ ) );
63
- wp_enqueue_script( 'printful-connect', plugins_url( '../assets/js/connect.js', __FILE__ ) );
64
- wp_enqueue_script( 'printful-block-loader', plugins_url( '../assets/js/block-loader.js', __FILE__ ) );
65
- wp_enqueue_script( 'printful-intercom', plugins_url( '../assets/js/intercom.min.js', __FILE__ ) );
66
- }
67
- }
68
-
69
- /**
70
- * Register admin menu pages
71
- */
72
- public function register_admin_menu_page() {
73
-
74
- add_menu_page(
75
- __( 'Dashboard', 'printful' ),
76
- self::MENU_TITLE_TOP,
77
- self::CAPABILITY,
78
- self::MENU_SLUG_DASHBOARD,
79
- array( 'Printful_Admin', 'route' ),
80
- Printful_Base::get_asset_url() . 'images/printful-menu-icon.png',
81
- 58
82
- );
83
- }
84
-
85
- /**
86
- * Route the tabs
87
- */
88
- public static function route() {
89
-
90
- $tabs = array(
91
- 'dashboard' => 'Printful_Admin_Dashboard',
92
- 'settings' => 'Printful_Admin_Settings',
93
- 'status' => 'Printful_Admin_Status',
94
- 'support' => 'Printful_Admin_Support',
95
- );
96
-
97
- $tab = ( ! empty( $_GET['tab'] ) ? $_GET['tab'] : 'dashboard' );
98
- if ( ! empty( $tabs[ $tab ] ) ) {
99
- call_user_func( array( $tabs[ $tab ], 'view' ) );
100
- }
101
- }
102
-
103
- /**
104
- * Get the tabs used in printful admin pages
105
- * @return array
106
- * @throws PrintfulException
107
- */
108
- public static function get_tabs() {
109
-
110
- $tabs = array(
111
- array( 'name' => __( 'Settings', 'printful' ), 'tab_url' => 'settings' ),
112
- array( 'name' => __( 'Status', 'printful' ), 'tab_url' => 'status' ),
113
- array( 'name' => __( 'Support', 'printful' ), 'tab_url' => 'support' ),
114
- );
115
-
116
- if ( Printful_Integration::instance()->is_connected() ) {
117
- array_unshift( $tabs, array( 'name' => __( 'Dashboard', 'printful' ), 'tab_url' => false ) );
118
- } else {
119
- array_unshift( $tabs, array( 'name' => __( 'Connect', 'printful' ), 'tab_url' => false ) );
120
- }
121
-
122
- return $tabs;
123
- }
124
-
125
- /**
126
- * Create the printful toolbar
127
- * @param $wp_admin_bar
128
- */
129
- public function add_printful_status_toolbar( $wp_admin_bar ) {
130
-
131
- $issueCount = get_transient( Printful_Admin_Status::PF_STATUS_ISSUE_COUNT );
132
-
133
- if ( $issueCount ) {
134
- //Add top level menu item
135
- $args = array(
136
- 'id' => 'printful_toolbar',
137
- 'title' => 'Printful Integration' . ( $issueCount > 0 ? ' <span class="printful-toolbar-issues">' . esc_attr( $issueCount ) . '</span>' : '' ),
138
- 'href' => get_admin_url( null, 'admin.php?page=' . Printful_Admin::MENU_SLUG_DASHBOARD ),
139
- 'meta' => array( 'class' => 'printful-toolbar' ),
140
- );
141
- $wp_admin_bar->add_node( $args );
142
-
143
- //Add status
144
- $args = array(
145
- 'id' => 'printful_toolbar_status',
146
- 'parent' => 'printful_toolbar',
147
- 'title' => 'Integration status' . ( $issueCount > 0 ? ' (' . esc_attr( $issueCount ) . _n( ' issue', ' issues', $issueCount ) . ')' : '' ),
148
- 'href' => get_admin_url( null, 'admin.php?page=' . Printful_Admin::MENU_SLUG_DASHBOARD . '&tab=status' ),
149
- 'meta' => array( 'class' => 'printful-toolbar-status' ),
150
- );
151
- $wp_admin_bar->add_node( $args );
152
- }
153
- }
154
-
155
- /**
156
- * Load a template file. Extract any variables that are passed
157
- * @param $name
158
- * @param array $variables
159
- */
160
- public static function load_template( $name, $variables = array() ) {
161
-
162
- if ( ! empty( $variables ) ) {
163
- extract( $variables );
164
- }
165
-
166
- $filename = plugin_dir_path( __FILE__ ) . 'templates/' . $name . '.php';
167
- if ( file_exists( $filename ) ) {
168
- include( $filename );
169
- }
170
- }
171
-
172
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit;
3
+
4
+ class Printful_Admin {
5
+
6
+ const MENU_TITLE_TOP = 'Printful';
7
+ const PAGE_TITLE_DASHBOARD = 'Dashboard';
8
+ const MENU_TITLE_DASHBOARD = 'Dashboard';
9
+ const MENU_SLUG_DASHBOARD = 'printful-dashboard';
10
+ const CAPABILITY = 'manage_options';
11
+
12
+ public static function init() {
13
+ $admin = new self;
14
+ $admin->register_admin();
15
+ }
16
+
17
+ /**
18
+ * Register admin scripts
19
+ */
20
+ public function register_admin() {
21
+
22
+ add_action( 'admin_menu', array( $this, 'register_admin_menu_page' ) );
23
+ add_action( 'admin_enqueue_scripts', array( $this, 'add_admin_styles' ) );
24
+ add_action( 'admin_enqueue_scripts', array( $this, 'add_admin_scripts' ) );
25
+ add_action( 'wp_enqueue_scripts', array( $this, 'add_global_style' ) );
26
+ add_action( 'admin_bar_menu', array( $this, 'add_printful_status_toolbar' ), 999 );
27
+ }
28
+
29
+ /**
30
+ * Loads stylesheets used in printful admin pages
31
+ * @param $hook
32
+ */
33
+ public function add_admin_styles($hook) {
34
+
35
+ wp_enqueue_style( 'printful-global', plugins_url( '../assets/css/global.css', __FILE__ ) );
36
+
37
+ if ( strpos( $hook, 'printful-dashboard' ) !== false ) {
38
+ wp_enqueue_style( 'wp-color-picker' );
39
+ wp_enqueue_style( 'printful-dashboard', plugins_url( '../assets/css/dashboard.css', __FILE__ ) );
40
+ wp_enqueue_style( 'printful-status', plugins_url( '../assets/css/status.css', __FILE__ ) );
41
+ wp_enqueue_style( 'printful-support', plugins_url( '../assets/css/support.css', __FILE__ ) );
42
+ wp_enqueue_style( 'printful-settings', plugins_url( '../assets/css/settings.css', __FILE__ ) );
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Loads stylesheet for printful toolbar element
48
+ */
49
+ public function add_global_style() {
50
+ if ( is_user_logged_in() ) {
51
+ wp_enqueue_style( 'printful-global', plugins_url( '../assets/css/global.css', __FILE__ ) );
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Loads scripts used in printful admin pages
57
+ * @param $hook
58
+ */
59
+ public function add_admin_scripts($hook) {
60
+ if ( strpos( $hook, 'printful-dashboard' ) !== false ) {
61
+ wp_enqueue_script( 'wp-color-picker' );
62
+ wp_enqueue_script( 'printful-settings', plugins_url( '../assets/js/settings.js', __FILE__ ) );
63
+ wp_enqueue_script( 'printful-connect', plugins_url( '../assets/js/connect.js', __FILE__ ) );
64
+ wp_enqueue_script( 'printful-block-loader', plugins_url( '../assets/js/block-loader.js', __FILE__ ) );
65
+ wp_enqueue_script( 'printful-intercom', plugins_url( '../assets/js/intercom.min.js', __FILE__ ) );
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Register admin menu pages
71
+ */
72
+ public function register_admin_menu_page() {
73
+
74
+ add_menu_page(
75
+ __( 'Dashboard', 'printful' ),
76
+ self::MENU_TITLE_TOP,
77
+ self::CAPABILITY,
78
+ self::MENU_SLUG_DASHBOARD,
79
+ array( 'Printful_Admin', 'route' ),
80
+ Printful_Base::get_asset_url() . 'images/printful-menu-icon.png',
81
+ 58
82
+ );
83
+ }
84
+
85
+ /**
86
+ * Route the tabs
87
+ */
88
+ public static function route() {
89
+
90
+ $tabs = array(
91
+ 'dashboard' => 'Printful_Admin_Dashboard',
92
+ 'settings' => 'Printful_Admin_Settings',
93
+ 'status' => 'Printful_Admin_Status',
94
+ 'support' => 'Printful_Admin_Support',
95
+ );
96
+
97
+ $tab = ( ! empty( $_GET['tab'] ) ? $_GET['tab'] : 'dashboard' );
98
+ if ( ! empty( $tabs[ $tab ] ) ) {
99
+ call_user_func( array( $tabs[ $tab ], 'view' ) );
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Get the tabs used in printful admin pages
105
+ * @return array
106
+ * @throws PrintfulException
107
+ */
108
+ public static function get_tabs() {
109
+
110
+ $tabs = array(
111
+ array( 'name' => __( 'Settings', 'printful' ), 'tab_url' => 'settings' ),
112
+ array( 'name' => __( 'Status', 'printful' ), 'tab_url' => 'status' ),
113
+ array( 'name' => __( 'Support', 'printful' ), 'tab_url' => 'support' ),
114
+ );
115
+
116
+ if ( Printful_Integration::instance()->is_connected() ) {
117
+ array_unshift( $tabs, array( 'name' => __( 'Dashboard', 'printful' ), 'tab_url' => false ) );
118
+ } else {
119
+ array_unshift( $tabs, array( 'name' => __( 'Connect', 'printful' ), 'tab_url' => false ) );
120
+ }
121
+
122
+ return $tabs;
123
+ }
124
+
125
+ /**
126
+ * Create the printful toolbar
127
+ * @param $wp_admin_bar
128
+ */
129
+ public function add_printful_status_toolbar( $wp_admin_bar ) {
130
+
131
+ $issueCount = get_transient( Printful_Admin_Status::PF_STATUS_ISSUE_COUNT );
132
+
133
+ if ( $issueCount ) {
134
+ //Add top level menu item
135
+ $args = array(
136
+ 'id' => 'printful_toolbar',
137
+ 'title' => 'Printful Integration' . ( $issueCount > 0 ? ' <span class="printful-toolbar-issues">' . esc_attr( $issueCount ) . '</span>' : '' ),
138
+ 'href' => get_admin_url( null, 'admin.php?page=' . Printful_Admin::MENU_SLUG_DASHBOARD ),
139
+ 'meta' => array( 'class' => 'printful-toolbar' ),
140
+ );
141
+ $wp_admin_bar->add_node( $args );
142
+
143
+ //Add status
144
+ $args = array(
145
+ 'id' => 'printful_toolbar_status',
146
+ 'parent' => 'printful_toolbar',
147
+ 'title' => 'Integration status' . ( $issueCount > 0 ? ' (' . esc_attr( $issueCount ) . _n( ' issue', ' issues', $issueCount ) . ')' : '' ),
148
+ 'href' => get_admin_url( null, 'admin.php?page=' . Printful_Admin::MENU_SLUG_DASHBOARD . '&tab=status' ),
149
+ 'meta' => array( 'class' => 'printful-toolbar-status' ),
150
+ );
151
+ $wp_admin_bar->add_node( $args );
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Load a template file. Extract any variables that are passed
157
+ * @param $name
158
+ * @param array $variables
159
+ */
160
+ public static function load_template( $name, $variables = array() ) {
161
+
162
+ if ( ! empty( $variables ) ) {
163
+ extract( $variables );
164
+ }
165
+
166
+ $filename = plugin_dir_path( __FILE__ ) . 'templates/' . $name . '.php';
167
+ if ( file_exists( $filename ) ) {
168
+ include( $filename );
169
+ }
170
+ }
171
+
172
  }
includes/class-printful-client.php CHANGED
@@ -1,192 +1,192 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) exit;
3
-
4
- /**
5
- * Printful API client
6
- */
7
- class Printful_Client {
8
-
9
- private $key = false;
10
- private $lastResponseRaw;
11
- private $lastResponse;
12
- private $userAgent = 'Printful WooCommerce Plugin';
13
- private $apiUrl;
14
-
15
- /**
16
- * @param string $key Printful Store API key
17
- * @param bool|string $disable_ssl Force HTTP instead of HTTPS for API requests
18
- *
19
- * @throws PrintfulException if the library failed to initialize
20
- */
21
- public function __construct( $key = '', $disable_ssl = false ) {
22
-
23
- $key = (string) $key;
24
-
25
- $this->userAgent .= ' ' . Printful_Base::VERSION . ' (WP ' . get_bloginfo( 'version' ) . ' + WC ' . WC()->version . ')';
26
-
27
- if ( ! function_exists( 'json_decode' ) || ! function_exists( 'json_encode' ) ) {
28
- throw new PrintfulException( 'PHP JSON extension is required for the Printful API library to work!' );
29
- }
30
- if ( strlen( $key ) < 32 ) {
31
- throw new PrintfulException( 'Missing or invalid Printful store key!' );
32
- }
33
- $this->key = $key;
34
-
35
- if ( $disable_ssl ) {
36
- $this->apiUrl = str_replace( 'https://', 'http://', $this->apiUrl );
37
- }
38
-
39
- //setup api host
40
- $this->apiUrl = Printful_Base::get_printful_api_host();
41
- }
42
-
43
- /**
44
- * Returns total available item count from the last request if it supports paging (e.g order list) or null otherwise.
45
- *
46
- * @return int|null Item count
47
- */
48
- public function getItemCount() {
49
- return isset( $this->lastResponse['paging']['total'] ) ? $this->lastResponse['paging']['total'] : null;
50
- }
51
-
52
- /**
53
- * Perform a GET request to the API
54
- * @param string $path Request path (e.g. 'orders' or 'orders/123')
55
- * @param array $params Additional GET parameters as an associative array
56
- * @return mixed API response
57
- * @throws PrintfulApiException if the API call status code is not in the 2xx range
58
- * @throws PrintfulException if the API call has failed or the response is invalid
59
- */
60
- public function get( $path, $params = array() ) {
61
- return $this->request( 'GET', $path, $params );
62
- }
63
-
64
- /**
65
- * Perform a DELETE request to the API
66
- * @param string $path Request path (e.g. 'orders' or 'orders/123')
67
- * @param array $params Additional GET parameters as an associative array
68
- * @return mixed API response
69
- * @throws PrintfulApiException if the API call status code is not in the 2xx range
70
- * @throws PrintfulException if the API call has failed or the response is invalid
71
- */
72
- public function delete( $path, $params = array() ) {
73
- return $this->request( 'DELETE', $path, $params );
74
- }
75
-
76
- /**
77
- * Perform a POST request to the API
78
- * @param string $path Request path (e.g. 'orders' or 'orders/123')
79
- * @param array $data Request body data as an associative array
80
- * @param array $params Additional GET parameters as an associative array
81
- * @return mixed API response
82
- * @throws PrintfulApiException if the API call status code is not in the 2xx range
83
- * @throws PrintfulException if the API call has failed or the response is invalid
84
- */
85
- public function post( $path, $data = array(), $params = array() ) {
86
- return $this->request( 'POST', $path, $params, $data );
87
- }
88
- /**
89
- * Perform a PUT request to the API
90
- * @param string $path Request path (e.g. 'orders' or 'orders/123')
91
- * @param array $data Request body data as an associative array
92
- * @param array $params Additional GET parameters as an associative array
93
- * @return mixed API response
94
- * @throws PrintfulApiException if the API call status code is not in the 2xx range
95
- * @throws PrintfulException if the API call has failed or the response is invalid
96
- */
97
- public function put( $path, $data = array(), $params = array() ) {
98
- return $this->request( 'PUT', $path, $params, $data );
99
- }
100
-
101
-
102
- /**
103
- * Perform a PATCH request to the API
104
- * @param string $path Request path
105
- * @param array $data Request body data as an associative array
106
- * @param array $params
107
- * @return mixed API response
108
- * @throws PrintfulApiException if the API call status code is not in the 2xx range
109
- * @throws PrintfulException if the API call has failed or the response is invalid
110
- */
111
- public function patch( $path, $data = array(), $params = array() )
112
- {
113
- return $this->request( 'PATCH', $path, $params, $data );
114
- }
115
-
116
- /**
117
- * Return raw response data from the last request
118
- * @return string|null Response data
119
- */
120
- public function getLastResponseRaw() {
121
- return $this->lastResponseRaw;
122
- }
123
- /**
124
- * Return decoded response data from the last request
125
- * @return array|null Response data
126
- */
127
- public function getLastResponse() {
128
- return $this->lastResponse;
129
- }
130
-
131
- /**
132
- * Internal request implementation
133
- *
134
- * @param $method
135
- * @param $path
136
- * @param array $params
137
- * @param null $data
138
- *
139
- * @return
140
- * @throws PrintfulApiException
141
- * @throws PrintfulException
142
- */
143
- private function request( $method, $path, array $params = array(), $data = null ) {
144
-
145
- $this->lastResponseRaw = null;
146
- $this->lastResponse = null;
147
-
148
- $url = trim( $path, '/' );
149
-
150
- if ( ! empty( $params ) ) {
151
- $url .= '?' . http_build_query( $params );
152
- }
153
-
154
- $request = array(
155
- 'timeout' => 10,
156
- 'user-agent' => $this->userAgent,
157
- 'method' => $method,
158
- 'headers' => array( 'Authorization' => 'Basic ' . base64_encode( $this->key ) ),
159
- 'body' => $data !== null ? json_encode( $data ) : null,
160
- );
161
-
162
- $result = wp_remote_get( $this->apiUrl . $url, $request );
163
-
164
- //allow other methods to hook in on the api result
165
- $result = apply_filters( 'printful_api_result', $result, $method, $this->apiUrl . $url, $request );
166
-
167
- if ( is_wp_error( $result ) ) {
168
- throw new PrintfulException( "API request failed - " . $result->get_error_message() );
169
- }
170
- $this->lastResponseRaw = $result['body'];
171
- $this->lastResponse = $response = json_decode( $result['body'], true );
172
-
173
- if ( ! isset( $response['code'], $response['result'] ) ) {
174
- throw new PrintfulException( 'Invalid API response' );
175
- }
176
- $status = (int) $response['code'];
177
- if ( $status < 200 || $status >= 300 ) {
178
- throw new PrintfulApiException( (string) $response['result'], $status );
179
- }
180
-
181
- return $response['result'];
182
- }
183
- }
184
-
185
- /**
186
- * Class PrintfulException Generic Printful exception
187
- */
188
- class PrintfulException extends Exception {}
189
- /**
190
- * Class PrintfulException Printful exception returned from the API
191
- */
192
  class PrintfulApiException extends PrintfulException {}
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit;
3
+
4
+ /**
5
+ * Printful API client
6
+ */
7
+ class Printful_Client {
8
+
9
+ private $key = false;
10
+ private $lastResponseRaw;
11
+ private $lastResponse;
12
+ private $userAgent = 'Printful WooCommerce Plugin';
13
+ private $apiUrl;
14
+
15
+ /**
16
+ * @param string $key Printful Store API key
17
+ * @param bool|string $disable_ssl Force HTTP instead of HTTPS for API requests
18
+ *
19
+ * @throws PrintfulException if the library failed to initialize
20
+ */
21
+ public function __construct( $key = '', $disable_ssl = false ) {
22
+
23
+ $key = (string) $key;
24
+
25
+ $this->userAgent .= ' ' . Printful_Base::VERSION . ' (WP ' . get_bloginfo( 'version' ) . ' + WC ' . WC()->version . ')';
26
+
27
+ if ( ! function_exists( 'json_decode' ) || ! function_exists( 'json_encode' ) ) {
28
+ throw new PrintfulException( 'PHP JSON extension is required for the Printful API library to work!' );
29
+ }
30
+ if ( strlen( $key ) < 32 ) {
31
+ throw new PrintfulException( 'Missing or invalid Printful store key!' );
32
+ }
33
+ $this->key = $key;
34
+
35
+ if ( $disable_ssl ) {
36
+ $this->apiUrl = str_replace( 'https://', 'http://', $this->apiUrl );
37
+ }
38
+
39
+ //setup api host
40
+ $this->apiUrl = Printful_Base::get_printful_api_host();
41
+ }
42
+
43
+ /**
44
+ * Returns total available item count from the last request if it supports paging (e.g order list) or null otherwise.
45
+ *
46
+ * @return int|null Item count
47
+ */
48
+ public function getItemCount() {
49
+ return isset( $this->lastResponse['paging']['total'] ) ? $this->lastResponse['paging']['total'] : null;
50
+ }
51
+
52
+ /**
53
+ * Perform a GET request to the API
54
+ * @param string $path Request path (e.g. 'orders' or 'orders/123')
55
+ * @param array $params Additional GET parameters as an associative array
56
+ * @return mixed API response
57
+ * @throws PrintfulApiException if the API call status code is not in the 2xx range
58
+ * @throws PrintfulException if the API call has failed or the response is invalid
59
+ */
60
+ public function get( $path, $params = array() ) {
61
+ return $this->request( 'GET', $path, $params );
62
+ }
63
+
64
+ /**
65
+ * Perform a DELETE request to the API
66
+ * @param string $path Request path (e.g. 'orders' or 'orders/123')
67
+ * @param array $params Additional GET parameters as an associative array
68
+ * @return mixed API response
69
+ * @throws PrintfulApiException if the API call status code is not in the 2xx range
70
+ * @throws PrintfulException if the API call has failed or the response is invalid
71
+ */
72
+ public function delete( $path, $params = array() ) {
73
+ return $this->request( 'DELETE', $path, $params );
74
+ }
75
+
76
+ /**
77
+ * Perform a POST request to the API
78
+ * @param string $path Request path (e.g. 'orders' or 'orders/123')
79
+ * @param array $data Request body data as an associative array
80
+ * @param array $params Additional GET parameters as an associative array
81
+ * @return mixed API response
82
+ * @throws PrintfulApiException if the API call status code is not in the 2xx range
83
+ * @throws PrintfulException if the API call has failed or the response is invalid
84
+ */
85
+ public function post( $path, $data = array(), $params = array() ) {
86
+ return $this->request( 'POST', $path, $params, $data );
87
+ }
88
+ /**
89
+ * Perform a PUT request to the API
90
+ * @param string $path Request path (e.g. 'orders' or 'orders/123')
91
+ * @param array $data Request body data as an associative array
92
+ * @param array $params Additional GET parameters as an associative array
93
+ * @return mixed API response
94
+ * @throws PrintfulApiException if the API call status code is not in the 2xx range
95
+ * @throws PrintfulException if the API call has failed or the response is invalid
96
+ */
97
+ public function put( $path, $data = array(), $params = array() ) {
98
+ return $this->request( 'PUT', $path, $params, $data );
99
+ }
100
+
101
+
102
+ /**
103
+ * Perform a PATCH request to the API
104
+ * @param string $path Request path
105
+ * @param array $data Request body data as an associative array
106
+ * @param array $params
107
+ * @return mixed API response
108
+ * @throws PrintfulApiException if the API call status code is not in the 2xx range
109
+ * @throws PrintfulException if the API call has failed or the response is invalid
110
+ */
111
+ public function patch( $path, $data = array(), $params = array() )
112
+ {
113
+ return $this->request( 'PATCH', $path, $params, $data );
114
+ }
115
+
116
+ /**
117
+ * Return raw response data from the last request
118
+ * @return string|null Response data
119
+ */
120
+ public function getLastResponseRaw() {
121
+ return $this->lastResponseRaw;
122
+ }
123
+ /**
124
+ * Return decoded response data from the last request
125
+ * @return array|null Response data
126
+ */
127
+ public function getLastResponse() {
128
+ return $this->lastResponse;
129
+ }
130
+
131
+ /**
132
+ * Internal request implementation
133
+ *
134
+ * @param $method
135
+ * @param $path
136
+ * @param array $params
137
+ * @param null $data
138
+ *
139
+ * @return
140
+ * @throws PrintfulApiException
141
+ * @throws PrintfulException
142
+ */
143
+ private function request( $method, $path, array $params = array(), $data = null ) {
144
+
145
+ $this->lastResponseRaw = null;
146
+ $this->lastResponse = null;
147
+
148
+ $url = trim( $path, '/' );
149
+
150
+ if ( ! empty( $params ) ) {
151
+ $url .= '?' . http_build_query( $params );
152
+ }
153
+
154
+ $request = array(
155
+ 'timeout' => 10,
156
+ 'user-agent' => $this->userAgent,
157
+ 'method' => $method,
158
+ 'headers' => array( 'Authorization' => 'Basic ' . base64_encode( $this->key ) ),
159
+ 'body' => $data !== null ? json_encode( $data ) : null,
160
+ );
161
+
162
+ $result = wp_remote_get( $this->apiUrl . $url, $request );
163
+
164
+ //allow other methods to hook in on the api result
165
+ $result = apply_filters( 'printful_api_result', $result, $method, $this->apiUrl . $url, $request );
166
+
167
+ if ( is_wp_error( $result ) ) {
168
+ throw new PrintfulException( "API request failed - " . $result->get_error_message() );
169
+ }
170
+ $this->lastResponseRaw = $result['body'];
171
+ $this->lastResponse = $response = json_decode( $result['body'], true );
172
+
173
+ if ( ! isset( $response['code'], $response['result'] ) ) {
174
+ throw new PrintfulException( 'Invalid API response' );
175
+ }
176
+ $status = (int) $response['code'];
177
+ if ( $status < 200 || $status >= 300 ) {
178
+ throw new PrintfulApiException( (string) $response['result'], $status );
179
+ }
180
+
181
+ return $response['result'];
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Class PrintfulException Generic Printful exception
187
+ */
188
+ class PrintfulException extends Exception {}
189
+ /**
190
+ * Class PrintfulException Printful exception returned from the API
191
+ */
192
  class PrintfulApiException extends PrintfulException {}
includes/class-printful-integration.php CHANGED
@@ -1,165 +1,165 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) exit;
3
-
4
- class Printful_Integration
5
- {
6
- const PF_API_CONNECT_STATUS = 'printful_api_connect_status';
7
- const PF_CONNECT_ERROR = 'printful_connect_error';
8
-
9
- public static $_instance;
10
-
11
- public static function instance() {
12
- if ( is_null( self::$_instance ) ) {
13
- self::$_instance = new self();
14
- }
15
-
16
- return self::$_instance;
17
- }
18
-
19
- public function __construct() {
20
- self::$_instance = $this;
21
- }
22
-
23
- /**
24
- * @return Printful_Client
25
- * @throws PrintfulException
26
- */
27
- public function get_client() {
28
-
29
- require_once 'class-printful-client.php';
30
- $client = new Printful_Client( $this->get_option( 'printful_key' ), $this->get_option( 'disable_ssl' ) == 'yes' );
31
-
32
- return $client;
33
- }
34
-
35
- /**
36
- * Check if the connection to printful is working
37
- * @param bool $force
38
- * @return bool
39
- * @throws PrintfulException
40
- */
41
- public function is_connected( $force = false ) {
42
-
43
- $api_key = $this->get_option( 'printful_key' );
44
-
45
- //dont need to show error - the plugin is simply not setup
46
- if ( empty( $api_key ) ) {
47
- return false;
48
- }
49
-
50
- //validate length, show error
51
- if ( strlen( $api_key ) != 36 ) {
52
- $message = 'Invalid API key - the key must be 36 characters long. Please ensure that your API key in <a href="%s">Settings</a> matches the one in your <a href="%s">Printful dashboard</a>.';
53
- $settings_url = admin_url( 'admin.php?page=printful-dashboard&tab=settings' );
54
- $printful_url = Printful_Base::get_printful_host() . 'dashboard/';
55
- $this->set_connect_error(sprintf( $message, $settings_url, $printful_url ) );
56
-
57
- return false;
58
- }
59
-
60
- //show connect status from cache
61
- if ( ! $force ) {
62
- $connected = get_transient( self::PF_API_CONNECT_STATUS );
63
- if ( $connected && $connected['status'] == 1 ) {
64
- $this->clear_connect_error();
65
-
66
- return true;
67
- } else if ( $connected && $connected['status'] == 0 ) { //try again in a minute
68
- return false;
69
- }
70
- }
71
-
72
- $client = $this->get_client();
73
- $response = false;
74
-
75
- //attempt to connect to printful to verify the API key
76
- try {
77
- $storeData = $client->get( 'store' );
78
- if ( ! empty( $storeData ) && $storeData['type'] == 'woocommerce') {
79
- $response = true;
80
- $this->clear_connect_error();
81
- set_transient( self::PF_API_CONNECT_STATUS, array( 'status' => 1 ) ); //no expiry
82
- } elseif ( $storeData['type'] != 'woocommerce' ) {
83
- $message = 'Invalid API key. This API key belongs to a ' . ucfirst( $storeData['type'] ) . ' store. Please copy the correct key from <a href="%s">Printful store settings</a> and enter it in the <a href="%s">Printful plugin settings</a>';
84
- $settings_url = admin_url( 'admin.php?page=printful-dashboard&tab=settings' );
85
- $printful_url = Printful_Base::get_printful_host() . 'dashboard/store';
86
- $this->set_connect_error( sprintf( $message, $settings_url, $printful_url ) );
87
- set_transient( self::PF_API_CONNECT_STATUS, array( 'status' => 0 ), MINUTE_IN_SECONDS ); //try again in 1 minute
88
- }
89
- } catch ( Exception $e ) {
90
-
91
- if ( $e->getCode() == 401 ) {
92
- $message = 'Invalid API key. Please ensure that your API key in <a href="%s">Printful plugin settings</a> matches the one in your <a href="%s">Printful store settings</a>.';
93
- $settings_url = admin_url( 'admin.php?page=printful-dashboard&tab=settings' );
94
- $printful_url = Printful_Base::get_printful_host() . 'dashboard/store';
95
- $this->set_connect_error( sprintf( $message, $settings_url, $printful_url ) );
96
- set_transient( self::PF_API_CONNECT_STATUS, array( 'status' => 0 ), MINUTE_IN_SECONDS ); //try again in 1 minute
97
- } else {
98
- $this->set_connect_error( 'Could not connect to Printful API. Please try again later. (Error ' . $e->getCode() . ': ' . $e->getMessage() . ')' );
99
- }
100
-
101
- //do nothing
102
- set_transient( self::PF_API_CONNECT_STATUS, array( 'status' => 0 ), MINUTE_IN_SECONDS ); //try again in 1 minute
103
- }
104
-
105
- return $response;
106
- }
107
-
108
- /**
109
- * Update connect error message
110
- * @param string $error
111
- */
112
- public function set_connect_error($error = '') {
113
- update_option( self::PF_CONNECT_ERROR, $error );
114
- }
115
-
116
- /**
117
- * Get current connect error message
118
- */
119
- public function get_connect_error() {
120
- return get_option( self::PF_CONNECT_ERROR, false );
121
- }
122
-
123
- /**
124
- * Remove option used for storing current connect error
125
- */
126
- public function clear_connect_error() {
127
- delete_option( self::PF_CONNECT_ERROR );
128
- }
129
-
130
- /**
131
- * AJAX call endpoint for connect status check
132
- * @throws PrintfulException
133
- */
134
- public static function ajax_force_check_connect_status() {
135
- if ( Printful_Integration::instance()->is_connected( true ) ) {
136
- die( 'OK' );
137
- }
138
-
139
- die( 'FAIL' );
140
- }
141
-
142
- /**
143
- * Wrapper method for getting an option
144
- * @param $name
145
- * @param array $default
146
- * @return bool
147
- */
148
- public function get_option( $name, $default = array() ) {
149
- $options = get_option( 'woocommerce_printful_settings', $default );
150
- if ( ! empty( $options[ $name ] ) ) {
151
- return $options[ $name ];
152
- }
153
-
154
- return false;
155
- }
156
-
157
- /**
158
- * Save the setting
159
- * @param $settings
160
- */
161
- public function update_settings( $settings ) {
162
- delete_transient( self::PF_API_CONNECT_STATUS ); //remove the successful API status since API key could have changed
163
- update_option( 'woocommerce_printful_settings', $settings );
164
- }
165
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit;
3
+
4
+ class Printful_Integration
5
+ {
6
+ const PF_API_CONNECT_STATUS = 'printful_api_connect_status';
7
+ const PF_CONNECT_ERROR = 'printful_connect_error';
8
+
9
+ public static $_instance;
10
+
11
+ public static function instance() {
12
+ if ( is_null( self::$_instance ) ) {
13
+ self::$_instance = new self();
14
+ }
15
+
16
+ return self::$_instance;
17
+ }
18
+
19
+ public function __construct() {
20
+ self::$_instance = $this;
21
+ }
22
+
23
+ /**
24
+ * @return Printful_Client
25
+ * @throws PrintfulException
26
+ */
27
+ public function get_client() {
28
+
29
+ require_once 'class-printful-client.php';
30
+ $client = new Printful_Client( $this->get_option( 'printful_key' ), $this->get_option( 'disable_ssl' ) == 'yes' );
31
+
32
+ return $client;
33
+ }
34
+
35
+ /**
36
+ * Check if the connection to printful is working
37
+ * @param bool $force
38
+ * @return bool
39
+ * @throws PrintfulException
40
+ */
41
+ public function is_connected( $force = false ) {
42
+
43
+ $api_key = $this->get_option( 'printful_key' );
44
+
45
+ //dont need to show error - the plugin is simply not setup
46
+ if ( empty( $api_key ) ) {
47
+ return false;
48
+ }
49
+
50
+ //validate length, show error
51
+ if ( strlen( $api_key ) != 36 ) {
52
+ $message = 'Invalid API key - the key must be 36 characters long. Please ensure that your API key in <a href="%s">Settings</a> matches the one in your <a href="%s">Printful dashboard</a>.';
53
+ $settings_url = admin_url( 'admin.php?page=printful-dashboard&tab=settings' );
54
+ $printful_url = Printful_Base::get_printful_host() . 'dashboard/';
55
+ $this->set_connect_error(sprintf( $message, $settings_url, $printful_url ) );
56
+
57
+ return false;
58
+ }
59
+
60
+ //show connect status from cache
61
+ if ( ! $force ) {
62
+ $connected = get_transient( self::PF_API_CONNECT_STATUS );
63
+ if ( $connected && $connected['status'] == 1 ) {
64
+ $this->clear_connect_error();
65
+
66
+ return true;
67
+ } else if ( $connected && $connected['status'] == 0 ) { //try again in a minute
68
+ return false;
69
+ }
70
+ }
71
+
72
+ $client = $this->get_client();
73
+ $response = false;
74
+
75
+ //attempt to connect to printful to verify the API key
76
+ try {
77
+ $storeData = $client->get( 'store' );
78
+ if ( ! empty( $storeData ) && $storeData['type'] == 'woocommerce') {
79
+ $response = true;
80
+ $this->clear_connect_error();
81
+ set_transient( self::PF_API_CONNECT_STATUS, array( 'status' => 1 ) ); //no expiry
82
+ } elseif ( $storeData['type'] != 'woocommerce' ) {
83
+ $message = 'Invalid API key. This API key belongs to a ' . ucfirst( $storeData['type'] ) . ' store. Please copy the correct key from <a href="%s">Printful store settings</a> and enter it in the <a href="%s">Printful plugin settings</a>';
84
+ $settings_url = admin_url( 'admin.php?page=printful-dashboard&tab=settings' );
85
+ $printful_url = Printful_Base::get_printful_host() . 'dashboard/store';
86
+ $this->set_connect_error( sprintf( $message, $settings_url, $printful_url ) );
87
+ set_transient( self::PF_API_CONNECT_STATUS, array( 'status' => 0 ), MINUTE_IN_SECONDS ); //try again in 1 minute
88
+ }
89
+ } catch ( Exception $e ) {
90
+
91
+ if ( $e->getCode() == 401 ) {
92
+ $message = 'Invalid API key. Please ensure that your API key in <a href="%s">Printful plugin settings</a> matches the one in your <a href="%s">Printful store settings</a>.';
93
+ $settings_url = admin_url( 'admin.php?page=printful-dashboard&tab=settings' );
94
+ $printful_url = Printful_Base::get_printful_host() . 'dashboard/store';
95
+ $this->set_connect_error( sprintf( $message, $settings_url, $printful_url ) );
96
+ set_transient( self::PF_API_CONNECT_STATUS, array( 'status' => 0 ), MINUTE_IN_SECONDS ); //try again in 1 minute
97
+ } else {
98
+ $this->set_connect_error( 'Could not connect to Printful API. Please try again later. (Error ' . $e->getCode() . ': ' . $e->getMessage() . ')' );
99
+ }
100
+
101
+ //do nothing
102
+ set_transient( self::PF_API_CONNECT_STATUS, array( 'status' => 0 ), MINUTE_IN_SECONDS ); //try again in 1 minute
103
+ }
104
+
105
+ return $response;
106
+ }
107
+
108
+ /**
109
+ * Update connect error message
110
+ * @param string $error
111
+ */
112
+ public function set_connect_error($error = '') {
113
+ update_option( self::PF_CONNECT_ERROR, $error );
114
+ }
115
+
116
+ /**
117
+ * Get current connect error message
118
+ */
119
+ public function get_connect_error() {
120
+ return get_option( self::PF_CONNECT_ERROR, false );
121
+ }
122
+
123
+ /**
124
+ * Remove option used for storing current connect error
125
+ */
126
+ public function clear_connect_error() {
127
+ delete_option( self::PF_CONNECT_ERROR );
128
+ }
129
+
130
+ /**
131
+ * AJAX call endpoint for connect status check
132
+ * @throws PrintfulException
133
+ */
134
+ public static function ajax_force_check_connect_status() {
135
+ if ( Printful_Integration::instance()->is_connected( true ) ) {
136
+ die( 'OK' );
137
+ }
138
+
139
+ die( 'FAIL' );
140
+ }
141
+
142
+ /**
143
+ * Wrapper method for getting an option
144
+ * @param $name
145
+ * @param array $default
146
+ * @return bool
147
+ */
148
+ public function get_option( $name, $default = array() ) {
149
+ $options = get_option( 'woocommerce_printful_settings', $default );
150
+ if ( ! empty( $options[ $name ] ) ) {
151
+ return $options[ $name ];
152
+ }
153
+
154
+ return false;
155
+ }
156
+
157
+ /**
158
+ * Save the setting
159
+ * @param $settings
160
+ */
161
+ public function update_settings( $settings ) {
162
+ delete_transient( self::PF_API_CONNECT_STATUS ); //remove the successful API status since API key could have changed
163
+ update_option( 'woocommerce_printful_settings', $settings );
164
+ }
165
  }
includes/class-printful-request-log.php CHANGED
@@ -1,151 +1,151 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) exit;
3
-
4
- class Printful_Request_log {
5
-
6
- const PF_USER_AGENT = 'Printful WooCommerce Integration';
7
- const PF_OPTION_LAST_API_RESPONSE = 'printful_last_api_response';
8
- const PF_OPTION_INCOMING_API_REQUEST_LOG = 'printful_incoming_api_request_log';
9
- const PF_OPTION_OUTGOING_API_REQUEST_LOG = 'printful_outgoing_api_request_log';
10
- const PF_INCOMING_API_ERRORS = 'printful-incoming-api-errors';
11
- const PF_OUTGOING_API_ERRORS = 'printful-outgoing-api-errors';
12
-
13
- public static function init() {
14
- $printful_log = new self;
15
- add_filter( 'woocommerce_api_serve_request', array( $printful_log, 'log_incoming_printful_api_requests' ), 10, 3 );
16
- add_filter( 'printful_api_result', array( $printful_log, 'log_outgoing_printful_api_requests'), 10, 4 );
17
- }
18
-
19
- /**
20
- * Log printful API errors and save the last 20 API responses
21
- * @param $served
22
- * @param $result
23
- * @param $request
24
- *
25
- * @return mixed
26
- */
27
- public function log_incoming_printful_api_requests( $served, $result, $request ) {
28
-
29
- if ( ! $this->isPrintfulApiRequest( $request ) ) {
30
- return $served;
31
- }
32
-
33
- $last_api_response = get_option( self::PF_OPTION_LAST_API_RESPONSE, false );
34
- $response_hash = md5( serialize( array( 'request' => $request, 'results' => $result ) ) );
35
-
36
- if ( $last_api_response == $response_hash ) { //do not allow the same response to be logged twice
37
- return $served;
38
- }
39
-
40
- //save full error to WC logs
41
- if ( ! empty( $result['errors'] ) ) {
42
- $this->save_to_wc_log( $request, $result, self::PF_INCOMING_API_ERRORS );
43
- }
44
-
45
- //save summary in database to be easily accessible for status page
46
- $this->save_to_printful_log( $request->method . ' ' . $request->path, $result, $response_hash, self::PF_OPTION_INCOMING_API_REQUEST_LOG );
47
-
48
- return $served; //we avoid changing the result
49
- }
50
-
51
-
52
- /**
53
- * @param $result
54
- * @param $method
55
- * @param $url
56
- * @param $request
57
- * @return array|mixed|object
58
- */
59
- public function log_outgoing_printful_api_requests($result, $method, $url, $request) {
60
-
61
- $original_result = $result;
62
- $request['path'] = $url;
63
- $params_set = null;
64
- $code_success = null;
65
-
66
- if ( ! is_wp_error( $result ) ) {
67
- $result = json_decode( $result['body'], true );
68
- $params_set = ! isset( $result['code'], $result['result'] );
69
- $status = (int) $result['code'];
70
- $code_success = ( $status < 200 || $status >= 300 );
71
- }
72
-
73
- //if the request contains error, log it
74
- if ( is_wp_error($result) || $params_set || $code_success ) {
75
- $this->save_to_wc_log( $request, $result, self::PF_OUTGOING_API_ERRORS );
76
- }
77
-
78
- $response_hash = md5( serialize( array( 'request' => $request, 'results' => $result ) ) );
79
-
80
- //save summary in database to be easily accessible for status page
81
- $this->save_to_printful_log( $method . ' ' . $url, $result, $response_hash, self::PF_OPTION_OUTGOING_API_REQUEST_LOG );
82
-
83
- return $original_result; //don't change the result
84
- }
85
-
86
- /**
87
- * Write Printful API request errors to log
88
- *
89
- * @param $request
90
- * @param $result
91
- * @param string $context
92
- * @return bool
93
- */
94
- private function save_to_wc_log( $request, $result, $context ) {
95
-
96
- if ( ! function_exists( 'wc_get_logger' ) ) {
97
- return false;
98
- }
99
-
100
- $logger = wc_get_logger();
101
- $context = array( 'source' => $context );
102
- $log_item = array(
103
- 'request' => (array) $request,
104
- 'results' => (array) $result,
105
- );
106
- $logger->error( wc_print_r( $log_item, true ), $context );
107
-
108
- return true;
109
- }
110
-
111
- /**
112
- * Save 20 lasts requests in easily accessible location
113
- *
114
- * @param $request_title
115
- * @param $result
116
- * @param $response_hash
117
- * @param $log
118
- */
119
- private function save_to_printful_log( $request_title, $result, $response_hash, $log ) {
120
-
121
- $request_log = get_option( $log, array() );
122
- if ( count( $request_log ) > 20 ) {
123
- $request_log = array_slice( $request_log, 1, 19 ); //if there are more than 20, remove the first entry
124
- }
125
-
126
- $is_error = is_wp_error($result) || !empty( $result['errors'] );
127
-
128
- $request_log[] = array(
129
- 'date' => date( 'Y-m-d H:i:s' ),
130
- 'request' => $request_title,
131
- 'result' => ( $is_error ? 'ERROR' : 'OK' ),
132
- );
133
-
134
- update_option( $log, $request_log );
135
- update_option( self::PF_OPTION_LAST_API_RESPONSE, $response_hash );
136
- }
137
-
138
- /**
139
- * Check requests header for indications that this is a printful api request
140
- * @param $request
141
- * @return bool
142
- */
143
- private function isPrintfulApiRequest( $request ) {
144
-
145
- if ( ! empty( $request->headers ) && ! empty( $request->headers['USER_AGENT'] ) && $request->headers['USER_AGENT'] == self::PF_USER_AGENT ) {
146
- return true;
147
- }
148
-
149
- return false;
150
- }
151
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit;
3
+
4
+ class Printful_Request_log {
5
+
6
+ const PF_USER_AGENT = 'Printful WooCommerce Integration';
7
+ const PF_OPTION_LAST_API_RESPONSE = 'printful_last_api_response';
8
+ const PF_OPTION_INCOMING_API_REQUEST_LOG = 'printful_incoming_api_request_log';
9
+ const PF_OPTION_OUTGOING_API_REQUEST_LOG = 'printful_outgoing_api_request_log';
10
+ const PF_INCOMING_API_ERRORS = 'printful-incoming-api-errors';
11
+ const PF_OUTGOING_API_ERRORS = 'printful-outgoing-api-errors';
12
+
13
+ public static function init() {
14
+ $printful_log = new self;
15
+ add_filter( 'woocommerce_api_serve_request', array( $printful_log, 'log_incoming_printful_api_requests' ), 10, 3 );
16
+ add_filter( 'printful_api_result', array( $printful_log, 'log_outgoing_printful_api_requests'), 10, 4 );
17
+ }
18
+
19
+ /**
20
+ * Log printful API errors and save the last 20 API responses
21
+ * @param $served
22
+ * @param $result
23
+ * @param $request
24
+ *
25
+ * @return mixed
26
+ */
27
+ public function log_incoming_printful_api_requests( $served, $result, $request ) {
28
+
29
+ if ( ! $this->isPrintfulApiRequest( $request ) ) {
30
+ return $served;
31
+ }
32
+
33
+ $last_api_response = get_option( self::PF_OPTION_LAST_API_RESPONSE, false );
34
+ $response_hash = md5( serialize( array( 'request' => $request, 'results' => $result ) ) );
35
+
36
+ if ( $last_api_response == $response_hash ) { //do not allow the same response to be logged twice
37
+ return $served;
38
+ }
39
+
40
+ //save full error to WC logs
41
+ if ( ! empty( $result['errors'] ) ) {
42
+ $this->save_to_wc_log( $request, $result, self::PF_INCOMING_API_ERRORS );
43
+ }
44
+
45
+ //save summary in database to be easily accessible for status page
46
+ $this->save_to_printful_log( $request->method . ' ' . $request->path, $result, $response_hash, self::PF_OPTION_INCOMING_API_REQUEST_LOG );
47
+
48
+ return $served; //we avoid changing the result
49
+ }
50
+
51
+
52
+ /**
53
+ * @param $result
54
+ * @param $method
55
+ * @param $url
56
+ * @param $request
57
+ * @return array|mixed|object
58
+ */
59
+ public function log_outgoing_printful_api_requests($result, $method, $url, $request) {
60
+
61
+ $original_result = $result;
62
+ $request['path'] = $url;
63
+ $params_set = null;
64
+ $code_success = null;
65
+
66
+ if ( ! is_wp_error( $result ) ) {
67
+ $result = json_decode( $result['body'], true );
68
+ $params_set = ! isset( $result['code'], $result['result'] );
69
+ $status = (int) $result['code'];
70
+ $code_success = ( $status < 200 || $status >= 300 );
71
+ }
72
+
73
+ //if the request contains error, log it
74
+ if ( is_wp_error($result) || $params_set || $code_success ) {
75
+ $this->save_to_wc_log( $request, $result, self::PF_OUTGOING_API_ERRORS );
76
+ }
77
+
78
+ $response_hash = md5( serialize( array( 'request' => $request, 'results' => $result ) ) );
79
+
80
+ //save summary in database to be easily accessible for status page
81
+ $this->save_to_printful_log( $method . ' ' . $url, $result, $response_hash, self::PF_OPTION_OUTGOING_API_REQUEST_LOG );
82
+
83
+ return $original_result; //don't change the result
84
+ }
85
+
86
+ /**
87
+ * Write Printful API request errors to log
88
+ *
89
+ * @param $request
90
+ * @param $result
91
+ * @param string $context
92
+ * @return bool
93
+ */
94
+ private function save_to_wc_log( $request, $result, $context ) {
95
+
96
+ if ( ! function_exists( 'wc_get_logger' ) ) {
97
+ return false;
98
+ }
99
+
100
+ $logger = wc_get_logger();
101
+ $context = array( 'source' => $context );
102
+ $log_item = array(
103
+ 'request' => (array) $request,
104
+ 'results' => (array) $result,
105
+ );
106
+ $logger->error( wc_print_r( $log_item, true ), $context );
107
+
108
+ return true;
109
+ }
110
+
111
+ /**
112
+ * Save 20 lasts requests in easily accessible location
113
+ *
114
+ * @param $request_title
115
+ * @param $result
116
+ * @param $response_hash
117
+ * @param $log
118
+ */
119
+ private function save_to_printful_log( $request_title, $result, $response_hash, $log ) {
120
+
121
+ $request_log = get_option( $log, array() );
122
+ if ( count( $request_log ) > 20 ) {
123
+ $request_log = array_slice( $request_log, 1, 19 ); //if there are more than 20, remove the first entry
124
+ }
125
+
126
+ $is_error = is_wp_error($result) || !empty( $result['errors'] );
127
+
128
+ $request_log[] = array(
129
+ 'date' => date( 'Y-m-d H:i:s' ),
130
+ 'request' => $request_title,
131
+ 'result' => ( $is_error ? 'ERROR' : 'OK' ),
132
+ );
133
+
134
+ update_option( $log, $request_log );
135
+ update_option( self::PF_OPTION_LAST_API_RESPONSE, $response_hash );
136
+ }
137
+
138
+ /**
139
+ * Check requests header for indications that this is a printful api request
140
+ * @param $request
141
+ * @return bool
142
+ */
143
+ private function isPrintfulApiRequest( $request ) {
144
+
145
+ if ( ! empty( $request->headers ) && ! empty( $request->headers['USER_AGENT'] ) && $request->headers['USER_AGENT'] == self::PF_USER_AGENT ) {
146
+ return true;
147
+ }
148
+
149
+ return false;
150
+ }
151
  }
includes/class-printful-taxes.php CHANGED
@@ -1,189 +1,189 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) exit;
3
-
4
- class Printful_Taxes {
5
-
6
- /**
7
- * Initialize the values, hooks and actions
8
- */
9
- public static function init() {
10
- if ( Printful_Integration::instance()->get_option( 'calculate_tax' ) == 'yes' ) {
11
- //Update tax options if taxes are enabled
12
- if ( get_option( 'woocommerce_calc_taxes' ) != 'yes' ) {
13
- update_option( 'woocommerce_calc_taxes', 'yes' );
14
- }
15
- if ( get_option( 'woocommerce_tax_based_on' ) != 'shipping' ) {
16
- update_option( 'woocommerce_tax_based_on', 'shipping' );
17
- }
18
-
19
- //Override tax rates calculated by Woocommerce
20
- $taxes = new self;
21
- add_filter( 'woocommerce_matched_tax_rates', array( $taxes, 'calculate_tax' ), 10, 6 );
22
- }
23
- }
24
-
25
- /**
26
- * @param $matched_tax_rates
27
- * @param $country
28
- * @param $state
29
- * @param $postcode
30
- * @param $city
31
- * @param $tax_class
32
- *
33
- * @return mixed
34
- */
35
- public function calculate_tax( $matched_tax_rates, $country, $state, $postcode, $city, $tax_class ) {
36
- //if a tax rate is already matched, avoid adding extra one
37
- if ( ! empty( $matched_tax_rates ) ) {
38
- return $matched_tax_rates;
39
- }
40
-
41
- $countries = $this->get_tax_countries();
42
- if ( isset( $countries[ $country ][ $state ] ) && !empty($postcode) ) { //only make the request if country, state and zip are set
43
- $key = 'printful_tax_rate_' . $country . '-' . $state . '-' . $city . '-' . $postcode;
44
- $rate = get_transient( $key );
45
- $response = null;
46
-
47
- if ( $rate === false ) {
48
- try {
49
- $client = Printful_Integration::instance()->get_client();
50
- $response = $client->post( 'tax/rates', array(
51
- 'recipient' => array(
52
- 'country_code' => $country,
53
- 'state_code' => $state,
54
- 'city' => $city,
55
- 'zip' => $postcode,
56
- ),
57
- ) );
58
- } catch ( Exception $e ) {
59
- }
60
-
61
- if ( isset( $response['rate'] ) ) {
62
- $rate = $response;
63
- } else {
64
- $rate = array(
65
- 'required' => false,
66
- 'rate' => 0,
67
- 'shipping_taxable' => false,
68
- );
69
- }
70
- set_transient( $key, $rate, 1800 );
71
- }
72
-
73
- if ( $rate['required'] ) {
74
- $rate_item = array(
75
- 'rate' => $rate['rate'] * 100,
76
- 'label' => 'Sales Tax',
77
- 'shipping' => $rate['shipping_taxable'] ? 'yes' : 'no',
78
- 'compound' => 'no',
79
- );
80
-
81
- if ( $this->isRateUnique( $rate_item, $matched_tax_rates ) ) {
82
- $id = $this->get_printful_rate_id( $country, $state, $rate['shipping_taxable'] );
83
- $matched_tax_rates[ $id ] = $rate_item;
84
- }
85
- }
86
- }
87
-
88
- return $matched_tax_rates;
89
- }
90
-
91
- /**
92
- * Checks if a equal tax rate is not already set
93
- *
94
- * @param $rate
95
- * @param $matched_tax_rates
96
- *
97
- * @return bool
98
- */
99
- private function isRateUnique( $rate, $matched_tax_rates ) {
100
- if ( empty( $matched_tax_rates ) ) {
101
- return true;
102
- }
103
-
104
- foreach ( $matched_tax_rates as $mr ) {
105
- if ( floatval( $mr['rate'] ) == floatval( $rate['rate'] ) && $mr['shipping'] == $rate['shipping'] ) {
106
- return false;
107
- }
108
- }
109
-
110
- return true;
111
- }
112
-
113
- /**
114
- * Gets list of countries and states where Printful needs to calculate sales tax
115
- * @return array|mixed
116
- */
117
- private function get_tax_countries() {
118
- $countries = get_transient( 'printful_tax_countries' );
119
-
120
- if ( ! $countries ) {
121
- $countries = array();
122
-
123
- try {
124
- $client = Printful_Integration::instance()->get_client();
125
- $list = $client->get( 'tax/countries' );
126
-
127
- foreach ( $list as $country ) {
128
- foreach ( $country['states'] as $state ) {
129
- $countries[ $country['code'] ][ $state['code'] ] = 1;
130
- }
131
- }
132
-
133
- if ( ! empty( $countries ) ) {
134
- set_transient( 'printful_tax_countries', $countries, 6 * 3600 );
135
- }
136
- } catch ( Exception $e ) {
137
- //Default to CA if can't get the actual state list
138
- return array( 'US' => array( 'CA' => 1 ) );
139
- }
140
- }
141
-
142
- return $countries;
143
- }
144
-
145
- /**
146
- * Creates dummy tax rate ID to display Printful tax rates in the cart summary.
147
- *
148
- * @param $cc
149
- * @param $state
150
- * @param bool $includeShipping
151
- *
152
- * @return int|null|string
153
- */
154
- private function get_printful_rate_id( $cc, $state, $includeShipping = false ) {
155
- global $wpdb;
156
-
157
- $includeShipping = (int) $includeShipping;
158
-
159
- $states = WC()->countries->get_states( $cc );
160
- $tax_title = ( isset( $states[ $state ] ) ? $states[ $state ] . ' ' : '' ) . __( 'Sales Tax', 'printful' );
161
- $id = $wpdb->get_var(
162
- $wpdb->prepare( "SELECT tax_rate_id FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_class='printful'
163
- and tax_rate_country = %s AND tax_rate_state = %s AND tax_rate_shipping = %s LIMIT 1",
164
- $cc,
165
- $state,
166
- $includeShipping
167
- ) );
168
- if ( empty( $id ) ) {
169
- $wpdb->insert(
170
- $wpdb->prefix . "woocommerce_tax_rates",
171
- array(
172
- 'tax_rate_country' => $cc,
173
- 'tax_rate_state' => $state,
174
- 'tax_rate' => 0,
175
- 'tax_rate_name' => $tax_title,
176
- 'tax_rate_priority' => 1,
177
- 'tax_rate_compound' => 0,
178
- 'tax_rate_shipping' => $includeShipping,
179
- 'tax_rate_class' => 'printful',
180
- )
181
- );
182
- $id = $wpdb->insert_id;
183
- }
184
-
185
- return $id;
186
- }
187
-
188
-
189
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit;
3
+
4
+ class Printful_Taxes {
5
+
6
+ /**
7
+ * Initialize the values, hooks and actions
8
+ */
9
+ public static function init() {
10
+ if ( Printful_Integration::instance()->get_option( 'calculate_tax' ) == 'yes' ) {
11
+ //Update tax options if taxes are enabled
12
+ if ( get_option( 'woocommerce_calc_taxes' ) != 'yes' ) {
13
+ update_option( 'woocommerce_calc_taxes', 'yes' );
14
+ }
15
+ if ( get_option( 'woocommerce_tax_based_on' ) != 'shipping' ) {
16
+ update_option( 'woocommerce_tax_based_on', 'shipping' );
17
+ }
18
+
19
+ //Override tax rates calculated by Woocommerce
20
+ $taxes = new self;
21
+ add_filter( 'woocommerce_matched_tax_rates', array( $taxes, 'calculate_tax' ), 10, 6 );
22
+ }
23
+ }
24
+
25
+ /**
26
+ * @param $matched_tax_rates
27
+ * @param $country
28
+ * @param $state
29
+ * @param $postcode
30
+ * @param $city
31
+ * @param $tax_class
32
+ *
33
+ * @return mixed
34
+ */
35
+ public function calculate_tax( $matched_tax_rates, $country, $state, $postcode, $city, $tax_class ) {
36
+ //if a tax rate is already matched, avoid adding extra one
37
+ if ( ! empty( $matched_tax_rates ) ) {
38
+ return $matched_tax_rates;
39
+ }
40
+
41
+ $countries = $this->get_tax_countries();
42
+ if ( isset( $countries[ $country ][ $state ] ) && !empty($postcode) ) { //only make the request if country, state and zip are set
43
+ $key = 'printful_tax_rate_' . $country . '-' . $state . '-' . $city . '-' . $postcode;
44
+ $rate = get_transient( $key );
45
+ $response = null;
46
+
47
+ if ( $rate === false ) {
48
+ try {
49
+ $client = Printful_Integration::instance()->get_client();
50
+ $response = $client->post( 'tax/rates', array(
51
+ 'recipient' => array(
52
+ 'country_code' => $country,
53
+ 'state_code' => $state,
54
+ 'city' => $city,
55
+ 'zip' => $postcode,
56
+ ),
57
+ ) );
58
+ } catch ( Exception $e ) {
59
+ }
60
+
61
+ if ( isset( $response['rate'] ) ) {
62
+ $rate = $response;
63
+ } else {
64
+ $rate = array(
65
+ 'required' => false,
66
+ 'rate' => 0,
67
+ 'shipping_taxable' => false,
68
+ );
69
+ }
70
+ set_transient( $key, $rate, 1800 );
71
+ }
72
+
73
+ if ( $rate['required'] ) {
74
+ $rate_item = array(
75
+ 'rate' => $rate['rate'] * 100,
76
+ 'label' => 'Sales Tax',
77
+ 'shipping' => $rate['shipping_taxable'] ? 'yes' : 'no',
78
+ 'compound' => 'no',
79
+ );
80
+
81
+ if ( $this->isRateUnique( $rate_item, $matched_tax_rates ) ) {
82
+ $id = $this->get_printful_rate_id( $country, $state, $rate['shipping_taxable'] );
83
+ $matched_tax_rates[ $id ] = $rate_item;
84
+ }
85
+ }
86
+ }
87
+
88
+ return $matched_tax_rates;
89
+ }
90
+
91
+ /**
92
+ * Checks if a equal tax rate is not already set
93
+ *
94
+ * @param $rate
95
+ * @param $matched_tax_rates
96
+ *
97
+ * @return bool
98
+ */
99
+ private function isRateUnique( $rate, $matched_tax_rates ) {
100
+ if ( empty( $matched_tax_rates ) ) {
101
+ return true;
102
+ }
103
+
104
+ foreach ( $matched_tax_rates as $mr ) {
105
+ if ( floatval( $mr['rate'] ) == floatval( $rate['rate'] ) && $mr['shipping'] == $rate['shipping'] ) {
106
+ return false;
107
+ }
108
+ }
109
+
110
+ return true;
111
+ }
112
+
113
+ /**
114
+ * Gets list of countries and states where Printful needs to calculate sales tax
115
+ * @return array|mixed
116
+ */
117
+ private function get_tax_countries() {
118
+ $countries = get_transient( 'printful_tax_countries' );
119
+
120
+ if ( ! $countries ) {
121
+ $countries = array();
122
+
123
+ try {
124
+ $client = Printful_Integration::instance()->get_client();
125
+ $list = $client->get( 'tax/countries' );
126
+
127
+ foreach ( $list as $country ) {
128
+ foreach ( $country['states'] as $state ) {
129
+ $countries[ $country['code'] ][ $state['code'] ] = 1;
130
+ }
131
+ }
132
+
133
+ if ( ! empty( $countries ) ) {
134
+ set_transient( 'printful_tax_countries', $countries, 6 * 3600 );
135
+ }
136
+ } catch ( Exception $e ) {
137
+ //Default to CA if can't get the actual state list
138
+ return array( 'US' => array( 'CA' => 1 ) );
139
+ }
140
+ }
141
+
142
+ return $countries;
143
+ }
144
+
145
+ /**
146
+ * Creates dummy tax rate ID to display Printful tax rates in the cart summary.
147
+ *
148
+ * @param $cc
149
+ * @param $state
150
+ * @param bool $includeShipping
151
+ *
152
+ * @return int|null|string
153
+ */
154
+ private function get_printful_rate_id( $cc, $state, $includeShipping = false ) {
155
+ global $wpdb;
156
+
157
+ $includeShipping = (int) $includeShipping;
158
+
159
+ $states = WC()->countries->get_states( $cc );
160
+ $tax_title = ( isset( $states[ $state ] ) ? $states[ $state ] . ' ' : '' ) . __( 'Sales Tax', 'printful' );
161
+ $id = $wpdb->get_var(
162
+ $wpdb->prepare( "SELECT tax_rate_id FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_class='printful'
163
+ and tax_rate_country = %s AND tax_rate_state = %s AND tax_rate_shipping = %s LIMIT 1",
164
+ $cc,
165
+ $state,
166
+ $includeShipping
167
+ ) );
168
+ if ( empty( $id ) ) {
169
+ $wpdb->insert(
170
+ $wpdb->prefix . "woocommerce_tax_rates",
171
+ array(
172
+ 'tax_rate_country' => $cc,
173
+ 'tax_rate_state' => $state,
174
+ 'tax_rate' => 0,
175
+ 'tax_rate_name' => $tax_title,
176
+ 'tax_rate_priority' => 1,
177
+ 'tax_rate_compound' => 0,
178
+ 'tax_rate_shipping' => $includeShipping,
179
+ 'tax_rate_class' => 'printful',
180
+ )
181
+ );
182
+ $id = $wpdb->insert_id;
183
+ }
184
+
185
+ return $id;
186
+ }
187
+
188
+
189
  }
includes/templates/ajax-loader.php CHANGED
@@ -1,11 +1,11 @@
1
- <div id="loader-block-<?php echo esc_attr($action); ?>">
2
- <div class="block-loader loader-wrap">
3
- <img src="<?php echo esc_url( admin_url( 'images/spinner-2x.gif' ) ) ?>" class="loader" width="20px" height="20px" alt="loader"/>
4
- <span class="message"><?php echo esc_html($message); ?></span>
5
- </div>
6
- </div>
7
- <script type="text/javascript">
8
- jQuery(document).ready(function () {
9
- Printful_Block_Loader.load('<?php echo esc_url(admin_url( 'admin-ajax.php?action=' . $action )); ?>', 'loader-block-<?php echo esc_attr($action); ?>');
10
- });
11
  </script>
1
+ <div id="loader-block-<?php echo esc_attr($action); ?>">
2
+ <div class="block-loader loader-wrap">
3
+ <img src="<?php echo esc_url( admin_url( 'images/spinner-2x.gif' ) ) ?>" class="loader" width="20px" height="20px" alt="loader"/>
4
+ <span class="message"><?php echo esc_html($message); ?></span>
5
+ </div>
6
+ </div>
7
+ <script type="text/javascript">
8
+ jQuery(document).ready(function () {
9
+ Printful_Block_Loader.load('<?php echo esc_url(admin_url( 'admin-ajax.php?action=' . $action )); ?>', 'loader-block-<?php echo esc_attr($action); ?>');
10
+ });
11
  </script>
includes/templates/connect.php CHANGED
@@ -1,40 +1,40 @@
1
- <div class="printful-connect">
2
-
3
- <div class="printful-connect-inner">
4
-
5
- <h1><?php esc_html_e('Connect to Printful', 'printful'); ?></h1>
6
-
7
- <img src=" <?php echo esc_url(Printful_Base::get_asset_url() . 'images/connect.svg'); ?>" class="connect-image" alt="connect to printful">
8
-
9
- <?php
10
- if ( ! empty( $issues ) ) {
11
- ?>
12
- <p><?php esc_html_e('To connect your store to Printful, fix the following errors:', 'printful'); ?></p>
13
- <div class="printful-notice">
14
- <ul>
15
- <?php
16
- foreach ( $issues as $issue ) {
17
- echo '<li>' . wp_kses_post( $issue ) . '</li>';
18
- }
19
- ?>
20
- </ul>
21
- </div>
22
- <?php
23
- $url = '#';
24
- } else {
25
- ?><p class="connect-description"><?php esc_html_e('You\'re almost done! Just 2 more steps to have your WooCommerce store connected to Printful for automatic order fulfillment.', 'printful'); ?></p><?php
26
- $url = Printful_Base::get_printful_host() . 'dashboard/woocommerce/plugin-connect?website=' . urlencode( trailingslashit( get_home_url() ) ) . '&key=' . urlencode( $consumer_key ) . '&returnUrl=' . urlencode( get_admin_url( null,'admin.php?page=' . Printful_Admin::MENU_SLUG_DASHBOARD ) );
27
- }
28
-
29
- echo '<a href="' . esc_url($url) . '" class="button button-primary printful-connect-button ' . ( ! empty( $issues ) ? 'disabled' : '' ) . '" target="_blank">' . esc_html__('Connect', 'printful') . '</a>';
30
- ?>
31
-
32
- <img src="<?php echo esc_url( admin_url( 'images/spinner-2x.gif' ) ) ?>" class="loader hidden" width="20px" height="20px" alt="loader"/>
33
-
34
- <script type="text/javascript">
35
- jQuery(document).ready(function () {
36
- Printful_Connect.init('<?php echo esc_url( admin_url( 'admin-ajax.php?action=ajax_force_check_connect_status' ) ); ?>');
37
- });
38
- </script>
39
- </div>
40
  </div>
1
+ <div class="printful-connect">
2
+
3
+ <div class="printful-connect-inner">
4
+
5
+ <h1><?php esc_html_e('Connect to Printful', 'printful'); ?></h1>
6
+
7
+ <img src=" <?php echo esc_url(Printful_Base::get_asset_url() . 'images/connect.svg'); ?>" class="connect-image" alt="connect to printful">
8
+
9
+ <?php
10
+ if ( ! empty( $issues ) ) {
11
+ ?>
12
+ <p><?php esc_html_e('To connect your store to Printful, fix the following errors:', 'printful'); ?></p>
13
+ <div class="printful-notice">
14
+ <ul>
15
+ <?php
16
+ foreach ( $issues as $issue ) {
17
+ echo '<li>' . wp_kses_post( $issue ) . '</li>';
18
+ }
19
+ ?>
20
+ </ul>
21
+ </div>
22
+ <?php
23
+ $url = '#';
24
+ } else {
25
+ ?><p class="connect-description"><?php esc_html_e('You\'re almost done! Just 2 more steps to have your WooCommerce store connected to Printful for automatic order fulfillment.', 'printful'); ?></p><?php
26
+ $url = Printful_Base::get_printful_host() . 'dashboard/woocommerce/plugin-connect?website=' . urlencode( trailingslashit( get_home_url() ) ) . '&key=' . urlencode( $consumer_key ) . '&returnUrl=' . urlencode( get_admin_url( null,'admin.php?page=' . Printful_Admin::MENU_SLUG_DASHBOARD ) );
27
+ }
28
+
29
+ echo '<a href="' . esc_url($url) . '" class="button button-primary printful-connect-button ' . ( ! empty( $issues ) ? 'disabled' : '' ) . '" target="_blank">' . esc_html__('Connect', 'printful') . '</a>';
30
+ ?>
31
+
32
+ <img src="<?php echo esc_url( admin_url( 'images/spinner-2x.gif' ) ) ?>" class="loader hidden" width="20px" height="20px" alt="loader"/>
33
+
34
+ <script type="text/javascript">
35
+ jQuery(document).ready(function () {
36
+ Printful_Connect.init('<?php echo esc_url( admin_url( 'admin-ajax.php?action=ajax_force_check_connect_status' ) ); ?>');
37
+ });
38
+ </script>
39
+ </div>
40
  </div>
includes/templates/header.php CHANGED
@@ -1,20 +1,20 @@
1
- <div class="wrap">
2
-
3
- <?php
4
- $base_url = '?page=printful-dashboard';
5
- ?>
6
-
7
- <h2 class="nav-tab-wrapper printful-tabs">
8
- <?php foreach ($tabs as $tab) : ?>
9
- <?php
10
- $active = '';
11
- if ( ! empty( $_GET['tab'] ) && $_GET['tab'] == $tab['tab_url'] ) {
12
- $active = 'nav-tab-active';
13
- }
14
- if ( empty( $_GET['tab'] ) && $tab['tab_url'] == '' ) {
15
- $active = 'nav-tab-active';
16
- }
17
- ?>
18
- <a href="<?php echo esc_url($base_url . ($tab['tab_url'] ? '&tab=' . $tab['tab_url'] : '') ); ?>" class="nav-tab <?php echo esc_attr($active);?>"><?php echo esc_html($tab['name']); ?></a>
19
- <?php endforeach; ?>
20
  </h2>
1
+ <div class="wrap">
2
+
3
+ <?php
4
+ $base_url = '?page=printful-dashboard';
5
+ ?>
6
+
7
+ <h2 class="nav-tab-wrapper printful-tabs">
8
+ <?php foreach ($tabs as $tab) : ?>
9
+ <?php
10
+ $active = '';
11
+ if ( ! empty( $_GET['tab'] ) && $_GET['tab'] == $tab['tab_url'] ) {
12
+ $active = 'nav-tab-active';
13
+ }
14
+ if ( empty( $_GET['tab'] ) && $tab['tab_url'] == '' ) {
15
+ $active = 'nav-tab-active';
16
+ }
17
+ ?>
18
+ <a href="<?php echo esc_url($base_url . ($tab['tab_url'] ? '&tab=' . $tab['tab_url'] : '') ); ?>" class="nav-tab <?php echo esc_attr($active);?>"><?php echo esc_html($tab['name']); ?></a>
19
+ <?php endforeach; ?>
20
  </h2>
includes/templates/inline-script.php CHANGED
@@ -1,3 +1,3 @@
1
- <script type="text/javascript">
2
- <?php echo esc_js( $script ); ?>
3
  </script>
1
+ <script type="text/javascript">
2
+ <?php echo esc_js( $script ); ?>
3
  </script>
includes/templates/order-table.php CHANGED
@@ -1,69 +1,69 @@
1
-
2
- <h2>Printful product orders</h2>
3
-
4
- <?php if ( ! empty( $orders ) && $orders['count'] > 0 ): ?>
5
-
6
- <table class="wp-list-table widefat fixed striped printful-latest-orders">
7
- <thead>
8
- <tr>
9
- <th class="col-order"><?php esc_html_e('Order', 'printful'); ?></th>
10
- <th class="col-date"><?php esc_html_e('Date', 'printful'); ?></th>
11
- <th class="col-from"><?php esc_html_e('From', 'printful'); ?></th>
12
- <th class="col-status"><?php esc_html_e('Status', 'printful'); ?></th>
13
- <th class="col-total"><?php esc_html_e('Total', 'printful'); ?></th>
14
- <th class="col-actions"><?php esc_html_e('Actions', 'printful'); ?></th>
15
- </tr>
16
- </thead>
17
- <tbody>
18
-
19
- <?php foreach ( $orders['results'] as $order ) : ?>
20
-
21
- <tr>
22
- <td>
23
- <?php
24
- if ( $order['external_id'] ) {
25
- echo '<a href="' . esc_url( get_edit_post_link( $order['external_id'] ) ) . '">';
26
- echo '#' . esc_html( $order['external_id'] );
27
- echo '</a>';
28
- } else {
29
- echo '#' . esc_html( $order['id'] );
30
- }
31
- ?>
32
- </td>
33
- <td>
34
- <?php echo esc_html( date('Y-m-d', $order['created']) ); ?>
35
- </td>
36
- <td>
37
- <?php echo esc_html( $order['recipient']['name'] ); ?>
38
- </td>
39
- <td>
40
- <?php echo esc_html( ucfirst($order['status']) ); ?>
41
- </td>
42
- <td>
43
- $<?php echo esc_html( $order['costs']['total'] ); ?>
44
- </td>
45
- <td>
46
- <a href="<?php echo esc_url(Printful_Base::get_printful_host()); ?>dashboard?order_id=<?php echo esc_attr($order['id']); ?>" target="_blank"><?php esc_html_e('Open in Printful', 'printful'); ?></a>
47
- </td>
48
- </tr>
49
-
50
- <?php endforeach; ?>
51
-
52
- </tbody>
53
- <tfoot>
54
- <tr>
55
- <th class="col-order"><?php esc_html_e('Order', 'printful'); ?></th>
56
- <th class="col-date"><?php esc_html_e('Date', 'printful'); ?></th>
57
- <th class="col-from"><?php esc_html_e('From', 'printful'); ?></th>
58
- <th class="col-status"><?php esc_html_e('Status', 'printful'); ?></th>
59
- <th class="col-total"><?php esc_html_e('Total', 'printful'); ?></th>
60
- <th class="col-actions"><?php esc_html_e('Actions', 'printful'); ?></th>
61
- </tr>
62
- </tfoot>
63
- </table>
64
-
65
- <?php else: ?>
66
- <div class="printful-latest-orders">
67
- <p><?php esc_html_e('Once your store gets some Printful product orders, they will be shown here!', 'printful'); ?></p>
68
- </div>
69
  <?php endif; ?>
1
+
2
+ <h2>Printful product orders</h2>
3
+
4
+ <?php if ( ! empty( $orders ) && $orders['count'] > 0 ): ?>
5
+
6
+ <table class="wp-list-table widefat fixed striped printful-latest-orders">
7
+ <thead>
8
+ <tr>
9
+ <th class="col-order"><?php esc_html_e('Order', 'printful'); ?></th>
10
+ <th class="col-date"><?php esc_html_e('Date', 'printful'); ?></th>
11
+ <th class="col-from"><?php esc_html_e('From', 'printful'); ?></th>
12
+ <th class="col-status"><?php esc_html_e('Status', 'printful'); ?></th>
13
+ <th class="col-total"><?php esc_html_e('Total', 'printful'); ?></th>
14
+ <th class="col-actions"><?php esc_html_e('Actions', 'printful'); ?></th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+
19
+ <?php foreach ( $orders['results'] as $order ) : ?>
20
+
21
+ <tr>
22
+ <td>
23
+ <?php
24
+ if ( $order['external_id'] ) {
25
+ echo '<a href="' . esc_url( get_edit_post_link( $order['external_id'] ) ) . '">';
26
+ echo '#' . esc_html( $order['external_id'] );
27
+ echo '</a>';
28
+ } else {
29
+ echo '#' . esc_html( $order['id'] );
30
+ }
31
+ ?>
32
+ </td>
33
+ <td>
34
+ <?php echo esc_html( date('Y-m-d', $order['created']) ); ?>
35
+ </td>
36
+ <td>
37
+ <?php echo esc_html( $order['recipient']['name'] ); ?>
38
+ </td>
39
+ <td>
40
+ <?php echo esc_html( ucfirst($order['status']) ); ?>
41
+ </td>
42
+ <td>
43
+ $<?php echo esc_html( $order['costs']['total'] ); ?>
44
+ </td>
45
+ <td>
46
+ <a href="<?php echo esc_url(Printful_Base::get_printful_host()); ?>dashboard?order_id=<?php echo esc_attr($order['id']); ?>" target="_blank"><?php esc_html_e('Open in Printful', 'printful'); ?></a>
47
+ </td>
48
+ </tr>
49
+
50
+ <?php endforeach; ?>
51
+
52
+ </tbody>
53
+ <tfoot>
54
+ <tr>
55
+ <th class="col-order"><?php esc_html_e('Order', 'printful'); ?></th>
56
+ <th class="col-date"><?php esc_html_e('Date', 'printful'); ?></th>
57
+ <th class="col-from"><?php esc_html_e('From', 'printful'); ?></th>
58
+ <th class="col-status"><?php esc_html_e('Status', 'printful'); ?></th>
59
+ <th class="col-total"><?php esc_html_e('Total', 'printful'); ?></th>
60
+ <th class="col-actions"><?php esc_html_e('Actions', 'printful'); ?></th>
61
+ </tr>
62
+ </tfoot>
63
+ </table>
64
+
65
+ <?php else: ?>
66
+ <div class="printful-latest-orders">
67
+ <p><?php esc_html_e('Once your store gets some Printful product orders, they will be shown here!', 'printful'); ?></p>
68
+ </div>
69
  <?php endif; ?>
includes/templates/personalize-button.php CHANGED
@@ -1,12 +1,12 @@
1
- <?php
2
- /**
3
- * @var string $pfc_button_color
4
- * @var string $site_url
5
- * @var string $pfc_button_text
6
- */
7
- ?>
8
- <a class="button"
9
- style="background-color: <?php esc_attr_e($pfc_button_color); ?>"
10
- onclick="Printful_Product_Customizer.onCustomizeClick( '<?php echo esc_url($site_url); ?>')">
11
- <?php esc_html_e($pfc_button_text, 'printful'); ?>
12
  </a>
1
+ <?php
2
+ /**
3
+ * @var string $pfc_button_color
4
+ * @var string $site_url
5
+ * @var string $pfc_button_text
6
+ */
7
+ ?>
8
+ <a class="button"
9
+ style="background-color: <?php esc_attr_e($pfc_button_color); ?>"
10
+ onclick="Printful_Product_Customizer.onCustomizeClick( '<?php echo esc_url($site_url); ?>')">
11
+ <?php esc_html_e($pfc_button_text, 'printful'); ?>
12
  </a>
includes/templates/setting-submit.php CHANGED
@@ -1,24 +1,24 @@
1
- <?php
2
- /**
3
- * @var bool $disabled
4
- */
5
- ?>
6
- <p class="printful-submit">
7
- <input name="save" class="button-primary woocommerce-save-button <?php if($disabled) { echo 'disabled'; } ?>" type="submit" value="<?php esc_attr_e('Save changes', 'printful'); ?>" <?php if($disabled) { echo 'disabled'; } ?>/>
8
- <input type="hidden" id="_wpnonce" name="_wpnonce" value="<?php echo esc_attr($nonce); ?>">
9
- <?php wp_referer_field(true); ?>
10
- <span class="loader-wrap">
11
- <img src="<?php echo esc_url( admin_url( 'images/spinner-2x.gif' ) ) ?>" class="loader" width="20px" height="20px" alt="loader"/>
12
- <span class="pass">
13
- <span class="dashicons dashicons-yes"></span>
14
- <?php esc_html_e('Saved successfully', 'printful'); ?>
15
- </span>
16
- <span class="fail">
17
- </span>
18
- </span>
19
- </p>
20
- <script type="text/javascript">
21
- jQuery(document).ready(function () {
22
- Printful_Settings.init_submit();
23
- });
24
  </script>
1
+ <?php
2
+ /**
3
+ * @var bool $disabled
4
+ */
5
+ ?>
6
+ <p class="printful-submit">
7
+ <input name="save" class="button-primary woocommerce-save-button <?php if($disabled) { echo 'disabled'; } ?>" type="submit" value="<?php esc_attr_e('Save changes', 'printful'); ?>" <?php if($disabled) { echo 'disabled'; } ?>/>
8
+ <input type="hidden" id="_wpnonce" name="_wpnonce" value="<?php echo esc_attr($nonce); ?>">
9
+ <?php wp_referer_field(true); ?>
10
+ <span class="loader-wrap">
11
+ <img src="<?php echo esc_url( admin_url( 'images/spinner-2x.gif' ) ) ?>" class="loader" width="20px" height="20px" alt="loader"/>
12
+ <span class="pass">
13
+ <span class="dashicons dashicons-yes"></span>
14
+ <?php esc_html_e('Saved successfully', 'printful'); ?>
15
+ </span>
16
+ <span class="fail">
17
+ </span>
18
+ </span>
19
+ </p>
20
+ <script type="text/javascript">
21
+ jQuery(document).ready(function () {
22
+ Printful_Settings.init_submit();
23
+ });
24
  </script>
includes/templates/shipping-notification.php CHANGED
@@ -1,4 +1,4 @@
1
- <div class="printful-setting-group">
2
- <h2><?php esc_html_e('Printful Shipping', 'printful'); ?></h2>
3
- <p><?php esc_html_e('To enable/disable Printful shipping for your store go to', 'printful'); ?> <a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&section=printful_shipping' ) ); ?>"><?php esc_html_e('WooCommerce Shipping settings', 'printful'); ?></a>.</p>
4
  </div>
1
+ <div class="printful-setting-group">
2
+ <h2><?php esc_html_e('Printful Shipping', 'printful'); ?></h2>
3
+ <p><?php esc_html_e('To enable/disable Printful shipping for your store go to', 'printful'); ?> <a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&section=printful_shipping' ) ); ?>"><?php esc_html_e('WooCommerce Shipping settings', 'printful'); ?></a>.</p>
4
  </div>
includes/templates/stats.php CHANGED
@@ -1,44 +1,44 @@
1
- <div class="printful-stats">
2
- <div class="printful-stats-item">
3
- <h4><?php echo esc_html(get_woocommerce_currency_symbol($stats['currency'])) . ' ' . esc_html($stats['orders_today']['total']); ?></h4>
4
- <b>
5
- <?php
6
- echo esc_html($stats['orders_today']['orders']);
7
- echo ' ' . _n('ORDER', 'ORDERS', $stats['orders_today']['orders'], 'printful' );
8
- ?>
9
- </b>
10
- <?php esc_html_e('today', 'printful'); ?>
11
- </div>
12
- <div class="printful-stats-item">
13
- <h4>
14
- <?php echo esc_html(get_woocommerce_currency_symbol($stats['currency'])) . ' ' . esc_html($stats['orders_last_7_days']['total']); ?>
15
- <?php echo '<span class="dashicons dashicons-arrow-' . esc_attr($stats['orders_last_7_days']['trend']) .'-alt"></span>'; ?>
16
- </h4>
17
- <b>
18
- <?php
19
- echo esc_html($stats['orders_last_7_days']['orders']);
20
- echo ' ' . _n( 'ORDER', 'ORDERS', $stats['orders_last_7_days']['orders'], 'printful' );
21
- ?>
22
- </b>
23
- <?php esc_html_e('last 7 days', 'printful'); ?>
24
- </div>
25
- <div class="printful-stats-item">
26
- <h4>
27
- <?php echo esc_html(get_woocommerce_currency_symbol($stats['currency'])) . ' ' . esc_html($stats['orders_last_28_days']['total']); ?>
28
- <?php echo '<span class="dashicons dashicons-arrow-' . esc_attr($stats['orders_last_28_days']['trend']) .'-alt"></span>'; ?>
29
- </h4>
30
- <b>
31
- <?php
32
- echo esc_html($stats['orders_last_28_days']['orders']);
33
- echo ' ' . _n( 'ORDER', 'ORDERS', $stats['orders_last_28_days']['orders'], 'printful' );
34
- ?>
35
- </b> <?php esc_html_e('last 28 days', 'printful'); ?>
36
- </div>
37
- <div class="printful-stats-item">
38
- <h4>
39
- <?php echo esc_html(get_woocommerce_currency_symbol($stats['currency'])) . ' ' . esc_attr($stats['profit_last_28_days']); ?>
40
- <?php echo '<span class="dashicons dashicons-arrow-' . esc_attr($stats['profit_trend_last_28_days']) .'-alt"></span>'; ?>
41
- </h4>
42
- <b><?php esc_html_e('PROFIT', 'printful'); ?></b> <?php esc_html_e('last 28 days', 'printful'); ?>
43
- </div>
44
  </div>
1
+ <div class="printful-stats">
2
+ <div class="printful-stats-item">
3
+ <h4><?php echo esc_html(get_woocommerce_currency_symbol($stats['currency'])) . ' ' . esc_html($stats['orders_today']['total']); ?></h4>
4
+ <b>
5
+ <?php
6
+ echo esc_html($stats['orders_today']['orders']);
7
+ echo ' ' . _n('ORDER', 'ORDERS', $stats['orders_today']['orders'], 'printful' );
8
+ ?>
9
+ </b>
10
+ <?php esc_html_e('today', 'printful'); ?>
11
+ </div>
12
+ <div class="printful-stats-item">
13
+ <h4>
14
+ <?php echo esc_html(get_woocommerce_currency_symbol($stats['currency'])) . ' ' . esc_html($stats['orders_last_7_days']['total']); ?>
15
+ <?php echo '<span class="dashicons dashicons-arrow-' . esc_attr($stats['orders_last_7_days']['trend']) .'-alt"></span>'; ?>
16
+ </h4>
17
+ <b>
18
+ <?php
19
+ echo esc_html($stats['orders_last_7_days']['orders']);
20
+ echo ' ' . _n( 'ORDER', 'ORDERS', $stats['orders_last_7_days']['orders'], 'printful' );
21
+ ?>
22
+ </b>
23
+ <?php esc_html_e('last 7 days', 'printful'); ?>
24
+ </div>
25
+ <div class="printful-stats-item">
26
+ <h4>
27
+ <?php echo esc_html(get_woocommerce_currency_symbol($stats['currency'])) . ' ' . esc_html($stats['orders_last_28_days']['total']); ?>
28
+ <?php echo '<span class="dashicons dashicons-arrow-' . esc_attr($stats['orders_last_28_days']['trend']) .'-alt"></span>'; ?>
29
+ </h4>
30
+ <b>
31
+ <?php
32
+ echo esc_html($stats['orders_last_28_days']['orders']);
33
+ echo ' ' . _n( 'ORDER', 'ORDERS', $stats['orders_last_28_days']['orders'], 'printful' );
34
+ ?>
35
+ </b> <?php esc_html_e('last 28 days', 'printful'); ?>
36
+ </div>
37
+ <div class="printful-stats-item">
38
+ <h4>
39
+ <?php echo esc_html(get_woocommerce_currency_symbol($stats['currency'])) . ' ' . esc_attr($stats['profit_last_28_days']); ?>
40
+ <?php echo '<span class="dashicons dashicons-arrow-' . esc_attr($stats['profit_trend_last_28_days']) .'-alt"></span>'; ?>
41
+ </h4>
42
+ <b><?php esc_html_e('PROFIT', 'printful'); ?></b> <?php esc_html_e('last 28 days', 'printful'); ?>
43
+ </div>
44
  </div>
includes/templates/status-report.php CHANGED
@@ -1,23 +1,23 @@
1
- <div class="support-report-wrap">
2
- <p>
3
- <?php esc_html_e('Copy the box content below and add it to your support message', 'printful'); ?>
4
- <br/>
5
- <?php esc_html_e('Note: this status report may not include an error log. Contact your hosting provider if you need help with acquiring error logs.'); ?>
6
- </p>
7
- <textarea class="support-report"><?php echo esc_html($status_report); ?></textarea>
8
- <button class="button button-primary button-large support-report-btn"><?php esc_html_e('Copy', 'printful'); ?></button>
9
- <script type="text/javascript">
10
- var copyTextareaBtn = document.querySelector('.support-report-btn');
11
-
12
- copyTextareaBtn.addEventListener('click', function() {
13
- var copyTextarea = document.querySelector('.support-report');
14
- copyTextarea.select();
15
-
16
- try {
17
- document.execCommand('copy');
18
- } catch (err) {
19
- //do nothing
20
- }
21
- });
22
- </script>
23
  </div>
1
+ <div class="support-report-wrap">
2
+ <p>
3
+ <?php esc_html_e('Copy the box content below and add it to your support message', 'printful'); ?>
4
+ <br/>
5
+ <?php esc_html_e('Note: this status report may not include an error log. Contact your hosting provider if you need help with acquiring error logs.'); ?>
6
+ </p>
7
+ <textarea class="support-report"><?php echo esc_html($status_report); ?></textarea>
8
+ <button class="button button-primary button-large support-report-btn"><?php esc_html_e('Copy', 'printful'); ?></button>
9
+ <script type="text/javascript">
10
+ var copyTextareaBtn = document.querySelector('.support-report-btn');
11
+
12
+ copyTextareaBtn.addEventListener('click', function() {
13
+ var copyTextarea = document.querySelector('.support-report');
14
+ copyTextarea.select();
15
+
16
+ try {
17
+ document.execCommand('copy');
18
+ } catch (err) {
19
+ //do nothing
20
+ }
21
+ });
22
+ </script>
23
  </div>
includes/templates/support-info.php CHANGED
@@ -1,27 +1,27 @@
1
- <div class="support-info-wrap">
2
-
3
- <div class="support-info-block">
4
- <h3><?php esc_html_e('Need help? Get in touch!', 'printful') ?></h3>
5
- <p><?php esc_html_e('Email, call, text, or visit us. We\'ve got support teams in the USA and Europe to make sure we\'re there when you need us.', 'printful') ?><br/><?php esc_html_e('We\'d love to hear from you.', 'printful') ?></p>
6
- <div class="btn-wrap">
7
- <a href="<?php echo esc_url(Printful_Base::get_printful_host()); ?>contacts" class="button button-primary button-large" target="_blank"><?php esc_html_e('Contact support', 'printful') ?></a>
8
- </div>
9
- </div>
10
-
11
- <div class="support-info-block">
12
- <h3><?php esc_html_e('Read our FAQs', 'printful') ?></h3>
13
- <p><?php esc_html_e('Getting started made easy – read the FAQs to jumpstart your business.', 'printful') ?><br/><?php esc_html_e('Whether you\'re a video tutorial fan or prefer the written answers – we\'ve got it covered!', 'printful') ?></p>
14
- <div class="btn-wrap">
15
- <a href="<?php echo esc_url(Printful_Base::get_printful_host()); ?>faq" class="button button-primary button-large" target="_blank"><?php esc_html_e('See Printful FAQ', 'printful') ?></a>
16
- </div>
17
- </div>
18
-
19
- <div class="support-info-block">
20
- <h3><?php esc_html_e('Integration help', 'printful') ?></h3>
21
- <p><?php esc_html_e('Are you experiencing technical issues? Solve them on your own by reading these helpful guides and video tutorials.', 'printful') ?></p>
22
- <div class="btn-wrap">
23
- <a href="<?php echo esc_url(Printful_Base::get_printful_host()); ?>faq/integrations/woocommerce" class="button button-primary button-large" target="_blank"><?php esc_html_e('Integration help', 'printful') ?></a>
24
- </div>
25
- </div>
26
-
27
  </div>
1
+ <div class="support-info-wrap">
2
+
3
+ <div class="support-info-block">
4
+ <h3><?php esc_html_e('Need help? Get in touch!', 'printful') ?></h3>
5
+ <p><?php esc_html_e('Email, call, text, or visit us. We\'ve got support teams in the USA and Europe to make sure we\'re there when you need us.', 'printful') ?><br/><?php esc_html_e('We\'d love to hear from you.', 'printful') ?></p>
6
+ <div class="btn-wrap">
7
+ <a href="<?php echo esc_url(Printful_Base::get_printful_host()); ?>contacts" class="button button-primary button-large" target="_blank"><?php esc_html_e('Contact support', 'printful') ?></a>
8
+ </div>
9
+ </div>
10
+
11
+ <div class="support-info-block">
12
+ <h3><?php esc_html_e('Read our FAQs', 'printful') ?></h3>
13
+ <p><?php esc_html_e('Getting started made easy – read the FAQs to jumpstart your business.', 'printful') ?><br/><?php esc_html_e('Whether you\'re a video tutorial fan or prefer the written answers – we\'ve got it covered!', 'printful') ?></p>
14
+ <div class="btn-wrap">
15
+ <a href="<?php echo esc_url(Printful_Base::get_printful_host()); ?>faq" class="button button-primary button-large" target="_blank"><?php esc_html_e('See Printful FAQ', 'printful') ?></a>
16
+ </div>
17
+ </div>
18
+
19
+ <div class="support-info-block">
20
+ <h3><?php esc_html_e('Integration help', 'printful') ?></h3>
21
+ <p><?php esc_html_e('Are you experiencing technical issues? Solve them on your own by reading these helpful guides and video tutorials.', 'printful') ?></p>
22
+ <div class="btn-wrap">
23
+ <a href="<?php echo esc_url(Printful_Base::get_printful_host()); ?>faq/integrations/woocommerce" class="button button-primary button-large" target="_blank"><?php esc_html_e('Integration help', 'printful') ?></a>
24
+ </div>
25
+ </div>
26
+
27
  </div>
printful-shipping.php CHANGED
@@ -3,13 +3,13 @@
3
  Plugin Name: Printful Integration for WooCommerce
4
  Plugin URI: https://wordpress.org/plugins/printful-shipping-for-woocommerce/
5
  Description: Calculate correct shipping and tax rates for your Printful-Woocommerce integration.
6
- Version: 2.1.19
7
  Author: Printful
8
  Author URI: http://www.printful.com
9
  License: GPL2 http://www.gnu.org/licenses/gpl-2.0.html
10
  Text Domain: printful
11
  WC requires at least: 3.0.0
12
- WC tested up to: 4.9
13
  */
14
 
15
  if ( ! defined( 'ABSPATH' ) ) exit;
@@ -20,7 +20,7 @@ if ( ! defined( 'PF_PLUGIN_FILE' ) ) {
20
 
21
  class Printful_Base {
22
 
23
- const VERSION = '2.1.19';
24
  const PF_HOST = 'https://www.printful.com/';
25
  const PF_API_HOST = 'https://api.printful.com/';
26
 
3
  Plugin Name: Printful Integration for WooCommerce
4
  Plugin URI: https://wordpress.org/plugins/printful-shipping-for-woocommerce/
5
  Description: Calculate correct shipping and tax rates for your Printful-Woocommerce integration.
6
+ Version: 2.1.20
7
  Author: Printful
8
  Author URI: http://www.printful.com
9
  License: GPL2 http://www.gnu.org/licenses/gpl-2.0.html
10
  Text Domain: printful
11
  WC requires at least: 3.0.0
12
+ WC tested up to: 5.0
13
  */
14
 
15
  if ( ! defined( 'ABSPATH' ) ) exit;
20
 
21
  class Printful_Base {
22
 
23
+ const VERSION = '2.1.20';
24
  const PF_HOST = 'https://www.printful.com/';
25
  const PF_API_HOST = 'https://api.printful.com/';
26
 
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: woocommerce, printful, drop shipping, shipping, shipping rates, fulfillmen
4
  Requires at least: 5.3
5
  Tested up to: 5.6
6
  Requires PHP: 5.6
7
- Stable tag: 2.1.19
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -64,6 +64,9 @@ Go to https://www.printful.com/dashboard/store , select your WooCommerce store,
64
 
65
  == Upgrade Notice ==
66
 
 
 
 
67
  = 2.1.19 =
68
  Woocommerce compatibility raised to 4.9
69
 
@@ -198,6 +201,9 @@ First release
198
 
199
  == Changelog ==
200
 
 
 
 
201
  = 2.1.19 =
202
  * Woocommerce compatibility raised to 4.9
203
 
4
  Requires at least: 5.3
5
  Tested up to: 5.6
6
  Requires PHP: 5.6
7
+ Stable tag: 2.1.20
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
64
 
65
  == Upgrade Notice ==
66
 
67
+ = 2.1.20 =
68
+ Woocommerce compatibility raised to 5.0
69
+
70
  = 2.1.19 =
71
  Woocommerce compatibility raised to 4.9
72
 
201
 
202
  == Changelog ==
203
 
204
+ = 2.1.20 =
205
+ * Woocommerce compatibility raised to 5.0
206
+
207
  = 2.1.19 =
208
  * Woocommerce compatibility raised to 4.9
209