PB SEO Friendly Images - Version 4.0.3

Version Description

  • Bugfix & Optimization
Download this release

Release Info

Developer PascalBajorat
Plugin Icon 128x128 PB SEO Friendly Images
Version 4.0.3
Comparing to
See all releases

Code changes from version 3.1.0 to 4.0.3

Files changed (52) hide show
  1. assets/css/admin.css +227 -0
  2. assets/css/admin.css.map +1 -0
  3. assets/css/admin.scss +271 -0
  4. {css → assets/css}/lazy.css +0 -0
  5. assets/img/bajorat-media-white.svg +1 -0
  6. assets/img/check.png +0 -0
  7. {img → assets/img}/code.png +0 -0
  8. {img → assets/img}/icon.png +0 -0
  9. {img → assets/img}/mailcrypt.png +0 -0
  10. {img → assets/img}/warning.png +0 -0
  11. {js → assets/js}/unveil.js +0 -0
  12. css/admin.css +0 -183
  13. css/admin.css.map +0 -7
  14. css/admin.scss +0 -259
  15. img/primusnote.png +0 -0
  16. inc/pbSettingsFramework.php +0 -206
  17. inc/pbSettingsFramework_2.php +220 -0
  18. inc/pbcockpitnotice.php +328 -0
  19. inc/pbsfi_admin_interface.php +598 -0
  20. inc/pbsfi_cache.php +115 -0
  21. inc/pbsfi_frontend.php +138 -0
  22. inc/pbsfi_optimizer.php +519 -0
  23. inc/pbsfi_upgrade.php +103 -0
  24. inc/settings.php +0 -617
  25. index.php +2 -0
  26. lang/pb-seo-friendly-images-de_DE.mo +0 -0
  27. lang/pb-seo-friendly-images-de_DE.po +300 -227
  28. lang/pb-seo-friendly-images-de_DE_formal.mo +0 -0
  29. lang/pb-seo-friendly-images-de_DE_formal.po +0 -614
  30. lang/pb-seo-friendly-images.pot +267 -188
  31. pb-seo-friendly-images.php +274 -463
  32. plugin-update-checker/css/puc-debug-bar.css +0 -62
  33. plugin-update-checker/debug-bar-panel.php +0 -146
  34. plugin-update-checker/debug-bar-plugin.php +0 -102
  35. plugin-update-checker/github-checker.php +0 -459
  36. plugin-update-checker/js/debug-bar.js +0 -52
  37. plugin-update-checker/languages/plugin-update-checker-de_DE.mo +0 -0
  38. plugin-update-checker/languages/plugin-update-checker-de_DE.po +0 -38
  39. plugin-update-checker/languages/plugin-update-checker-fa_IR.mo +0 -0
  40. plugin-update-checker/languages/plugin-update-checker-fa_IR.po +0 -38
  41. plugin-update-checker/languages/plugin-update-checker-fr_FR.mo +0 -0
  42. plugin-update-checker/languages/plugin-update-checker-fr_FR.po +0 -38
  43. plugin-update-checker/languages/plugin-update-checker-hu_HU.mo +0 -0
  44. plugin-update-checker/languages/plugin-update-checker-hu_HU.po +0 -41
  45. plugin-update-checker/languages/plugin-update-checker.pot +0 -39
  46. plugin-update-checker/license.txt +0 -7
  47. plugin-update-checker/plugin-update-checker.php +0 -1663
  48. plugin-update-checker/vendor/Parsedown.php +0 -1538
  49. plugin-update-checker/vendor/ParsedownLegacy.php +0 -1535
  50. plugin-update-checker/vendor/readme-parser.php +0 -331
  51. readme.txt +16 -3
  52. templates/options_page.php +116 -0
assets/css/admin.css ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url("https://fonts.googleapis.com/css?family=Open+Sans:400,600,700");
2
+ .pb-wp-app-wrapper {
3
+ box-sizing: border-box;
4
+ font-family: "Open Sans", sans-serif;
5
+ font-size: 14px;
6
+ padding: 10px;
7
+ }
8
+ .pb-wp-app-wrapper * {
9
+ box-sizing: border-box;
10
+ }
11
+ .pb-wp-app-wrapper p {
12
+ font-size: 14px;
13
+ }
14
+ .pb-wp-app-wrapper .pro-section {
15
+ font-size: 26px;
16
+ border-top: 1px solid #aaa;
17
+ position: relative;
18
+ text-align: center;
19
+ margin: 55px 0 20px 0;
20
+ }
21
+ .pb-wp-app-wrapper .pro-section span {
22
+ top: -12px;
23
+ position: relative;
24
+ background: #f1f1f1;
25
+ padding: 0 15px;
26
+ }
27
+ .pb-wp-app-wrapper .pb-wrapper {
28
+ display: flex;
29
+ }
30
+ .pb-wp-app-wrapper .pb-wrapper .pb-main {
31
+ width: calc(100% - 300px);
32
+ padding-right: 30px;
33
+ max-width: 1024px;
34
+ }
35
+ .pb-wp-app-wrapper .pb-wrapper .pb-main .pb-custom-message {
36
+ margin-bottom: 0;
37
+ -moz-box-shadow: none;
38
+ -webkit-box-shadow: none;
39
+ box-shadow: none;
40
+ }
41
+ .pb-wp-app-wrapper .pb-wrapper .pb-sidebar {
42
+ width: 300px;
43
+ padding-top: 30px;
44
+ }
45
+ .pb-wp-app-wrapper .pb-wrapper .pb-sidebar h3:first-child {
46
+ margin-top: 0;
47
+ color: #888;
48
+ }
49
+ .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box, .pb-wp-app-wrapper .pb-wrapper .pb-support-box {
50
+ background: #fff;
51
+ padding: 15px 15px;
52
+ opacity: 0.8;
53
+ margin-bottom: 35px;
54
+ -webkit-transition: opacity 0.5s;
55
+ -moz-transition: opacity 0.5s;
56
+ transition: opacity 0.5s;
57
+ }
58
+ .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box:hover, .pb-wp-app-wrapper .pb-wrapper .pb-support-box:hover {
59
+ opacity: 1;
60
+ }
61
+ .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box h4, .pb-wp-app-wrapper .pb-wrapper .pb-support-box h4 {
62
+ margin-top: 0;
63
+ display: flex;
64
+ }
65
+ .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box h4 .icon, .pb-wp-app-wrapper .pb-wrapper .pb-support-box h4 .icon {
66
+ width: 50px;
67
+ height: auto;
68
+ }
69
+ .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box h4 .icon img, .pb-wp-app-wrapper .pb-wrapper .pb-support-box h4 .icon img {
70
+ max-width: 100%;
71
+ height: auto;
72
+ }
73
+ .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box h4 .text, .pb-wp-app-wrapper .pb-wrapper .pb-support-box h4 .text {
74
+ padding: 7px 0 0 10px;
75
+ width: calc(100% - 50px);
76
+ display: flex;
77
+ height: 50px;
78
+ }
79
+ .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box p:last-child, .pb-wp-app-wrapper .pb-wrapper .pb-support-box p:last-child {
80
+ margin-bottom: 0;
81
+ }
82
+ .pb-wp-app-wrapper .pb-section-title {
83
+ color: #23282d;
84
+ font-weight: 600;
85
+ background: #fff;
86
+ padding: 15px 25px;
87
+ margin-bottom: 0;
88
+ display: inline-block;
89
+ }
90
+ .pb-wp-app-wrapper h3.pb-section-title {
91
+ padding-top: 10px;
92
+ padding-bottom: 10px;
93
+ font-size: 16px;
94
+ font-weight: 400;
95
+ }
96
+ .pb-wp-app-wrapper .pb-section-wrap, .pb-wp-app-wrapper .form-table {
97
+ background: #fff;
98
+ padding: 25px;
99
+ margin-bottom: 25px;
100
+ max-width: 1024px;
101
+ }
102
+ .pb-wp-app-wrapper .pb-section-wrap.no-margin-bottom, .pb-wp-app-wrapper .form-table.no-margin-bottom {
103
+ margin-bottom: 0;
104
+ padding-bottom: 5px;
105
+ }
106
+ .pb-wp-app-wrapper .pb-section-wrap p:first-child, .pb-wp-app-wrapper .form-table p:first-child {
107
+ margin-top: 0;
108
+ }
109
+ .pb-wp-app-wrapper .pb-section-wrap p:last-child, .pb-wp-app-wrapper .form-table p:last-child {
110
+ margin-bottom: 0;
111
+ }
112
+ .pb-wp-app-wrapper .pb-section-wrap input[type=text], .pb-wp-app-wrapper .pb-section-wrap textarea, .pb-wp-app-wrapper .pb-section-wrap select, .pb-wp-app-wrapper .form-table input[type=text], .pb-wp-app-wrapper .form-table textarea, .pb-wp-app-wrapper .form-table select {
113
+ box-sizing: border-box;
114
+ width: 100%;
115
+ margin-left: 0;
116
+ border-radius: 4px;
117
+ border: none;
118
+ box-shadow: none;
119
+ background: #F1F5F9;
120
+ padding: 13px;
121
+ font-size: 14px;
122
+ color: #32373C;
123
+ height: auto;
124
+ font-family: "Open Sans", sans-serif;
125
+ font-size: 14px;
126
+ margin-bottom: 0;
127
+ -webkit-transition: background 0.5s;
128
+ -moz-transition: background 0.5s;
129
+ transition: background 0.5s;
130
+ }
131
+ .pb-wp-app-wrapper .pb-section-wrap input[type=text]:focus, .pb-wp-app-wrapper .pb-section-wrap textarea:focus, .pb-wp-app-wrapper .pb-section-wrap select:focus, .pb-wp-app-wrapper .form-table input[type=text]:focus, .pb-wp-app-wrapper .form-table textarea:focus, .pb-wp-app-wrapper .form-table select:focus {
132
+ background-color: #E0E5EA;
133
+ }
134
+ .pb-wp-app-wrapper .pb-section-wrap input:disabled, .pb-wp-app-wrapper .pb-section-wrap textarea:disabled, .pb-wp-app-wrapper .pb-section-wrap select:disabled, .pb-wp-app-wrapper .form-table input:disabled, .pb-wp-app-wrapper .form-table textarea:disabled, .pb-wp-app-wrapper .form-table select:disabled {
135
+ cursor: not-allowed;
136
+ opacity: 0.75;
137
+ }
138
+ .pb-wp-app-wrapper .pb-section-wrap select, .pb-wp-app-wrapper .form-table select {
139
+ height: 39px;
140
+ padding: 3px 7px;
141
+ }
142
+ .pb-wp-app-wrapper .pb-custom-message ~ .no-margin-bottom {
143
+ padding-bottom: 25px !important;
144
+ }
145
+ .pb-wp-app-wrapper .button.button-primary {
146
+ text-shadow: none;
147
+ -webkit-transition: background 0.5s;
148
+ -moz-transition: background 0.5s;
149
+ transition: background 0.5s;
150
+ color: #FFF;
151
+ cursor: pointer;
152
+ background-color: #17a8e3;
153
+ -webkit-box-shadow: none;
154
+ -moz-box-shadow: none;
155
+ box-shadow: none;
156
+ border: none;
157
+ padding: 0 20px;
158
+ font-size: 18px;
159
+ font-weight: 300;
160
+ height: 53px;
161
+ line-height: 53px;
162
+ display: inline-block;
163
+ text-decoration: none;
164
+ -moz-border-radius: 3px;
165
+ -webkit-border-radius: 3px;
166
+ border-radius: 3px;
167
+ position: relative;
168
+ }
169
+ .pb-wp-app-wrapper .button.button-primary:hover {
170
+ background-color: #1286b5;
171
+ }
172
+
173
+ .pb-custom-message {
174
+ justify-content: space-between;
175
+ font-family: "Open Sans", sans-serif;
176
+ box-sizing: border-box;
177
+ border-radius: 4px;
178
+ -ms-flex-align: center;
179
+ align-items: center;
180
+ background: #fff url("../img/icon.png") no-repeat left;
181
+ background-size: contain;
182
+ border: 0;
183
+ display: -ms-flexbox;
184
+ display: flex;
185
+ min-height: 100px;
186
+ padding: 15px 35px 15px 135px;
187
+ -ms-flex-pack: justify;
188
+ max-width: 1024px;
189
+ margin-bottom: 25px;
190
+ -moz-box-shadow: 2px 2px 6px 1px rgba(55, 55, 55, 0.2);
191
+ -webkit-box-shadow: 2px 2px 6px 1px rgba(55, 55, 55, 0.2);
192
+ box-shadow: 2px 2px 6px 1px rgba(55, 55, 55, 0.2);
193
+ }
194
+ .pb-custom-message p {
195
+ font-size: 14px;
196
+ }
197
+ .pb-custom-message.code {
198
+ background: #fff url("../img/code.png") no-repeat left;
199
+ background-size: contain;
200
+ -moz-box-shadow: none;
201
+ -webkit-box-shadow: none;
202
+ box-shadow: none;
203
+ }
204
+ .pb-custom-message.info {
205
+ background: #fff url("../img/warning.png") no-repeat left;
206
+ background-size: contain;
207
+ }
208
+ .pb-custom-message .pb-btn {
209
+ cursor: pointer;
210
+ text-decoration: none;
211
+ white-space: nowrap;
212
+ border: 0;
213
+ border-radius: 4px;
214
+ background-color: #17a8e3;
215
+ color: #fff;
216
+ padding: 15px 35px;
217
+ text-transform: uppercase;
218
+ margin-left: 20px;
219
+ -webkit-transition: background 0.5s;
220
+ -moz-transition: background 0.5s;
221
+ transition: background 0.5s;
222
+ }
223
+ .pb-custom-message .pb-btn:hover {
224
+ background-color: #1286b5;
225
+ }
226
+
227
+ /*# sourceMappingURL=admin.css.map */
assets/css/admin.css.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sourceRoot":"","sources":["admin.scss"],"names":[],"mappings":"AAAQ;AAMR;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAIJ;EACE;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;;AAGF;EACE;EACA;;AACA;EACE;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;;AAIJ;EACE;;AASN;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAKF;EACE;EACA;;AAIJ;EACE;EACA;;AAKJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAKN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE","file":"admin.css"}
assets/css/admin.scss ADDED
@@ -0,0 +1,271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url('https://fonts.googleapis.com/css?family=Open+Sans:400,600,700');
2
+
3
+ .settings_page_pb-seo-friendly-images #wpcontent {
4
+ //background: #F1F5F9;
5
+ }
6
+
7
+ .pb-wp-app-wrapper {
8
+ box-sizing: border-box;
9
+ font-family: 'Open Sans', sans-serif;
10
+ font-size: 14px;
11
+ padding: 10px;
12
+
13
+ * {
14
+ box-sizing: border-box;
15
+ }
16
+
17
+ p {
18
+ font-size: 14px;
19
+ }
20
+
21
+ .pro-section {
22
+ font-size: 26px;
23
+ border-top: 1px solid #aaa;
24
+ position: relative;
25
+ text-align: center;
26
+ margin: 55px 0 20px 0;
27
+
28
+ span {
29
+ top: -12px;
30
+ position: relative;
31
+ background: #f1f1f1;
32
+ padding: 0 15px;
33
+ }
34
+ }
35
+
36
+ .pb-wrapper {
37
+ display: flex;
38
+
39
+ .pb-main {
40
+ width: calc(100% - 300px);
41
+ padding-right: 30px;
42
+ max-width: 1024px;
43
+
44
+ .pb-custom-message {
45
+ margin-bottom: 0;
46
+ -moz-box-shadow: none;
47
+ -webkit-box-shadow: none;
48
+ box-shadow: none;
49
+ }
50
+ }
51
+
52
+ .pb-sidebar {
53
+ width: 300px;
54
+ padding-top: 30px;
55
+
56
+ h3:first-child {
57
+ margin-top: 0;
58
+ color: #888;
59
+ }
60
+ }
61
+
62
+ .pb-plugin-box, .pb-support-box {
63
+ background: #fff;
64
+ padding: 15px 15px;
65
+ opacity: .8;
66
+ margin-bottom: 35px;
67
+ -webkit-transition: opacity .5s;
68
+ -moz-transition: opacity .5s;
69
+ transition: opacity .5s;
70
+
71
+
72
+ &:hover {
73
+ opacity: 1;
74
+ }
75
+
76
+ h4 {
77
+ margin-top: 0;
78
+ display: flex;
79
+ .icon {
80
+ width: 50px;
81
+ height: auto;
82
+
83
+ img {
84
+ max-width: 100%;
85
+ height: auto;
86
+ }
87
+ }
88
+
89
+ .text {
90
+ padding: 7px 0 0 10px;
91
+ width: calc(100% - 50px);
92
+ display: flex;
93
+ height: 50px;
94
+ }
95
+ }
96
+
97
+ p:last-child {
98
+ margin-bottom: 0;
99
+ }
100
+
101
+ .desc {
102
+
103
+ }
104
+ }
105
+ }
106
+
107
+ .pb-section-title {
108
+ color: #23282d;
109
+ font-weight: 600;
110
+ background: #fff;
111
+ padding: 15px 25px;
112
+ margin-bottom: 0;
113
+ display: inline-block;
114
+ }
115
+
116
+ h3.pb-section-title {
117
+ padding-top: 10px;
118
+ padding-bottom: 10px;
119
+ font-size: 16px;
120
+ font-weight: 400;
121
+ }
122
+
123
+ .pb-section-wrap, .form-table {
124
+ background: #fff;
125
+ padding: 25px;
126
+ margin-bottom: 25px;
127
+ max-width: 1024px;
128
+
129
+ &.no-margin-bottom {
130
+ margin-bottom: 0;
131
+ padding-bottom: 5px;
132
+ }
133
+
134
+ p:first-child {
135
+ margin-top: 0;
136
+ }
137
+
138
+ p:last-child {
139
+ margin-bottom: 0;
140
+ }
141
+
142
+ input[type="text"], textarea, select {
143
+ box-sizing: border-box;
144
+ width: 100%;
145
+ margin-left: 0;
146
+ border-radius: 4px;
147
+ border: none;
148
+ box-shadow: none;
149
+ background: #F1F5F9;
150
+ padding: 13px;
151
+ font-size: 14px;
152
+ color: #32373C;
153
+ height: auto;
154
+ font-family: 'Open Sans', sans-serif;
155
+ font-size: 14px;
156
+ margin-bottom: 0;
157
+ -webkit-transition: background .5s;
158
+ -moz-transition: background .5s;
159
+ transition: background .5s;
160
+
161
+ &:focus {
162
+ background-color: #E0E5EA;
163
+ }
164
+ }
165
+
166
+ input, textarea, select {
167
+ &:disabled {
168
+ cursor: not-allowed;
169
+ opacity: .75;
170
+ }
171
+ }
172
+
173
+ select {
174
+ height: 39px;
175
+ padding: 3px 7px;
176
+ }
177
+
178
+ }
179
+
180
+ .pb-custom-message ~ .no-margin-bottom {
181
+ padding-bottom: 25px !important;
182
+ }
183
+
184
+ .button.button-primary {
185
+ text-shadow: none;
186
+ -webkit-transition: background .5s;
187
+ -moz-transition: background .5s;
188
+ transition: background .5s;
189
+ color: #FFF;
190
+ cursor: pointer;
191
+ background-color: #17a8e3;
192
+ -webkit-box-shadow: none;
193
+ -moz-box-shadow: none;
194
+ box-shadow: none;
195
+ border: none;
196
+ padding: 0 20px;
197
+ font-size: 18px;
198
+ font-weight: 300;
199
+ height: 53px;
200
+ line-height: 53px;
201
+ display: inline-block;
202
+ text-decoration: none;
203
+ -moz-border-radius: 3px;
204
+ -webkit-border-radius: 3px;
205
+ border-radius: 3px;
206
+ position: relative;
207
+
208
+ &:hover {
209
+ background-color: darken(#17a8e3, 10);
210
+ }
211
+ }
212
+ }
213
+
214
+ .pb-custom-message {
215
+ justify-content: space-between;
216
+ font-family: 'Open Sans', sans-serif;
217
+ box-sizing: border-box;
218
+ border-radius: 4px;
219
+ -ms-flex-align: center;
220
+ align-items: center;
221
+ background: #fff url("../img/icon.png") no-repeat left;
222
+ background-size: contain;
223
+ border: 0;
224
+ display: -ms-flexbox;
225
+ display: flex;
226
+ min-height: 100px;
227
+ padding: 15px 35px 15px 135px;
228
+ -ms-flex-pack: justify;
229
+ max-width: 1024px;
230
+ margin-bottom: 25px;
231
+ -moz-box-shadow: 2px 2px 6px 1px rgba(55,55,55,.2);
232
+ -webkit-box-shadow: 2px 2px 6px 1px rgba(55,55,55,.2);
233
+ box-shadow: 2px 2px 6px 1px rgba(55,55,55,.2);
234
+
235
+ p {
236
+ font-size: 14px;
237
+ }
238
+
239
+ &.code {
240
+ background: #fff url("../img/code.png") no-repeat left;
241
+ background-size: contain;
242
+ -moz-box-shadow: none;
243
+ -webkit-box-shadow: none;
244
+ box-shadow: none;
245
+ }
246
+
247
+ &.info {
248
+ background: #fff url("../img/warning.png") no-repeat left;
249
+ background-size: contain;
250
+ }
251
+
252
+ .pb-btn {
253
+ cursor: pointer;
254
+ text-decoration: none;
255
+ white-space: nowrap;
256
+ border: 0;
257
+ border-radius: 4px;
258
+ background-color: #17a8e3;
259
+ color: #fff;
260
+ padding: 15px 35px;
261
+ text-transform: uppercase;
262
+ margin-left: 20px;
263
+ -webkit-transition: background .5s;
264
+ -moz-transition: background .5s;
265
+ transition: background .5s;
266
+
267
+ &:hover {
268
+ background-color: darken(#17a8e3, 10);
269
+ }
270
+ }
271
+ }
{css → assets/css}/lazy.css RENAMED
File without changes
assets/img/bajorat-media-white.svg ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 798 182" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><g id="Layer-1" serif:id="Layer 1"><path d="M197.923,91.724l0,22.794l17.773,0c9.339,0 13.557,-2.007 13.557,-10.844c0,-9.841 -4.921,-11.95 -13.355,-11.95l-17.975,0Zm0,-32.535l0,22.795l11.347,0c13.255,0 18.075,-0.803 18.075,-11.147c0,-9.539 -4.72,-11.648 -15.163,-11.648l-14.259,0Zm42.376,10.042c0,10.142 -2.711,15.765 -9.941,17.272l0,0.301c9.238,1.305 11.849,8.335 11.849,18.075c0,16.669 -8.837,20.887 -26.109,20.887c-6.828,0 -21.59,-0.301 -29.623,-0.904c-1.205,-0.1 -1.506,-0.302 -1.506,-1.406l0,-73.305c0,-1.104 0.301,-1.305 1.506,-1.406c8.033,-0.602 19.983,-0.803 26.912,-0.803c18.276,0 26.912,4.921 26.912,21.289" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M268.92,101.765c-5.321,0 -7.731,1.707 -7.731,6.729c0,5.723 2.71,7.129 10.141,7.129c2.511,0 8.034,-0.201 11.448,-1.105l0,-12.753l-13.858,0Zm26.009,-16.066l0,34.945c0,1.306 -0.201,2.309 -2.009,2.912c-5.222,1.506 -14.059,2.209 -22.594,2.209c-14.058,0 -21.188,-2.209 -21.188,-16.77c0,-12.752 6.728,-15.966 19.08,-15.966l14.56,0l0,-5.222c0,-5.623 -3.314,-8.033 -11.347,-8.033l-16.469,0c-1.205,0 -1.506,-0.301 -1.506,-1.506l0,-6.126c0,-1.205 0.401,-1.405 1.406,-1.606c6.025,-1.105 11.448,-1.306 16.569,-1.306c17.674,0 23.498,5.624 23.498,16.469" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M320.235,53.866c0,4.418 -2.61,6.929 -7.229,6.929c-4.72,0 -7.332,-2.511 -7.332,-6.929c0,-4.418 2.612,-6.929 7.332,-6.929c4.619,0 7.229,2.511 7.229,6.929m-2.711,15.866c1.004,0 1.506,0.502 1.506,1.507l0,64.066c0,9.539 -5.824,10.443 -12.552,10.443c-1.507,0 -5.723,-0.301 -6.828,-0.602c-1.105,-0.201 -1.507,-0.703 -1.507,-1.808l0,-6.727c0,-1.005 0.603,-1.407 1.607,-1.407l2.41,0c4.218,0 4.72,-0.502 4.72,-4.418l0,-59.547c0,-1.005 0.501,-1.507 1.506,-1.507l9.138,0Z" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M341.423,97.547c0,14.159 1.507,17.674 12.251,17.674c10.745,0 12.251,-3.515 12.251,-17.674c0,-14.258 -1.506,-17.773 -12.251,-17.773c-10.744,0 -12.251,3.515 -12.251,17.773m36.753,0c0,22.595 -4.418,28.218 -24.502,28.218c-20.083,0 -24.401,-5.623 -24.401,-28.218c0,-22.693 4.318,-28.317 24.401,-28.317c20.084,0 24.502,5.624 24.502,28.317" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M417.442,70.335c1.004,0.301 1.606,0.703 1.606,1.808l0,6.125c0,1.105 -0.602,1.607 -1.707,1.506l-9.137,0c-6.026,0 -7.833,1.004 -7.833,5.423l0,38.56c0,1.004 -0.502,1.506 -1.506,1.506l-9.138,0c-1.005,0 -1.507,-0.502 -1.507,-1.506l0,-41.673c0,-11.95 9.54,-12.853 16.971,-12.853c2.611,0 9.54,0.301 12.251,1.104" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M443.55,101.765c-5.321,0 -7.731,1.707 -7.731,6.729c0,5.723 2.71,7.129 10.141,7.129c2.511,0 8.034,-0.201 11.448,-1.105l0,-12.753l-13.858,0Zm26.009,-16.066l0,34.945c0,1.306 -0.201,2.309 -2.009,2.912c-5.222,1.506 -14.059,2.209 -22.594,2.209c-14.058,0 -21.188,-2.209 -21.188,-16.77c0,-12.752 6.728,-15.966 19.08,-15.966l14.56,0l0,-5.222c0,-5.623 -3.314,-8.033 -11.347,-8.033l-16.469,0c-1.205,0 -1.506,-0.301 -1.506,-1.506l0,-6.126c0,-1.205 0.401,-1.405 1.406,-1.606c6.025,-1.105 11.448,-1.306 16.569,-1.306c17.674,0 23.498,5.624 23.498,16.469" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M494.764,54.369c1.105,-0.301 1.708,0.301 1.708,1.406l0,14.058l9.941,0c1.004,0 1.607,0.502 1.607,1.507l0,6.326c0,1.104 -0.603,1.606 -1.607,1.606l-9.941,0l0,30.627c0,4.419 1.305,5.323 6.226,5.323l4.418,0c1.205,0 1.707,0.402 1.707,1.406l0,6.627c0,1.105 -0.502,1.607 -1.506,1.807c-2.812,0.502 -5.623,0.703 -7.13,0.703c-7.832,0 -15.966,-0.201 -15.966,-12.251l0,-34.242l-5.725,0c-1.003,0 -1.606,-0.502 -1.606,-1.606l0,-6.326c0,-1.005 0.603,-1.507 1.606,-1.507l5.725,0l0,-11.548c0,-1.004 0.502,-1.406 1.405,-1.606l9.138,-2.31Z" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M609.544,50.151c0.903,0 1.405,0.402 1.506,1.406l6.225,72.401c0,0.904 -0.502,1.305 -1.304,1.305l-5.121,0c-0.804,0 -1.205,-0.401 -1.306,-1.305l-4.82,-61.154l-23.297,58.945c-0.302,0.803 -0.904,1.205 -1.808,1.205l-5.423,0c-0.903,0 -1.506,-0.402 -1.807,-1.205l-23.297,-58.945l-4.82,61.154c-0.1,0.904 -0.502,1.305 -1.305,1.305l-5.122,0c-0.803,0 -1.305,-0.401 -1.305,-1.305l6.226,-72.401c0.1,-1.004 0.602,-1.406 1.506,-1.406l5.624,0c2.108,0 2.61,1.004 3.714,3.715l23.298,60.351l23.297,-60.351c1.105,-2.711 1.607,-3.715 3.715,-3.715l5.624,0Z" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M635.355,95.138l28.619,0c-0.201,-14.862 -2.511,-18.276 -14.058,-18.276c-12.151,0 -14.361,3.615 -14.561,18.276m35.949,1.104l0,2.913c0,1.707 -0.301,2.509 -3.113,2.509l-32.836,0c0.301,13.959 2.812,17.674 14.561,17.674l15.765,0c0.803,0 1.306,0.402 1.306,1.306l0,3.113c0,0.702 -0.403,1.205 -1.205,1.305c-4.72,0.502 -10.745,0.703 -15.866,0.703c-18.176,0 -21.892,-5.523 -21.892,-27.715c0,-22.192 3.716,-27.615 21.892,-27.615c17.17,0 21.187,5.121 21.388,25.807" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M703.439,76.862c-13.857,0 -15.464,4.117 -15.464,21.087c0,17.171 1.607,21.389 14.761,21.389c4.318,0 9.239,-0.301 14.56,-1.004l0,-41.472l-13.857,0Zm19.782,-26.711c0.905,0 1.306,0.502 1.306,1.305l0,71.196c0,1.004 -0.401,1.406 -1.405,1.506c-9.24,1.406 -13.456,1.607 -20.386,1.607c-18.577,0 -22.092,-5.423 -22.092,-27.715c0,-22.192 3.515,-27.615 22.795,-27.615c5.624,0 10.243,0.201 13.857,0.603l0,-19.582c0,-0.803 0.403,-1.305 1.206,-1.305l4.719,0Z" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M744.512,70.938c0.803,0 1.306,0.502 1.306,1.306l0,51.714c0,0.904 -0.503,1.306 -1.306,1.306l-4.72,0c-0.904,0 -1.305,-0.402 -1.305,-1.306l0,-51.714c0,-0.804 0.401,-1.306 1.305,-1.306l4.72,0Zm2.31,-15.364c0,3.113 -1.607,4.82 -4.62,4.82c-3.113,0 -4.82,-1.707 -4.82,-4.82c0,-3.012 1.707,-4.619 4.82,-4.619c3.013,0 4.62,1.607 4.62,4.619" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M773.032,101.364c-6.527,0 -9.54,2.209 -9.54,8.535c0,7.432 3.313,9.54 12.753,9.54c3.113,0 10.142,-0.201 14.36,-1.305l0,-16.77l-17.573,0Zm24.803,-15.364l0,35.146c0,0.804 0.1,1.908 -1.808,2.612c-3.112,1.205 -12.451,2.007 -21.389,2.007c-13.155,0 -18.377,-3.313 -18.377,-15.866c0,-11.046 5.625,-14.861 16.771,-14.861l17.573,0l0,-7.933c0,-7.532 -5.021,-10.242 -14.862,-10.242l-13.557,0c-1.004,0 -1.305,-0.302 -1.305,-1.306l0,-2.812c0,-1.004 0.301,-1.205 1.205,-1.405c5.523,-0.804 10.042,-0.904 13.657,-0.904c13.857,0 22.092,3.916 22.092,15.564" style="fill:#7e8082;fill-rule:nonzero;"/><path d="M69.111,3.434l-56.294,32.502c-7.932,4.579 -12.817,13.042 -12.817,22.2l0,65.003c0,9.159 4.885,17.621 12.817,22.201l56.294,32.5c7.932,4.58 17.703,4.58 25.635,0l56.294,-32.5c7.931,-4.58 12.817,-13.042 12.817,-22.201l0,-65.003c0,-9.158 -4.886,-17.621 -12.817,-22.2l-56.294,-32.502c-3.966,-2.29 -8.392,-3.434 -12.818,-3.434c-4.426,0 -8.851,1.144 -12.817,3.434Z" style="fill:url(#_Linear1);fill-rule:nonzero;"/><use id="_Image2_" serif:id="_Image2" xlink:href="#_Image2" x="0" y="0" width="133px" height="150px" transform="matrix(0.995946,0,0,0.996875,29.6553,0.0777562)"/><path d="M102.276,120.437l-12.722,0l0,-24.172l12.722,0c8.395,0 13.212,4.352 13.212,11.941c0,7.767 -4.817,12.231 -13.212,12.231m-27.721,-35.428l-12.72,0c-8.397,0 -13.213,-4.458 -13.213,-12.232c0,-7.587 4.816,-11.939 13.213,-11.939l12.72,0l0,24.171Zm14.999,-24.171l8.411,0c8.395,0 13.212,4.352 13.212,11.939c0,7.774 -4.817,12.232 -13.212,12.232l-8.411,0l0,-24.171Zm30.926,28.648l-1.129,-0.735l0.843,-1.047c3.261,-4.071 4.912,-9.288 4.912,-15.515c0,-14.545 -9.325,-22.556 -26.26,-22.556l-37.892,0c-16.935,0 -26.26,8.011 -26.26,22.556c0,15.269 9.571,24.025 26.26,24.025l13.601,0l0,35.427l28.601,0c16.688,0 26.259,-8.753 26.259,-24.023c0,-8.151 -3.008,-14.248 -8.935,-18.132" style="fill:#fff;fill-rule:nonzero;"/></g><defs><linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(125.049,-125.049,125.049,125.049,19.4037,153.162)"><stop offset="0" style="stop-color:#1565c0;stop-opacity:1"/><stop offset="1" style="stop-color:#00bcd4;stop-opacity:1"/><stop offset="1" style="stop-color:#00bcd4;stop-opacity:1"/></linearGradient><image id="_Image2" width="133px" height="150px" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIUAAACWCAYAAADwmEsJAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAcMUlEQVR4nO2de6wdR33Hv7/Zc+4999yXfe1rO75+4pAESBOSlraohVJKC1JbKlVtVVX8UaBVhZBpS3lXBUTpAwolBNqqlShCfVC1QYoKtAKaFprQFBCP4DSJkzgh2E5wgu3Ednx9fe/Z6R+7Z3dm9zezv9mz55x7HR/JuuPZ2Z2Z/X3m95rdc0hrjY32OX5uWd/+6Ck8+NR5PHzmAr5z7iKOLa/h+HIPy5rQbRF2dSPsnm5j/8wknjU7hQObunjJzgXaOtEa9/DX/Yc2EhS33n9M/9Xdj+KLj6+ipwGtKD+o0r+U/gMV6gnttsLPL83iDc9bwosW54yTL3/Mz7qH4sT5Ff3Rrx/B3z14GseW07H2hU4E3RctGf8AgIipV1n5mvkJ/NbV2/DaZ19B01GfnMsfYB1D8b2zT+s3f/E+3HL0PFbjwqoHUuEmFdqEQRkN2HplXWd6IsKrDyzgPTfspflW1Pg8NuJn3UGx2uvpP7njXnzo7tM420srOTORlVMwSvUMSFk9leoXOhHeff0SXnflFaSe4YZlXUHxqf/7jn7bl4/i4fOJ6LThD6BoJqxyAQxC2XyU6o1rZpcgPGfTBG5+wX68dPv8MxaNdQHF3SdO6YNfuA+3P76aVCiVyUsreARslFN/ITcl5GhP5XJ2PO/n53bN4qYfehb2T08+4+AYKxSnl1f0W247hL8/fA6rloAIZAiIjTKKZaJMqLrSfMDhe9ggTbQIB6/ainddt/cZ5YyOBQoN4M//5z79vq9+D6dWuRVNqYwoE1bZZyiWyRK6GySunrx+yLZOC3903RJefWA7PRPUxsih+NwDx/UbbzuC+5/S0EAugILgyCjngk7rRGaBCVcBt38CyoGx6pHV37gwiZt/cB9euPXSznGMDIqHTp3VB//9ED7/3YtJRXqjeTCoH21aoaftM6BC2Ey46nNAkZ7D1ttO6S/vmcMHb9yPpamJSxKOoUPx9OqafscXDuFj3z6NlZ6hpo0bnQnOWOlk/R+5wMCFn+k1ReGqw6yYkUyp3gAp/TvVIrzpqkW8/do9NHmJxbBDheJvvvagfveXjuKJZZ3f3EzY+eoHFTQGUSYHW9D5f+R5iWK4aq96WR7DOMEEVQG7plp433W78Kt7Fy8ZMoYCxR2PPK7f8G/34e4n1hJhm7aeMwvpnxwMw3wYx5OyCwyfP0CG6Smv+so8hhek5MALt0zhIzfuww2bpzc8HI1C8ejZZf2Gz9yFfz38NEwATGEjK8NayXZbMnNSjO+QC1YXBefyB7Jw1bHqnQ4r4AcpB0Ypwqt2z+F91+/Dtk57w8LRCBQXY4333Ha3vvl/T+DCKjxagFnNfTCMOl00HxUr2dIALn/AMA3+8LZ4HXKbDw4YRZhpKbzj6kX83jVL1NqAQezAUPzjXY/ot3/uCB49ExdUfq62TWGzq7Ow+ksRgtNRzMvyvASXEmfaW/WKgYe5vjEfDeBAt40PXr+EVy5t2VBk1Ibim489qV9/6yF87ehKdpMsld83HwVhWw5lVqbCKi0I0hKQywkkRx6DyhCWUuJM+1K9KsDjGk9+HZ0uipduncJHbtiL58x1NwQcwVCcWl7Vv/OZb+FfvvVU8qBL/4B5z7KwE6ywy2AUVHxRkKawwQitH79ygnbumzDhaqUZ4gBzaD8kffR9noiA39y7CX983R5sarfWNRxiKHpa4/1fuk9/4L+O4exK/+xUEEAmS6RlS7BMqFcMQXPVCxTDVXBti8edeQyXWckrZO2NTis1kTlulS8cAhbaCu+6Zhtef+XOdbtFL4LiM4cf079767145GTfi0RykwpRQH/hZAVOCMaNy5NWhdXJRCV52aGuAUe4SramsUxAXsG2t65PgjJ4DdM3m8bx585O4KYfWMLLtm9ed2h4obj/5NP6dbd8A7c/uAz025mOmCEEVnicWmWTVoyKZyCyNBC3OkHWtXRRvRdXsbHhxra3rl8A1zyXnX+/TFn7Us6GgJ9d7OKm6/fiwExn3cDBQnF2tYe3fvou/YmvPIHV9BEHVtUDHjAcatVYnZkpcUYlYEyJY+VbAs371iUzZp5LpbJ2moMCuFl/DNBWX2TdO128ngImCDi4bzPe9dzdmGlFY4fDgkID+Is7j+j3fPYhPHkuTiqLK4BzxFRRcGk7rxo2ruOMSsBAxJkao08LvqS9Oy9BhXrytC8uhn6tckQxMMCBNS5dvF56bPtkhPdevR2v2T/eLfoMii8+/H198J8P4fDxC7DseboYMtXnfKxeFW6IS61S+YY5o5K0jS9ctc4papH8jrOCZtPXRrhaHAczPkoL5SiG6cMCo2iO8vY3zk3gw9fuwo+NaYuejp1dwe/feQyf/OwDWq/FxoTSGatcfpnNLarvrN4UGKNWC6rdEhwXlfSvU1TXnHovApe1ybVY+XUAY4xWfRqVcJAX5pMvaSXbvTX6KM3V6kfjV3bM4s+etxu7u6N9JJC2/PXXcX5lTa/dezLTDPkAkxGTsSI1d+PZlUzM9Yx6mOc6ohLANkPGmMqwoWA+zFkq/trO3U9DwxS1WqHP/qE+IeUHewrnZWNL2xfHWhjTlCK8af8C3nb1Eqai0QSxank1hl5Jn6U3fU4NALFdHxtzM9vGZtk4ULoe057ph1ztuTGZZWcf+QHyjsOs1+X2lWUd1l7r8lwL5WWt8YcPncQ1/3kP/uno90fyRFTC6IVeXmMJOB2Z8QfaAMN1U82IpnQ917l2P04wzDFx13P2YYDhHDc/JhFIPjA4aAPAAICjK2v4tbuO4UV33Ke/cfrcUOFIoLjYqyC8AEYsAcM4IBECI2znzeLGVDrOlR0aIxSMMWiM/ufLT63gh+88gtd+82F94sLFocChoAG9sgbAs4K41akdpsQ6L+brvSuvQmNsVDCqFkYAGLEGPv7YGVz9pfvx/gce0xdj02YP/imZD+fEQ0yJVRaAUaGZ/D4GA4Z1nBmTy5R4F0VycGBT4rx+Mi7SWnyfzvR6eOsDT+Da/z6MT3/vdGNgKABar/SsDv03KrbrJRpD4mO4wDBNidOHKGgx83oCv0fuYzBguCCJ8waNmpLCWAkaDyyv4pXfPIqXf/VBfc+Z8wPDofTKWn6DXGA4bg7rYzgn4wDDe1MZMLjrM1rMausURN7hujIlcSw2JX0wAODzJ8/j+XcewcG7j+pTF1drw6Gw0nOu5NqmRKIxKldYv1wRrlqC97QN9TEEWmwkzqdQi/XBWI2Bjx5/Elfdfj8++p3HdR1vQ/WdTJft99+oAhihUYn4JoWAwWiMuuFqiONdOYekMAowEAMn12IcPHwCz//yYX3b988EoaFgahmXwEJujsSU1ALDYx7MclVbiY8ROqZRgBFoSvpjOvT0Rbzs64/gt+85rteED1QpxNq5akROYYgp8UQl1SCV+6kNRqgpCRiTtzws59MFhlF/87HTePFXj+hjy9W5DaVjWzUngze1h3TwhetoiSmxAaxub1S4wOCikibACBiTrBwPDwzwYNz51AXc+JUj+I8Kc6Ko59IMDjAkUUmIKSn0U92+3I/T7laB4dSERlQiDqHjcptKszJEMBwa44mLPbziW9/Fe4+ccBoTZT+SXbxwAxpD5GMIwHDlS0SmpE5UUj9cHa4pYcJVD3wcGL0Y+IOHnsAbDz/KcqGwpv0XNm2/N3Q0zy0MRGRK6vgYYwpXmwJD5wV5Ag1AzGgMjzw4MKCBm46ewi0nniqBobThaLonPni0IPIZCgDWdj6dmU/G7HBguMJVsRmtCYb4+qhhShjfUQOvvec47n96xQJDZTa9f1MFdjY4I8lpDOd5AjCGlfkMzWOEzF1U9pgSrt8GfIwzazF+6dvfxbJx3xXWysJ2qzLtqPcNvo4pMf7j0jB1heDSLsMyJVrLFpEEjEY0Rvk+HTq3gtfdm/sXiaZghO1WZZqvZ0nulwueuUtjSMAIMVmustm2ypQ0AYZkTFZ59GB84tEn8anHE/9CZclxJgQNBsOrPYYUlZTKvO0sjbfK7Djn7ghXBxkTWx59uHrTIycB2I+JssJ229AGnM9QU9IUGNrdtjGN4TKjPpBK/Y5WY9zx5DK+fe4CFCJVKWy3xnCAERKuijKZDlPSRAQwTDA2oCn5y6OnoNB/Sy0EDKvMRyWh2+6VEwjdK2HMg7M9s5Kt0HYIYIz8mU9hgusfHntSKzJfUHMJuw+G05SUzQ7g0TBVYAhCQycYo4hKJHmM9QiGQGOc6+lEU4iEXWlKym1L7UvlclRSPQEHGI2ZEiEYoRrDYUaDMpkmGFrQviYYitIvIncLjwFDspJNjeGN08tRSfUEBBpDAgY3DxcYozIlVWH+CDSGgmk+nMmhsrBFEEl8DE5gotUWCEZdHyMEDMPvkQsulreP88phgpE4mqIBhZgSPirxb0MXwKhcMZCZklJ5/YarwT5GiOkJAENl3y0hSsUyKXFnJw4wJCu5ypRYgrbHFGxKOCFXmZImwJCYEgkYQ9AYyvo2LtdNqhD2QGCERCUSMCSmpMo8mGVmTM6HgS8RMBRaFLhhgzBT4niCSxSVVAJqlh2mJBQMpynxtBXcp40EhqJOBCAWwmDW61K9aHdVnOBqMFwdBRjOuYwQjIZ8DEXZzzzHzWiMQRJc61VjPMN8DIWICC2V1zRtSqyyICpxCcyw4ZVRRq3MpyfSMMtVbZ1zqROu1gFj8N1VBQ3QZMuKgWUr0iybdyIbG19uKI8R9DUILpCGZUqEIbQ5vqoxjVJjJN/uNNkqXbS2xhBNlr85Qa8oijRAQ1GJ2UbaVmBK3EDz/YwKjORryDoRM5k6GqOg6ovHfXsl/RvrTVqVnc/GH9RhMp/+jTFh21AwxqgxEvPRaTli79hpBir3P0IgKtSLElxNgOHNfAq1QHBbfkzVIOUVwwYj8TAnoqQzc+DZCbHzQpX7H5LBSPIYdU2Jq58mfIyB2jJjWkemJPlGx4ko+30m3mHSzoFWbqWHps8F0GlTCJzGcGqAQFPCmCz/xlgNMGr5GEnFsMDIfoyCOi17MqWJa+eFKsHwTrBfLu+rlK7tEgIXroaakoB+RBqjCiKfKakqG2HxMMBQ/QqambAOOjWGy8dwdhaX2obkPErXbsKU1HpFccimZFzOJyOL/Buk+1AYB3nns4Yp4cLVwFUTtO0uEnR9IYwCjKFvu/vNR1KjZtqwPt7JuFPitU3JwAmuwcNVWdkj7ApYh/IElxH9NAWGygaiiGi6zQqNB8OjMQISXCGPAZbaV4SRwWB4IxGzvA40hsuUiOeQ9GNdP/0YP7qlcxPCXHgg59Mqx/62ElMiEViVxvBEJbKyZ/+jLhiOMTW2V8ICU9YYyjxJzbaZk1CtMSSmJAQMrm2p3lcugOHKS0giAG9IbffTvMbIO3feHxTrBzclyhwcddv21VxghGgM500tRyWhD+qEqHiZKeHDYj8kIVqA0S6VPoYAjFCN4QIj7Sr/+RYNgEA0M1G5OrP22jzejPMZakpCMpIyMAIAzL5HO0QL1NEYQzAlHo2hioNTs32/IkAIEjAC9kpCH9Txg1EwVU2DkZUZUzKkzGfoN+qEgqHMCgJAs2a+QnBzSnmMAfZKQpJhkjFl5QE1RmhUIspmjkBj1AxXVami0yKaNBzOkNVp0CbKfIaYEgkYTZsS1yaa96YOISoZsSlR3MFoS6e+EFxghAhbYkpCoxImWrDAEEYlg4NR1L5CMBxjGkYeQ3EH1UIn2TS1LiDwzHXxuHZOzB1pDJ7HEIFhjLWRvZKBspkh2qVfHp7GKJkPAECkiOYmyvV1NYZjEEGmJDC/UPuZT6Fmqv08RhUY3ntZLAeCYVRU7H3wB9XmqeTk0kADVmdW53Y+K3dMRYI2/hO6V8KBIelHbEqE5sEB6zg0hnKtZDU/gf4rhV4wXCu4KiqRhJTZl7TlVcN+E23dgeFtWx5TMBgot8l/TLp4EhGphQ6fwgVkpoTLfIrDu345RGPwfk/j2+61vmR+HYDhmLtn76MMhlrolCfShPMpTiEX+gnNY4hNSUEjaYfPMHBU4gHDBeugPob2tc8rrL0Pu6ENBk21CR37nRCxxuBA8gBYXa4wJR4Vz7avSnCJopIBwBg08ymAtW6CS5UnYgss2jpV6jzU+QzdXa2csClop3YJBKOuKSlopqCohDPNIWAMYko8GkPxE8/BUFs6QKQKFwhwPr0awxOVhGiMQcAolde/8zlsMPIHd0sNUzCIKNo+za7ekimp2OIWPcHlVXP9ekZjODXNZTCAMDCs5JULDLW1A7QVe7GSxqgLRhNRSWBKPDTBJR5TWl8bjEF9jAHBKCWvWDBAFG3r2p1rx+AAVEUlIudT4lBWpcRdWmyAqIS7xlCjklKfw9cY7N4HB4baMpX7FszNKZsSfx5DpDEkSauQPEboeyWmEErJuOI4mDGl9RvNlPB7H9xEFEgtdr0X84Lh8kkCwtVG3l1t6L2S6n4Em2jDAmNAU+Lc++AmEi127B+DkDifknA1ICVeqQVEvskApqQKDJd/Jcl7DJj5lIGRHwje++iXrYkoIrVYfNaiXBZHJVWmZBwaw3tuOSqp7KfWS80hwm7elLj3PhwTibZ1gRa5V4cLjJAEl5kSd2mMKhVZw/Zn1w7UGOsyXA0YU9DeBzsRIoqWZvztQ51P78Q9YDjHW94rcc+tmXB1FCnxYp++MQ2iMbx7Hy4w1Pwk0Uy73D7UnvtA0lo0rtrfqDNIgouLSkxBNxGV6H7ZM48hgaGodJIMjGhpNkWqQTC4ybicTxcYXD9OGKrHJPo6x6FrjHI+phIM0YZbeUzJ3geMFREABk1GRojq2cNwbnoJNYZ13AOGs88KjeEak8h/MSo4jSHsp46PUezTbmtDFKox8peBaoARbeuC2lE+QhEM/ECCNIbj2iFRyUDb7lUruSmNMVCkUR8M+2WgUDD6TqervUtVW2WB81nKY7jHlc+hOJaAlPi6NiUhYJgVcjBKGc1QMNTsBKlNkyKBudWpPyVu1ZvjkmgMDkARGBsgKgkBI0BjsBnNUDCinTOwf9/UozGc9f5NNKssGNf4TElaMayopNgPp1EHBIPdEAPCwKBIUWv3rLi9W2MY/6kCSRsVDtAqU+LmHIaZ4IqHBYbQbxCnzxOZOTfEgDAw1OwEZY/uCTKS7OAApxD8GmMA51OUDGsADJGgh72JZif1XG1VZQQQAEa0YxqqW/zyd0+4yqk+wBaCWGN4NFlAHsOZDKv1dY41ohLJXslAUUl12/yL0DyDDQCDot1zoBZJ2zesMdyaKcjHkCS4JJFVXTDG7HxaX4Tm7lAOBrUVRUuzjA11C8ytMQTOZ4jGqFLbkrauZ0QaNyXjA0ORZyDFshQMNTtBausU/2hfxY30aowqkCR5jBBTIhSYrFy4fqjzWTPzWQcMO81dHMgAYETbp0HdNjPxuELdhpuSYT6Psa7AGJHGyL+GuXkwKNo9C7QUM5HqlHio8xm6iVa5MTYqMESCHi0Yyj35wcGglqLWvnlAEQ/GIKakqr0kwzpEU7KR3yspJa8aB2MyotaeOYC4iRTaD6IxvLG3ljmFXAg6CBheMzm4xpCVw8Fgk1eNg9FtJRlPduLMSi5cs6wxBJtonMYQRwuFfkRZUj4qGfZeiawcBobzae7GwZiZyHZUG49KmNUe6nxWgiHRAI6NvaGCUTMs9oHh3PsAAsEoHSsLQM1PUrRjWqYxQk1JFUjZ8Q2QEq8RlcjKMjC8ex9AABgSQWtALXRILU452oc7n5pLP2tHe7Mf0XxR/oRAlHZV3d6oqKsxRO3L/fBpbgFlTYMRLXZJbXa9P6JleQzBvkSQKakSXrAGaEBjjAmMypeB+Mk0AMaOaVILk24wKsY0kPPpArBKeMEaIBCM2Lgw9zyGA2LnJppX6zJgpB/Ry0D9T+NgbJ+maLEbrjE4DQDINEbVXokpbO6mXsoaI/1r7H2MBwy1pUPRFdOwWBUIzK0xPGMqtq8NRmiUsbHAKOx9jAmM+Ulq7ZoBsWB4nM+anjmvMYTOZ3ZeQ2AEqPhRgcHsfYwHDJpuU7RnNvtCV7u9cA/Dqq8DhnvujZiSWl+1NAIwYrsfx97HmMDotCjaOwdql794TTqmxk0JN19tnufvo1QeBIwq57MhjeHZ+xgTGG1FrT2zoMlWWObTWS+ISkKex+D6lDxwPCowPMk9KRgVex/jAQPp0+FqU0fWvrI8JI1h1gf/+N0AYBhjHYbGEOx9jAkMAqnFKYqumAGVvmurjsbwr+ZGwJA8w7kBwBDufYwJDCQOaGv3LNRUwFPioXkMduX7xwWEZT7L90B72/ufEveAgWJbflw+MAL2PsYHBlqKop0ziBY6yUkBY2rmKfHAvZIxJbjcbfl+XGAE7n2MEQyA1OYOtbhXFCtMSejDwFZZ0M96AqMJU+I1H+sQDFCnRe3ds6Dp9oAawx+VWOWGTclQ310VPfXtBmPvzATyJbeBwIAiau2YpmhHN3dCa2kM/mmpSo3BXBsYAAzX5pZ40605jfEbV23t731sQDA0oLptinbPQm2azBMOwRrDM6Zi2RyXxJSEpMQFDw8N25RMKsJrrt5Kxt7HxgSDKPU1lmZB3TYGBiPkYWDXfLlwNDhhFdjerODAEITFv7hvM7Z0WsW9jw0KBpBEKNu6FG2fBrXQuPN5STyo47on0OhECm9+/hUEsHsfGxgMpPsnS7NQmydgRe+ibfeaD+qI5tv/O2YwHOd96IW78NzNyW/GOfY+NjYYAEjNT1K0axo0N5lnY1waQ/IwcF1TMkwwGnqv5FXPXsCvX7OYHfbsfWxwMDSS7xKfn6Bo5wzU5kkgotGZksbBGM7rA9cuTOHmH99nJUQr9j4uATAAgEA0k8Kx0AFU4G+iDUtjBL8nEgqSUcGAMddS+OTPHMBUy7gfEO19XCJgJO2JptsUXTFNamEKmIisNs28cFQd/VjlQUyJ8QkFY1IBH/up/bhyvlPaNmlZJ1O5TBrQlFY42pTbp5WaAtqnEybi2yM5pK1j/j587WmqRdFUC3q1p/X5NegLa4DWydaKdR3PmNKudYxkeQnHVSo7+rDvjXFerPPfXen3nbZ395PLcM/cBD75igO4YXGa3UdryQV96YEBANSOiDZFACa1vtCDvrAKrPRyQfvGlLaxwMjOGzIYFbDyZY1X7N2Ej//0AZqf7H9TcvnTkl70UgYjrSfqRKBOBEBrvdxDfGENerWXtokBUuz1M42RCVg2rkY0RhUYKaSKCO/8kZ148wuW+mc4P61sIJfByMsgom4LUbcFHWutL6xBX+wBq3G1KenXmxojpnJYTA5hu8CIAa1QqpdojB3dNv725c/CS3bNV/EAIPmNH+jLYDjHRIoI3XayKwtovRoDazH0xeRv9qmpMVhhx3EeIRV8Bt6U8FqsExEO3rgdb3nBLppu2xGG79NCf/yXwXCOyRA0UVsBbQXqJidnkKz2gJ4GoB1gpNL3zdfQIhYYElNSuE+/cOUm/OlP7MPeuUmRdjA/LXvil8FwjckSdD4mA5I0kIu11rEG9eLkjXitoVNYwJkSn7BrOJ/XLk7hAz+5Dy/eLTMV3MdyNC+DUQsMu70iIkUJKP1qSlvEGoh1mpzUzHx1Pl8Y4wLl/ShK/5sOKP23pdvGO390J15z3Q7rfao6n/8H0923Jqssn7MAAAAASUVORK5CYII="/></defs></svg>
assets/img/check.png ADDED
Binary file
{img → assets/img}/code.png RENAMED
File without changes
{img → assets/img}/icon.png RENAMED
File without changes
{img → assets/img}/mailcrypt.png RENAMED
File without changes
{img → assets/img}/warning.png RENAMED
File without changes
{js → assets/js}/unveil.js RENAMED
File without changes
css/admin.css DELETED
@@ -1,183 +0,0 @@
1
- @import url("https://fonts.googleapis.com/css?family=Open+Sans:400,600,700");
2
- .pb-wp-app-wrapper {
3
- box-sizing: border-box;
4
- font-family: 'Open Sans', sans-serif;
5
- font-size: 14px;
6
- padding: 10px; }
7
- .pb-wp-app-wrapper * {
8
- box-sizing: border-box; }
9
- .pb-wp-app-wrapper p {
10
- font-size: 14px; }
11
- .pb-wp-app-wrapper .pro-section {
12
- font-size: 26px;
13
- border-top: 1px solid #aaa;
14
- position: relative;
15
- text-align: center;
16
- margin: 55px 0 20px 0; }
17
- .pb-wp-app-wrapper .pro-section span {
18
- top: -12px;
19
- position: relative;
20
- background: #f1f1f1;
21
- padding: 0 15px; }
22
- .pb-wp-app-wrapper .pb-wrapper {
23
- display: flex; }
24
- .pb-wp-app-wrapper .pb-wrapper .pb-main {
25
- width: calc(100% - 300px);
26
- padding-right: 30px;
27
- max-width: 1024px; }
28
- .pb-wp-app-wrapper .pb-wrapper .pb-sidebar {
29
- width: 300px;
30
- padding-top: 30px; }
31
- .pb-wp-app-wrapper .pb-wrapper .pb-sidebar h3:first-child {
32
- margin-top: 0;
33
- color: #888; }
34
- .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box, .pb-wp-app-wrapper .pb-wrapper .pb-support-box {
35
- background: #fff;
36
- padding: 15px 15px;
37
- opacity: .6;
38
- margin-bottom: 35px;
39
- -webkit-transition: opacity .5s;
40
- -moz-transition: opacity .5s;
41
- transition: opacity .5s; }
42
- .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box:hover, .pb-wp-app-wrapper .pb-wrapper .pb-support-box:hover {
43
- opacity: 1; }
44
- .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box h4, .pb-wp-app-wrapper .pb-wrapper .pb-support-box h4 {
45
- margin-top: 0;
46
- display: flex; }
47
- .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box h4 .icon, .pb-wp-app-wrapper .pb-wrapper .pb-support-box h4 .icon {
48
- width: 50px;
49
- height: auto; }
50
- .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box h4 .icon img, .pb-wp-app-wrapper .pb-wrapper .pb-support-box h4 .icon img {
51
- max-width: 100%;
52
- height: auto; }
53
- .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box h4 .text, .pb-wp-app-wrapper .pb-wrapper .pb-support-box h4 .text {
54
- padding: 7px 0 0 10px;
55
- width: calc(100% - 50px);
56
- display: flex;
57
- height: 50px; }
58
- .pb-wp-app-wrapper .pb-wrapper .pb-plugin-box p:last-child, .pb-wp-app-wrapper .pb-wrapper .pb-support-box p:last-child {
59
- margin-bottom: 0; }
60
- .pb-wp-app-wrapper .pb-section-title {
61
- color: #23282d;
62
- font-weight: 600;
63
- background: #fff;
64
- padding: 15px 25px;
65
- margin-bottom: 0;
66
- display: inline-block; }
67
- .pb-wp-app-wrapper h3.pb-section-title {
68
- padding-top: 10px;
69
- padding-bottom: 10px;
70
- font-size: 16px;
71
- font-weight: 400; }
72
- .pb-wp-app-wrapper .pb-section-wrap, .pb-wp-app-wrapper .form-table {
73
- background: #fff;
74
- padding: 25px;
75
- margin-bottom: 25px;
76
- max-width: 1024px; }
77
- .pb-wp-app-wrapper .pb-section-wrap.no-margin-bottom, .pb-wp-app-wrapper .form-table.no-margin-bottom {
78
- margin-bottom: 0;
79
- padding-bottom: 5px; }
80
- .pb-wp-app-wrapper .pb-section-wrap p:first-child, .pb-wp-app-wrapper .form-table p:first-child {
81
- margin-top: 0; }
82
- .pb-wp-app-wrapper .pb-section-wrap p:last-child, .pb-wp-app-wrapper .form-table p:last-child {
83
- margin-bottom: 0; }
84
- .pb-wp-app-wrapper .pb-section-wrap input[type="text"], .pb-wp-app-wrapper .pb-section-wrap textarea, .pb-wp-app-wrapper .pb-section-wrap select, .pb-wp-app-wrapper .form-table input[type="text"], .pb-wp-app-wrapper .form-table textarea, .pb-wp-app-wrapper .form-table select {
85
- box-sizing: border-box;
86
- width: 100%;
87
- margin-left: 0;
88
- border-radius: 4px;
89
- border: none;
90
- box-shadow: none;
91
- background: #F1F5F9;
92
- padding: 13px;
93
- font-size: 14px;
94
- color: #32373C;
95
- height: auto;
96
- font-family: 'Open Sans', sans-serif;
97
- font-size: 14px;
98
- margin-bottom: 0;
99
- -webkit-transition: background .5s;
100
- -moz-transition: background .5s;
101
- transition: background .5s; }
102
- .pb-wp-app-wrapper .pb-section-wrap input[type="text"]:focus, .pb-wp-app-wrapper .pb-section-wrap textarea:focus, .pb-wp-app-wrapper .pb-section-wrap select:focus, .pb-wp-app-wrapper .form-table input[type="text"]:focus, .pb-wp-app-wrapper .form-table textarea:focus, .pb-wp-app-wrapper .form-table select:focus {
103
- background-color: #E0E5EA; }
104
- .pb-wp-app-wrapper .pb-section-wrap input:disabled, .pb-wp-app-wrapper .pb-section-wrap textarea:disabled, .pb-wp-app-wrapper .pb-section-wrap select:disabled, .pb-wp-app-wrapper .form-table input:disabled, .pb-wp-app-wrapper .form-table textarea:disabled, .pb-wp-app-wrapper .form-table select:disabled {
105
- cursor: not-allowed;
106
- opacity: .75; }
107
- .pb-wp-app-wrapper .pb-section-wrap select, .pb-wp-app-wrapper .form-table select {
108
- height: 39px;
109
- padding: 3px 7px; }
110
- .pb-wp-app-wrapper .button.button-primary {
111
- text-shadow: none;
112
- -webkit-transition: background .5s;
113
- -moz-transition: background .5s;
114
- transition: background .5s;
115
- color: #FFF;
116
- cursor: pointer;
117
- background-color: #17a8e3;
118
- -webkit-box-shadow: none;
119
- -moz-box-shadow: none;
120
- box-shadow: none;
121
- border: none;
122
- padding: 0 20px;
123
- font-size: 18px;
124
- font-weight: 300;
125
- height: 53px;
126
- line-height: 53px;
127
- display: inline-block;
128
- text-decoration: none;
129
- -moz-border-radius: 3px;
130
- -webkit-border-radius: 3px;
131
- border-radius: 3px;
132
- position: relative; }
133
- .pb-wp-app-wrapper .button.button-primary:hover {
134
- background-color: #1286b5; }
135
-
136
- .pb-custom-message {
137
- font-family: 'Open Sans', sans-serif;
138
- box-sizing: border-box;
139
- border-radius: 4px;
140
- -ms-flex-align: center;
141
- align-items: center;
142
- background: #fff url("../img/icon.png") no-repeat left;
143
- background-size: contain;
144
- border: 0;
145
- display: -ms-flexbox;
146
- display: flex;
147
- min-height: 100px;
148
- padding: 15px 35px 15px 135px;
149
- -ms-flex-pack: justify;
150
- max-width: 1024px;
151
- margin-bottom: 25px;
152
- -moz-box-shadow: 2px 2px 6px 1px rgba(55, 55, 55, 0.2);
153
- -webkit-box-shadow: 2px 2px 6px 1px rgba(55, 55, 55, 0.2);
154
- box-shadow: 2px 2px 6px 1px rgba(55, 55, 55, 0.2); }
155
- .pb-custom-message p {
156
- font-size: 14px; }
157
- .pb-custom-message.code {
158
- background: #fff url("../img/code.png") no-repeat left;
159
- background-size: contain;
160
- -moz-box-shadow: none;
161
- -webkit-box-shadow: none;
162
- box-shadow: none; }
163
- .pb-custom-message.info {
164
- background: #fff url("../img/warning.png") no-repeat left;
165
- background-size: contain; }
166
- .pb-custom-message .pb-btn {
167
- cursor: pointer;
168
- text-decoration: none;
169
- white-space: nowrap;
170
- border: 0;
171
- border-radius: 4px;
172
- background-color: #17a8e3;
173
- color: #fff;
174
- padding: 15px 35px;
175
- text-transform: uppercase;
176
- margin-left: 20px;
177
- -webkit-transition: background .5s;
178
- -moz-transition: background .5s;
179
- transition: background .5s; }
180
- .pb-custom-message .pb-btn:hover {
181
- background-color: #1286b5; }
182
-
183
- /*# sourceMappingURL=admin.css.map */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
css/admin.css.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "mappings": "AAAQ,4EAAoE;AAM5E,kBAAmB;EACf,UAAU,EAAE,UAAU;EACtB,WAAW,EAAE,uBAAuB;EACpC,SAAS,EAAE,IAAI;EACf,OAAO,EAAE,IAAI;EAEb,oBAAE;IACE,UAAU,EAAE,UAAU;EAG1B,oBAAE;IACE,SAAS,EAAE,IAAI;EAGnB,+BAAa;IACT,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,cAAc;IAC1B,QAAQ,EAAE,QAAQ;IAClB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,aAAa;IAErB,oCAAK;MACD,GAAG,EAAE,KAAK;MACV,QAAQ,EAAE,QAAQ;MAClB,UAAU,EAAE,OAAO;MACnB,OAAO,EAAE,MAAM;EAIvB,8BAAY;IACR,OAAO,EAAE,IAAI;IAEb,uCAAS;MACL,KAAK,EAAE,kBAAkB;MACzB,aAAa,EAAE,IAAI;MACnB,SAAS,EAAE,MAAM;IAGrB,0CAAY;MACR,KAAK,EAAE,KAAK;MACZ,WAAW,EAAE,IAAI;MAEjB,yDAAe;QACX,UAAU,EAAE,CAAC;QACb,KAAK,EAAE,IAAI;IAInB,6FAAgC;MAC5B,UAAU,EAAE,IAAI;MAChB,OAAO,EAAE,SAAS;MAClB,OAAO,EAAE,EAAE;MACX,aAAa,EAAE,IAAI;MACnB,kBAAkB,EAAE,WAAW;MAC/B,eAAe,EAAE,WAAW;MAC5B,UAAU,EAAE,WAAW;MAGvB,yGAAQ;QACJ,OAAO,EAAE,CAAC;MAGd,mGAAG;QACC,UAAU,EAAE,CAAC;QACb,OAAO,EAAE,IAAI;QACb,+GAAM;UACF,KAAK,EAAE,IAAI;UACX,MAAM,EAAE,IAAI;UAEZ,uHAAI;YACA,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,IAAI;QAIpB,+GAAM;UACF,OAAO,EAAE,YAAY;UACrB,KAAK,EAAE,iBAAiB;UACxB,OAAO,EAAE,IAAI;UACb,MAAM,EAAE,IAAI;MAIpB,uHAAa;QACT,aAAa,EAAE,CAAC;EAS5B,oCAAkB;IACd,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,GAAG;IAChB,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,SAAS;IAClB,aAAa,EAAE,CAAC;IAChB,OAAO,EAAE,YAAY;EAGzB,sCAAoB;IAChB,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,IAAI;IACpB,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,GAAG;EAGpB,mEAA8B;IAC1B,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,IAAI;IACb,aAAa,EAAE,IAAI;IACnB,SAAS,EAAE,MAAM;IAEjB,qGAAmB;MACf,aAAa,EAAE,CAAC;MAChB,cAAc,EAAE,GAAG;IAGvB,+FAAc;MACV,UAAU,EAAE,CAAC;IAGjB,6FAAa;MACT,aAAa,EAAE,CAAC;IAGpB,mRAAqC;MACjC,UAAU,EAAE,UAAU;MACtB,KAAK,EAAE,IAAI;MACX,WAAW,EAAE,CAAC;MACd,aAAa,EAAE,GAAG;MAClB,MAAM,EAAE,IAAI;MACZ,UAAU,EAAE,IAAI;MAChB,UAAU,EAAE,OAAO;MACnB,OAAO,EAAE,IAAI;MACb,SAAS,EAAE,IAAI;MACf,KAAK,EAAE,OAAO;MACd,MAAM,EAAE,IAAI;MACZ,WAAW,EAAE,uBAAuB;MACpC,SAAS,EAAE,IAAI;MACf,aAAa,EAAE,CAAC;MAChB,kBAAkB,EAAE,cAAc;MAClC,eAAe,EAAE,cAAc;MAC/B,UAAU,EAAE,cAAc;MAE1B,uTAAQ;QACJ,gBAAgB,EAAE,OAAO;IAK7B,+SAAW;MACP,MAAM,EAAE,WAAW;MACnB,OAAO,EAAE,GAAG;IAIpB,iFAAO;MACH,MAAM,EAAE,IAAI;MACZ,OAAO,EAAE,OAAO;EAKxB,yCAAuB;IACnB,WAAW,EAAE,IAAI;IACjB,kBAAkB,EAAE,cAAc;IAClC,eAAe,EAAE,cAAc;IAC/B,UAAU,EAAE,cAAc;IAC1B,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,OAAO;IACf,gBAAgB,EAAE,OAAO;IACzB,kBAAkB,EAAE,IAAI;IACxB,eAAe,EAAE,IAAI;IACrB,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,MAAM;IACf,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,GAAG;IAChB,MAAM,EAAE,IAAI;IACZ,WAAW,EAAE,IAAI;IACjB,OAAO,EAAE,YAAY;IACrB,eAAe,EAAE,IAAI;IACrB,kBAAkB,EAAE,GAAG;IACvB,qBAAqB,EAAE,GAAG;IAC1B,aAAa,EAAE,GAAG;IAClB,QAAQ,EAAE,QAAQ;IAElB,+CAAQ;MACJ,gBAAgB,EAAE,OAAmB;;AAKjD,kBAAmB;EACf,WAAW,EAAE,uBAAuB;EACpC,UAAU,EAAE,UAAU;EACtB,aAAa,EAAE,GAAG;EAClB,cAAc,EAAE,MAAM;EACtB,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,0CAA0C;EACtD,eAAe,EAAE,OAAO;EACxB,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,WAAW;EACpB,OAAO,EAAE,IAAI;EACb,UAAU,EAAE,KAAK;EACjB,OAAO,EAAE,oBAAoB;EAC7B,aAAa,EAAE,OAAO;EACtB,SAAS,EAAE,MAAM;EACjB,aAAa,EAAE,IAAI;EACnB,eAAe,EAAE,qCAAiC;EAClD,kBAAkB,EAAG,qCAAiC;EACtD,UAAU,EAAE,qCAAiC;EAE7C,oBAAE;IACE,SAAS,EAAE,IAAI;EAGnB,uBAAO;IACH,UAAU,EAAE,0CAA0C;IACtD,eAAe,EAAE,OAAO;IACxB,eAAe,EAAE,IAAI;IACrB,kBAAkB,EAAG,IAAI;IACzB,UAAU,EAAE,IAAI;EAGpB,uBAAO;IACH,UAAU,EAAE,6CAA6C;IACzD,eAAe,EAAE,OAAO;EAG5B,0BAAQ;IACJ,MAAM,EAAE,OAAO;IACf,eAAe,EAAE,IAAI;IACrB,WAAW,EAAE,MAAM;IACnB,MAAM,EAAE,CAAC;IACT,aAAa,EAAE,GAAG;IAClB,gBAAgB,EAAE,OAAO;IACzB,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,SAAS;IAClB,cAAc,EAAE,SAAS;IACzB,WAAW,EAAE,IAAI;IACjB,kBAAkB,EAAE,cAAc;IAClC,eAAe,EAAE,cAAc;IAC/B,UAAU,EAAE,cAAc;IAE1B,gCAAQ;MACJ,gBAAgB,EAAE,OAAmB",
4
- "sources": ["admin.scss"],
5
- "names": [],
6
- "file": "admin.css"
7
- }
 
 
 
 
 
 
 
css/admin.scss DELETED
@@ -1,259 +0,0 @@
1
- @import url('https://fonts.googleapis.com/css?family=Open+Sans:400,600,700');
2
-
3
- .settings_page_pb-seo-friendly-images #wpcontent {
4
- //background: #F1F5F9;
5
- }
6
-
7
- .pb-wp-app-wrapper {
8
- box-sizing: border-box;
9
- font-family: 'Open Sans', sans-serif;
10
- font-size: 14px;
11
- padding: 10px;
12
-
13
- * {
14
- box-sizing: border-box;
15
- }
16
-
17
- p {
18
- font-size: 14px;
19
- }
20
-
21
- .pro-section {
22
- font-size: 26px;
23
- border-top: 1px solid #aaa;
24
- position: relative;
25
- text-align: center;
26
- margin: 55px 0 20px 0;
27
-
28
- span {
29
- top: -12px;
30
- position: relative;
31
- background: #f1f1f1;
32
- padding: 0 15px;
33
- }
34
- }
35
-
36
- .pb-wrapper {
37
- display: flex;
38
-
39
- .pb-main {
40
- width: calc(100% - 300px);
41
- padding-right: 30px;
42
- max-width: 1024px;
43
- }
44
-
45
- .pb-sidebar {
46
- width: 300px;
47
- padding-top: 30px;
48
-
49
- h3:first-child {
50
- margin-top: 0;
51
- color: #888;
52
- }
53
- }
54
-
55
- .pb-plugin-box, .pb-support-box {
56
- background: #fff;
57
- padding: 15px 15px;
58
- opacity: .6;
59
- margin-bottom: 35px;
60
- -webkit-transition: opacity .5s;
61
- -moz-transition: opacity .5s;
62
- transition: opacity .5s;
63
-
64
-
65
- &:hover {
66
- opacity: 1;
67
- }
68
-
69
- h4 {
70
- margin-top: 0;
71
- display: flex;
72
- .icon {
73
- width: 50px;
74
- height: auto;
75
-
76
- img {
77
- max-width: 100%;
78
- height: auto;
79
- }
80
- }
81
-
82
- .text {
83
- padding: 7px 0 0 10px;
84
- width: calc(100% - 50px);
85
- display: flex;
86
- height: 50px;
87
- }
88
- }
89
-
90
- p:last-child {
91
- margin-bottom: 0;
92
- }
93
-
94
- .desc {
95
-
96
- }
97
- }
98
- }
99
-
100
- .pb-section-title {
101
- color: #23282d;
102
- font-weight: 600;
103
- background: #fff;
104
- padding: 15px 25px;
105
- margin-bottom: 0;
106
- display: inline-block;
107
- }
108
-
109
- h3.pb-section-title {
110
- padding-top: 10px;
111
- padding-bottom: 10px;
112
- font-size: 16px;
113
- font-weight: 400;
114
- }
115
-
116
- .pb-section-wrap, .form-table {
117
- background: #fff;
118
- padding: 25px;
119
- margin-bottom: 25px;
120
- max-width: 1024px;
121
-
122
- &.no-margin-bottom {
123
- margin-bottom: 0;
124
- padding-bottom: 5px;
125
- }
126
-
127
- p:first-child {
128
- margin-top: 0;
129
- }
130
-
131
- p:last-child {
132
- margin-bottom: 0;
133
- }
134
-
135
- input[type="text"], textarea, select {
136
- box-sizing: border-box;
137
- width: 100%;
138
- margin-left: 0;
139
- border-radius: 4px;
140
- border: none;
141
- box-shadow: none;
142
- background: #F1F5F9;
143
- padding: 13px;
144
- font-size: 14px;
145
- color: #32373C;
146
- height: auto;
147
- font-family: 'Open Sans', sans-serif;
148
- font-size: 14px;
149
- margin-bottom: 0;
150
- -webkit-transition: background .5s;
151
- -moz-transition: background .5s;
152
- transition: background .5s;
153
-
154
- &:focus {
155
- background-color: #E0E5EA;
156
- }
157
- }
158
-
159
- input, textarea, select {
160
- &:disabled {
161
- cursor: not-allowed;
162
- opacity: .75;
163
- }
164
- }
165
-
166
- select {
167
- height: 39px;
168
- padding: 3px 7px;
169
- }
170
-
171
- }
172
-
173
- .button.button-primary {
174
- text-shadow: none;
175
- -webkit-transition: background .5s;
176
- -moz-transition: background .5s;
177
- transition: background .5s;
178
- color: #FFF;
179
- cursor: pointer;
180
- background-color: #17a8e3;
181
- -webkit-box-shadow: none;
182
- -moz-box-shadow: none;
183
- box-shadow: none;
184
- border: none;
185
- padding: 0 20px;
186
- font-size: 18px;
187
- font-weight: 300;
188
- height: 53px;
189
- line-height: 53px;
190
- display: inline-block;
191
- text-decoration: none;
192
- -moz-border-radius: 3px;
193
- -webkit-border-radius: 3px;
194
- border-radius: 3px;
195
- position: relative;
196
-
197
- &:hover {
198
- background-color: darken(#17a8e3, 10);
199
- }
200
- }
201
- }
202
-
203
- .pb-custom-message {
204
- font-family: 'Open Sans', sans-serif;
205
- box-sizing: border-box;
206
- border-radius: 4px;
207
- -ms-flex-align: center;
208
- align-items: center;
209
- background: #fff url("../img/icon.png") no-repeat left;
210
- background-size: contain;
211
- border: 0;
212
- display: -ms-flexbox;
213
- display: flex;
214
- min-height: 100px;
215
- padding: 15px 35px 15px 135px;
216
- -ms-flex-pack: justify;
217
- max-width: 1024px;
218
- margin-bottom: 25px;
219
- -moz-box-shadow: 2px 2px 6px 1px rgba(55,55,55,.2);
220
- -webkit-box-shadow: 2px 2px 6px 1px rgba(55,55,55,.2);
221
- box-shadow: 2px 2px 6px 1px rgba(55,55,55,.2);
222
-
223
- p {
224
- font-size: 14px;
225
- }
226
-
227
- &.code {
228
- background: #fff url("../img/code.png") no-repeat left;
229
- background-size: contain;
230
- -moz-box-shadow: none;
231
- -webkit-box-shadow: none;
232
- box-shadow: none;
233
- }
234
-
235
- &.info {
236
- background: #fff url("../img/warning.png") no-repeat left;
237
- background-size: contain;
238
- }
239
-
240
- .pb-btn {
241
- cursor: pointer;
242
- text-decoration: none;
243
- white-space: nowrap;
244
- border: 0;
245
- border-radius: 4px;
246
- background-color: #17a8e3;
247
- color: #fff;
248
- padding: 15px 35px;
249
- text-transform: uppercase;
250
- margin-left: 20px;
251
- -webkit-transition: background .5s;
252
- -moz-transition: background .5s;
253
- transition: background .5s;
254
-
255
- &:hover {
256
- background-color: darken(#17a8e3, 10);
257
- }
258
- }
259
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
img/primusnote.png DELETED
Binary file
inc/pbSettingsFramework.php DELETED
@@ -1,206 +0,0 @@
1
- <?php
2
-
3
- /* Security-Check */
4
- if ( !class_exists('WP') ) {
5
- die();
6
- }
7
-
8
- if( ! class_exists('pbSettingsFramework') ):
9
- class pbSettingsFramework
10
- {
11
- const version = '1.3.0';
12
- static $textDomain = false;
13
- static $page = false;
14
- static $section = false;
15
- static $optionGroup = false;
16
- static $args = array();
17
-
18
- /**
19
- * pbSettingsFramework constructor.
20
- *
21
- * @param array $args
22
- */
23
- public function __construct($args=array())
24
- {
25
- pbSettingsFramework::$textDomain = $args['text-domain'] || 'pbSettingsFramework';
26
- pbSettingsFramework::$page = $args['page'];
27
- pbSettingsFramework::$section = $args['section'];
28
- pbSettingsFramework::$optionGroup = $args['option-group'];
29
- pbSettingsFramework::$args = $args;
30
- }
31
-
32
- /**
33
- * Register setting
34
- *
35
- * @param array $setting
36
- */
37
- public static function registerSetting($setting)
38
- {
39
- if( ! isset(pbSettingsFramework::$args['option-group']) ) {
40
- die(__FUNCTION__.': $args[\'option-group\'] not set!');
41
- }
42
-
43
- return register_setting(pbSettingsFramework::$args['option-group'], $setting);
44
- }
45
-
46
- /**
47
- * Add settings section
48
- *
49
- * @param $id
50
- * @param $title
51
- * @param $callback
52
- */
53
- public static function addSettingsSection($id, $title, $callback)
54
- {
55
- add_settings_section(
56
- $id,
57
- $title,
58
- $callback,
59
- pbSettingsFramework::$args['page']
60
- );
61
- }
62
-
63
- /**
64
- * Add settings field
65
- *
66
- * @param $id
67
- * @param $title
68
- * @param $args
69
- * @param array $callback
70
- * @param bool $register_setting
71
- */
72
- public static function addSettingsField($id, $title, $args, $callback=array(__CLASS__, 'fieldsHTML'), $register_setting=true)
73
- {
74
- if( $register_setting )
75
- register_setting( pbSettingsFramework::$args['option-group'], $id, 'esc_attr' );
76
-
77
-
78
- add_settings_field(
79
- $id,
80
- '<label for="'.$id.'">'.$title.'</label>',
81
- $callback,
82
- pbSettingsFramework::$page,
83
- pbSettingsFramework::$section,
84
- array_merge_recursive(
85
- array(
86
- 'id' => $id,
87
- 'section' => pbSettingsFramework::$section
88
- ),
89
-
90
- $args
91
- )
92
- );
93
- }
94
-
95
- /**
96
- * get array key
97
- *
98
- * @param $key
99
- * @param $array
100
- * @return bool
101
- */
102
- public static function getArrayKey($key, $array)
103
- {
104
- if( array_key_exists($key, $array) ) {
105
- return $array[$key];
106
- } else {
107
- return false;
108
- }
109
- }
110
-
111
- /**
112
- * html code for fields
113
- *
114
- * @param $args
115
- */
116
- public static function fieldsHTML( $args )
117
- {
118
- $option = get_option($args['id']);
119
- $html = '';
120
-
121
- if( pbSettingsFramework::getArrayKey('type', $args) == 'text' ) {
122
-
123
- if ( empty( $option ) ) {
124
- $val = pbSettingsFramework::getArrayKey('default', $args);
125
- } else {
126
- $val = $option;
127
- }
128
- $html = '<input type="text" id="' . $args['id'] . '" name="' . $args['id'] . '" class="regular-text" value="' . $val . '" '.((pbSettingsFramework::getArrayKey('disabled', $args))?'disabled="disabled"':'').' />';
129
-
130
- $desc = pbSettingsFramework::getArrayKey('desc', $args);
131
-
132
- if ( ! empty( $desc ) ) {
133
- $html .= '<p class="description">' . $desc . '</p>';
134
- }
135
-
136
- } elseif( $args['type'] == 'checkbox' ) {
137
-
138
- if( $option === false ){
139
- $val = pbSettingsFramework::getArrayKey('default', $args);
140
- }else{
141
- $val = $option;
142
- }
143
- $html = '<input type="checkbox" id="'.$args['id'].'" name="'.$args['id'].'" value="1" '.((pbSettingsFramework::getArrayKey('disabled', $args))?'disabled="disabled"':'').' '.checked(1, $val, false).'/>';
144
-
145
- $html .= '<label for="'.$args['id'].'"> '. pbSettingsFramework::getArrayKey('desc', $args) .'</label>';
146
-
147
- } elseif( $args['type'] == 'select' ) {
148
-
149
- if ( empty( $option ) ) {
150
- $val = pbSettingsFramework::getArrayKey('default', $args);
151
- } else {
152
- $val = $option;
153
- }
154
-
155
- $html = '<select id="'.$args['id'].'" name="'.$args['id'].'">';
156
- foreach ($args['select'] as $name => $value ) {
157
- $html .= '<option value="'.$name.'" '.(($val==$name)?'selected="selected"':'').' '.((pbSettingsFramework::getArrayKey('disabled', $args))?'disabled="disabled"':'').'>'.esc_html($value).'</option>';
158
- }
159
- $html .= '</select>';
160
-
161
- $desc = pbSettingsFramework::getArrayKey('desc', $args);
162
-
163
- if ( ! empty( $desc ) ) {
164
- $html .= '<p class="description">' . $desc . '</p>';
165
- }
166
-
167
- }
168
-
169
- echo $html;
170
- }
171
-
172
- public static function doSettingsSections( $page ) {
173
- global $wp_settings_sections, $wp_settings_fields;
174
-
175
- if ( ! isset( $wp_settings_sections[$page] ) )
176
- return;
177
-
178
- foreach ( (array) $wp_settings_sections[$page] as $section ) {
179
- if ( isset($section['prepend']) && !empty($section['prepend']) ){
180
- echo $section['prepend'];
181
- }
182
-
183
- if ( isset($section['title']) && !empty($section['title']) ) {
184
- echo "<h2 class='pb-section-title'>{$section['title']}</h2>\n";
185
- }
186
-
187
- if ( isset($section['callback']) && !empty($section['callback']) ) {
188
- call_user_func( $section['callback'], $section );
189
- }
190
-
191
- if ( ! isset( $wp_settings_fields ) || !isset( $wp_settings_fields[$page] ) || !isset( $wp_settings_fields[$page][$section['id']] ) )
192
- continue;
193
-
194
- echo '<div class="pb-section-wrap">';
195
- echo '<table class="form-table">';
196
- do_settings_fields( $page, $section['id'] );
197
- echo '</table>';
198
- echo '</div>';
199
-
200
- if ( isset($section['append']) && !empty($section['append']) ) {
201
- echo $section['append'];
202
- }
203
- }
204
- }
205
- }
206
- endif; //class_exists
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/pbSettingsFramework_2.php ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* Security-Check */
3
+ if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ if( ! class_exists('pbSettingsFramework_2') ):
6
+ class pbSettingsFramework_2
7
+ {
8
+ var $textDomain = false;
9
+ var $page = false;
10
+ var $section = false;
11
+ var $optionGroup = false;
12
+ var $args = array();
13
+
14
+ public function __construct( $args=array() )
15
+ {
16
+ $this->textDomain = $args['text-domain'] || 'pbSettingsFramework';
17
+ $this->page = $args['page'];
18
+ $this->section = $args['section'];
19
+ $this->optionGroup = $args['option-group'];
20
+ $this->args = $args;
21
+ }
22
+
23
+ /**
24
+ * Register setting
25
+ *
26
+ * @param string $setting
27
+ */
28
+ public function registerSetting( $setting )
29
+ {
30
+ if( ! isset($this->args['option-group']) ) {
31
+ die(__FUNCTION__.': $args[\'option-group\'] not set!');
32
+ }
33
+
34
+ register_setting(
35
+ $this->args['option-group'],
36
+ $setting
37
+ );
38
+ }
39
+
40
+ /**
41
+ * Add settings section
42
+ *
43
+ * @param $id
44
+ * @param $title
45
+ * @param $callback
46
+ */
47
+ public function addSettingsSection($id, $title, $callback)
48
+ {
49
+ add_settings_section(
50
+ $id,
51
+ $title,
52
+ $callback,
53
+ $this->args['page']
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Add settings field
59
+ *
60
+ * @param $id
61
+ * @param $title
62
+ * @param $args
63
+ * @param array $callback
64
+ * @param bool $register_setting
65
+ */
66
+ public function addSettingsField($id, $title, $args, $callback=array(), $register_setting=false)
67
+ {
68
+ if( count($callback) === 0 ) {
69
+ $callback = array($this, 'fieldsHTML');
70
+ }
71
+
72
+ if( $register_setting ) {
73
+ //register_setting( $this->args['option-group'], $id, 'esc_attr' );
74
+ $this->registerSetting( $this->optionGroup );
75
+ }
76
+
77
+ add_settings_field(
78
+ $id,
79
+ '<label for="'.$id.'">'.$title.'</label>',
80
+ $callback,
81
+ $this->page,
82
+ $this->section,
83
+
84
+ array_merge_recursive(
85
+ array(
86
+ 'id' => $id,
87
+ 'section' => $this->section
88
+ ),
89
+
90
+ $args
91
+ )
92
+ );
93
+ }
94
+
95
+ /**
96
+ * get array key
97
+ *
98
+ * @param $key
99
+ * @param $array
100
+ * @return bool
101
+ */
102
+ public function getArrayKey($key, $array)
103
+ {
104
+ if( array_key_exists($key, $array) ) {
105
+ return $array[$key];
106
+ } else {
107
+ return false;
108
+ }
109
+ }
110
+
111
+ /**
112
+ * html code for fields
113
+ *
114
+ * @param $args
115
+ */
116
+ public function fieldsHTML( $args )
117
+ {
118
+ $option = get_option($this->optionGroup);
119
+
120
+ if( isset($option[$args['id']]) ) {
121
+ $option = $option[$args['id']];
122
+ } else {
123
+ $option = null;
124
+ }
125
+
126
+ $html = '';
127
+
128
+ if( $this->getArrayKey('type', $args) == 'text' || $this->getArrayKey('type', $args) == 'number' ) {
129
+
130
+ if ( empty( $option ) ) {
131
+ $val = $this->getArrayKey('default', $args);
132
+ } else {
133
+ $val = $option;
134
+ }
135
+
136
+ if( $this->getArrayKey('type', $args) == 'number' ) {
137
+ $input_type = 'number';
138
+ } else {
139
+ $input_type = 'text';
140
+ }
141
+
142
+ $html = '<input type="'.$input_type.'" id="' . $args['id'] . '" name="'.$this->optionGroup.'['.$args['id'].']" class="regular-text" value="' . $val . '" '.(($this->getArrayKey('disabled', $args))?'disabled="disabled"':'').' />';
143
+
144
+ $desc = $this->getArrayKey('desc', $args);
145
+
146
+ if ( ! empty( $desc ) ) {
147
+ $html .= '<p class="description">' . $desc . '</p>';
148
+ }
149
+
150
+ } elseif( $args['type'] == 'checkbox' ) {
151
+
152
+ if( $option === false ){
153
+ $val = $this->getArrayKey('default', $args);
154
+ }else{
155
+ $val = $option;
156
+ }
157
+ $html = '<input type="checkbox" id="'.$args['id'].'" name="'.$this->optionGroup.'['.$args['id'].']" value="1" '.(($this->getArrayKey('disabled', $args))?'disabled="disabled"':'').' '.checked(1, $val, false).'/>';
158
+
159
+ $html .= '<label for="'.$args['id'].'"> '. $this->getArrayKey('desc', $args) .'</label>';
160
+
161
+ } elseif( $args['type'] == 'select' ) {
162
+
163
+ if ( empty( $option ) ) {
164
+ $val = $this->getArrayKey('default', $args);
165
+ } else {
166
+ $val = $option;
167
+ }
168
+
169
+ $html = '<select id="'.$args['id'].'" name="'.$this->optionGroup.'['.$args['id'].']">';
170
+ foreach ($args['select'] as $name => $value ) {
171
+ $html .= '<option value="'.$name.'" '.(($val==$name)?'selected="selected"':'').' '.(($this->getArrayKey('disabled', $args))?'disabled="disabled"':'').'>'.esc_html($value).'</option>';
172
+ }
173
+ $html .= '</select>';
174
+
175
+ $desc = $this->getArrayKey('desc', $args);
176
+
177
+ if ( ! empty( $desc ) ) {
178
+ $html .= '<p class="description">' . $desc . '</p>';
179
+ }
180
+
181
+ }
182
+
183
+ echo $html;
184
+ }
185
+
186
+ public function doSettingsSections( $page ) {
187
+ global $wp_settings_sections, $wp_settings_fields;
188
+
189
+ if ( ! isset( $wp_settings_sections[$page] ) )
190
+ return;
191
+
192
+ foreach ( (array) $wp_settings_sections[$page] as $section ) {
193
+ if ( isset($section['prepend']) && !empty($section['prepend']) ){
194
+ echo $section['prepend'];
195
+ }
196
+
197
+ if ( isset($section['title']) && !empty($section['title']) ) {
198
+ echo "<h2 class='pb-section-title'>{$section['title']}</h2>\n";
199
+ }
200
+
201
+ if ( isset($section['callback']) && !empty($section['callback']) ) {
202
+ call_user_func( $section['callback'], $section );
203
+ }
204
+
205
+ if ( ! isset( $wp_settings_fields ) || !isset( $wp_settings_fields[$page] ) || !isset( $wp_settings_fields[$page][$section['id']] ) )
206
+ continue;
207
+
208
+ echo '<div id="'.$section['id'].'" class="pb-section-wrap">';
209
+ echo '<table class="form-table">';
210
+ do_settings_fields( $page, $section['id'] );
211
+ echo '</table>';
212
+ echo '</div>';
213
+
214
+ if ( isset($section['append']) && !empty($section['append']) ) {
215
+ echo $section['append'];
216
+ }
217
+ }
218
+ }
219
+ }
220
+ endif;
inc/pbcockpitnotice.php ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if( ! class_exists('pbcockpitnotice') ):
3
+ class pbcockpitnotice
4
+ {
5
+ var $version = '20200216';
6
+
7
+ var $transient_name = 'cockpit_notice';
8
+ var $transient_closed_val = 'closed';
9
+ var $allowed_screens = array();
10
+ var $only_on_screens = false;
11
+ var $close_on_screens = false;
12
+ var $logo = false;
13
+ var $link_de = 'https://cockpit.bajorat-media.com/infos/';
14
+ var $link_en = 'https://cockpit.bajorat-media.com/en/infos/';
15
+
16
+ public function __construct( $config = array() )
17
+ {
18
+ $config = apply_filters('pbcockpitnotice_config', $config);
19
+
20
+ if( isset($config['logo']) && !empty($config['logo']) ) {
21
+ $this->logo = $config['logo'];
22
+ }
23
+
24
+ if( isset($config['allowed_screens']) && !empty($config['allowed_screens']) ) {
25
+ $this->allowed_screens = $config['allowed_screens'];
26
+ }
27
+
28
+ if( isset($config['only_on_screens']) && !empty($config['only_on_screens']) ) {
29
+ $this->only_on_screens = $config['only_on_screens'];
30
+ }
31
+
32
+ if( isset($config['close_on_screens']) && !empty($config['close_on_screens']) ) {
33
+ $this->close_on_screens = $config['close_on_screens'];
34
+ }
35
+
36
+ if( isset($config['link_de']) && !empty($config['link_de']) ) {
37
+ $this->link_de = $config['link_de'];
38
+ }
39
+
40
+ if( isset($config['link_en']) && !empty($config['link_en']) ) {
41
+ $this->link_en = $config['link_en'];
42
+ }
43
+
44
+ if( is_user_logged_in() && is_admin() ) {
45
+ $this->transient_name = apply_filters('pbcockpitnotice_transient_name', $this->transient_name);
46
+
47
+ add_action('admin_init', [$this, 'close']);
48
+ add_action('admin_notices', [$this, 'notice']);
49
+ }
50
+ }
51
+
52
+ public function notice()
53
+ {
54
+ global $pbcockpitnotice_duplicate_check;
55
+
56
+ $screen = get_current_screen();
57
+ $closed_transient = get_option($this->transient_name, false);
58
+
59
+ if( ! $closed_transient ) {
60
+ $closed_transient = get_transient($this->transient_name);
61
+ }
62
+
63
+ if( $pbcockpitnotice_duplicate_check === true ) return;
64
+
65
+ if( $closed_transient == $this->transient_closed_val &&
66
+ ( is_object($screen) && ! in_array($screen->id, $this->allowed_screens) ) ) return;
67
+
68
+ if( $this->only_on_screens &&
69
+ ( is_object($screen) && ! in_array($screen->id, $this->allowed_screens) ) ) return;
70
+
71
+ if( $this->close_on_screens &&
72
+ $closed_transient == $this->transient_closed_val ) return;
73
+
74
+ if (get_locale() == 'de_DE_formal' || get_locale() == 'de_DE') {
75
+ $link = $this->link_de;
76
+ } else {
77
+ $link = $this->link_en;
78
+ }
79
+
80
+ $pbcockpitnotice_duplicate_check = true;
81
+ ?>
82
+ <style type="text/css">
83
+
84
+ @import url('https://fonts.googleapis.com/css?family=Roboto:300,400&display=swap');
85
+
86
+ .bmcockpit-container {
87
+ margin: 0 auto;
88
+ box-sizing: border-box;
89
+ width: 100%;
90
+ padding: 45px 10px 5px 0;
91
+ }
92
+ <?php
93
+ foreach( $this->allowed_screens as $screen_id ) {
94
+ echo '.'.$screen_id.' .bmcockpit-container { padding: 20px 20px 10px 0; }';
95
+ }
96
+ ?>
97
+
98
+ .bmlogo {
99
+ padding:0;
100
+ border-radius:0;
101
+ position:absolute;
102
+ z-index:2;
103
+ top:50%;
104
+ left:30px;
105
+ transform: translate(0, -50%);
106
+ line-height:1;
107
+ outline: 0;
108
+ }
109
+ .bmcockpit-banner {
110
+ font-family: 'Roboto', sans-serif;
111
+ background: #0668b6;
112
+ background: -moz-linear-gradient(left, #0668b6 0%, #01b1cf 100%);
113
+ background: -webkit-linear-gradient(left, #0668b6 0%, #01b1cf 100%);
114
+ background: linear-gradient(to right, #0668b6 0%, #01b1cf 100%);
115
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0668b6', endColorstr='#01b1cf',GradientType=1 );
116
+ color: #fff;
117
+ padding: 20px 250px 20px 280px;
118
+ position: relative;
119
+ overflow:hidden;
120
+ box-sizing: border-box;
121
+ }
122
+ .bmcockpit-banner:before {
123
+ position:absolute;
124
+ content:'';
125
+ top:0;
126
+ left:200px;
127
+ width: 0;
128
+ height: 0;
129
+ border-style: solid;
130
+ border-width: 180px 0 0 100px;
131
+ border-color: transparent transparent transparent #fff;
132
+ z-index:1;
133
+ }
134
+ @media (max-width: 1470px) {
135
+ .bmcockpit-banner:before {
136
+ border-width: 230px 0 0 100px;
137
+ }
138
+ }
139
+ .bmcockpit-banner:after {
140
+ position:absolute;
141
+ top:0;
142
+ left:0;
143
+ content:'';
144
+ height:100%;
145
+ width:100%;
146
+ max-width:200px;
147
+ z-index:1;
148
+ background:#fff;
149
+ }
150
+ @media (max-width: 1200px) {
151
+ .bmcockpit-banner {
152
+ padding: 80px 30px 20px 30px;
153
+ text-align:center;
154
+ width:100%;
155
+ }
156
+ }
157
+ .bmcockpit-banner a.bmbtn {
158
+ background: #fff;
159
+ display: inline-block;
160
+ padding: 10px 20px;
161
+ border-radius: 30px;
162
+ color: #01b1cf !important;
163
+ border: none;
164
+ font-size:18px;
165
+ font-weight: 600;
166
+ cursor: pointer;
167
+ width: auto;
168
+ outline: none;
169
+ text-decoration: none;
170
+ transition: 0.3s ease-in-out all;
171
+ position: absolute;
172
+ top: 50%;
173
+ right: 40px;
174
+ transform: translate(0, -50%);
175
+ animation: pulse 2s infinite;
176
+ }
177
+ @media (max-width: 1200px) {
178
+ .bmcockpit-banner a.bmbtn {
179
+ position: static;
180
+ margin-top: 10px;
181
+ transform: none; }
182
+ }
183
+ .bmcockpit-banner a.bmbtn:hover {
184
+ /*animation: pulse 2s 1;*/
185
+ background: rgba(255, 255, 255, 0.9) !important; }
186
+ @-webkit-keyframes pulse {
187
+ 0% {
188
+ -webkit-box-shadow: 0 0 0 0 rgba(0, 255, 255, 0.7); }
189
+ 70% {
190
+ -webkit-box-shadow: 0 0 0 10px rgba(0, 255, 255, 0); }
191
+ 100% {
192
+ -webkit-box-shadow: 0 0 0 0 rgba(0, 255, 255, 0); } }
193
+ @keyframes pulse {
194
+ 0% {
195
+ -moz-box-shadow: 0 0 0 0 rgba(0, 255, 255, 0.7);
196
+ box-shadow: 0 0 0 0 rgba(0, 255, 255, 0.7); }
197
+ 70% {
198
+ -moz-box-shadow: 0 0 0 10px rgba(0, 255, 255, 0);
199
+ box-shadow: 0 0 0 10px rgba(0, 255, 255, 0); }
200
+ 100% {
201
+ -moz-box-shadow: 0 0 0 0 rgba(0, 255, 255, 0);
202
+ box-shadow: 0 0 0 0 rgba(0, 255, 255, 0); } }
203
+ .bmcockpit-banner h1,
204
+ .bmcockpit-banner p,
205
+ .bmcockpit-banner ul {
206
+ color: #fff;
207
+ margin: 0;
208
+ padding: 0;
209
+ font-size: 16px;
210
+ font-weight: 300; }
211
+ .bmcockpit-banner h1 {
212
+ font-size: 25px;
213
+ margin-bottom: 10px;
214
+ line-height: 1.2;
215
+ font-weight: 300; }
216
+
217
+ @media (max-width: 1600px) {
218
+ .bmcockpit-banner h1 {
219
+ font-size: 20px;}
220
+ }
221
+
222
+ .bmcockpit-banner ul.bmcockpit-benefits {
223
+ list-style: none;
224
+ margin-top: 0!important;
225
+ display: block; }
226
+ .bmcockpit-banner ul.bmcockpit-benefits li {
227
+ margin: 10px 15px 5px 0;
228
+ display: inline-block; }
229
+ .bmcockpit-banner ul.bmcockpit-benefits li:before {
230
+ content: '\2713';
231
+ padding: 0 5px;
232
+ color: #01b1cf;
233
+ margin-right: 5px;
234
+ display: inline-block;
235
+ background: #fff;
236
+ border-radius: 100px; }
237
+ .bmcockpit-banner .bmcockpit-banner-close {
238
+ position:absolute;
239
+ top:0;
240
+ right:0;
241
+ background:rgba(255,255,255,0.2);
242
+ color:#fff!important;
243
+ font-size:16px;
244
+ border-radius:0;
245
+ animation:none!important;
246
+ padding:5px 10px;
247
+ transform:none;
248
+ z-index:5;
249
+ text-decoration:none;
250
+ }
251
+ .bmcockpit-banner .bmcockpit-banner-close:hover {
252
+ color:#0668b6!important;
253
+ }
254
+ @media (max-width: 1200px) {
255
+ .bmcockpit-banner:before {
256
+ display:none;
257
+ }
258
+ .bmcockpit-banner:after {
259
+ content:'';
260
+ height:60px;
261
+ width:100%;
262
+ max-width:100%;
263
+ }
264
+ .bmcockpit-banner .bmlogo {
265
+ top:10px;
266
+ left:50%;
267
+ transform: translate(-50%, 0);
268
+ }
269
+ .bmcockpit-banner .bmcockpit-banner-close {
270
+ color:#0668b6!important;
271
+ }
272
+ .bmbtn-container {
273
+ text-align:center;
274
+ }
275
+ }
276
+
277
+ </style>
278
+ <div class="bmcockpit-container">
279
+ <div class="bmcockpit-banner">
280
+ <?php if( ( is_object($screen) && ! in_array($screen->id, $this->allowed_screens) ) || $this->close_on_screens ): ?>
281
+ <a class="bmcockpit-banner-close" href="<?php echo esc_url( admin_url('/?cockpit_notice=close') ); ?>">&#215;</a>
282
+ <?php endif; ?>
283
+
284
+ <a href="<?php echo esc_url($link); ?>" class="bmlogo" target="_blank">
285
+ <?php if( ! empty($this->logo) ): ?>
286
+ <img width="170" height="39" src="<?php echo esc_url($this->logo) ?>" alt="Bajorat Media" />
287
+ <?php endif; ?>
288
+ </a>
289
+
290
+ <?php if (get_locale() == 'de_DE_formal' || get_locale() == 'de_DE'): ?>
291
+ <h1>Design &amp; Entwicklungsleistungen rund um WordPress!</h1>
292
+ <ul class="bmcockpit-benefits">
293
+ <li>Kostenlose Projektanfrage</li>
294
+ <li>Schnelle Reaktionszeiten</li>
295
+ <li>Erfahrenes Team</li>
296
+ <li>OnDemand-Service</li>
297
+ </ul>
298
+
299
+ <div class="bmbtn-container">
300
+ <a class="bmbtn" href="<?php echo esc_url($link); ?>" target="_blank">Jetzt mehr erfahren!</a>
301
+ </div>
302
+ <?php else: ?>
303
+ <h1>Design &amp; development services for WordPress, try our on-demand service portal</h1>
304
+ <ul class="bmcockpit-benefits">
305
+ <li>free estimates</li>
306
+ <li>fast response times</li>
307
+ <li>experienced team</li>
308
+ <li>top service</li>
309
+ </ul>
310
+
311
+ <div class="bmbtn-container">
312
+ <a class="bmbtn" href="<?php echo esc_url($link); ?>" target="_blank">Find out more now!</a>
313
+ </div>
314
+ <?php endif; ?>
315
+
316
+ </div>
317
+ </div>
318
+ <?php
319
+ }
320
+
321
+ public function close()
322
+ {
323
+ if( isset($_GET['cockpit_notice']) && $_GET['cockpit_notice'] == 'close' ) {
324
+ update_option($this->transient_name, $this->transient_closed_val);
325
+ }
326
+ }
327
+ }
328
+ endif;
inc/pbsfi_admin_interface.php ADDED
@@ -0,0 +1,598 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* Security-Check */
3
+ if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class pbsfi_admin_interface
6
+ {
7
+ /** @var pbSEOFriendlyImages */
8
+ var $pbSEOFriendlyImages;
9
+
10
+ /** @var pbSettingsFramework_2 */
11
+ var $settingsFramework;
12
+
13
+ public function __construct( pbSEOFriendlyImages &$pb_SEO_friendly_images )
14
+ {
15
+ $this->pbSEOFriendlyImages = $pb_SEO_friendly_images;
16
+ }
17
+
18
+ /**
19
+ * Initialize Backend functions
20
+ */
21
+ public function initialize()
22
+ {
23
+ add_action( 'admin_enqueue_scripts', [ $this, 'css_js' ] );
24
+
25
+ add_action('admin_menu', [ $this, 'options_page_menu' ]);
26
+ add_action('admin_init', [ $this, 'init_settings' ]);
27
+
28
+ add_filter('plugin_action_links_'.$this->pbSEOFriendlyImages->plugin['basename'], [ $this, 'settings_link' ]);
29
+ }
30
+
31
+ /**
32
+ * Backend Assets
33
+ */
34
+ public function css_js()
35
+ {
36
+ wp_register_style(
37
+ 'pbsfi-admin-css',
38
+ $this->pbSEOFriendlyImages->plugin['url'].'/assets/css/admin.css',
39
+ false,
40
+ $this->pbSEOFriendlyImages->version
41
+ );
42
+
43
+ wp_enqueue_style( 'pbsfi-admin-css' );
44
+ }
45
+
46
+ /**
47
+ * Settings Link for Plugin Overview
48
+ *
49
+ * @param $data
50
+ *
51
+ * @return array
52
+ */
53
+ public function settings_link( $data )
54
+ {
55
+ if( ! current_user_can('manage_options') ) {
56
+ return $data;
57
+ }
58
+
59
+ $data = array_merge(
60
+ $data,
61
+ array(
62
+ sprintf(
63
+ '<a href="%s">%s</a>',
64
+ add_query_arg(
65
+ array(),
66
+ admin_url('options-general.php?page=pb-seo-friendly-images')
67
+ ),
68
+ __('Settings', 'pb-seo-friendly-images')
69
+ )
70
+ )
71
+ );
72
+
73
+ if( ! $this->pbSEOFriendlyImages->isProVersion() ) {
74
+ $data = array_merge(
75
+ $data,
76
+ array(
77
+ sprintf(
78
+ '<a href="%s" style="color: #e00; font-weight: bold;" target="_blank">%s</a>',
79
+ $this->pbSEOFriendlyImages->proURL,
80
+ __('Get Pro Version', 'pb-seo-friendly-images')
81
+ )
82
+ )
83
+ );
84
+ }
85
+
86
+ return $data;
87
+ }
88
+
89
+ /**
90
+ * Settings
91
+ */
92
+ public function init_settings()
93
+ {
94
+ $this->settingsFramework = new pbSettingsFramework_2(array(
95
+ 'text-domain' => 'pb-seo-friendly-images',
96
+ 'page' => 'pb-seo-friendly-images',
97
+ 'section' => 'pb-seo-friendly-images',
98
+ 'option-group' => 'pb-seo-friendly-images'
99
+ ));
100
+
101
+ //register_setting('pbseofriendlyimages_settings', 'pbseofriendlyimages_settings');
102
+ $this->settingsFramework->registerSetting( 'pb-seo-friendly-images' );
103
+
104
+ $this->settingsFramework->addSettingsSection(
105
+ 'pb-seo-friendly-images',
106
+ __('Image "alt" and "title" Settings', 'pb-seo-friendly-images'),
107
+ function()
108
+ {
109
+ echo '<div class="pb-section-wrap no-margin-bottom">';
110
+ echo '<p>'.__('PB SEO Friendly Images automatically adds "alt" and "title" attributes to all images and post thumbnails in your posts. The default options are a good starting point for the optimization and basically fine for most websites.', 'pb-seo-friendly-images').'</p>';
111
+ echo '<p><strong>'.__('Override feature', 'pb-seo-friendly-images').':</strong> '.__('Enable the override means that a possible sync and also hand picked "alt" / "title" attributes will be overwritten with the selected scheme. If you have good hand picked "alt" or "title" attributes in your images, I can not recommend to use the override. Automatic sync between "alt" and "title" will do it\'s best for you.', 'pb-seo-friendly-images').'</p>';
112
+
113
+ echo '<p>'.sprintf(
114
+ __('PB SEO Friendly Images Pro is a WordPress Plugin by <a href="%s" target="_blank">Pascal Bajorat</a> and made with %s in Berlin, Germany.', 'pb-seo-friendly-images'),
115
+ 'https://www.pascal-bajorat.com',
116
+ '<span style="color: #f00;">&#9829;</span>'
117
+ ).'</p>';
118
+
119
+ echo '<hr />';
120
+ echo '<p><strong style="text-decoration: underline;">'.__('How it works', 'pb-seo-friendly-images').':</strong> '.__('You only need to configure the plugin with the following settings. The plugin will optimize your HTML code on-the-fly. This means, that you see the "alt" and "title" directly in the HTML code output and not in your media library or editor. This is not a hard rewrite of your media library values. You can change this values without the risk to damage some media library data.', 'pb-seo-friendly-images').'</p>';
121
+
122
+ echo '</div>';
123
+
124
+ if( ! $this->pbSEOFriendlyImages->isProVersion() ) {
125
+ echo '<div class="pb-custom-message info"><p>';
126
+ echo sprintf(
127
+ __('Please consider upgrading to <a href="%s" target="_blank">PB SEO Friendly Images Pro</a> if you want to use more features and support the development of this plugin.', 'pb-seo-friendly-images'),
128
+ $this->pbSEOFriendlyImages->proURL
129
+
130
+ );
131
+ echo '</p><a href="'.$this->pbSEOFriendlyImages->proURL2.'" class="pb-btn" target="_blank">'.__('Upgrade now', 'pb-seo-friendly-images').'</a></div>';
132
+ }
133
+ }
134
+ );
135
+
136
+ $this->settingsFramework->addSettingsField(
137
+ 'optimize_img',
138
+ __('optimize images', 'pb-seo-friendly-images'),
139
+ array(
140
+ 'type' => 'select',
141
+ 'default' => 'all',
142
+ 'select' => array(
143
+ 'all' => __('post thumbnails and images in post content', 'pb-seo-friendly-images').' ('.__('recommended', 'pb-seo-friendly-images').')',
144
+ 'thumbs' => __('only post thumbnails', 'pb-seo-friendly-images'),
145
+ 'post' => __('only images in post content', 'pb-seo-friendly-images'),
146
+ ),
147
+ 'desc' => __('which images should be optimized', 'pb-seo-friendly-images'),
148
+ )
149
+ );
150
+
151
+ $this->settingsFramework->addSettingsField(
152
+ 'sync_method',
153
+ __('sync method', 'pb-seo-friendly-images'),
154
+ array(
155
+ 'type' => 'select',
156
+ 'default' => 'both',
157
+ 'select' => array(
158
+ 'both' => __('alt <=> title', 'pb-seo-friendly-images').' ('.__('recommended', 'pb-seo-friendly-images').')',
159
+ 'alt' => __('alt => title', 'pb-seo-friendly-images'),
160
+ 'title' => __('alt <= title', 'pb-seo-friendly-images'),
161
+ ),
162
+ 'desc' => __('select sync method for "alt" and "title" attribute.', 'pb-seo-friendly-images').'<br />'.
163
+ __('<code>alt <=> title</code> - if one attribute is set use it also for the other one', 'pb-seo-friendly-images').'<br />'.
164
+ __('<code>alt => title</code> - if "alt" is set use it for the title attribute', 'pb-seo-friendly-images').'<br />'.
165
+ __('<code>alt <= title</code> - if "title" is set use it for the alt attribute', 'pb-seo-friendly-images')
166
+ )
167
+ );
168
+
169
+ $this->settingsFramework->addSettingsField(
170
+ 'override_alt',
171
+ __('override "alt"', 'pb-seo-friendly-images'),
172
+ array(
173
+ 'type' => 'checkbox',
174
+ 'default' => '',
175
+ 'desc' => __('override existing image alt attributes', 'pb-seo-friendly-images')
176
+ )
177
+ );
178
+
179
+ $this->settingsFramework->addSettingsField(
180
+ 'override_title',
181
+ __('override "title"', 'pb-seo-friendly-images'),
182
+ array(
183
+ 'type' => 'checkbox',
184
+ 'default' => '',
185
+ 'desc' => __('override existing image title attributes', 'pb-seo-friendly-images')
186
+ )
187
+ );
188
+
189
+ $placeholder = __('possible variables:', 'pb-seo-friendly-images').'<br />'.
190
+ '<code>%title</code> - '.__('replaces post title', 'pb-seo-friendly-images').'<br />'.
191
+ '<code>%desc</code> - '.__('replaces post excerpt', 'pb-seo-friendly-images').'<br />'.
192
+ '<code>%name</code> - '.__('replaces image filename (without extension)', 'pb-seo-friendly-images').'<br />'.
193
+ '<code>%category</code> - '.__('replaces post category', 'pb-seo-friendly-images').'<br />'.
194
+ '<code>%tags</code> - '.__('replaces post tags', 'pb-seo-friendly-images').'<br />'.
195
+ '<code>%media_title</code> - '.__('replaces attachment title (could be empty if not set)', 'pb-seo-friendly-images').'<br />'.
196
+ '<code>%media_alt</code> - '.__('replaces attachment alt-text (could be empty if not set)', 'pb-seo-friendly-images').'<br />'.
197
+ '<code>%media_caption</code> - '.__('replaces attachment caption (could be empty if not set)', 'pb-seo-friendly-images').'<br />'.
198
+ '<code>%media_description</code> - '.__('replaces attachment description (could be empty if not set)', 'pb-seo-friendly-images');
199
+
200
+ $this->settingsFramework->addSettingsField(
201
+ 'alt_scheme',
202
+ __('alt scheme', 'pb-seo-friendly-images'),
203
+ array(
204
+ 'type' => 'text',
205
+ 'default' => '%name - %title',
206
+ 'desc' => __('default', 'pb-seo-friendly-images').': <code>%name - %title</code><br />'.$placeholder
207
+ )
208
+ );
209
+
210
+ $this->settingsFramework->addSettingsField(
211
+ 'title_scheme',
212
+ __('title scheme', 'pb-seo-friendly-images'),
213
+ array(
214
+ 'type' => 'text',
215
+ 'default' => '%title',
216
+ 'desc' => __('default', 'pb-seo-friendly-images').': <code>%title</code><br />'.$placeholder
217
+ )
218
+ );
219
+
220
+ /**
221
+ * Section Pro 4
222
+ */
223
+ $this->settingsFramework = new pbSettingsFramework_2(array(
224
+ 'text-domain' => 'pb-seo-friendly-images',
225
+ 'page' => 'pb-seo-friendly-images',
226
+ 'section' => 'pb-seo-friendly-images-pro5',
227
+ 'option-group' => 'pb-seo-friendly-images'
228
+ ));
229
+
230
+ $this->settingsFramework->addSettingsSection(
231
+ 'pb-seo-friendly-images-pro5',
232
+ '',
233
+ function()
234
+ {
235
+ echo '<h2 class="pro-section"><span>'.__('Pro Features', 'pb-seo-friendly-images').'</span></h2>';
236
+
237
+ echo '<h2 class="pb-section-title">'.__('Caching', 'pb-seo-friendly-images').'</h2>';
238
+ echo '<div class="pb-section-wrap no-margin-bottom">';
239
+ echo '<p>'.__('Caching can highly increase the performance of your website with PB SEO Friendly Images. If you already use a caching plugin you do not need to enable this function.', 'pb-seo-friendly-images').'</p>';
240
+ echo '<p>'.sprintf(__('We recommend to use <a href="%1$s" target="_blank">WP Rocket</a> as one of the best Performance and Caching Solutions for WordPress. If you are interested in a professional and individual Performance-Optimization <a href="%2$s" target="_blank">get a free quote here</a>.', 'pb-seo-friendly-images'), 'https://shareasale.com/r.cfm?b=1075949&u=1974809&m=74778&urllink=&afftrack=pb-seo-friendly-images', __('https://www.pascal-bajorat.com/en/lp/wordpress-performance-optimization/', 'pb-seo-friendly-images')).'</p>';
241
+ echo '</div>';
242
+
243
+ if( ! $this->pbSEOFriendlyImages->isProVersion() ) {
244
+ echo '<div class="pb-custom-message info"><p>';
245
+ echo sprintf(
246
+ __('Please consider upgrading to <a href="%s" target="_blank">PB SEO Friendly Images Pro</a> if you want to use this feature.', 'pb-seo-friendly-images'),
247
+ $this->pbSEOFriendlyImages->proURL
248
+ );
249
+ echo '</p><a href="'.$this->pbSEOFriendlyImages->proURL2.'" class="pb-btn" target="_blank">'.__('Upgrade now', 'pb-seo-friendly-images').'</a></div>';
250
+ }
251
+ }
252
+ );
253
+
254
+ $this->settingsFramework->addSettingsField(
255
+ 'enable_caching',
256
+ __('enable content caching', 'pb-seo-friendly-images'),
257
+ array(
258
+ 'type' => 'checkbox',
259
+ 'default' => true,
260
+ 'desc' => __('enable content caching and boost up your site speed with PB SEO Friendly Images', 'pb-seo-friendly-images'),
261
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
262
+ )
263
+ );
264
+
265
+ $this->settingsFramework->addSettingsField(
266
+ 'caching_ttl',
267
+ __('TTL', 'pb-seo-friendly-images'),
268
+ array(
269
+ 'type' => 'number',
270
+ 'default' => '86400',
271
+ 'desc' => __('TTL in seconds: 86400 = 24h; 3600 = 1h; 0 = never expire;', 'pb-seo-friendly-images'),
272
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
273
+ )
274
+ );
275
+
276
+ /**
277
+ * Section Pro
278
+ */
279
+ $this->settingsFramework = new pbSettingsFramework_2(array(
280
+ 'text-domain' => 'pb-seo-friendly-images',
281
+ 'page' => 'pb-seo-friendly-images',
282
+ 'section' => 'pb-seo-friendly-images-pro',
283
+ 'option-group' => 'pb-seo-friendly-images'
284
+ ));
285
+
286
+ $this->settingsFramework->addSettingsSection(
287
+ 'pb-seo-friendly-images-pro',
288
+ '',
289
+ function()
290
+ {
291
+ echo '<h2 class="pb-section-title">'.__('Lazy Load settings', 'pb-seo-friendly-images').'</h2>';
292
+ echo '<div class="pb-section-wrap no-margin-bottom">';
293
+ echo '<p>'.__('This function is very useful and it boosts performance by delaying loading of images in long web pages, because images outside of viewport (visible part of web page) won\'t be loaded until the user scrolls to them.', 'pb-seo-friendly-images').'</p>';
294
+ echo '<p>'.__('The lazy load is powered by unveil.js, one of the fastest and thinnest lazy loader in the web. The implementation is highly seo compatible with a no js fallback.', 'pb-seo-friendly-images').'</p>';
295
+ echo '<p>'.__('If enabled the lazy load will be added automatically to images in your post or page content and also to post thumbnails.', 'pb-seo-friendly-images').'</p>';
296
+ echo '</div>';
297
+
298
+ if( ! $this->pbSEOFriendlyImages->isProVersion() ) {
299
+ echo '<div class="pb-custom-message info"><p>';
300
+ echo sprintf(
301
+ __('Please consider upgrading to <a href="%s" target="_blank">PB SEO Friendly Images Pro</a> if you want to use this feature.', 'pb-seo-friendly-images'),
302
+ $this->pbSEOFriendlyImages->proURL
303
+ );
304
+ echo '</p><a href="'.$this->pbSEOFriendlyImages->proURL2.'" class="pb-btn" target="_blank">'.__('Upgrade now', 'pb-seo-friendly-images').'</a></div>';
305
+ }
306
+ }
307
+ );
308
+
309
+ $this->settingsFramework->addSettingsField(
310
+ 'enable_lazyload',
311
+ __('enable lazy load', 'pb-seo-friendly-images'),
312
+ array(
313
+ 'type' => 'checkbox',
314
+ 'default' => true,
315
+ 'desc' => __('enable lazy load and boost up your site speed', 'pb-seo-friendly-images'),
316
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
317
+ )
318
+ );
319
+
320
+ $this->settingsFramework->addSettingsField(
321
+ 'enable_lazyload_acf',
322
+ __('enable lazy load for acf', 'pb-seo-friendly-images'),
323
+ array(
324
+ 'type' => 'checkbox',
325
+ 'default' => true,
326
+ 'desc' => __('enable lazy load for AdvancedCustomFields', 'pb-seo-friendly-images'),
327
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
328
+ )
329
+ );
330
+
331
+ $this->settingsFramework->addSettingsField(
332
+ 'enable_lazyload_styles',
333
+ __('lazy load default styles', 'pb-seo-friendly-images'),
334
+ array(
335
+ 'type' => 'checkbox',
336
+ 'default' => false,
337
+ 'desc' => __('enable lazy load default styles', 'pb-seo-friendly-images'),
338
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
339
+ )
340
+ );
341
+
342
+ $this->settingsFramework->addSettingsField(
343
+ 'lazyload_threshold',
344
+ __('threshold', 'pb-seo-friendly-images'),
345
+ array(
346
+ 'type' => 'text',
347
+ 'default' => '0',
348
+ 'desc' => __('By default, images are only loaded when the user scrolls to them and they became visible on the screen (default value for this field <code>0</code>). If you want your images to load earlier than that, lets say 200px then you need to type in <code>200</code>.', 'pb-seo-friendly-images'),
349
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
350
+ )
351
+ );
352
+
353
+ /**
354
+ * Section Pro 2
355
+ */
356
+ $this->settingsFramework = new pbSettingsFramework_2(array(
357
+ 'text-domain' => 'pb-seo-friendly-images',
358
+ 'page' => 'pb-seo-friendly-images',
359
+ 'section' => 'pb-seo-friendly-images-pro2',
360
+ 'option-group' => 'pb-seo-friendly-images'
361
+ ));
362
+
363
+ $this->settingsFramework->addSettingsSection(
364
+ 'pb-seo-friendly-images-pro2',
365
+ '',
366
+ function()
367
+ {
368
+ echo '<h3 class="pb-section-title">'.__('Theme-Integration (only for developers relevant)', 'pb-seo-friendly-images').'</h3>';
369
+ echo '<div class="pb-section-wrap" style="margin-bottom: 2px">';
370
+ echo '<p>'.__('Want to add lazy load to images in your theme? You only need to do some small modifications. Add class "lazy" and modify the "src" like this:', 'pb-seo-friendly-images').'</p>';
371
+ echo '</div>';
372
+
373
+ echo '<div class="pb-custom-message code">';
374
+ echo '<p><code>&lt;img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="<strong>'.__('REAL SRC HERE', 'pb-seo-friendly-images').'</strong>" class="pb-seo-lazy" /&gt;</code></p>';
375
+ echo '</div>';
376
+ }
377
+ );
378
+
379
+ /**
380
+ * Section WooCommerce
381
+ */
382
+ $this->settingsFramework = new pbSettingsFramework_2(array(
383
+ 'text-domain' => 'pb-seo-friendly-images',
384
+ 'page' => 'pb-seo-friendly-images',
385
+ 'section' => 'pb-seo-friendly-images-pro3',
386
+ 'option-group' => 'pb-seo-friendly-images'
387
+ ));
388
+
389
+ $this->settingsFramework->addSettingsSection(
390
+ 'pb-seo-friendly-images-pro3',
391
+ '',
392
+ function()
393
+ {
394
+ echo '<h2 class="pb-section-title">'.__('WooCommerce settings', 'pb-seo-friendly-images').'</h2>';
395
+ echo '<div class="pb-section-wrap no-margin-bottom">';
396
+ echo '<p>'.__('This settings are specially for images inside your WooCommerce Shop. In most cases you need to activate the override to use your custom settings.', 'pb-seo-friendly-images').'</p>';
397
+ echo '</div>';
398
+
399
+ if( ! $this->pbSEOFriendlyImages->isProVersion() ) {
400
+ echo '<div class="pb-custom-message info"><p>';
401
+ echo sprintf(
402
+ __('Please consider upgrading to <a href="%s" target="_blank">PB SEO Friendly Images Pro</a> if you want to use this feature.', 'pb-seo-friendly-images'),
403
+ $this->pbSEOFriendlyImages->proURL
404
+ );
405
+ echo '</p><a href="'.$this->pbSEOFriendlyImages->proURL2.'" class="pb-btn" target="_blank">'.__('Upgrade now', 'pb-seo-friendly-images').'</a></div>';
406
+ }
407
+ }
408
+ );
409
+
410
+ $this->settingsFramework->addSettingsField(
411
+ 'wc_title',
412
+ __('WooCommerce', 'pb-seo-friendly-images'),
413
+ array(
414
+ 'type' => 'checkbox',
415
+ 'default' => false,
416
+ 'desc' => __('Use the product name as alt and title for WooCommerce product images', 'pb-seo-friendly-images'),
417
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
418
+ )
419
+ );
420
+
421
+ $this->settingsFramework->addSettingsField(
422
+ 'wc_sync_method',
423
+ __('sync method', 'pb-seo-friendly-images'),
424
+ array(
425
+ 'type' => 'select',
426
+ 'default' => 'both',
427
+ 'select' => array(
428
+ 'both' => __('alt <=> title', 'pb-seo-friendly-images').' ('.__('recommended', 'pb-seo-friendly-images').')',
429
+ 'alt' => __('alt => title', 'pb-seo-friendly-images'),
430
+ 'title' => __('alt <= title', 'pb-seo-friendly-images'),
431
+ ),
432
+ 'desc' => __('select sync method for "alt" and "title" attribute.', 'pb-seo-friendly-images').'<br />'.
433
+ __('<code>alt <=> title</code> - if one attribute is set use it also for the other one', 'pb-seo-friendly-images').'<br />'.
434
+ __('<code>alt => title</code> - if "alt" is set use it for the title attribute', 'pb-seo-friendly-images').'<br />'.
435
+ __('<code>alt <= title</code> - if "title" is set use it for the alt attribute', 'pb-seo-friendly-images'),
436
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
437
+ )
438
+ );
439
+
440
+ $this->settingsFramework->addSettingsField(
441
+ 'wc_override_alt',
442
+ __('override "alt"', 'pb-seo-friendly-images'),
443
+ array(
444
+ 'type' => 'checkbox',
445
+ 'default' => '',
446
+ 'desc' => __('override existing image alt attributes', 'pb-seo-friendly-images'),
447
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
448
+ )
449
+ );
450
+
451
+ $this->settingsFramework->addSettingsField(
452
+ 'wc_override_title',
453
+ __('override "title"', 'pb-seo-friendly-images'),
454
+ array(
455
+ 'type' => 'checkbox',
456
+ 'default' => '',
457
+ 'desc' => __('override existing image title attributes', 'pb-seo-friendly-images'),
458
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
459
+ )
460
+ );
461
+
462
+ $this->settingsFramework->addSettingsField(
463
+ 'wc_alt_scheme',
464
+ __('alt scheme', 'pb-seo-friendly-images'),
465
+ array(
466
+ 'type' => 'text',
467
+ 'default' => '%name - %title',
468
+ 'desc' => __('default', 'pb-seo-friendly-images').': <code>%name - %title</code><br />'.$placeholder,
469
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
470
+ )
471
+ );
472
+
473
+ $this->settingsFramework->addSettingsField(
474
+ 'wc_title_scheme',
475
+ __('title scheme', 'pb-seo-friendly-images'),
476
+ array(
477
+ 'type' => 'text',
478
+ 'default' => '%title',
479
+ 'desc' => __('default', 'pb-seo-friendly-images').': <code>%title</code><br />'.$placeholder,
480
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
481
+ )
482
+ );
483
+
484
+ /**
485
+ * Additional features
486
+ */
487
+ $this->settingsFramework = new pbSettingsFramework_2(array(
488
+ 'text-domain' => 'pb-seo-friendly-images',
489
+ 'page' => 'pb-seo-friendly-images',
490
+ 'section' => 'pb-seo-friendly-images-pro4',
491
+ 'option-group' => 'pb-seo-friendly-images'
492
+ ));
493
+
494
+ $this->settingsFramework->addSettingsSection(
495
+ 'pb-seo-friendly-images-pro4',
496
+ '',
497
+ function()
498
+ {
499
+ echo '<h2 class="pb-section-title">'.__('Additional features', 'pb-seo-friendly-images').'</h2>';
500
+ }
501
+ );
502
+
503
+ $this->settingsFramework->addSettingsField(
504
+ 'link_title',
505
+ __('set title for links', 'pb-seo-friendly-images'),
506
+ array(
507
+ 'type' => 'checkbox',
508
+ 'default' => false,
509
+ 'desc' => __('Use the power of PB SEO Friendly Images also for seo friendly links. This will set the title depending on the link text and only if there is no existing title', 'pb-seo-friendly-images'),
510
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
511
+ )
512
+ );
513
+
514
+ $this->settingsFramework->addSettingsField(
515
+ 'disable_srcset',
516
+ __('disable srcset', 'pb-seo-friendly-images'),
517
+ array(
518
+ 'type' => 'checkbox',
519
+ 'default' => false,
520
+ 'desc' => __('disable srcset attribute and responsive images in WordPress if you don\'t need them', 'pb-seo-friendly-images'),
521
+ 'disabled' => (($this->pbSEOFriendlyImages->isProVersion())?false:true)
522
+ )
523
+ );
524
+
525
+ /**
526
+ * Section Encoding and Parser
527
+ */
528
+ $this->settingsFramework = new pbSettingsFramework_2(array(
529
+ 'text-domain' => 'pb-seo-friendly-images',
530
+ 'page' => 'pb-seo-friendly-images',
531
+ 'section' => 'pb-seo-friendly-images-encoding',
532
+ 'option-group' => 'pb-seo-friendly-images'
533
+ ));
534
+
535
+ $this->settingsFramework->addSettingsSection(
536
+ 'pb-seo-friendly-images-encoding',
537
+ '',
538
+ function()
539
+ {
540
+ echo '<h2 class="pb-section-title">'.__('Encoding and Parser', 'pb-seo-friendly-images').'</h2>';
541
+ echo '<div class="pb-section-wrap no-margin-bottom">';
542
+ echo '<p>'.__('Here you can configure the HTML-Parser of the plugin. You <u>only</u> need to change this settings if you have <u>problems with your encoding</u> after activating the plugin.', 'pb-seo-friendly-images').'</p>';
543
+ echo '</div>';
544
+ }
545
+ );
546
+
547
+ $this->settingsFramework->addSettingsField(
548
+ 'encoding',
549
+ __('encoding', 'pb-seo-friendly-images'),
550
+ array(
551
+ 'type' => 'text',
552
+ 'default' => '',
553
+ 'desc' => __('leave blank to use WordPress default encoding or type in something like "utf-8"', 'pb-seo-friendly-images')
554
+ )
555
+ );
556
+
557
+ $this->settingsFramework->addSettingsField(
558
+ 'encoding_mode',
559
+ __('encoding mode', 'pb-seo-friendly-images'),
560
+ array(
561
+ 'type' => 'select',
562
+ 'default' => 'entities',
563
+ 'select' => array(
564
+ 'entities' => __('HTML-ENTITIES', 'pb-seo-friendly-images').' ('.__('default', 'pb-seo-friendly-images').')',
565
+ 'off' => __('disable convert encoding', 'pb-seo-friendly-images'),
566
+ )
567
+ )
568
+ );
569
+ }
570
+
571
+ /**
572
+ * Admin Menu
573
+ */
574
+ public function options_page_menu()
575
+ {
576
+ add_submenu_page(
577
+ 'options-general.php',
578
+ __('PB SEO Friendly Images', 'pb-seo-friendly-images'),
579
+ __('SEO Friendly Images', 'pb-seo-friendly-images'),
580
+ 'manage_options',
581
+ 'pb-seo-friendly-images',
582
+ [ $this, 'options_page' ]
583
+ );
584
+ }
585
+
586
+ /**
587
+ * Load Options Page
588
+ */
589
+ public function options_page()
590
+ {
591
+ if ( ! current_user_can('manage_options') ) {
592
+ return;
593
+ }
594
+
595
+ // Backend Template
596
+ require_once $this->pbSEOFriendlyImages->plugin['path'] . 'templates/options_page.php';
597
+ }
598
+ }
inc/pbsfi_cache.php ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* Security-Check */
3
+ if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class pbsfi_cache
6
+ {
7
+ protected $status;
8
+ protected $expire;
9
+
10
+ protected $prefix = 'pbsfi_cache_';
11
+
12
+ public function __construct($status=false, $expire=3600)
13
+ {
14
+ $this->status = $status;
15
+ $this->expire = $expire;
16
+ }
17
+
18
+ /**
19
+ * Get content from transient cache
20
+ *
21
+ * @param $key
22
+ * @return bool|mixed
23
+ */
24
+ public function get_cache( $key )
25
+ {
26
+ if( $this->status !== true )
27
+ return false;
28
+
29
+ $cache = get_transient($this->prefix.$key);
30
+
31
+ if( $cache ) {
32
+ return $cache;
33
+ }
34
+
35
+ return false;
36
+ }
37
+
38
+ /**
39
+ * Set content for transient cache
40
+ *
41
+ * @param $key
42
+ * @param $value
43
+ * @return bool
44
+ */
45
+ public function set_cache($key, $value)
46
+ {
47
+ if( $this->status !== true )
48
+ return false;
49
+
50
+ return set_transient($this->prefix.$key, $value, $this->expire);
51
+ }
52
+
53
+ /**
54
+ * Delete a transient
55
+ *
56
+ * @param $key
57
+ * @return bool
58
+ */
59
+ public function delete_cache($key)
60
+ {
61
+ return delete_transient($this->prefix.$key);
62
+ }
63
+
64
+ /**
65
+ * Clear transients for a specific post
66
+ *
67
+ * @param $post_ID
68
+ * @return int
69
+ */
70
+ public function clear_post_cache($post_ID)
71
+ {
72
+ if( ! is_numeric($post_ID) ) return false;
73
+
74
+ global $wpdb;
75
+
76
+ $results = $wpdb->get_results( "SELECT option_name FROM {$wpdb->prefix}options WHERE option_name LIKE '_transient_{$this->prefix}post_{$post_ID}%'", OBJECT );
77
+
78
+ $deleted = 0;
79
+
80
+ if( $results ) {
81
+ foreach($results as $result) {
82
+ $key = str_replace('_transient_'.$this->prefix, '', $result->option_name);
83
+ $this->delete_cache( $key );
84
+
85
+ $deleted++;
86
+ }
87
+ }
88
+
89
+ return $deleted;
90
+ }
91
+
92
+ /**
93
+ * Clear site cache
94
+ *
95
+ * @return int
96
+ */
97
+ public function clear_cache()
98
+ {
99
+ global $wpdb;
100
+
101
+ $results = $wpdb->get_results( "SELECT option_name FROM {$wpdb->prefix}options WHERE option_name LIKE '_transient_{$this->prefix}post_%'", OBJECT );
102
+
103
+ $deleted = 0;
104
+
105
+ if( $results ) {
106
+ foreach($results as $result) {
107
+ $key = str_replace('_transient_'.$this->prefix, '', $result->option_name);
108
+ $this->delete_cache( $key );
109
+ $deleted++;
110
+ }
111
+ }
112
+
113
+ return $deleted;
114
+ }
115
+ }
inc/pbsfi_frontend.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* Security-Check */
3
+ if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class pbsfi_frontend
6
+ {
7
+ /** @var pbSEOFriendlyImages */
8
+ var $pbSEOFriendlyImages;
9
+
10
+ /** @var pbsfi_optimizer */
11
+ var $optimizer;
12
+
13
+ var $enable_caching = false;
14
+ var $caching_ttl = 3600;
15
+
16
+ public function __construct( pbSEOFriendlyImages &$pb_SEO_friendly_images )
17
+ {
18
+ $this->pbSEOFriendlyImages = $pb_SEO_friendly_images;
19
+
20
+ if( isset($this->pbSEOFriendlyImages->settings['enable_caching']) && $this->pbSEOFriendlyImages->settings['enable_caching'] == true ) {
21
+ $this->enable_caching = true;
22
+ }
23
+
24
+ if( isset($this->pbSEOFriendlyImages->settings['caching_ttl']) && is_numeric($this->pbSEOFriendlyImages->settings['caching_ttl']) ) {
25
+ $this->caching_ttl = $this->pbSEOFriendlyImages->settings['caching_ttl'];
26
+ }
27
+ }
28
+
29
+ /**
30
+ * initialize frontend functions
31
+ *
32
+ * @return void
33
+ */
34
+ public function initialize()
35
+ {
36
+ // process post thumbnails
37
+ if( isset($this->pbSEOFriendlyImages->settings['optimize_img']) && ($this->pbSEOFriendlyImages->settings['optimize_img'] == 'all' || $this->pbSEOFriendlyImages->settings['optimize_img'] == 'thumbs') ) {
38
+
39
+ if( function_exists('is_woocommerce') && is_woocommerce() && $this->pbSEOFriendlyImages->isProVersion() ) {
40
+
41
+ add_filter( 'wp_get_attachment_image_attributes', [ $this, 'optimize_image_attributes' ], 10, 2 );
42
+
43
+ } else {
44
+ add_filter( 'wp_get_attachment_image_attributes', [ $this, 'optimize_image_attributes' ], 10, 2 );
45
+ }
46
+
47
+ } else if( function_exists('is_woocommerce') && is_woocommerce() && $this->pbSEOFriendlyImages->isProVersion() ) {
48
+ add_filter( 'wp_get_attachment_image_attributes', [ $this, 'optimize_image_attributes' ], 10, 2 );
49
+ }
50
+
51
+ // process post images
52
+ if( isset($this->pbSEOFriendlyImages->settings['optimize_img']) && ($this->pbSEOFriendlyImages->settings['optimize_img'] == 'all' || $this->pbSEOFriendlyImages->settings['optimize_img'] == 'post') ) {
53
+ add_filter( 'the_content', [ $this, 'optimize_html' ], 9999, 1 );
54
+
55
+ /*
56
+ * Support for AdvancedCustomFields
57
+ */
58
+ add_filter('acf/load_value/type=textarea', [ $this, 'optimize_html' ], 20, 3);
59
+ add_filter('acf/load_value/type=wysiwyg', [ $this, 'optimize_html' ], 20, 3);
60
+
61
+ // support for acf below v.4 removed
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Check if the optimizer is already initialized and initialize if not
67
+ *
68
+ * @return void
69
+ */
70
+ private function _maybe_initialize_optimizer()
71
+ {
72
+ if( false === is_a($this->optimizer, 'pbsfi_optimizer') ) {
73
+ $this->optimizer = new pbsfi_optimizer( $this->pbSEOFriendlyImages->settings );
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Optimize given HTML code
79
+ *
80
+ * @param string $content
81
+ *
82
+ * @param int $post_id
83
+ * @param null|string $field
84
+ * @return string
85
+ */
86
+ public function optimize_html( $content, $post_id=0, $field=null )
87
+ {
88
+ if( $post_id === 0 ) {
89
+ // set post_id
90
+ $post_id = get_the_ID();
91
+ }
92
+
93
+ $caching = apply_filters('pbsfi_optimize_html_caching', $this->enable_caching, $post_id, $field);
94
+
95
+ // Get Cache
96
+ if( $caching ) {
97
+ $cache = new pbsfi_cache($this->enable_caching, $this->caching_ttl);
98
+
99
+ $cache_key = 'post_'.$post_id.(!empty($field) ? '_'.$field : '');
100
+
101
+ $cache_item = $cache->get_cache( $cache_key );
102
+
103
+ if( $cache_item )
104
+ return $cache_item;
105
+ }
106
+
107
+ // maybe initialize the optimizer class
108
+ $this->_maybe_initialize_optimizer();
109
+
110
+ // optimize html
111
+ $content = $this->optimizer->optimize_html( $content );
112
+
113
+ // Set Cache
114
+ if( $caching && isset($cache_key) && isset($cache) ) {
115
+ $cache->set_cache($cache_key, $content);
116
+ }
117
+
118
+ return $content;
119
+ }
120
+
121
+ /**
122
+ * Add image title and alt to post thumbnails
123
+ *
124
+ * @param array $attr
125
+ * @param WP_Post $attachment
126
+ * @return array
127
+ */
128
+ public function optimize_image_attributes( $attr, $attachment = null )
129
+ {
130
+ // maybe initialize the optimizer class
131
+ $this->_maybe_initialize_optimizer();
132
+
133
+ // optimize image attributes
134
+ $attr = $this->optimizer->optimize_image_attributes( $attr, $attachment );
135
+
136
+ return $attr;
137
+ }
138
+ }
inc/pbsfi_optimizer.php ADDED
@@ -0,0 +1,519 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* Security-Check */
3
+ if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class pbsfi_optimizer
6
+ {
7
+ protected $settings = array();
8
+ protected $defaults = array();
9
+
10
+ /** @var DOMDocument */
11
+ protected $document;
12
+
13
+ public function __construct( $settings=array() )
14
+ {
15
+ // check WP charset or set default to utf-8
16
+ $charset = ( (defined('DB_CHARSET') ) ? DB_CHARSET : 'utf-8' );
17
+
18
+ // default settings
19
+ $this->defaults = array(
20
+ 'encoding' => $charset,
21
+ 'encoding_mode' => 'off',
22
+ 'create_domdocument' => true
23
+ );
24
+
25
+ // merge defaults and custom settings
26
+ $this->settings = array_merge(
27
+ $this->defaults,
28
+ $settings
29
+ );
30
+
31
+ // settings filter
32
+ $this->settings = apply_filters('pbsfi_optimizer_settings', $this->settings);
33
+
34
+ if( class_exists('DOMDocument') && false !== $this->settings['create_domdocument'] ) {
35
+
36
+ $this->document = new DOMDocument( '1.0', $this->settings['encoding'] );
37
+
38
+ $this->document = apply_filters(
39
+ 'pbsfi_optimizer_domdocument', // filter name
40
+ $this->document, // create DOMDocument
41
+ $this->settings // settings
42
+ );
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Check if content could be optimized
48
+ *
49
+ * @param array $data data for the optimization check
50
+ *
51
+ * @return bool
52
+ */
53
+ public function is_optimization_allowed( $data=array() )
54
+ {
55
+ if(
56
+ ! class_exists('DOMDocument') || // do not run optimization, DOMDocument not available
57
+ get_post_type() == 'tribe_events' || // exclude for Events Calendar
58
+ is_feed() || // exclude for feeds
59
+ strstr( strtolower($data['content']), 'arforms') || // exclude for ARForms
60
+ strstr( strtolower($data['content']), 'arf_form') || // exclude for ARForms
61
+ strstr( strtolower($data['content']), 'spb_gallery') || // exclude for spb_gallery_widget
62
+ isset($_GET['dslc']) // exclude for LiveComposer
63
+ ) {
64
+ return apply_filters( 'is_optimization_allowed', false, $data );
65
+ }
66
+
67
+ return apply_filters( 'is_optimization_allowed', true, $data );
68
+ }
69
+
70
+ /**
71
+ * get array key
72
+ *
73
+ * @param $key
74
+ * @param $array
75
+ * @return bool
76
+ */
77
+ public function get_array_key($key, $array)
78
+ {
79
+ if( array_key_exists($key, $array) ) {
80
+ return $array[$key];
81
+ } else {
82
+ return false;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * get image id by url
88
+ *
89
+ * @param $url
90
+ *
91
+ * @return bool|int
92
+ */
93
+ public function get_image_id($url)
94
+ {
95
+ global $wpdb;
96
+
97
+ $transient_name = sanitize_title( $url );
98
+ $transient = get_transient( $transient_name );
99
+
100
+ // return numeric transient
101
+ if( false !== $transient && is_numeric($transient) ) {
102
+ return (int) $transient;
103
+ }
104
+
105
+ // transient with false string (details below)
106
+ if( false !== $transient && 'false' === $transient ) {
107
+ return false;
108
+ }
109
+
110
+ $sql = $wpdb->prepare(
111
+ 'SELECT `ID` FROM `'.$wpdb->posts.'` WHERE `guid` = \'%s\';',
112
+ esc_sql($url)
113
+ );
114
+
115
+ $attachment = $wpdb->get_col($sql);
116
+
117
+ if( is_numeric( $this->get_array_key(0, $attachment) ) ) {
118
+
119
+ // set transient
120
+ set_transient( $transient_name, $attachment[0], YEAR_IN_SECONDS );
121
+
122
+ return (int) $attachment[0];
123
+ }
124
+
125
+ // set transient => false as string because transients can't deal with boolean values
126
+ set_transient( $transient_name, 'false', YEAR_IN_SECONDS );
127
+
128
+ return false;
129
+ }
130
+
131
+ public function convert_replacements( $content, $data=array() )
132
+ {
133
+
134
+ $post = get_post();
135
+ $imageID = ( (isset($data['image_id'])) ? $data['image_id'] : '' );
136
+ $src = ( (isset($data['src'])) ? $data['src'] : '');
137
+
138
+ $cats = '';
139
+ if ( strrpos( $content, '%category' ) !== false ) {
140
+
141
+ if( get_post_type($post) == 'product' ) {
142
+ $categories = get_the_terms( $post->ID, 'product_cat' );
143
+ if ( ! $categories || is_wp_error( $categories ) ) {
144
+ $categories = array();
145
+ }
146
+
147
+ $categories = array_values( $categories );
148
+
149
+ foreach ( array_keys( $categories ) as $key ) {
150
+ _make_cat_compat( $categories[$key] );
151
+ }
152
+ } else {
153
+ $categories = get_the_category();
154
+ }
155
+
156
+ if ( $categories ) {
157
+ $i = 0;
158
+ foreach ( $categories as $cat ) {
159
+ if ( $i == 0 ) {
160
+ $cats = $cat->slug . $cats;
161
+ } else {
162
+ $cats = $cat->slug . ', ' . $cats;
163
+ }
164
+ ++$i;
165
+ }
166
+ }
167
+ }
168
+
169
+ $tags = '';
170
+ if ( strrpos( $content, '%tags' ) !== false ) {
171
+ $posttags = get_the_tags();
172
+
173
+ if ( $posttags ) {
174
+ $i = 0;
175
+ foreach ( $posttags as $tag ) {
176
+ if ( $i == 0 ) {
177
+ $tags = $tag->name . $tags;
178
+ } else {
179
+ $tags = $tag->name . ', ' . $tags;
180
+ }
181
+ ++$i;
182
+ }
183
+ }
184
+ }
185
+
186
+ if( $src ) {
187
+ $info = @pathinfo($src);
188
+ $src = @basename($src,'.'.$info['extension']);
189
+
190
+ $src = str_replace('-', ' ', $src);
191
+ $src = str_replace('_', ' ', $src);
192
+ } else {
193
+ $src = '';
194
+ }
195
+
196
+ if( is_numeric($imageID) ) {
197
+ $attachment = wp_prepare_attachment_for_js($imageID);
198
+
199
+ if( is_array($attachment) ) {
200
+ $content = str_replace('%media_title', $attachment['title'], $content );
201
+ $content = str_replace('%media_alt', $attachment['alt'], $content );
202
+ $content = str_replace('%media_caption', $attachment['caption'], $content );
203
+ $content = str_replace('%media_description', $attachment['description'], $content );
204
+ }
205
+ }
206
+
207
+ $content = str_replace('%media_title', $post->post_title, $content );
208
+ $content = str_replace('%media_alt', $post->post_title, $content );
209
+ $content = str_replace('%media_caption', $post->post_title, $content );
210
+ $content = str_replace('%media_description', $post->post_title, $content );
211
+
212
+ $content = str_replace('%name', $src, $content );
213
+ $content = str_replace('%title', $post->post_title, $content );
214
+ $content = str_replace('%category', $cats, $content );
215
+ $content = str_replace('%tags', $tags, $content );
216
+ $content = str_replace('%desc', $post->post_excerpt, $content);
217
+
218
+ return $content;
219
+ }
220
+
221
+ public function optimize_html( $content, $force_optimization = false )
222
+ {
223
+ $is_optimization_allowed = $this->is_optimization_allowed([
224
+ 'post_id' => get_the_ID(),
225
+ 'post_type' => get_post_type(),
226
+ 'content' => $content
227
+ ]);
228
+
229
+ // filter for $is_optimization_allowed
230
+ $is_optimization_allowed = apply_filters( 'optimize_html__is_optimization_allowed', $is_optimization_allowed );
231
+
232
+ // Check if content could be optimized and if optimization is allowed
233
+ if( false === $is_optimization_allowed && true !== $force_optimization ) {
234
+ return $content;
235
+ }
236
+
237
+ // check again if DOMDocument is really available in case of force_optimization setting
238
+ if( ! is_a($this->document, 'DOMDocument') ) {
239
+ return $content;
240
+ }
241
+
242
+ $encoding_declaration = sprintf('<?xml encoding="%s" ?>', $this->settings['encoding']);
243
+
244
+ // Optimize encoding
245
+ if( function_exists('mb_convert_encoding') && $this->settings['encoding_mode'] != 'off' ) {
246
+ //$content = @mb_convert_encoding( $content, 'utf-8', $this->settings['encoding'] );
247
+ $content = @mb_convert_encoding( $content, 'HTML-ENTITIES', $this->settings['encoding'] );
248
+ } else {
249
+ $content = $encoding_declaration.$content;
250
+ }
251
+
252
+ @$this->document->loadHTML( $content ); // LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
253
+
254
+
255
+ if( ! $this->document ) return $content;
256
+
257
+ /*
258
+ * Use WooCommerce settings if is pro and WC page
259
+ */
260
+ if( function_exists('is_woocommerce') && is_woocommerce() && $this->settings['proVersion'] ) {
261
+ if( isset($this->settings['wc_sync_method']) ) {
262
+ $this->settings['sync_method'] = $this->settings['wc_sync_method'];
263
+ }
264
+
265
+ if( isset($this->settings['wc_title_scheme']) ) {
266
+ $this->settings['title_scheme'] = $this->settings['wc_title_scheme'];
267
+ }
268
+
269
+ if( isset($this->settings['wc_alt_scheme']) ) {
270
+ $this->settings['alt_scheme'] = $this->settings['wc_alt_scheme'];
271
+ }
272
+
273
+ if( isset($this->settings['wc_override_title']) ) {
274
+ $this->settings['override_title'] = $this->settings['wc_override_title'];
275
+ }
276
+
277
+ if( isset($this->settings['wc_override_alt']) ) {
278
+ $this->settings['override_alt'] = $this->settings['wc_override_alt'];
279
+ }
280
+ }
281
+
282
+ /*
283
+ * Optimize Figure
284
+ *
285
+ * Recommendation by BasTaller
286
+ * @url https://wordpress.org/support/topic/proposal-for-best-replacement/
287
+ */
288
+ $figTags = $this->document->getElementsByTagName('figure');
289
+
290
+ if( $figTags->length ) {
291
+ foreach ($figTags as $tag){
292
+ $caption = $tag->nodeValue;
293
+ $imgTags = $tag->getElementsByTagName('img');
294
+
295
+ if( empty($caption) )
296
+ continue;
297
+
298
+ foreach ($imgTags as $tag) {
299
+ $tag->setAttribute('title', $caption);
300
+ }
301
+ }
302
+ }
303
+
304
+ // check for image tags
305
+ $imgTags = $this->document->getElementsByTagName('img');
306
+
307
+ // return $content if there are no image tags in $content
308
+ if( $imgTags->length ) {
309
+
310
+ // check all image tags
311
+ foreach ($imgTags as $tag) {
312
+ $data_src = trim($tag->getAttribute('data-src'));
313
+ $src = trim($tag->getAttribute('src'));
314
+
315
+ if( !empty($data_src) ) {
316
+ $src = $data_src;
317
+ }
318
+
319
+ $imageID = $this->get_image_id($src);
320
+
321
+ /**
322
+ * Override Area
323
+ */
324
+ if( isset($this->settings['override_alt']) ) {
325
+ $alt = trim($this->convert_replacements(
326
+ $this->settings['alt_scheme'],
327
+ array(
328
+ 'src' => $src,
329
+ 'image_id' => $imageID
330
+ )
331
+ ));
332
+
333
+ $alt = apply_filters('pbsfi-alt', $alt);
334
+
335
+ $tag->setAttribute('alt', $alt);
336
+ } else {
337
+ $alt = trim($tag->getAttribute('alt'));
338
+ $alt = apply_filters('pbsfi-alt', $alt);
339
+ }
340
+
341
+ if( isset($this->settings['override_title']) ) {
342
+
343
+ $title = trim($this->convert_replacements(
344
+ $this->settings['title_scheme'],
345
+ array(
346
+ 'src' => $src,
347
+ 'image_id' => $imageID
348
+ )
349
+ ));
350
+
351
+ $title = apply_filters('pbsfi-title', $title);
352
+
353
+ $tag->setAttribute('title', $title);
354
+ } else {
355
+ $title = trim($tag->getAttribute('title'));
356
+ $title = apply_filters('pbsfi-title', $title);
357
+ }
358
+
359
+ /**
360
+ * Check attributes
361
+ */
362
+ if( !empty($alt) && empty($title) && ($this->settings['sync_method'] == 'both' || $this->settings['sync_method'] == 'alt' ) ) {
363
+
364
+ $alt = apply_filters('pbsfi-title', $alt);
365
+ $tag->setAttribute('title', $alt);
366
+ $title = $alt;
367
+
368
+ } else if( empty($alt) && !empty($title) && ($this->settings['sync_method'] == 'both' || $this->settings['sync_method'] == 'title' ) ) {
369
+
370
+ $title = apply_filters('pbsfi-alt', $title);
371
+ $tag->setAttribute('alt', $title);
372
+ $alt = $title;
373
+
374
+ }
375
+
376
+ /**
377
+ * set if empty after sync
378
+ */
379
+ if( empty($alt) ) {
380
+ $alt = trim($this->convert_replacements(
381
+ $this->settings['alt_scheme'],
382
+ array(
383
+ 'src' => $src,
384
+ 'image_id' => $imageID
385
+ )
386
+ ));
387
+
388
+ $alt = apply_filters('pbsfi-alt', $alt);
389
+ $tag->setAttribute('alt', $alt);
390
+ }
391
+
392
+ if( empty($title) ) {
393
+ $title = trim($this->convert_replacements(
394
+ $this->settings['title_scheme'],
395
+ array(
396
+ 'src' => $src,
397
+ 'image_id' => $imageID
398
+ )
399
+ ));
400
+
401
+ $title = apply_filters('pbsfi-title', $title);
402
+ $tag->setAttribute('title', $title);
403
+ }
404
+ }
405
+
406
+ }
407
+
408
+ $aTags = $this->document->getElementsByTagName('a');
409
+
410
+ if( $this->settings['proVersion'] && isset($this->settings['link_title']) && $this->settings['link_title'] && $aTags->length ) {
411
+
412
+ foreach ($aTags as $tag) {
413
+ $title = trim( $tag->getAttribute('title') );
414
+
415
+ if( empty($title) ) {
416
+
417
+ $newTitle = '';
418
+
419
+ if( ! empty( $tag->textContent ) ) {
420
+
421
+ $newTitle = $tag->textContent;
422
+
423
+ } elseif( $tag->hasChildNodes() ) {
424
+ $childNodes = $tag->childNodes;
425
+
426
+ if( ! $childNodes->length || $childNodes->length == 0 )
427
+ continue;
428
+
429
+ foreach( $childNodes as $subChildNodes ) {
430
+ if( ! empty( $subChildNodes->textContent ) ) {
431
+
432
+ $newTitle = $subChildNodes->textContent;
433
+ break;
434
+
435
+ } elseif( $subChildNodes->tagName == 'img' ) {
436
+ $title = trim( $subChildNodes->getAttribute('title') );
437
+
438
+ if( !empty($title) ) {
439
+ $newTitle = $title;
440
+ break;
441
+ }
442
+ }
443
+ }
444
+ }
445
+
446
+ $tag->setAttribute('title', $newTitle);
447
+ }
448
+ }
449
+
450
+ }
451
+
452
+ $return = $this->document->saveHTML();
453
+ $return = str_replace($encoding_declaration, '', $return);
454
+ $return = preg_replace('/^<!DOCTYPE.+?>/', '', str_replace( array('<html>', '</html>', '<body>', '</body>'), array('', '', '', ''), $return));
455
+
456
+ return $return;
457
+ }
458
+
459
+ /**
460
+ * Add image title and alt to post thumbnails
461
+ *
462
+ * @param array $attr
463
+ * @param WP_Post $attachment
464
+ * @return array
465
+ */
466
+ public function optimize_image_attributes( $attr, $attachment = null )
467
+ {
468
+ if( function_exists('is_woocommerce') && is_woocommerce() && $this->settings['proVersion'] ) {
469
+ $title_scheme = (isset($this->settings['wc_title_scheme']) ? $this->settings['wc_title_scheme'] : '');
470
+ $alt_scheme = (isset($this->settings['wc_title_scheme']) ? $this->settings['wc_alt_scheme'] : '');
471
+ $sync_method = (isset($this->settings['wc_title_scheme']) ? $this->settings['wc_sync_method'] : '');
472
+ } else {
473
+ $title_scheme = (isset($this->settings['wc_title_scheme']) ? $this->settings['title_scheme'] : '');
474
+ $alt_scheme = (isset($this->settings['wc_title_scheme']) ? $this->settings['alt_scheme'] : '');
475
+ $sync_method = (isset($this->settings['wc_title_scheme']) ? $this->settings['sync_method'] : '');
476
+ }
477
+
478
+ if( empty($attr['alt']) ) {
479
+
480
+ $attr['title'] = trim($this->convert_replacements(
481
+ $title_scheme,
482
+ array(
483
+ 'src' => $attr['src']
484
+ )
485
+ ));
486
+
487
+ $attr['alt'] = trim($this->convert_replacements(
488
+ $alt_scheme,
489
+ array(
490
+ 'src' => $attr['src']
491
+ )
492
+ ));
493
+
494
+ } else {
495
+
496
+ if( $sync_method == 'both' || $sync_method == 'alt' ) {
497
+ $attr['title'] = trim( strip_tags($attachment->post_title) );
498
+ } else {
499
+ $attr['title'] = trim($this->convert_replacements(
500
+ $title_scheme,
501
+ array(
502
+ 'src' => $attr['src']
503
+ )
504
+ ));
505
+ }
506
+
507
+ }
508
+
509
+ if( function_exists('is_woocommerce') && is_woocommerce() && isset($this->settings['wc_title']) && $this->settings['wc_title'] && $this->settings['proVersion'] ) {
510
+ $attr['alt'] = get_the_title();
511
+ $attr['title'] = get_the_title();
512
+ }
513
+
514
+ $attr['alt'] = apply_filters('pbsfi-alt', $attr['alt']);
515
+ $attr['title'] = apply_filters('pbsfi-title', $attr['title']);
516
+
517
+ return $attr;
518
+ }
519
+ }
inc/pbsfi_upgrade.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* Security-Check */
3
+ if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class pbsfi_upgrade
6
+ {
7
+ /** @var pbSEOFriendlyImages */
8
+ protected $pbSEOFriendlyImages;
9
+
10
+ /** @var string Current DB Version */
11
+ var $current_dbv;
12
+
13
+ public function __construct( pbSEOFriendlyImages $pbSEOFriendlyImages )
14
+ {
15
+ $this->pbSEOFriendlyImages = $pbSEOFriendlyImages;
16
+
17
+ // get DB version
18
+ $this->current_dbv = get_option( $this->pbSEOFriendlyImages->option_name_dbv );
19
+
20
+ // If there is no dbv option it must be version 3.x.x or prior
21
+ if( ! $this->current_dbv ) {
22
+ $this->current_dbv = '3.0.0';
23
+ }
24
+ }
25
+
26
+ public function maybe_do_upgrade()
27
+ {
28
+ if( version_compare($this->current_dbv, $this->pbSEOFriendlyImages->db_version, '<') ) {
29
+ return $this->_upgrade_3xx_to_4xx();
30
+ }
31
+
32
+ // false could mean: No upgrade needed or upgrade has failed
33
+ return false;
34
+ }
35
+
36
+ protected function _upgrade_3xx_to_4xx ()
37
+ {
38
+ $settings_v3 = $this->v3_settings();
39
+ $upgrade_3xx_to_4xx = update_option($this->pbSEOFriendlyImages->option_name, $settings_v3);
40
+
41
+ if( $upgrade_3xx_to_4xx ) {
42
+ update_option($this->pbSEOFriendlyImages->option_name_dbv, $this->pbSEOFriendlyImages->db_version);
43
+
44
+ $this->v3_clean_db();
45
+
46
+ return true;
47
+ }
48
+ }
49
+
50
+ public function v3_settings()
51
+ {
52
+ return array(
53
+ 'optimize_img' => get_option('pbsfi_optimize_img', 'all'),
54
+ 'sync_method' => get_option('pbsfi_sync_method', 'both'),
55
+ 'override_alt' => get_option('pbsfi_override_alt', false),
56
+ 'override_title' => get_option('pbsfi_override_title', false),
57
+ 'alt_scheme' => get_option('pbsfi_alt_scheme', '%name - %title'),
58
+ 'title_scheme' => get_option('pbsfi_title_scheme', '%title'),
59
+ 'pbsfi_enable_caching' => get_option('pbsfi_enable_caching', false),
60
+ 'pbsfi_enable_caching_ttl' => get_option('pbsfi_enable_caching_ttl', 86400),
61
+ 'enable_lazyload' => get_option('pbsfi_enable_lazyload', true),
62
+ 'enable_lazyload_acf' => get_option('pbsfi_enable_lazyload_acf', true),
63
+ 'enable_lazyload_styles' => get_option('pbsfi_enable_lazyload_styles', false),
64
+ 'lazyload_threshold' => get_option('pbsfi_lazyload_threshold', false),
65
+ 'wc_title' => get_option('pbsfi_wc_title', false),
66
+ 'wc_sync_method' => get_option('pbsfi_wc_sync_method', false),
67
+ 'wc_override_alt' => get_option('pbsfi_wc_override_alt', false),
68
+ 'wc_override_title' => get_option('pbsfi_wc_override_title', false),
69
+ 'wc_alt_scheme' => get_option('pbsfi_wc_alt_scheme', false),
70
+ 'wc_title_scheme' => get_option('pbsfi_wc_title_scheme', false),
71
+ 'disable_srcset' => get_option('pbsfi_disable_srcset', false),
72
+ 'link_title' => get_option('pbsfi_link_title', false),
73
+ 'encoding' => get_option('pbsfi_encoding', false),
74
+ 'encoding_mode' => get_option('pbsfi_encoding_mode', false)
75
+ );
76
+ }
77
+
78
+ protected function v3_clean_db()
79
+ {
80
+ delete_option('pbsfi_optimize_img');
81
+ delete_option('pbsfi_sync_method');
82
+ delete_option('pbsfi_override_alt');
83
+ delete_option('pbsfi_override_title');
84
+ delete_option('pbsfi_alt_scheme');
85
+ delete_option('pbsfi_title_scheme');
86
+ delete_option('pbsfi_enable_caching');
87
+ delete_option('pbsfi_enable_caching_ttl');
88
+ delete_option('pbsfi_enable_lazyload');
89
+ delete_option('pbsfi_enable_lazyload_acf');
90
+ delete_option('pbsfi_enable_lazyload_styles');
91
+ delete_option('pbsfi_lazyload_threshold');
92
+ delete_option('pbsfi_wc_title');
93
+ delete_option('pbsfi_wc_sync_method');
94
+ delete_option('pbsfi_wc_override_alt');
95
+ delete_option('pbsfi_wc_override_title');
96
+ delete_option('pbsfi_wc_alt_scheme');
97
+ delete_option('pbsfi_wc_title_scheme');
98
+ delete_option('pbsfi_disable_srcset');
99
+ delete_option('pbsfi_link_title');
100
+ delete_option('pbsfi_encoding');
101
+ delete_option('pbsfi_encoding_mode');
102
+ }
103
+ }
inc/settings.php DELETED
@@ -1,617 +0,0 @@
1
- <?php
2
- /* Security-Check */
3
- if ( !class_exists('WP') ) {
4
- die();
5
- }
6
-
7
- if( !class_exists('pbSEOFriendlyImagesSettings') ):
8
-
9
- class pbSEOFriendlyImagesSettings extends pbSEOFriendlyImages
10
- {
11
- public static $settings = false;
12
-
13
- public static function addSettings()
14
- {
15
- add_action('admin_menu', array(__CLASS__, 'optionsPageMenu'));
16
- add_action('admin_init', array(__CLASS__, 'initSettings'));
17
-
18
- add_filter('plugin_action_links_'.pbSEOFriendlyImages::$basename, array(__CLASS__, 'settingsLink'));
19
-
20
- $showUpgradeBanner = get_option('pbsfi_upgrade_notice');
21
-
22
- if( $showUpgradeBanner != pbSEOFriendlyImages::$verMajor && pbSEOFriendlyImages::getArrayKey('page', $_GET) != 'pb-seo-friendly-images' ) {
23
- add_action( 'admin_notices', array(__CLASS__, 'adminUpgradeNotice') );
24
- }
25
- }
26
-
27
- public static function adminUpgradeNotice()
28
- {
29
- $current_user = wp_get_current_user();
30
-
31
- $username = ((!empty($current_user->user_firstname)) ? $current_user->user_firstname : $current_user->user_login );
32
-
33
- echo '<div class="notice pb-custom-message" style="max-width: 100%;"><p>';
34
- echo sprintf(
35
- __('<strong>Hey %s</strong>, we have updated <a href="%s">PB SEO Friendly Images</a>. Visit the <a href="%s">plugin settings page</a> to get deeper insights about the new features. This message will disappear automatically after you\'ve visited the plugin settings.', 'pb-seo-friendly-images'),
36
- $username,
37
- admin_url('options-general.php?page=pb-seo-friendly-images'),
38
- admin_url('options-general.php?page=pb-seo-friendly-images')
39
- );
40
- echo '</p><a href="'.admin_url('options-general.php?page=pb-seo-friendly-images').'" class="pb-btn">'.__('Close', 'pb-seo-friendly-images').'</a></div>';
41
- }
42
-
43
- public static function settingsLink( $data )
44
- {
45
- if( ! current_user_can('manage_options') ) {
46
- return $data;
47
- }
48
-
49
- $data = array_merge(
50
- $data,
51
- array(
52
- sprintf(
53
- '<a href="%s">%s</a>',
54
- add_query_arg(
55
- array(),
56
- admin_url('options-general.php?page=pb-seo-friendly-images')
57
- ),
58
- __('Settings', 'pb-seo-friendly-images')
59
- )
60
- )
61
- );
62
-
63
- if( ! pbSEOFriendlyImages::$proVersion ) {
64
- $data = array_merge(
65
- $data,
66
- array(
67
- sprintf(
68
- '<a href="%s" style="color: #e00; font-weight: bold;" target="_blank">%s</a>',
69
- pbSEOFriendlyImages::$proURL,
70
- __('Get Pro Version', 'pb-seo-friendly-images')
71
- )
72
- )
73
- );
74
- }
75
-
76
- return $data;
77
- }
78
-
79
- public static function initSettings()
80
- {
81
- pbSEOFriendlyImagesSettings::$settings = new pbSettingsFramework(array(
82
- 'text-domain' => 'pb-seo-friendly-images',
83
- 'page' => 'pb-seo-friendly-images',
84
- 'section' => 'pb-seo-friendly-images',
85
- 'option-group' => 'pb-seo-friendly-images'
86
- ));
87
-
88
- // register a new setting for "wporg" page
89
- register_setting('pb-seo-friendly-images', 'pbsfi_options');
90
-
91
- pbSEOFriendlyImagesSettings::$settings->addSettingsSection(
92
- 'pb-seo-friendly-images',
93
- __('Image "alt" and "title" Settings', 'pb-seo-friendly-images'),
94
- function()
95
- {
96
- echo '<div class="pb-section-wrap no-margin-bottom">';
97
- echo '<p>'.__('PB SEO Friendly Images automatically adds "alt" and "title" attributes to all images and post thumbnails in your posts. The default options are a good starting point for the optimization and basically fine for most websites.', 'pb-seo-friendly-images').'</p>';
98
- echo '<p><strong>'.__('Override feature', 'pb-seo-friendly-images').':</strong> '.__('Enable the override means that a possible sync and also hand picked "alt" / "title" attributes will be overwritten with the selected scheme. If you have good hand picked "alt" or "title" attributes in your images, I can not recommend to use the override. Automatic sync between "alt" and "title" will do it\'s best for you.', 'pb-seo-friendly-images').'</p>';
99
-
100
- echo '<p>'.sprintf(
101
- __('PB SEO Friendly Images Pro is a WordPress Plugin by <a href="%s" target="_blank">Pascal Bajorat</a> and made with %s in Berlin, Germany.', 'pb-seo-friendly-images'),
102
- 'https://www.pascal-bajorat.com',
103
- '<span style="color: #f00;">&#9829;</span>'
104
- ).'</p>';
105
-
106
- echo '<hr />';
107
- echo '<p><strong style="text-decoration: underline;">'.__('How it works', 'pb-seo-friendly-images').':</strong> '.__('You only need to configure the plugin with the following settings. The plugin will optimize your HTML code on-the-fly. This means, that you see the "alt" and "title" directly in the HTML code output and not in your media library or editor. This is not a hard rewrite of your media library values. You can change this values without the risk to damage some media library data.', 'pb-seo-friendly-images').'</p>';
108
-
109
- echo '</div> <!-- .pb-section-wrap -->';
110
-
111
- if( ! pbSEOFriendlyImages::$proVersion ) {
112
- echo '<div class="pb-custom-message info"><p>';
113
- echo sprintf(
114
- __('Please consider upgrading to <a href="%s" target="_blank">PB SEO Friendly Images Pro</a> if you want to use more features and support the development of this plugin.', 'pb-seo-friendly-images'),
115
- pbSEOFriendlyImages::$proURL
116
- );
117
- echo '</p><a href="'.pbSEOFriendlyImages::$proURL2.'" class="pb-btn" target="_blank">'.__('Upgrade now', 'pb-seo-friendly-images').'</a></div>';
118
- }
119
- }
120
- );
121
-
122
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
123
- 'pbsfi_optimize_img',
124
- __('optimize images', 'pb-seo-friendly-images'),
125
- array(
126
- 'type' => 'select',
127
- 'default' => 'all',
128
- 'select' => array(
129
- 'all' => __('post thumbnails and images in post content', 'pb-seo-friendly-images').' ('.__('recommended', 'pb-seo-friendly-images').')',
130
- 'thumbs' => __('only post thumbnails', 'pb-seo-friendly-images'),
131
- 'post' => __('only images in post content', 'pb-seo-friendly-images'),
132
- ),
133
- 'desc' => __('which images should be optimized', 'pb-seo-friendly-images'),
134
- )
135
- );
136
-
137
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
138
- 'pbsfi_sync_method',
139
- __('sync method', 'pb-seo-friendly-images'),
140
- array(
141
- 'type' => 'select',
142
- 'default' => 'both',
143
- 'select' => array(
144
- 'both' => __('alt <=> title', 'pb-seo-friendly-images').' ('.__('recommended', 'pb-seo-friendly-images').')',
145
- 'alt' => __('alt => title', 'pb-seo-friendly-images'),
146
- 'title' => __('alt <= title', 'pb-seo-friendly-images'),
147
- ),
148
- 'desc' => __('select sync method for "alt" and "title" attribute.', 'pb-seo-friendly-images').'<br />'.
149
- __('<code>alt <=> title</code> - if one attribute is set use it also for the other one', 'pb-seo-friendly-images').'<br />'.
150
- __('<code>alt => title</code> - if "alt" is set use it for the title attribute', 'pb-seo-friendly-images').'<br />'.
151
- __('<code>alt <= title</code> - if "title" is set use it for the alt attribute', 'pb-seo-friendly-images')
152
- )
153
- );
154
-
155
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
156
- 'pbsfi_override_alt',
157
- __('override "alt"', 'pb-seo-friendly-images'),
158
- array(
159
- 'type' => 'checkbox',
160
- 'default' => '',
161
- 'desc' => __('override existing image alt attributes', 'pb-seo-friendly-images')
162
- )
163
- );
164
-
165
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
166
- 'pbsfi_override_title',
167
- __('override "title"', 'pb-seo-friendly-images'),
168
- array(
169
- 'type' => 'checkbox',
170
- 'default' => '',
171
- 'desc' => __('override existing image title attributes', 'pb-seo-friendly-images')
172
- )
173
- );
174
-
175
- $placeholder = __('possible variables:', 'pb-seo-friendly-images').'<br />'.
176
- '<code>%title</code> - '.__('replaces post title', 'pb-seo-friendly-images').'<br />'.
177
- '<code>%desc</code> - '.__('replaces post excerpt', 'pb-seo-friendly-images').'<br />'.
178
- '<code>%name</code> - '.__('replaces image filename (without extension)', 'pb-seo-friendly-images').'<br />'.
179
- '<code>%category</code> - '.__('replaces post category', 'pb-seo-friendly-images').'<br />'.
180
- '<code>%tags</code> - '.__('replaces post tags', 'pb-seo-friendly-images').'<br />'.
181
- '<code>%media_title</code> - '.__('replaces attachment title (could be empty if not set)', 'pb-seo-friendly-images').'<br />'.
182
- '<code>%media_alt</code> - '.__('replaces attachment alt-text (could be empty if not set)', 'pb-seo-friendly-images').'<br />'.
183
- '<code>%media_caption</code> - '.__('replaces attachment caption (could be empty if not set)', 'pb-seo-friendly-images').'<br />'.
184
- '<code>%media_description</code> - '.__('replaces attachment description (could be empty if not set)', 'pb-seo-friendly-images');
185
-
186
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
187
- 'pbsfi_alt_scheme',
188
- __('alt scheme', 'pb-seo-friendly-images'),
189
- array(
190
- 'type' => 'text',
191
- 'default' => '%name - %title',
192
- 'desc' => __('default', 'pb-seo-friendly-images').': <code>%name - %title</code><br />'.$placeholder
193
- )
194
- );
195
-
196
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
197
- 'pbsfi_title_scheme',
198
- __('title scheme', 'pb-seo-friendly-images'),
199
- array(
200
- 'type' => 'text',
201
- 'default' => '%title',
202
- 'desc' => __('default', 'pb-seo-friendly-images').': <code>%title</code><br />'.$placeholder
203
- )
204
- );
205
-
206
- /**
207
- * Section Pro
208
- */
209
- pbSEOFriendlyImagesSettings::$settings = new pbSettingsFramework(array(
210
- 'text-domain' => 'pb-seo-friendly-images',
211
- 'page' => 'pb-seo-friendly-images',
212
- 'section' => 'pb-seo-friendly-images-pro',
213
- 'option-group' => 'pb-seo-friendly-images'
214
- ));
215
-
216
- pbSEOFriendlyImagesSettings::$settings->addSettingsSection(
217
- 'pb-seo-friendly-images-pro',
218
- '',
219
- function()
220
- {
221
- echo '<h2 class="pro-section"><span>'.__('Pro Features', 'pb-seo-friendly-images').'</span></h2>';
222
-
223
- echo '<h2 class="pb-section-title">'.__('Lazy Load settings', 'pb-seo-friendly-images').'</h2>';
224
- echo '<div class="pb-section-wrap no-margin-bottom">';
225
- echo '<p>'.__('This function is very useful and it boosts performance by delaying loading of images in long web pages, because images outside of viewport (visible part of web page) won\'t be loaded until the user scrolls to them.', 'pb-seo-friendly-images').'</p>';
226
- echo '<p>'.__('The lazy load is powered by unveil.js, one of the fastest and thinnest lazy loader in the web. The implementation is highly seo compatible with a no js fallback.', 'pb-seo-friendly-images').'</p>';
227
- echo '<p>'.__('If enabled the lazy load will be added automatically to images in your post or page content and also to post thumbnails.', 'pb-seo-friendly-images').'</p>';
228
- echo '</div>';
229
-
230
- if( ! pbSEOFriendlyImages::$proVersion ) {
231
- echo '<div class="pb-custom-message info"><p>';
232
- echo sprintf(
233
- __('Please consider upgrading to <a href="%s" target="_blank">PB SEO Friendly Images Pro</a> if you want to use this feature.', 'pb-seo-friendly-images'),
234
- pbSEOFriendlyImages::$proURL
235
- );
236
- echo '</p><a href="'.pbSEOFriendlyImages::$proURL2.'" class="pb-btn" target="_blank">'.__('Upgrade now', 'pb-seo-friendly-images').'</a></div>';
237
- }
238
- }
239
- );
240
-
241
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
242
- 'pbsfi_enable_lazyload',
243
- __('enable lazy load', 'pb-seo-friendly-images'),
244
- array(
245
- 'type' => 'checkbox',
246
- 'default' => true,
247
- 'desc' => __('enable lazy load and boost up your site speed', 'pb-seo-friendly-images'),
248
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
249
- )
250
- );
251
-
252
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
253
- 'pbsfi_enable_lazyload_acf',
254
- __('enable lazy load for acf', 'pb-seo-friendly-images'),
255
- array(
256
- 'type' => 'checkbox',
257
- 'default' => true,
258
- 'desc' => __('enable lazy load for AdvancedCustomFields', 'pb-seo-friendly-images'),
259
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
260
- )
261
- );
262
-
263
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
264
- 'pbsfi_enable_lazyload_styles',
265
- __('lazy load default styles', 'pb-seo-friendly-images'),
266
- array(
267
- 'type' => 'checkbox',
268
- 'default' => false,
269
- 'desc' => __('enable lazy load default styles', 'pb-seo-friendly-images'),
270
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
271
- )
272
- );
273
-
274
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
275
- 'pbsfi_lazyload_threshold',
276
- __('threshold', 'pb-seo-friendly-images'),
277
- array(
278
- 'type' => 'text',
279
- 'default' => '0',
280
- 'desc' => __('By default, images are only loaded when the user scrolls to them and they became visible on the screen (default value for this field <code>0</code>). If you want your images to load earlier than that, lets say 200px then you need to type in <code>200</code>.', 'pb-seo-friendly-images'),
281
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
282
- )
283
- );
284
-
285
- /**
286
- * Section Pro 2
287
- */
288
- pbSEOFriendlyImagesSettings::$settings = new pbSettingsFramework(array(
289
- 'text-domain' => 'pb-seo-friendly-images',
290
- 'page' => 'pb-seo-friendly-images',
291
- 'section' => 'pb-seo-friendly-images-pro2',
292
- 'option-group' => 'pb-seo-friendly-images'
293
- ));
294
-
295
- pbSEOFriendlyImagesSettings::$settings->addSettingsSection(
296
- 'pb-seo-friendly-images-pro2',
297
- '',
298
- function()
299
- {
300
- echo '<h3 class="pb-section-title">'.__('Theme-Integration (only for developers relevant)', 'pb-seo-friendly-images').'</h3>';
301
- echo '<div class="pb-section-wrap" style="margin-bottom: 2px">';
302
- echo '<p>'.__('Want to add lazy load to images in your theme? You only need to do some small modifications. Add class "lazy" and modify the "src" like this:', 'pb-seo-friendly-images').'</p>';
303
- echo '</div>';
304
-
305
- echo '<div class="pb-custom-message code">';
306
- echo '<p><code>&lt;img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="<strong>'.__('REAL SRC HERE', 'pb-seo-friendly-images').'</strong>" class="pb-seo-lazy" /&gt;</code></p>';
307
- echo '</div>';
308
- }
309
- );
310
-
311
- /**
312
- * Section WooCommerce
313
- */
314
- pbSEOFriendlyImagesSettings::$settings = new pbSettingsFramework(array(
315
- 'text-domain' => 'pb-seo-friendly-images',
316
- 'page' => 'pb-seo-friendly-images',
317
- 'section' => 'pb-seo-friendly-images-pro3',
318
- 'option-group' => 'pb-seo-friendly-images'
319
- ));
320
-
321
- pbSEOFriendlyImagesSettings::$settings->addSettingsSection(
322
- 'pb-seo-friendly-images-pro3',
323
- '',
324
- function()
325
- {
326
- echo '<h2 class="pb-section-title">'.__('WooCommerce settings', 'pb-seo-friendly-images').'</h2>';
327
- echo '<div class="pb-section-wrap no-margin-bottom">';
328
- echo '<p>'.__('This settings are specially for images inside your WooCommerce Shop. In most cases you need to activate the override to use your custom settings.', 'pb-seo-friendly-images').'</p>';
329
- echo '</div>';
330
-
331
- if( ! pbSEOFriendlyImages::$proVersion ) {
332
- echo '<div class="pb-custom-message info"><p>';
333
- echo sprintf(
334
- __('Please consider upgrading to <a href="%s" target="_blank">PB SEO Friendly Images Pro</a> if you want to use this feature.', 'pb-seo-friendly-images'),
335
- pbSEOFriendlyImages::$proURL
336
- );
337
- echo '</p><a href="'.pbSEOFriendlyImages::$proURL2.'" class="pb-btn" target="_blank">'.__('Upgrade now', 'pb-seo-friendly-images').'</a></div>';
338
- }
339
- }
340
- );
341
-
342
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
343
- 'pbsfi_wc_title',
344
- __('WooCommerce', 'pb-seo-friendly-images'),
345
- array(
346
- 'type' => 'checkbox',
347
- 'default' => false,
348
- 'desc' => __('Use the product name as alt and title for WooCommerce product images', 'pb-seo-friendly-images'),
349
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
350
- )
351
- );
352
-
353
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
354
- 'pbsfi_wc_sync_method',
355
- __('sync method', 'pb-seo-friendly-images'),
356
- array(
357
- 'type' => 'select',
358
- 'default' => 'both',
359
- 'select' => array(
360
- 'both' => __('alt <=> title', 'pb-seo-friendly-images').' ('.__('recommended', 'pb-seo-friendly-images').')',
361
- 'alt' => __('alt => title', 'pb-seo-friendly-images'),
362
- 'title' => __('alt <= title', 'pb-seo-friendly-images'),
363
- ),
364
- 'desc' => __('select sync method for "alt" and "title" attribute.', 'pb-seo-friendly-images').'<br />'.
365
- __('<code>alt <=> title</code> - if one attribute is set use it also for the other one', 'pb-seo-friendly-images').'<br />'.
366
- __('<code>alt => title</code> - if "alt" is set use it for the title attribute', 'pb-seo-friendly-images').'<br />'.
367
- __('<code>alt <= title</code> - if "title" is set use it for the alt attribute', 'pb-seo-friendly-images'),
368
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
369
- )
370
- );
371
-
372
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
373
- 'pbsfi_wc_override_alt',
374
- __('override "alt"', 'pb-seo-friendly-images'),
375
- array(
376
- 'type' => 'checkbox',
377
- 'default' => '',
378
- 'desc' => __('override existing image alt attributes', 'pb-seo-friendly-images'),
379
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
380
- )
381
- );
382
-
383
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
384
- 'pbsfi_wc_override_title',
385
- __('override "title"', 'pb-seo-friendly-images'),
386
- array(
387
- 'type' => 'checkbox',
388
- 'default' => '',
389
- 'desc' => __('override existing image title attributes', 'pb-seo-friendly-images'),
390
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
391
- )
392
- );
393
-
394
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
395
- 'pbsfi_wc_alt_scheme',
396
- __('alt scheme', 'pb-seo-friendly-images'),
397
- array(
398
- 'type' => 'text',
399
- 'default' => '%name - %title',
400
- 'desc' => __('default', 'pb-seo-friendly-images').': <code>%name - %title</code><br />'.$placeholder,
401
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
402
- )
403
- );
404
-
405
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
406
- 'pbsfi_wc_title_scheme',
407
- __('title scheme', 'pb-seo-friendly-images'),
408
- array(
409
- 'type' => 'text',
410
- 'default' => '%title',
411
- 'desc' => __('default', 'pb-seo-friendly-images').': <code>%title</code><br />'.$placeholder,
412
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
413
- )
414
- );
415
-
416
- /**
417
- * Additional features
418
- */
419
- pbSEOFriendlyImagesSettings::$settings = new pbSettingsFramework(array(
420
- 'text-domain' => 'pb-seo-friendly-images',
421
- 'page' => 'pb-seo-friendly-images',
422
- 'section' => 'pb-seo-friendly-images-pro4',
423
- 'option-group' => 'pb-seo-friendly-images'
424
- ));
425
-
426
- pbSEOFriendlyImagesSettings::$settings->addSettingsSection(
427
- 'pb-seo-friendly-images-pro4',
428
- '',
429
- function()
430
- {
431
- echo '<h2 class="pb-section-title">'.__('Additional features', 'pb-seo-friendly-images').'</h2>';
432
- }
433
- );
434
-
435
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
436
- 'pbsfi_link_title',
437
- __('set title for links', 'pb-seo-friendly-images'),
438
- array(
439
- 'type' => 'checkbox',
440
- 'default' => false,
441
- 'desc' => __('Use the power of PB SEO Friendly Images also for seo friendly links. This will set the title depending on the link text and only if there is no existing title', 'pb-seo-friendly-images'),
442
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
443
- )
444
- );
445
-
446
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
447
- 'pbsfi_disable_srcset',
448
- __('disable srcset', 'pb-seo-friendly-images'),
449
- array(
450
- 'type' => 'checkbox',
451
- 'default' => false,
452
- 'desc' => __('disable srcset attribute and responsive images in WordPress if you don\'t need them', 'pb-seo-friendly-images'),
453
- 'disabled' => ((pbSEOFriendlyImages::$proVersion)?false:true)
454
- )
455
- );
456
-
457
- /**
458
- * Section Encoding and Parser
459
- */
460
- pbSEOFriendlyImagesSettings::$settings = new pbSettingsFramework(array(
461
- 'text-domain' => 'pb-seo-friendly-images',
462
- 'page' => 'pb-seo-friendly-images',
463
- 'section' => 'pb-seo-friendly-images-encoding',
464
- 'option-group' => 'pb-seo-friendly-images'
465
- ));
466
-
467
- pbSEOFriendlyImagesSettings::$settings->addSettingsSection(
468
- 'pb-seo-friendly-images-encoding',
469
- '',
470
- function()
471
- {
472
- echo '<h2 class="pb-section-title">'.__('Encoding and Parser', 'pb-seo-friendly-images').'</h2>';
473
- echo '<div class="pb-section-wrap no-margin-bottom">';
474
- echo '<p>'.__('Here you can configure the HTML-Parser of the plugin. You <u>only</u> need to change this settings if you have <u>problems with your encoding</u> after activating the plugin.', 'pb-seo-friendly-images').'</p>';
475
- echo '</div>';
476
- }
477
- );
478
-
479
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
480
- 'pbsfi_encoding',
481
- __('encoding', 'pb-seo-friendly-images'),
482
- array(
483
- 'type' => 'text',
484
- 'default' => '',
485
- 'desc' => __('leave blank to use WordPress default encoding or type in something like "utf-8"', 'pb-seo-friendly-images')
486
- )
487
- );
488
-
489
- pbSEOFriendlyImagesSettings::$settings->addSettingsField(
490
- 'pbsfi_encoding_mode',
491
- __('encoding mode', 'pb-seo-friendly-images'),
492
- array(
493
- 'type' => 'select',
494
- 'default' => 'entities',
495
- 'select' => array(
496
- 'entities' => __('HTML-ENTITIES', 'pb-seo-friendly-images').' ('.__('default', 'pb-seo-friendly-images').')',
497
- 'off' => __('disable convert encoding', 'pb-seo-friendly-images'),
498
- )
499
- )
500
- );
501
- }
502
-
503
- public static function optionsPageMenu()
504
- {
505
- add_submenu_page(
506
- 'options-general.php',
507
- __('PB SEO Friendly Images', 'pb-seo-friendly-images'),
508
- __('SEO Friendly Images', 'pb-seo-friendly-images'),
509
- 'manage_options',
510
- 'pb-seo-friendly-images',
511
- array(__CLASS__, 'optionsPage')
512
- );
513
- }
514
-
515
- public static function optionsPage()
516
- {
517
- if (!current_user_can('manage_options')) {
518
- return;
519
- }
520
-
521
- update_option( 'pbsfi_upgrade_notice', pbSEOFriendlyImages::$verMajor, false );
522
- ?>
523
- <div class="wrap pb-wp-app-wrapper">
524
- <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
525
-
526
- <div class="pb-wrapper">
527
- <div class="pb-main">
528
- <form action="<?php echo admin_url('options.php') ?>" method="post" target="_self">
529
- <?php
530
- settings_fields('pb-seo-friendly-images');
531
- pbSettingsFramework::doSettingsSections('pb-seo-friendly-images');
532
- submit_button();
533
- ?>
534
- </form>
535
- </div>
536
- <div class="pb-sidebar">
537
- <h3><?php esc_html_e('Plugins & Support', 'pb-seo-friendly-images') ?></h3>
538
-
539
- <?php if( strstr(get_locale(), 'de') ): ?>
540
- <div class="pb-support-box">
541
- <h4><?php _e('WordPress Kurs', 'pb-seo-friendly-images') ?></h4>
542
- <p><?php _e('Möchtest du mit WordPress richtig durchstarten? In meinem WordPress Kurs erfährst du spannende Tipps und Tricks zu WordPress und SEO!', 'pb-seo-friendly-images') ?></p>
543
-
544
- <p>
545
- <a href="https://wordpress-kurs.pascal-bajorat.com/" class="button" target="_blank"><?php _e('Jetzt Kurs ansehen', 'pb-seo-friendly-images') ?></a>
546
- </p>
547
- </div>
548
- <?php endif; ?>
549
-
550
- <div class="pb-plugin-box">
551
- <h4>
552
- <span class="icon">
553
- <img src="<?php echo plugins_url( 'img/primusnote.png', constant('pbsfi_file') ); ?>" alt="<?php _e('PrimusNote', 'pb-seo-friendly-images') ?>" />
554
- </span>
555
- <span class="text"><?php _e('PrimusNote', 'pb-seo-friendly-images') ?><br /><?php _e('Project Management', 'pb-seo-friendly-images') ?></span>
556
- </h4>
557
- <div class="desc">
558
- <p><?php _e('PrimusNote is a Project Management and Team Collaboration software based on WordPress.', 'pb-seo-friendly-images') ?></p>
559
- <p><a href="https://goo.gl/b7SZvA" target="_blank" class="button"><?php _e('Install Plugin', 'pb-seo-friendly-images') ?></a></p>
560
- </div>
561
- </div>
562
-
563
- <div class="pb-plugin-box">
564
- <h4>
565
- <span class="icon">
566
- <img src="<?php echo plugins_url( 'img/mailcrypt.png', constant('pbsfi_file') ); ?>" alt="<?php _e('MailCrypt - AntiSpam Email Encryption', 'pb-seo-friendly-images') ?>" />
567
- </span>
568
- <span class="text"><?php _e('MailCrypt - AntiSpam Email Encryption', 'pb-seo-friendly-images') ?></span>
569
- </h4>
570
- <div class="desc">
571
- <p><?php _e('This Plugin provides a Shortcode to encrypt email addresses / links and protect them against spam.', 'pb-seo-friendly-images') ?></p>
572
- <p><a href="<?php echo admin_url('plugin-install.php?s=PB+MailCrypt+-+AntiSpam+Email+Encryption&tab=search&type=term') ?>" class="button"><?php _e('Install Plugin', 'pb-seo-friendly-images') ?></a></p>
573
- </div>
574
- </div>
575
-
576
- <div class="pb-support-box">
577
- <h4><?php _e('Support', 'pb-seo-friendly-images') ?></h4>
578
- <p><?php _e('Do you need some help with this plugin? I am here to help you. Get in touch:', 'pb-seo-friendly-images') ?></p>
579
-
580
- <p>
581
- <?php if( ! pbSEOFriendlyImages::$proVersion ): ?>
582
- <a href="https://wordpress.org/support/plugin/pb-seo-friendly-images" class="button" target="_blank"><?php _e('Support Forum', 'pb-seo-friendly-images') ?></a>
583
- <?php else: ?>
584
- <a href="https://codecanyon.net/item/seo-friendly-images-pro-for-wordpress/19296704/support?ref=Pascal-Bajorat" class="button" target="_blank"><?php _e('Contact Support', 'pb-seo-friendly-images') ?></a>
585
- <?php endif; ?>
586
- &nbsp;<a href="https://wordpress.org/plugins/pb-seo-friendly-images/#developers" class="button" target="_blank"><?php _e('Changelog', 'pb-seo-friendly-images') ?></a>
587
- </p>
588
- </div>
589
- </div>
590
- </div>
591
- </div>
592
- <script>
593
- jQuery(document).ready(function(){
594
-
595
- var $wc_setting_elements = jQuery('#pbsfi_wc_sync_method, label[for="pbsfi_wc_sync_method"], #pbsfi_wc_override_alt, label[for="pbsfi_wc_override_alt"], #pbsfi_wc_override_title, label[for="pbsfi_wc_override_title"], #pbsfi_wc_alt_scheme, label[for="pbsfi_wc_alt_scheme"], #pbsfi_wc_title_scheme, label[for="pbsfi_wc_title_scheme"]');
596
-
597
- if( jQuery('#pbsfi_wc_title').is(':checked') ) {
598
- console.log('fade out');
599
- $wc_setting_elements.css('opacity', .4);
600
- }
601
-
602
- jQuery('#pbsfi_wc_title').on('change', function(e){
603
- if( jQuery(this).is(':checked') ) {
604
- $wc_setting_elements.css('opacity', .4);
605
- } else {
606
- $wc_setting_elements.css('opacity', 1);
607
- }
608
- });
609
- });
610
- </script>
611
- <?php
612
- }
613
-
614
-
615
- }
616
-
617
- endif; // class_exists
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ //Nothing to see here
lang/pb-seo-friendly-images-de_DE.mo CHANGED
Binary file
lang/pb-seo-friendly-images-de_DE.po CHANGED
@@ -1,18 +1,19 @@
1
  msgid ""
2
  msgstr ""
3
  "Project-Id-Version: PB SEO Friendly Images\n"
4
- "POT-Creation-Date: 2018-01-21 12:54+0100\n"
5
- "PO-Revision-Date: 2018-01-21 12:55+0100\n"
6
- "Last-Translator: Pascal Bajorat <pascal@pascal-bajorat.com>\n"
7
- "Language-Team: Pascal Bajorat <pascal@pascal-bajorat.com>\n"
8
- "Language: de\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
- "X-Generator: Poedit 1.8.12\n"
13
- "X-Poedit-Basepath: ..\n"
14
- "X-Poedit-WPHeader: pb-seo-friendly-images.php\n"
15
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
 
 
 
16
  "X-Poedit-SourceCharset: UTF-8\n"
17
  "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
18
  "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
@@ -20,53 +21,35 @@ msgstr ""
20
  "X-Poedit-SearchPath-0: .\n"
21
  "X-Poedit-SearchPathExcluded-0: *.js\n"
22
 
23
- #: inc/settings.php:35
24
- #, php-format
25
- msgid ""
26
- "<strong>Hey %s</strong>, we have updated <a href=\"%s\">PB SEO Friendly "
27
- "Images</a>. Visit the <a href=\"%s\">plugin settings page</a> to get deeper "
28
- "insights about the new features. This message will disappear automatically "
29
- "after you've visited the plugin settings."
30
- msgstr ""
31
- "<strong>Hey %s</strong>, wir haben <a href=\"%s\">PB SEO Friendly Images</a> "
32
- "aktualisiert. Besuche die <a href=\"%s\">Plugin-Einstellungen</a> und schau "
33
- "dir die neuen Funktionen an. Diese Nachricht verschwindet automatisch, "
34
- "nachdem du die Plugin-Einstellung geöffnet hast."
35
-
36
- #: inc/settings.php:40
37
- msgid "Close"
38
- msgstr "schließen"
39
-
40
- #: inc/settings.php:58
41
  msgid "Settings"
42
  msgstr "Einstellungen"
43
 
44
- #: inc/settings.php:70
45
  msgid "Get Pro Version"
46
  msgstr "Pro-Version kaufen"
47
 
48
- #: inc/settings.php:93
49
  msgid "Image \"alt\" and \"title\" Settings"
50
- msgstr "Bilder \"alt\" und \"title\" Einstellungen"
51
 
52
- #: inc/settings.php:97
53
  msgid ""
54
  "PB SEO Friendly Images automatically adds \"alt\" and \"title\" attributes "
55
  "to all images and post thumbnails in your posts. The default options are a "
56
  "good starting point for the optimization and basically fine for most "
57
  "websites."
58
  msgstr ""
59
- "PB SEO Friendly Images verwaltet automatisch die \"alt\" und \"title\" "
60
- "Attribute deiner Post-Thumbnails sowie aller Bilder innerhalb deiner Seiten "
61
- "und Artikel. Die Standard-Einstellungen sind eine gute erste Grundlage und "
62
- "werden für die meisten Webseiten gut funktionieren, ohne das Änderungen "
63
- "notwendig sind."
64
 
65
- #: inc/settings.php:98
66
  msgid "Override feature"
67
  msgstr "Override-Funktion"
68
 
69
- #: inc/settings.php:98
70
  msgid ""
71
  "Enable the override means that a possible sync and also hand picked \"alt"
72
  "\" / \"title\" attributes will be overwritten with the selected scheme. If "
@@ -75,12 +58,12 @@ msgid ""
75
  "\"title\" will do it's best for you."
76
  msgstr ""
77
  "Wenn du die Override (überschreiben) Funktion verwendest, werden alle "
78
- "manuellen \"alt\" und/oder \"title\" Attribute durch das gewählte Schema "
79
- "überschrieben. Wenn du bereits manuelle Attribute für deine Bilder gesetzt "
80
- "hast, solltest du einfach die Sync Funktion ihren Job machen lassen und "
81
- "keine Überschreibung erzwingen."
82
 
83
- #: inc/settings.php:101
84
  #, php-format
85
  msgid ""
86
  "PB SEO Friendly Images Pro is a WordPress Plugin by <a href=\"%s\" target="
@@ -90,11 +73,11 @@ msgstr ""
90
  "target=\"_blank\">Pascal Bajorat</a>, entwickelt und gepflegt mit %s in "
91
  "Berlin."
92
 
93
- #: inc/settings.php:107
94
  msgid "How it works"
95
- msgstr "Wie funktioniert das Plugin"
96
 
97
- #: inc/settings.php:107
98
  msgid ""
99
  "You only need to configure the plugin with the following settings. The "
100
  "plugin will optimize your HTML code on-the-fly. This means, that you see the "
@@ -111,67 +94,68 @@ msgstr ""
111
  "kannst also risikolos die Einstellungen anpassen, Änderungen werden immer "
112
  "direkt in der HTML Ausgabe berücksichtigt."
113
 
114
- #: inc/settings.php:114
115
  #, php-format
116
  msgid ""
117
  "Please consider upgrading to <a href=\"%s\" target=\"_blank\">PB SEO "
118
  "Friendly Images Pro</a> if you want to use more features and support the "
119
  "development of this plugin."
120
  msgstr ""
121
- "Bitte ziehe doch ein Upgrade auf <a href=\"%s\" target=\"_blank\">PB SEO "
122
- "Friendly Images Pro</a> in Erwägung, wenn du weitere Funktionen verwenden "
123
- "möchtest und die Entwicklung des Plugins unterstützen willst."
124
 
125
- #: inc/settings.php:117 inc/settings.php:236 inc/settings.php:337
 
126
  msgid "Upgrade now"
127
  msgstr "Jetzt upgraden"
128
 
129
- #: inc/settings.php:124
130
  msgid "optimize images"
131
  msgstr "Bilder optimieren"
132
 
133
- #: inc/settings.php:129
134
  msgid "post thumbnails and images in post content"
135
  msgstr "Thumbnails und Bilder innerhalb der Posts"
136
 
137
- #: inc/settings.php:129 inc/settings.php:144 inc/settings.php:360
 
138
  msgid "recommended"
139
  msgstr "empfohlen"
140
 
141
- #: inc/settings.php:130
142
  msgid "only post thumbnails"
143
  msgstr "Nur Postthumbnails"
144
 
145
- #: inc/settings.php:131
146
  msgid "only images in post content"
147
  msgstr "Nur Bilder im Post-Inhalt"
148
 
149
- #: inc/settings.php:133
150
  msgid "which images should be optimized"
151
- msgstr "Welche Bilder sollen optimiert werden."
152
 
153
- #: inc/settings.php:139 inc/settings.php:355
154
  msgid "sync method"
155
- msgstr "Synchronisierungsmethode"
156
 
157
- #: inc/settings.php:144 inc/settings.php:360
158
  msgid "alt <=> title"
159
  msgstr "alt <=> title"
160
 
161
- #: inc/settings.php:145 inc/settings.php:361
162
  msgid "alt => title"
163
  msgstr "alt => title"
164
 
165
- #: inc/settings.php:146 inc/settings.php:362
166
  msgid "alt <= title"
167
  msgstr "alt <= title"
168
 
169
- #: inc/settings.php:148 inc/settings.php:364
170
  msgid "select sync method for \"alt\" and \"title\" attribute."
171
- msgstr ""
172
- "Wähle die Synchronisierungsmethode für \"alt\" und \"title\" Attribute."
173
 
174
- #: inc/settings.php:149 inc/settings.php:365
175
  msgid ""
176
  "<code>alt <=> title</code> - if one attribute is set use it also for the "
177
  "other one"
@@ -179,105 +163,169 @@ msgstr ""
179
  "<code>alt <=> title</code> - Wenn ein Attribut gesetzt ist, wird dieses auch "
180
  "auf das andere übertragen"
181
 
182
- #: inc/settings.php:150 inc/settings.php:366
183
  msgid ""
184
  "<code>alt => title</code> - if \"alt\" is set use it for the title attribute"
185
  msgstr ""
186
- "<code>alt => title</code> - Wenn \"alt\" gesetzt ist, wird der Wert "
187
- "ebenfalls für \"title\" gesetzt"
188
 
189
- #: inc/settings.php:151 inc/settings.php:367
190
  msgid ""
191
  "<code>alt <= title</code> - if \"title\" is set use it for the alt attribute"
192
  msgstr ""
193
- "<code>alt <= title</code> - Wenn \"title\" gesetzt ist, wird der Wert "
194
- "ebenfalls für \"alt\" gesetzt"
195
 
196
- #: inc/settings.php:157 inc/settings.php:374
197
  msgid "override \"alt\""
198
- msgstr "\"alt\" überschreiben"
199
 
200
- #: inc/settings.php:161 inc/settings.php:378
201
  msgid "override existing image alt attributes"
202
- msgstr "Überschreibt bestehende \"alt\" Attribute"
203
 
204
- #: inc/settings.php:167 inc/settings.php:385
205
  msgid "override \"title\""
206
- msgstr "\"title\" überschreiben"
207
 
208
- #: inc/settings.php:171 inc/settings.php:389
209
  msgid "override existing image title attributes"
210
- msgstr "Überschreibt bestehende \"title\" Attribute"
211
 
212
- #: inc/settings.php:175
213
  msgid "possible variables:"
214
  msgstr "Mögliche Variablen:"
215
 
216
- #: inc/settings.php:176
217
  msgid "replaces post title"
218
- msgstr "Wird ersetzt durch Artikeltitel"
219
 
220
- #: inc/settings.php:177
221
  msgid "replaces post excerpt"
222
- msgstr "Wird ersetzt durch den Artikelauszug"
223
 
224
- #: inc/settings.php:178
225
  msgid "replaces image filename (without extension)"
226
  msgstr "Wird ersetzt mit dem Dateinamen (ohne Dateiendung)"
227
 
228
- #: inc/settings.php:179
229
  msgid "replaces post category"
230
- msgstr "Wird ersetzt durch die Artikelkategorien"
231
 
232
- #: inc/settings.php:180
233
  msgid "replaces post tags"
234
- msgstr "Wird ersetzt durch die Artikel-Tags"
235
 
236
- #: inc/settings.php:181
237
  msgid "replaces attachment title (could be empty if not set)"
238
  msgstr ""
239
  "Wird ersetzt durch den Medien-Titel (könnte leer sein, falls nicht gesetzt)"
240
 
241
- #: inc/settings.php:182
242
  msgid "replaces attachment alt-text (could be empty if not set)"
243
  msgstr ""
244
  "Wird ersetzt durch den Medien-Alternativtext (könnte leer sein, falls nicht "
245
  "gesetzt)"
246
 
247
- #: inc/settings.php:183
248
  msgid "replaces attachment caption (could be empty if not set)"
249
  msgstr ""
250
  "Wird ersetzt durch die Medien-Beschriftung (könnte leer sein, falls nicht "
251
  "gesetzt)"
252
 
253
- #: inc/settings.php:184
254
  msgid "replaces attachment description (could be empty if not set)"
255
  msgstr ""
256
  "Wird ersetzt durch die Medien-Beschreibung (könnte leer sein, falls nicht "
257
  "gesetzt)"
258
 
259
- #: inc/settings.php:188 inc/settings.php:396
260
  msgid "alt scheme"
261
  msgstr "Schema alt-Attribut"
262
 
263
- #: inc/settings.php:192 inc/settings.php:202 inc/settings.php:400
264
- #: inc/settings.php:411 inc/settings.php:496
 
265
  msgid "default"
266
  msgstr "Standard"
267
 
268
- #: inc/settings.php:198 inc/settings.php:407
269
  msgid "title scheme"
270
  msgstr "Schema title-Attribut"
271
 
272
- #: inc/settings.php:221
273
  msgid "Pro Features"
274
- msgstr "Pro Features"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
 
276
- #: inc/settings.php:223
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  msgid "Lazy Load settings"
278
  msgstr "Lazy Load Einstellungen"
279
 
280
- #: inc/settings.php:225
281
  msgid ""
282
  "This function is very useful and it boosts performance by delaying loading "
283
  "of images in long web pages, because images outside of viewport (visible "
@@ -288,7 +336,7 @@ msgstr ""
288
  "wenn diese in den Viewport scrollen, nicht vorher. Damit wird die initiale "
289
  "Datenlast beim Laden stark reduziert."
290
 
291
- #: inc/settings.php:226
292
  msgid ""
293
  "The lazy load is powered by unveil.js, one of the fastest and thinnest lazy "
294
  "loader in the web. The implementation is highly seo compatible with a no js "
@@ -298,52 +346,43 @@ msgstr ""
298
  "Lazy Loader im Web. Die Umsetzung ist SEO kompatibel aufgebaut und verfügt "
299
  "über einen JS Fallback."
300
 
301
- #: inc/settings.php:227
302
  msgid ""
303
  "If enabled the lazy load will be added automatically to images in your post "
304
  "or page content and also to post thumbnails."
305
  msgstr ""
306
- "Wenn der Lazy Load aktiviert ist, wird die Funktion automatisch in deinen "
307
  "Beiträgen, Seite und Artikelbildern aktiviert."
308
 
309
- #: inc/settings.php:233 inc/settings.php:334
310
- #, php-format
311
- msgid ""
312
- "Please consider upgrading to <a href=\"%s\" target=\"_blank\">PB SEO "
313
- "Friendly Images Pro</a> if you want to use this feature."
314
- msgstr ""
315
- "Bitte führe ein Upgrade auf <a href=\"%s\" target=\"_blank\">PB SEO Friendly "
316
- "Images Pro</a> durch, um diese Funktion verwenden zu können."
317
-
318
- #: inc/settings.php:243
319
  msgid "enable lazy load"
320
  msgstr "Lazy Load aktivieren"
321
 
322
- #: inc/settings.php:247
323
  msgid "enable lazy load and boost up your site speed"
324
- msgstr "Aktiviere Lazy Load und steigere die Performance deiner Webseite"
325
 
326
- #: inc/settings.php:254
327
  msgid "enable lazy load for acf"
328
  msgstr "Lazy Load für ACF"
329
 
330
- #: inc/settings.php:258
331
  msgid "enable lazy load for AdvancedCustomFields"
332
  msgstr "Lazy Load für AdvancedCustomFields aktivieren"
333
 
334
- #: inc/settings.php:265
335
  msgid "lazy load default styles"
336
  msgstr "Lazy Load Standard-Styles laden"
337
 
338
- #: inc/settings.php:269
339
  msgid "enable lazy load default styles"
340
- msgstr "Lazy Load Standard-Styles laden"
341
 
342
- #: inc/settings.php:276
343
  msgid "threshold"
344
  msgstr "Grenzwert für Lazy Load"
345
 
346
- #: inc/settings.php:280
347
  msgid ""
348
  "By default, images are only loaded when the user scrolls to them and they "
349
  "became visible on the screen (default value for this field <code>0</code>). "
@@ -352,32 +391,32 @@ msgid ""
352
  msgstr ""
353
  "Standardmäßig werden die Bilder nur dann geladen, wenn der Besucher zu den "
354
  "Bildern scrollt und diese in den sichtbaren Bereich rutschen (Standardwert "
355
- "für dieses Feld <code>0</code>). Wenn du die Bilder früher laden möchtest, "
356
- "sagen wir 200px vor dem Viewport, dann müssen <code>200</code> als Feldwert "
357
- "gesetzt werden."
358
 
359
- #: inc/settings.php:300
360
  msgid "Theme-Integration (only for developers relevant)"
361
  msgstr "Theme-Integration (nur für Entwickler relevant)"
362
 
363
- #: inc/settings.php:302
364
  msgid ""
365
  "Want to add lazy load to images in your theme? You only need to do some "
366
  "small modifications. Add class \"lazy\" and modify the \"src\" like this:"
367
  msgstr ""
368
  "Möchtest du den Lazy Load auch für Bilder in deinem Theme verwenden? Du "
369
  "musst lediglich ein paar kleinere Modifikationen durchführen. Füge die "
370
- "Klasse \"pb-seo-lazy\" hinzu und erweitere das \"src\" Attribut wie folgt:"
371
 
372
- #: inc/settings.php:306
373
  msgid "REAL SRC HERE"
374
- msgstr "Echter SRC Pfad"
375
 
376
- #: inc/settings.php:326
377
  msgid "WooCommerce settings"
378
  msgstr "WooCommerce Einstellungen"
379
 
380
- #: inc/settings.php:328
381
  msgid ""
382
  "This settings are specially for images inside your WooCommerce Shop. In most "
383
  "cases you need to activate the override to use your custom settings."
@@ -386,24 +425,24 @@ msgstr ""
386
  "Shops. In dein meisten Fällen muss der Override aktiviert werden, damit "
387
  "diese korrekt funktionieren."
388
 
389
- #: inc/settings.php:344
390
  msgid "WooCommerce"
391
  msgstr "WooCommerce"
392
 
393
- #: inc/settings.php:348
394
  msgid "Use the product name as alt and title for WooCommerce product images"
395
  msgstr ""
396
- "Verwende den Produktnamen als alt und title für WooCommerce Produktbilder."
397
 
398
- #: inc/settings.php:431
399
  msgid "Additional features"
400
- msgstr "Zusatzfunktionen"
401
 
402
- #: inc/settings.php:437
403
  msgid "set title for links"
404
  msgstr "Title für Links setzen"
405
 
406
- #: inc/settings.php:441
407
  msgid ""
408
  "Use the power of PB SEO Friendly Images also for seo friendly links. This "
409
  "will set the title depending on the link text and only if there is no "
@@ -413,11 +452,11 @@ msgstr ""
413
  "Links. Das Tool wird nicht vergebene Linktitel automatisch auf Basis der "
414
  "Linktexte oder enthaltener Bilder setzen"
415
 
416
- #: inc/settings.php:448
417
  msgid "disable srcset"
418
  msgstr "srcset ausschalten"
419
 
420
- #: inc/settings.php:452
421
  msgid ""
422
  "disable srcset attribute and responsive images in WordPress if you don't "
423
  "need them"
@@ -425,11 +464,11 @@ msgstr ""
425
  "deaktiviere das srcset Attribut und Responsive Bilder in Wordpress, wenn du "
426
  "diese nicht benötigst"
427
 
428
- #: inc/settings.php:472
429
  msgid "Encoding and Parser"
430
  msgstr "Encoding und Parser"
431
 
432
- #: inc/settings.php:474
433
  msgid ""
434
  "Here you can configure the HTML-Parser of the plugin. You <u>only</u> need "
435
  "to change this settings if you have <u>problems with your encoding</u> after "
@@ -439,11 +478,11 @@ msgstr ""
439
  "Einstellungen <u>nur dann ändern</u>, falls du <u>Probleme mit dem "
440
  "Encoding / Umlauten</u> nach Aktivierung des Plugins hast."
441
 
442
- #: inc/settings.php:481
443
  msgid "encoding"
444
  msgstr "Encoding"
445
 
446
- #: inc/settings.php:485
447
  msgid ""
448
  "leave blank to use WordPress default encoding or type in something like "
449
  "\"utf-8\""
@@ -451,70 +490,132 @@ msgstr ""
451
  "Lass dieses Feld leer um das WordPress Standard-Encoding zu verwenden oder "
452
  "gib etwas ein wie z.B. „utf-8“"
453
 
454
- #: inc/settings.php:491
455
  msgid "encoding mode"
456
  msgstr "Encoding-Modus"
457
 
458
- #: inc/settings.php:496
459
  msgid "HTML-ENTITIES"
460
  msgstr "HTML-ENTITIES"
461
 
462
- #: inc/settings.php:497
463
  msgid "disable convert encoding"
464
  msgstr "Konvertierung abschalten"
465
 
466
  #. Plugin Name of the plugin/theme
467
- #: inc/settings.php:507
468
  msgid "PB SEO Friendly Images"
469
  msgstr "PB SEO Friendly Images"
470
 
471
- #: inc/settings.php:508
472
  msgid "SEO Friendly Images"
473
- msgstr "SEO Friendly Images"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
474
 
475
- #: inc/settings.php:537
 
 
 
 
 
 
 
 
 
 
 
 
476
  msgid "Plugins & Support"
477
  msgstr "Plugins & Support"
478
 
479
- #: inc/settings.php:541
 
480
  msgid "WordPress Kurs"
481
- msgstr ""
 
 
 
 
482
 
483
- #: inc/settings.php:542
484
  msgid ""
485
  "Möchtest du mit WordPress richtig durchstarten? In meinem WordPress Kurs "
486
  "erfährst du spannende Tipps und Tricks zu WordPress und SEO!"
487
  msgstr ""
 
 
488
 
489
- #: inc/settings.php:545
490
  msgid "Jetzt Kurs ansehen"
491
- msgstr ""
492
-
493
- #: inc/settings.php:553 inc/settings.php:555
494
- msgid "PrimusNote"
495
- msgstr "PrimusNote"
496
 
497
- #: inc/settings.php:555
498
- msgid "Project Management"
499
- msgstr "Projekt-Management"
500
 
501
- #: inc/settings.php:558
502
  msgid ""
503
- "PrimusNote is a Project Management and Team Collaboration software based on "
504
- "WordPress."
 
505
  msgstr ""
506
- "PrimusNote ist eine Projekt-Management und Team-Kollaborations-Software auf "
507
- "WordPress Basis."
 
508
 
509
- #: inc/settings.php:559 inc/settings.php:572
510
- msgid "Install Plugin"
511
- msgstr "Plugin installieren"
512
 
513
- #: inc/settings.php:566 inc/settings.php:568
514
  msgid "MailCrypt - AntiSpam Email Encryption"
515
  msgstr "MailCrypt - E-Mail Verschlüsselung"
516
 
517
- #: inc/settings.php:571
518
  msgid ""
519
  "This Plugin provides a Shortcode to encrypt email addresses / links and "
520
  "protect them against spam."
@@ -522,49 +623,32 @@ msgstr ""
522
  "Dieses Plugin stellt einen Shortcode und Funktionen für die E-Mail "
523
  "Verschlüsselung zur Verfügung und schützt gegen Spam."
524
 
525
- #: inc/settings.php:577
 
 
 
 
526
  msgid "Support"
527
  msgstr "Support"
528
 
529
- #: inc/settings.php:578
530
  msgid ""
531
  "Do you need some help with this plugin? I am here to help you. Get in touch:"
532
  msgstr ""
533
  "Benötigst du Unterstützung mit diesem Plugin? Ich bin gerne bereit zu "
534
  "helfen, schreib mir einfach:"
535
 
536
- #: inc/settings.php:582
537
  msgid "Support Forum"
538
  msgstr "Support Forum"
539
 
540
- #: inc/settings.php:584
541
  msgid "Contact Support"
542
  msgstr "Support kontaktieren"
543
 
544
- #: inc/settings.php:586
545
  msgid "Changelog"
546
- msgstr "Changelog"
547
-
548
- #: plugin-update-checker/github-checker.php:119
549
- msgid "There is no changelog available."
550
- msgstr "Es steht kein Änderungsprotokoll zur Verfügung."
551
-
552
- #: plugin-update-checker/plugin-update-checker.php:776
553
- msgid "Check for updates"
554
- msgstr "Auf Aktualisierung prüfen"
555
-
556
- #: plugin-update-checker/plugin-update-checker.php:820
557
- msgid "This plugin is up to date."
558
- msgstr "Dieses Plugin ist auf dem neuesten Stand."
559
-
560
- #: plugin-update-checker/plugin-update-checker.php:822
561
- msgid "A new version of this plugin is available."
562
- msgstr "Eine neue Version dieses Plugins ist verfügbar."
563
-
564
- #: plugin-update-checker/plugin-update-checker.php:824
565
- #, php-format
566
- msgid "Unknown update checker status \"%s\""
567
- msgstr "Unbekannter Aktualisierungs-Status \"%s\""
568
 
569
  #. Plugin URI of the plugin/theme
570
  msgid "https://wordpress.org/extend/plugins/pb-seo-friendly-images/"
@@ -576,9 +660,10 @@ msgid ""
576
  "\"alt\" and \"title\" attributes for all images and post thumbnails. This "
577
  "plugin helps you to improve your traffic from search engines."
578
  msgstr ""
579
- "PB SEO Friendly Images: Einfach, schnell und automatisch "
580
- "suchmaschinenfreundliche Bilder für WordPress. Simple Optimierung von Alt- "
581
- "und Title Attributen."
 
582
 
583
  #. Author of the plugin/theme
584
  msgid "Pascal Bajorat"
@@ -588,27 +673,15 @@ msgstr "Pascal Bajorat"
588
  msgid "https://www.pascal-bajorat.com"
589
  msgstr "https://www.pascal-bajorat.com"
590
 
591
- #~ msgid ""
592
- #~ "Do you need some help with this plugin? We are here to help you. Get in "
593
- #~ "touch:"
594
- #~ msgstr ""
595
- #~ "Benötigst du Unterstützung? Wir sind da um zu helfen, nimm Kontakt mit "
596
- #~ "uns auf"
597
 
598
  #~ msgid ""
599
- #~ "PB SEO Friendly Images is a free WordPress Plugin by <a href=\"%s\" "
600
- #~ "target=\"_blank\">Pascal Bajorat</a> and made with %s in Berlin, Germany."
601
- #~ "<br />If you like it and maybe want to <a href=\"%s\" target=\"_blank"
602
- #~ "\">buy me a cup of coffee or a beer</a> I would appreciate that very much."
603
  #~ msgstr ""
604
- #~ "PB SEO Friendly Images ist ein kostenloses WordPress Plugin von <a href="
605
- #~ "\"%s\" target=\"_blank\">Pascal Bajorat</a> und wurde mit viel %s in "
606
- #~ "Berlin entwickelt.<br />Wenn du das Plugin magst würde ich mich freuen, "
607
- #~ "<a href=\"%s\" target=\"_blank\">wenn du mich mit einer kleinen Spende "
608
- #~ "virtuell auf einen Kaffee oder Bier einlädst</a>."
609
-
610
- #~ msgid "http://wordpress.org/extend/plugins/pb-seo-friendly-images/"
611
- #~ msgstr "http://wordpress.org/extend/plugins/pb-seo-friendly-images/"
612
-
613
- #~ msgid "PB SEO Friendly Images Pro"
614
- #~ msgstr "PB SEO Friendly Images Pro"
1
  msgid ""
2
  msgstr ""
3
  "Project-Id-Version: PB SEO Friendly Images\n"
4
+ "POT-Creation-Date: 2019-02-24 17:02+0100\n"
5
+ "PO-Revision-Date: 2019-02-24 17:02+0100\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: \n"
8
+ "Language: de_DE\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
 
 
 
12
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
13
+ "X-Generator: Poedit 2.2\n"
14
+ "X-Poedit-Basepath: ..\n"
15
+ "X-Poedit-Flags-xgettext: --add-comments=translators:\n"
16
+ "X-Poedit-WPHeader: pb-seo-friendly-images-pro.php\n"
17
  "X-Poedit-SourceCharset: UTF-8\n"
18
  "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
19
  "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
21
  "X-Poedit-SearchPath-0: .\n"
22
  "X-Poedit-SearchPathExcluded-0: *.js\n"
23
 
24
+ #: inc/pbsfi_admin_interface.php:68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  msgid "Settings"
26
  msgstr "Einstellungen"
27
 
28
+ #: inc/pbsfi_admin_interface.php:80
29
  msgid "Get Pro Version"
30
  msgstr "Pro-Version kaufen"
31
 
32
+ #: inc/pbsfi_admin_interface.php:106
33
  msgid "Image \"alt\" and \"title\" Settings"
34
+ msgstr "Bild alt und „Titel“ Einstellungen"
35
 
36
+ #: inc/pbsfi_admin_interface.php:110
37
  msgid ""
38
  "PB SEO Friendly Images automatically adds \"alt\" and \"title\" attributes "
39
  "to all images and post thumbnails in your posts. The default options are a "
40
  "good starting point for the optimization and basically fine for most "
41
  "websites."
42
  msgstr ""
43
+ "PB SEO Friendly Images verwaltet automatisch die alt und title Attribute "
44
+ "Ihrer Post-Thumbnails sowie aller Bilder innerhalb Ihrer Seiten und Artikel. "
45
+ "Die Standard-Einstellungen sind eine gute erste Grundlage und werden für die "
46
+ "meisten Webseiten gut funktionieren, ohne das Änderungen notwendig sind."
 
47
 
48
+ #: inc/pbsfi_admin_interface.php:111
49
  msgid "Override feature"
50
  msgstr "Override-Funktion"
51
 
52
+ #: inc/pbsfi_admin_interface.php:111
53
  msgid ""
54
  "Enable the override means that a possible sync and also hand picked \"alt"
55
  "\" / \"title\" attributes will be overwritten with the selected scheme. If "
58
  "\"title\" will do it's best for you."
59
  msgstr ""
60
  "Wenn du die Override (überschreiben) Funktion verwendest, werden alle "
61
+ "manuellen alt und/oder title Attribute durch das gewählte Schema "
62
+ "überschrieben. Wenn du bereits manuelle Attribute für Bilder gesetzt hast, "
63
+ "solltest du einfach die Sync Funktion ihren Job machen lassen und keine "
64
+ "Überschreibung erzwingen."
65
 
66
+ #: inc/pbsfi_admin_interface.php:114
67
  #, php-format
68
  msgid ""
69
  "PB SEO Friendly Images Pro is a WordPress Plugin by <a href=\"%s\" target="
73
  "target=\"_blank\">Pascal Bajorat</a>, entwickelt und gepflegt mit %s in "
74
  "Berlin."
75
 
76
+ #: inc/pbsfi_admin_interface.php:120
77
  msgid "How it works"
78
+ msgstr "Anleitung"
79
 
80
+ #: inc/pbsfi_admin_interface.php:120
81
  msgid ""
82
  "You only need to configure the plugin with the following settings. The "
83
  "plugin will optimize your HTML code on-the-fly. This means, that you see the "
94
  "kannst also risikolos die Einstellungen anpassen, Änderungen werden immer "
95
  "direkt in der HTML Ausgabe berücksichtigt."
96
 
97
+ #: inc/pbsfi_admin_interface.php:127
98
  #, php-format
99
  msgid ""
100
  "Please consider upgrading to <a href=\"%s\" target=\"_blank\">PB SEO "
101
  "Friendly Images Pro</a> if you want to use more features and support the "
102
  "development of this plugin."
103
  msgstr ""
104
+ "Bitte ziehe ein Upgrade auf <a href=\"%s\" target=\"_blank\">PB SEO Friendly "
105
+ "Images Pro</a> in Erwägung, wenn du weitere Funktionen verwenden möchten und "
106
+ "die Entwicklung des Plugins unterstützen möchtest."
107
 
108
+ #: inc/pbsfi_admin_interface.php:131 inc/pbsfi_admin_interface.php:249
109
+ #: inc/pbsfi_admin_interface.php:304 inc/pbsfi_admin_interface.php:405
110
  msgid "Upgrade now"
111
  msgstr "Jetzt upgraden"
112
 
113
+ #: inc/pbsfi_admin_interface.php:138
114
  msgid "optimize images"
115
  msgstr "Bilder optimieren"
116
 
117
+ #: inc/pbsfi_admin_interface.php:143
118
  msgid "post thumbnails and images in post content"
119
  msgstr "Thumbnails und Bilder innerhalb der Posts"
120
 
121
+ #: inc/pbsfi_admin_interface.php:143 inc/pbsfi_admin_interface.php:158
122
+ #: inc/pbsfi_admin_interface.php:428
123
  msgid "recommended"
124
  msgstr "empfohlen"
125
 
126
+ #: inc/pbsfi_admin_interface.php:144
127
  msgid "only post thumbnails"
128
  msgstr "Nur Postthumbnails"
129
 
130
+ #: inc/pbsfi_admin_interface.php:145
131
  msgid "only images in post content"
132
  msgstr "Nur Bilder im Post-Inhalt"
133
 
134
+ #: inc/pbsfi_admin_interface.php:147
135
  msgid "which images should be optimized"
136
+ msgstr "Welche Bilder sollen optimiert werden"
137
 
138
+ #: inc/pbsfi_admin_interface.php:153 inc/pbsfi_admin_interface.php:423
139
  msgid "sync method"
140
+ msgstr "Synchronisationsmethode"
141
 
142
+ #: inc/pbsfi_admin_interface.php:158 inc/pbsfi_admin_interface.php:428
143
  msgid "alt <=> title"
144
  msgstr "alt <=> title"
145
 
146
+ #: inc/pbsfi_admin_interface.php:159 inc/pbsfi_admin_interface.php:429
147
  msgid "alt => title"
148
  msgstr "alt => title"
149
 
150
+ #: inc/pbsfi_admin_interface.php:160 inc/pbsfi_admin_interface.php:430
151
  msgid "alt <= title"
152
  msgstr "alt <= title"
153
 
154
+ #: inc/pbsfi_admin_interface.php:162 inc/pbsfi_admin_interface.php:432
155
  msgid "select sync method for \"alt\" and \"title\" attribute."
156
+ msgstr "Wähle die Synchronisierungsmethode für „alt“ und „title“ Attribute."
 
157
 
158
+ #: inc/pbsfi_admin_interface.php:163 inc/pbsfi_admin_interface.php:433
159
  msgid ""
160
  "<code>alt <=> title</code> - if one attribute is set use it also for the "
161
  "other one"
163
  "<code>alt <=> title</code> - Wenn ein Attribut gesetzt ist, wird dieses auch "
164
  "auf das andere übertragen"
165
 
166
+ #: inc/pbsfi_admin_interface.php:164 inc/pbsfi_admin_interface.php:434
167
  msgid ""
168
  "<code>alt => title</code> - if \"alt\" is set use it for the title attribute"
169
  msgstr ""
170
+ "<code>alt => title</code> - wenn alt gesetzt ist, verwende diesen für das "
171
+ "Title-Attribut"
172
 
173
+ #: inc/pbsfi_admin_interface.php:165 inc/pbsfi_admin_interface.php:435
174
  msgid ""
175
  "<code>alt <= title</code> - if \"title\" is set use it for the alt attribute"
176
  msgstr ""
177
+ "<code>alt <= title</code> - wenn title gesetzt ist, verwende diesen für "
178
+ "das Alt-Attribut"
179
 
180
+ #: inc/pbsfi_admin_interface.php:171 inc/pbsfi_admin_interface.php:442
181
  msgid "override \"alt\""
182
+ msgstr "Alt-Override"
183
 
184
+ #: inc/pbsfi_admin_interface.php:175 inc/pbsfi_admin_interface.php:446
185
  msgid "override existing image alt attributes"
186
+ msgstr "Überschreibt bestehende alt Attribute"
187
 
188
+ #: inc/pbsfi_admin_interface.php:181 inc/pbsfi_admin_interface.php:453
189
  msgid "override \"title\""
190
+ msgstr "Titel-Override"
191
 
192
+ #: inc/pbsfi_admin_interface.php:185 inc/pbsfi_admin_interface.php:457
193
  msgid "override existing image title attributes"
194
+ msgstr "Überschreibt bestehende title Attribute"
195
 
196
+ #: inc/pbsfi_admin_interface.php:189
197
  msgid "possible variables:"
198
  msgstr "Mögliche Variablen:"
199
 
200
+ #: inc/pbsfi_admin_interface.php:190
201
  msgid "replaces post title"
202
+ msgstr "wird ersetzt durch Artikeltitel"
203
 
204
+ #: inc/pbsfi_admin_interface.php:191
205
  msgid "replaces post excerpt"
206
+ msgstr "wird ersetzt durch den Artikelauszug"
207
 
208
+ #: inc/pbsfi_admin_interface.php:192
209
  msgid "replaces image filename (without extension)"
210
  msgstr "Wird ersetzt mit dem Dateinamen (ohne Dateiendung)"
211
 
212
+ #: inc/pbsfi_admin_interface.php:193
213
  msgid "replaces post category"
214
+ msgstr "wird ersetzt durch die Artikelkategorien"
215
 
216
+ #: inc/pbsfi_admin_interface.php:194
217
  msgid "replaces post tags"
218
+ msgstr "wird ersetzt durch die Artikel-Tags"
219
 
220
+ #: inc/pbsfi_admin_interface.php:195
221
  msgid "replaces attachment title (could be empty if not set)"
222
  msgstr ""
223
  "Wird ersetzt durch den Medien-Titel (könnte leer sein, falls nicht gesetzt)"
224
 
225
+ #: inc/pbsfi_admin_interface.php:196
226
  msgid "replaces attachment alt-text (could be empty if not set)"
227
  msgstr ""
228
  "Wird ersetzt durch den Medien-Alternativtext (könnte leer sein, falls nicht "
229
  "gesetzt)"
230
 
231
+ #: inc/pbsfi_admin_interface.php:197
232
  msgid "replaces attachment caption (could be empty if not set)"
233
  msgstr ""
234
  "Wird ersetzt durch die Medien-Beschriftung (könnte leer sein, falls nicht "
235
  "gesetzt)"
236
 
237
+ #: inc/pbsfi_admin_interface.php:198
238
  msgid "replaces attachment description (could be empty if not set)"
239
  msgstr ""
240
  "Wird ersetzt durch die Medien-Beschreibung (könnte leer sein, falls nicht "
241
  "gesetzt)"
242
 
243
+ #: inc/pbsfi_admin_interface.php:202 inc/pbsfi_admin_interface.php:464
244
  msgid "alt scheme"
245
  msgstr "Schema alt-Attribut"
246
 
247
+ #: inc/pbsfi_admin_interface.php:206 inc/pbsfi_admin_interface.php:216
248
+ #: inc/pbsfi_admin_interface.php:468 inc/pbsfi_admin_interface.php:479
249
+ #: inc/pbsfi_admin_interface.php:564
250
  msgid "default"
251
  msgstr "Standard"
252
 
253
+ #: inc/pbsfi_admin_interface.php:212 inc/pbsfi_admin_interface.php:475
254
  msgid "title scheme"
255
  msgstr "Schema title-Attribut"
256
 
257
+ #: inc/pbsfi_admin_interface.php:235
258
  msgid "Pro Features"
259
+ msgstr "Pro-Funktionen"
260
+
261
+ #: inc/pbsfi_admin_interface.php:237
262
+ msgid "Caching"
263
+ msgstr "Zwischenspeicher"
264
+
265
+ #: inc/pbsfi_admin_interface.php:239
266
+ msgid ""
267
+ "Caching can highly increase the performance of your website with PB SEO "
268
+ "Friendly Images. If you already use a caching plugin you do not need to "
269
+ "enable this function."
270
+ msgstr ""
271
+ "Das Caching kann die Leistung deiner Website mit PB SEO Friendly Images "
272
+ "stark steigern. Wenn du bereits ein Caching-Plugin verwendest, musst du "
273
+ "diese Funktion nicht aktivieren."
274
 
275
+ #: inc/pbsfi_admin_interface.php:240
276
+ #, php-format
277
+ msgid ""
278
+ "We recommend to use <a href=\"%1$s\" target=\"_blank\">WP Rocket</a> as one "
279
+ "of the best Performance and Caching Solutions for WordPress. If you are "
280
+ "interested in a professional and individual Performance-Optimization <a href="
281
+ "\"%2$s\" target=\"_blank\">get a free quote here</a>."
282
+ msgstr ""
283
+ "Wir empfehlen, <a href=\"%1$s\" target=\"_ blank\">WP Rocket</a> als eine "
284
+ "der besten Performance- und Caching-Lösungen für WordPress zu verwenden. "
285
+ "Wenn du an einer professionellen und individuellen Performance-Optimierung "
286
+ "interessiert bist, <a href=\"%2$s\" target=\"_blank\">erhältst du hier ein "
287
+ "kostenloses Angebot</a>."
288
+
289
+ #: inc/pbsfi_admin_interface.php:240 templates/options_page.php:58
290
+ msgid ""
291
+ "https://www.pascal-bajorat.com/en/lp/wordpress-performance-optimization/"
292
+ msgstr "https://www.pascal-bajorat.com/lp/wordpress-performance-optimierung/"
293
+
294
+ #: inc/pbsfi_admin_interface.php:246 inc/pbsfi_admin_interface.php:301
295
+ #: inc/pbsfi_admin_interface.php:402
296
+ #, php-format
297
+ msgid ""
298
+ "Please consider upgrading to <a href=\"%s\" target=\"_blank\">PB SEO "
299
+ "Friendly Images Pro</a> if you want to use this feature."
300
+ msgstr ""
301
+ "Bitte führe ein Upgrade auf <a href=\"%s\" target=\"_blank\">PB SEO Friendly "
302
+ "Images Pro</a> durch, um diese Funktion verwenden zu können."
303
+
304
+ #: inc/pbsfi_admin_interface.php:256
305
+ msgid "enable content caching"
306
+ msgstr "Content-Caching aktivieren"
307
+
308
+ #: inc/pbsfi_admin_interface.php:260
309
+ msgid ""
310
+ "enable content caching and boost up your site speed with PB SEO Friendly "
311
+ "Images"
312
+ msgstr ""
313
+ "Mit PB SEO Friendly Images Content Caching kannst du die Geschwindigkeit "
314
+ "deiner Website erhöhen"
315
+
316
+ #: inc/pbsfi_admin_interface.php:267
317
+ msgid "TTL"
318
+ msgstr "TTL"
319
+
320
+ #: inc/pbsfi_admin_interface.php:271
321
+ msgid "TTL in seconds: 86400 = 24h; 3600 = 1h; 0 = never expire;"
322
+ msgstr "TTL in Sekunden: 86400 = 24h; 3600 = 1h; 0 = läuft nie ab;"
323
+
324
+ #: inc/pbsfi_admin_interface.php:291
325
  msgid "Lazy Load settings"
326
  msgstr "Lazy Load Einstellungen"
327
 
328
+ #: inc/pbsfi_admin_interface.php:293
329
  msgid ""
330
  "This function is very useful and it boosts performance by delaying loading "
331
  "of images in long web pages, because images outside of viewport (visible "
336
  "wenn diese in den Viewport scrollen, nicht vorher. Damit wird die initiale "
337
  "Datenlast beim Laden stark reduziert."
338
 
339
+ #: inc/pbsfi_admin_interface.php:294
340
  msgid ""
341
  "The lazy load is powered by unveil.js, one of the fastest and thinnest lazy "
342
  "loader in the web. The implementation is highly seo compatible with a no js "
346
  "Lazy Loader im Web. Die Umsetzung ist SEO kompatibel aufgebaut und verfügt "
347
  "über einen JS Fallback."
348
 
349
+ #: inc/pbsfi_admin_interface.php:295
350
  msgid ""
351
  "If enabled the lazy load will be added automatically to images in your post "
352
  "or page content and also to post thumbnails."
353
  msgstr ""
354
+ "Wenn der Lazy Load aktiviert ist, wird die Funktion automatisch in Ihren "
355
  "Beiträgen, Seite und Artikelbildern aktiviert."
356
 
357
+ #: inc/pbsfi_admin_interface.php:311
 
 
 
 
 
 
 
 
 
358
  msgid "enable lazy load"
359
  msgstr "Lazy Load aktivieren"
360
 
361
+ #: inc/pbsfi_admin_interface.php:315
362
  msgid "enable lazy load and boost up your site speed"
363
+ msgstr "Aktiviere den Lazy Load und steiger die Performance deiner Webseite"
364
 
365
+ #: inc/pbsfi_admin_interface.php:322
366
  msgid "enable lazy load for acf"
367
  msgstr "Lazy Load für ACF"
368
 
369
+ #: inc/pbsfi_admin_interface.php:326
370
  msgid "enable lazy load for AdvancedCustomFields"
371
  msgstr "Lazy Load für AdvancedCustomFields aktivieren"
372
 
373
+ #: inc/pbsfi_admin_interface.php:333
374
  msgid "lazy load default styles"
375
  msgstr "Lazy Load Standard-Styles laden"
376
 
377
+ #: inc/pbsfi_admin_interface.php:337
378
  msgid "enable lazy load default styles"
379
+ msgstr "Aktiviere Lazy Load Standard-Styles"
380
 
381
+ #: inc/pbsfi_admin_interface.php:344
382
  msgid "threshold"
383
  msgstr "Grenzwert für Lazy Load"
384
 
385
+ #: inc/pbsfi_admin_interface.php:348
386
  msgid ""
387
  "By default, images are only loaded when the user scrolls to them and they "
388
  "became visible on the screen (default value for this field <code>0</code>). "
391
  msgstr ""
392
  "Standardmäßig werden die Bilder nur dann geladen, wenn der Besucher zu den "
393
  "Bildern scrollt und diese in den sichtbaren Bereich rutschen (Standardwert "
394
+ "für dieses Feld <code>0</code>). Wenn du die Bilder früher laden möchtest, "
395
+ "sagen wir z.B. 200px vor dem Viewport, dann müssen <code>200</code> als "
396
+ "Feldwert gesetzt werden."
397
 
398
+ #: inc/pbsfi_admin_interface.php:368
399
  msgid "Theme-Integration (only for developers relevant)"
400
  msgstr "Theme-Integration (nur für Entwickler relevant)"
401
 
402
+ #: inc/pbsfi_admin_interface.php:370
403
  msgid ""
404
  "Want to add lazy load to images in your theme? You only need to do some "
405
  "small modifications. Add class \"lazy\" and modify the \"src\" like this:"
406
  msgstr ""
407
  "Möchtest du den Lazy Load auch für Bilder in deinem Theme verwenden? Du "
408
  "musst lediglich ein paar kleinere Modifikationen durchführen. Füge die "
409
+ "Klasse pb-seo-lazy hinzu und erweitere das src Attribut wie folgt:"
410
 
411
+ #: inc/pbsfi_admin_interface.php:374
412
  msgid "REAL SRC HERE"
413
+ msgstr "ECHTER SRC HIER"
414
 
415
+ #: inc/pbsfi_admin_interface.php:394
416
  msgid "WooCommerce settings"
417
  msgstr "WooCommerce Einstellungen"
418
 
419
+ #: inc/pbsfi_admin_interface.php:396
420
  msgid ""
421
  "This settings are specially for images inside your WooCommerce Shop. In most "
422
  "cases you need to activate the override to use your custom settings."
425
  "Shops. In dein meisten Fällen muss der Override aktiviert werden, damit "
426
  "diese korrekt funktionieren."
427
 
428
+ #: inc/pbsfi_admin_interface.php:412
429
  msgid "WooCommerce"
430
  msgstr "WooCommerce"
431
 
432
+ #: inc/pbsfi_admin_interface.php:416
433
  msgid "Use the product name as alt and title for WooCommerce product images"
434
  msgstr ""
435
+ "Verwende den Produktnamen als alt und title für WooCommerce Produktbilder"
436
 
437
+ #: inc/pbsfi_admin_interface.php:499
438
  msgid "Additional features"
439
+ msgstr "Weitere Funktionen"
440
 
441
+ #: inc/pbsfi_admin_interface.php:505
442
  msgid "set title for links"
443
  msgstr "Title für Links setzen"
444
 
445
+ #: inc/pbsfi_admin_interface.php:509
446
  msgid ""
447
  "Use the power of PB SEO Friendly Images also for seo friendly links. This "
448
  "will set the title depending on the link text and only if there is no "
452
  "Links. Das Tool wird nicht vergebene Linktitel automatisch auf Basis der "
453
  "Linktexte oder enthaltener Bilder setzen"
454
 
455
+ #: inc/pbsfi_admin_interface.php:516
456
  msgid "disable srcset"
457
  msgstr "srcset ausschalten"
458
 
459
+ #: inc/pbsfi_admin_interface.php:520
460
  msgid ""
461
  "disable srcset attribute and responsive images in WordPress if you don't "
462
  "need them"
464
  "deaktiviere das srcset Attribut und Responsive Bilder in Wordpress, wenn du "
465
  "diese nicht benötigst"
466
 
467
+ #: inc/pbsfi_admin_interface.php:540
468
  msgid "Encoding and Parser"
469
  msgstr "Encoding und Parser"
470
 
471
+ #: inc/pbsfi_admin_interface.php:542
472
  msgid ""
473
  "Here you can configure the HTML-Parser of the plugin. You <u>only</u> need "
474
  "to change this settings if you have <u>problems with your encoding</u> after "
478
  "Einstellungen <u>nur dann ändern</u>, falls du <u>Probleme mit dem "
479
  "Encoding / Umlauten</u> nach Aktivierung des Plugins hast."
480
 
481
+ #: inc/pbsfi_admin_interface.php:549
482
  msgid "encoding"
483
  msgstr "Encoding"
484
 
485
+ #: inc/pbsfi_admin_interface.php:553
486
  msgid ""
487
  "leave blank to use WordPress default encoding or type in something like "
488
  "\"utf-8\""
490
  "Lass dieses Feld leer um das WordPress Standard-Encoding zu verwenden oder "
491
  "gib etwas ein wie z.B. „utf-8“"
492
 
493
+ #: inc/pbsfi_admin_interface.php:559
494
  msgid "encoding mode"
495
  msgstr "Encoding-Modus"
496
 
497
+ #: inc/pbsfi_admin_interface.php:564
498
  msgid "HTML-ENTITIES"
499
  msgstr "HTML-ENTITIES"
500
 
501
+ #: inc/pbsfi_admin_interface.php:565
502
  msgid "disable convert encoding"
503
  msgstr "Konvertierung abschalten"
504
 
505
  #. Plugin Name of the plugin/theme
506
+ #: inc/pbsfi_admin_interface.php:578 pbseofriendlyimages.php:71
507
  msgid "PB SEO Friendly Images"
508
  msgstr "PB SEO Friendly Images"
509
 
510
+ #: inc/pbsfi_admin_interface.php:579
511
  msgid "SEO Friendly Images"
512
+ msgstr "PB SEO Friendly Images"
513
+
514
+ #: pbseofriendlyimages.php:197
515
+ msgid "Clear Cache"
516
+ msgstr "Cache leeren"
517
+
518
+ #: pbseofriendlyimages.php:305
519
+ #, php-format
520
+ msgid "Can not find: %s"
521
+ msgstr "Nicht gefunden: %s"
522
+
523
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:54
524
+ msgid "View details"
525
+ msgstr "Details anzeigen"
526
+
527
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:77
528
+ #, php-format
529
+ msgid "More information about %s"
530
+ msgstr "Mehr Informationen über %s"
531
+
532
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:128
533
+ msgid "Check for updates"
534
+ msgstr "Auf Aktualisierungen prüfen"
535
+
536
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:213
537
+ #, php-format
538
+ msgctxt "the plugin title"
539
+ msgid "The %s plugin is up to date."
540
+ msgstr "Das %s Plugin ist aktuell."
541
+
542
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:215
543
+ #, php-format
544
+ msgctxt "the plugin title"
545
+ msgid "A new version of the %s plugin is available."
546
+ msgstr "Eine neue Version des Plugins %s ist verfügbar."
547
+
548
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:217
549
+ #, php-format
550
+ msgctxt "the plugin title"
551
+ msgid "Could not determine if updates are available for %s."
552
+ msgstr "Konnte nicht prüfen, ob Updates für das Plugin %s verfügbar sind."
553
+
554
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:223
555
+ #, php-format
556
+ msgid "Unknown update checker status \"%s\""
557
+ msgstr "Unbekannter Status für Aktualisierungscheck „%s“"
558
 
559
+ #: plugin-update-checker/Puc/v4p5/Vcs/PluginUpdateChecker.php:98
560
+ msgid "There is no changelog available."
561
+ msgstr "Es steht kein Änderungsprotokoll zur Verfügung."
562
+
563
+ #: templates/options_page.php:11
564
+ #, php-format
565
+ msgid ""
566
+ "<strong>Cache cleared!</strong> %d elements are removed from transient cache."
567
+ msgstr ""
568
+ "<strong>Cache geleert!</strong> %d Elemente wurden aus dem Transient-Cache "
569
+ "entfernt."
570
+
571
+ #: templates/options_page.php:28
572
  msgid "Plugins & Support"
573
  msgstr "Plugins & Support"
574
 
575
+ #: templates/options_page.php:35 templates/options_page.php:37
576
+ #: templates/options_page.php:52
577
  msgid "WordPress Kurs"
578
+ msgstr "WordPress Kurs"
579
+
580
+ #: templates/options_page.php:37 templates/options_page.php:54
581
+ msgid "Recommendation"
582
+ msgstr "Empfehlung"
583
 
584
+ #: templates/options_page.php:39
585
  msgid ""
586
  "Möchtest du mit WordPress richtig durchstarten? In meinem WordPress Kurs "
587
  "erfährst du spannende Tipps und Tricks zu WordPress und SEO!"
588
  msgstr ""
589
+ "Möchtest du mit WordPress richtig durchstarten? In meinem WordPress Kurs "
590
+ "erfährst du spannende Tipps und Tricks zu WordPress und SEO!"
591
 
592
+ #: templates/options_page.php:43
593
  msgid "Jetzt Kurs ansehen"
594
+ msgstr "Jetzt Kurs ansehen"
 
 
 
 
595
 
596
+ #: templates/options_page.php:54
597
+ msgid "WordPress Performance"
598
+ msgstr "WordPress Performance"
599
 
600
+ #: templates/options_page.php:55
601
  msgid ""
602
+ "Do you want a professional and individual performance optimization for your "
603
+ "website? Increase your Google Pagespeed and SEO traffic with our high "
604
+ "performance optimization."
605
  msgstr ""
606
+ "Möchtest du eine professionelle und individuelle Performance-Optimierung für "
607
+ "deine Website? Erhöhe deinen Google Pagespeed und SEO-Traffic mit unserer "
608
+ "Hochleistungsoptimierung."
609
 
610
+ #: templates/options_page.php:59
611
+ msgid "Get a free quote"
612
+ msgstr "Erhalte ein kostenloses Angebot"
613
 
614
+ #: templates/options_page.php:67 templates/options_page.php:69
615
  msgid "MailCrypt - AntiSpam Email Encryption"
616
  msgstr "MailCrypt - E-Mail Verschlüsselung"
617
 
618
+ #: templates/options_page.php:72
619
  msgid ""
620
  "This Plugin provides a Shortcode to encrypt email addresses / links and "
621
  "protect them against spam."
623
  "Dieses Plugin stellt einen Shortcode und Funktionen für die E-Mail "
624
  "Verschlüsselung zur Verfügung und schützt gegen Spam."
625
 
626
+ #: templates/options_page.php:75
627
+ msgid "Install Plugin"
628
+ msgstr "Plugin installieren"
629
+
630
+ #: templates/options_page.php:80
631
  msgid "Support"
632
  msgstr "Support"
633
 
634
+ #: templates/options_page.php:81
635
  msgid ""
636
  "Do you need some help with this plugin? I am here to help you. Get in touch:"
637
  msgstr ""
638
  "Benötigst du Unterstützung mit diesem Plugin? Ich bin gerne bereit zu "
639
  "helfen, schreib mir einfach:"
640
 
641
+ #: templates/options_page.php:86
642
  msgid "Support Forum"
643
  msgstr "Support Forum"
644
 
645
+ #: templates/options_page.php:89
646
  msgid "Contact Support"
647
  msgstr "Support kontaktieren"
648
 
649
+ #: templates/options_page.php:92
650
  msgid "Changelog"
651
+ msgstr "Änderungsprotokoll"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
652
 
653
  #. Plugin URI of the plugin/theme
654
  msgid "https://wordpress.org/extend/plugins/pb-seo-friendly-images/"
660
  "\"alt\" and \"title\" attributes for all images and post thumbnails. This "
661
  "plugin helps you to improve your traffic from search engines."
662
  msgstr ""
663
+ "Dieses Plugin ist eine vollwertige Lösung für SEO-freundliche Bilder. "
664
+ "Optimiere die Attribute „alt“ und „title“ für alle Bilder und Post-"
665
+ "Thumbnails. Dieses Plugin hilft dir deinen organischen Traffic aus "
666
+ "Suchmaschinen zu verbessern."
667
 
668
  #. Author of the plugin/theme
669
  msgid "Pascal Bajorat"
673
  msgid "https://www.pascal-bajorat.com"
674
  msgstr "https://www.pascal-bajorat.com"
675
 
676
+ #~ msgid "PrimusNote"
677
+ #~ msgstr "PrimusNote"
678
+
679
+ #~ msgid "Project Management"
680
+ #~ msgstr "Projektmanagement"
 
681
 
682
  #~ msgid ""
683
+ #~ "PrimusNote is a Project Management and Team Collaboration software based "
684
+ #~ "on WordPress."
 
 
685
  #~ msgstr ""
686
+ #~ "PrimusNote ist eine Projekt-Management und Team-Kollaborations-Software "
687
+ #~ "auf WordPress Basis."
 
 
 
 
 
 
 
 
 
lang/pb-seo-friendly-images-de_DE_formal.mo DELETED
Binary file
lang/pb-seo-friendly-images-de_DE_formal.po DELETED
@@ -1,614 +0,0 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: PB SEO Friendly Images\n"
4
- "POT-Creation-Date: 2018-01-21 12:54+0100\n"
5
- "PO-Revision-Date: 2018-01-21 12:55+0100\n"
6
- "Last-Translator: Pascal Bajorat <pascal@pascal-bajorat.com>\n"
7
- "Language-Team: Pascal Bajorat <pascal@pascal-bajorat.com>\n"
8
- "Language: de\n"
9
- "MIME-Version: 1.0\n"
10
- "Content-Type: text/plain; charset=UTF-8\n"
11
- "Content-Transfer-Encoding: 8bit\n"
12
- "X-Generator: Poedit 1.8.12\n"
13
- "X-Poedit-Basepath: ..\n"
14
- "X-Poedit-WPHeader: pb-seo-friendly-images.php\n"
15
- "Plural-Forms: nplurals=2; plural=(n != 1);\n"
16
- "X-Poedit-SourceCharset: UTF-8\n"
17
- "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
18
- "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
19
- "_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
20
- "X-Poedit-SearchPath-0: .\n"
21
- "X-Poedit-SearchPathExcluded-0: *.js\n"
22
-
23
- #: inc/settings.php:35
24
- #, php-format
25
- msgid ""
26
- "<strong>Hey %s</strong>, we have updated <a href=\"%s\">PB SEO Friendly "
27
- "Images</a>. Visit the <a href=\"%s\">plugin settings page</a> to get deeper "
28
- "insights about the new features. This message will disappear automatically "
29
- "after you've visited the plugin settings."
30
- msgstr ""
31
- "<strong>Hey %s</strong>, wir haben <a href=\"%s\">PB SEO Friendly Images</a> "
32
- "aktualisiert. Besuche die <a href=\"%s\">Plugin-Einstellungen</a> und schau "
33
- "dir die neuen Funktionen an. Diese Nachricht verschwindet automatisch, "
34
- "nachdem du die Plugin-Einstellung geöffnet hast."
35
-
36
- #: inc/settings.php:40
37
- msgid "Close"
38
- msgstr "schließen"
39
-
40
- #: inc/settings.php:58
41
- msgid "Settings"
42
- msgstr "Einstellungen"
43
-
44
- #: inc/settings.php:70
45
- msgid "Get Pro Version"
46
- msgstr "Pro-Version kaufen"
47
-
48
- #: inc/settings.php:93
49
- msgid "Image \"alt\" and \"title\" Settings"
50
- msgstr "Bilder \"alt\" und \"title\" Einstellungen"
51
-
52
- #: inc/settings.php:97
53
- msgid ""
54
- "PB SEO Friendly Images automatically adds \"alt\" and \"title\" attributes "
55
- "to all images and post thumbnails in your posts. The default options are a "
56
- "good starting point for the optimization and basically fine for most "
57
- "websites."
58
- msgstr ""
59
- "PB SEO Friendly Images verwaltet automatisch die \"alt\" und \"title\" "
60
- "Attribute deiner Post-Thumbnails sowie aller Bilder innerhalb deiner Seiten "
61
- "und Artikel. Die Standard-Einstellungen sind eine gute erste Grundlage und "
62
- "werden für die meisten Webseiten gut funktionieren, ohne das Änderungen "
63
- "notwendig sind."
64
-
65
- #: inc/settings.php:98
66
- msgid "Override feature"
67
- msgstr "Override-Funktion"
68
-
69
- #: inc/settings.php:98
70
- msgid ""
71
- "Enable the override means that a possible sync and also hand picked \"alt"
72
- "\" / \"title\" attributes will be overwritten with the selected scheme. If "
73
- "you have good hand picked \"alt\" or \"title\" attributes in your images, I "
74
- "can not recommend to use the override. Automatic sync between \"alt\" and "
75
- "\"title\" will do it's best for you."
76
- msgstr ""
77
- "Wenn du die Override (überschreiben) Funktion verwendest, werden alle "
78
- "manuellen \"alt\" und/oder \"title\" Attribute durch das gewählte Schema "
79
- "überschrieben. Wenn du bereits manuelle Attribute für deine Bilder gesetzt "
80
- "hast, solltest du einfach die Sync Funktion ihren Job machen lassen und "
81
- "keine Überschreibung erzwingen."
82
-
83
- #: inc/settings.php:101
84
- #, php-format
85
- msgid ""
86
- "PB SEO Friendly Images Pro is a WordPress Plugin by <a href=\"%s\" target="
87
- "\"_blank\">Pascal Bajorat</a> and made with %s in Berlin, Germany."
88
- msgstr ""
89
- "PB SEO Friendly Images Pro ist ein Wordpress - Plugin von <a href=\"%s\" "
90
- "target=\"_blank\">Pascal Bajorat</a>, entwickelt und gepflegt mit %s in "
91
- "Berlin."
92
-
93
- #: inc/settings.php:107
94
- msgid "How it works"
95
- msgstr "Wie funktioniert das Plugin"
96
-
97
- #: inc/settings.php:107
98
- msgid ""
99
- "You only need to configure the plugin with the following settings. The "
100
- "plugin will optimize your HTML code on-the-fly. This means, that you see the "
101
- "\"alt\" and \"title\" directly in the HTML code output and not in your media "
102
- "library or editor. This is not a hard rewrite of your media library values. "
103
- "You can change this values without the risk to damage some media library "
104
- "data."
105
- msgstr ""
106
- "Du musst das Plugin einfach nur über die folgenden Einstellungen "
107
- "konfigurieren. Das Plugin optimiert on-the-fly die Ausgabe deines HTML-"
108
- "Codes. Das heißt, dass die „alt“ und „title“ Attribute direkt im HTML-Code "
109
- "optimiert werden und nicht in deiner Mediathek. Das Plugin überschreibt also "
110
- "nicht einfach die Daten innerhalb deiner Mediathek bzw. der Datenbank. Du "
111
- "kannst also risikolos die Einstellungen anpassen, Änderungen werden immer "
112
- "direkt in der HTML Ausgabe berücksichtigt."
113
-
114
- #: inc/settings.php:114
115
- #, php-format
116
- msgid ""
117
- "Please consider upgrading to <a href=\"%s\" target=\"_blank\">PB SEO "
118
- "Friendly Images Pro</a> if you want to use more features and support the "
119
- "development of this plugin."
120
- msgstr ""
121
- "Bitte ziehe doch ein Upgrade auf <a href=\"%s\" target=\"_blank\">PB SEO "
122
- "Friendly Images Pro</a> in Erwägung, wenn du weitere Funktionen verwenden "
123
- "möchtest und die Entwicklung des Plugins unterstützen willst."
124
-
125
- #: inc/settings.php:117 inc/settings.php:236 inc/settings.php:337
126
- msgid "Upgrade now"
127
- msgstr "Jetzt upgraden"
128
-
129
- #: inc/settings.php:124
130
- msgid "optimize images"
131
- msgstr "Bilder optimieren"
132
-
133
- #: inc/settings.php:129
134
- msgid "post thumbnails and images in post content"
135
- msgstr "Thumbnails und Bilder innerhalb der Posts"
136
-
137
- #: inc/settings.php:129 inc/settings.php:144 inc/settings.php:360
138
- msgid "recommended"
139
- msgstr "empfohlen"
140
-
141
- #: inc/settings.php:130
142
- msgid "only post thumbnails"
143
- msgstr "Nur Postthumbnails"
144
-
145
- #: inc/settings.php:131
146
- msgid "only images in post content"
147
- msgstr "Nur Bilder im Post-Inhalt"
148
-
149
- #: inc/settings.php:133
150
- msgid "which images should be optimized"
151
- msgstr "Welche Bilder sollen optimiert werden."
152
-
153
- #: inc/settings.php:139 inc/settings.php:355
154
- msgid "sync method"
155
- msgstr "Synchronisierungsmethode"
156
-
157
- #: inc/settings.php:144 inc/settings.php:360
158
- msgid "alt <=> title"
159
- msgstr "alt <=> title"
160
-
161
- #: inc/settings.php:145 inc/settings.php:361
162
- msgid "alt => title"
163
- msgstr "alt => title"
164
-
165
- #: inc/settings.php:146 inc/settings.php:362
166
- msgid "alt <= title"
167
- msgstr "alt <= title"
168
-
169
- #: inc/settings.php:148 inc/settings.php:364
170
- msgid "select sync method for \"alt\" and \"title\" attribute."
171
- msgstr ""
172
- "Wähle die Synchronisierungsmethode für \"alt\" und \"title\" Attribute."
173
-
174
- #: inc/settings.php:149 inc/settings.php:365
175
- msgid ""
176
- "<code>alt <=> title</code> - if one attribute is set use it also for the "
177
- "other one"
178
- msgstr ""
179
- "<code>alt <=> title</code> - Wenn ein Attribut gesetzt ist, wird dieses auch "
180
- "auf das andere übertragen"
181
-
182
- #: inc/settings.php:150 inc/settings.php:366
183
- msgid ""
184
- "<code>alt => title</code> - if \"alt\" is set use it for the title attribute"
185
- msgstr ""
186
- "<code>alt => title</code> - Wenn \"alt\" gesetzt ist, wird der Wert "
187
- "ebenfalls für \"title\" gesetzt"
188
-
189
- #: inc/settings.php:151 inc/settings.php:367
190
- msgid ""
191
- "<code>alt <= title</code> - if \"title\" is set use it for the alt attribute"
192
- msgstr ""
193
- "<code>alt <= title</code> - Wenn \"title\" gesetzt ist, wird der Wert "
194
- "ebenfalls für \"alt\" gesetzt"
195
-
196
- #: inc/settings.php:157 inc/settings.php:374
197
- msgid "override \"alt\""
198
- msgstr "\"alt\" überschreiben"
199
-
200
- #: inc/settings.php:161 inc/settings.php:378
201
- msgid "override existing image alt attributes"
202
- msgstr "Überschreibt bestehende \"alt\" Attribute"
203
-
204
- #: inc/settings.php:167 inc/settings.php:385
205
- msgid "override \"title\""
206
- msgstr "\"title\" überschreiben"
207
-
208
- #: inc/settings.php:171 inc/settings.php:389
209
- msgid "override existing image title attributes"
210
- msgstr "Überschreibt bestehende \"title\" Attribute"
211
-
212
- #: inc/settings.php:175
213
- msgid "possible variables:"
214
- msgstr "Mögliche Variablen:"
215
-
216
- #: inc/settings.php:176
217
- msgid "replaces post title"
218
- msgstr "Wird ersetzt durch Artikeltitel"
219
-
220
- #: inc/settings.php:177
221
- msgid "replaces post excerpt"
222
- msgstr "Wird ersetzt durch den Artikelauszug"
223
-
224
- #: inc/settings.php:178
225
- msgid "replaces image filename (without extension)"
226
- msgstr "Wird ersetzt mit dem Dateinamen (ohne Dateiendung)"
227
-
228
- #: inc/settings.php:179
229
- msgid "replaces post category"
230
- msgstr "Wird ersetzt durch die Artikelkategorien"
231
-
232
- #: inc/settings.php:180
233
- msgid "replaces post tags"
234
- msgstr "Wird ersetzt durch die Artikel-Tags"
235
-
236
- #: inc/settings.php:181
237
- msgid "replaces attachment title (could be empty if not set)"
238
- msgstr ""
239
- "Wird ersetzt durch den Medien-Titel (könnte leer sein, falls nicht gesetzt)"
240
-
241
- #: inc/settings.php:182
242
- msgid "replaces attachment alt-text (could be empty if not set)"
243
- msgstr ""
244
- "Wird ersetzt durch den Medien-Alternativtext (könnte leer sein, falls nicht "
245
- "gesetzt)"
246
-
247
- #: inc/settings.php:183
248
- msgid "replaces attachment caption (could be empty if not set)"
249
- msgstr ""
250
- "Wird ersetzt durch die Medien-Beschriftung (könnte leer sein, falls nicht "
251
- "gesetzt)"
252
-
253
- #: inc/settings.php:184
254
- msgid "replaces attachment description (could be empty if not set)"
255
- msgstr ""
256
- "Wird ersetzt durch die Medien-Beschreibung (könnte leer sein, falls nicht "
257
- "gesetzt)"
258
-
259
- #: inc/settings.php:188 inc/settings.php:396
260
- msgid "alt scheme"
261
- msgstr "Schema alt-Attribut"
262
-
263
- #: inc/settings.php:192 inc/settings.php:202 inc/settings.php:400
264
- #: inc/settings.php:411 inc/settings.php:496
265
- msgid "default"
266
- msgstr "Standard"
267
-
268
- #: inc/settings.php:198 inc/settings.php:407
269
- msgid "title scheme"
270
- msgstr "Schema title-Attribut"
271
-
272
- #: inc/settings.php:221
273
- msgid "Pro Features"
274
- msgstr "Pro Features"
275
-
276
- #: inc/settings.php:223
277
- msgid "Lazy Load settings"
278
- msgstr "Lazy Load Einstellungen"
279
-
280
- #: inc/settings.php:225
281
- msgid ""
282
- "This function is very useful and it boosts performance by delaying loading "
283
- "of images in long web pages, because images outside of viewport (visible "
284
- "part of web page) won't be loaded until the user scrolls to them."
285
- msgstr ""
286
- "Diese Funktion ist unglaublich hilfreich auf Seiten mit vielen Bildern. Die "
287
- "Performance wird erheblich erhöht, dadurch das Bilder erst geladen werden, "
288
- "wenn diese in den Viewport scrollen, nicht vorher. Damit wird die initiale "
289
- "Datenlast beim Laden stark reduziert."
290
-
291
- #: inc/settings.php:226
292
- msgid ""
293
- "The lazy load is powered by unveil.js, one of the fastest and thinnest lazy "
294
- "loader in the web. The implementation is highly seo compatible with a no js "
295
- "fallback."
296
- msgstr ""
297
- "Der Lazy Load basiert auf unveil.js, einer der schnellsten und kleinsten "
298
- "Lazy Loader im Web. Die Umsetzung ist SEO kompatibel aufgebaut und verfügt "
299
- "über einen JS Fallback."
300
-
301
- #: inc/settings.php:227
302
- msgid ""
303
- "If enabled the lazy load will be added automatically to images in your post "
304
- "or page content and also to post thumbnails."
305
- msgstr ""
306
- "Wenn der Lazy Load aktiviert ist, wird die Funktion automatisch in deinen "
307
- "Beiträgen, Seite und Artikelbildern aktiviert."
308
-
309
- #: inc/settings.php:233 inc/settings.php:334
310
- #, php-format
311
- msgid ""
312
- "Please consider upgrading to <a href=\"%s\" target=\"_blank\">PB SEO "
313
- "Friendly Images Pro</a> if you want to use this feature."
314
- msgstr ""
315
- "Bitte führe ein Upgrade auf <a href=\"%s\" target=\"_blank\">PB SEO Friendly "
316
- "Images Pro</a> durch, um diese Funktion verwenden zu können."
317
-
318
- #: inc/settings.php:243
319
- msgid "enable lazy load"
320
- msgstr "Lazy Load aktivieren"
321
-
322
- #: inc/settings.php:247
323
- msgid "enable lazy load and boost up your site speed"
324
- msgstr "Aktiviere Lazy Load und steigere die Performance deiner Webseite"
325
-
326
- #: inc/settings.php:254
327
- msgid "enable lazy load for acf"
328
- msgstr "Lazy Load für ACF"
329
-
330
- #: inc/settings.php:258
331
- msgid "enable lazy load for AdvancedCustomFields"
332
- msgstr "Lazy Load für AdvancedCustomFields aktivieren"
333
-
334
- #: inc/settings.php:265
335
- msgid "lazy load default styles"
336
- msgstr "Lazy Load Standard-Styles laden"
337
-
338
- #: inc/settings.php:269
339
- msgid "enable lazy load default styles"
340
- msgstr "Lazy Load Standard-Styles laden"
341
-
342
- #: inc/settings.php:276
343
- msgid "threshold"
344
- msgstr "Grenzwert für Lazy Load"
345
-
346
- #: inc/settings.php:280
347
- msgid ""
348
- "By default, images are only loaded when the user scrolls to them and they "
349
- "became visible on the screen (default value for this field <code>0</code>). "
350
- "If you want your images to load earlier than that, lets say 200px then you "
351
- "need to type in <code>200</code>."
352
- msgstr ""
353
- "Standardmäßig werden die Bilder nur dann geladen, wenn der Besucher zu den "
354
- "Bildern scrollt und diese in den sichtbaren Bereich rutschen (Standardwert "
355
- "für dieses Feld <code>0</code>). Wenn du die Bilder früher laden möchtest, "
356
- "sagen wir 200px vor dem Viewport, dann müssen <code>200</code> als Feldwert "
357
- "gesetzt werden."
358
-
359
- #: inc/settings.php:300
360
- msgid "Theme-Integration (only for developers relevant)"
361
- msgstr "Theme-Integration (nur für Entwickler relevant)"
362
-
363
- #: inc/settings.php:302
364
- msgid ""
365
- "Want to add lazy load to images in your theme? You only need to do some "
366
- "small modifications. Add class \"lazy\" and modify the \"src\" like this:"
367
- msgstr ""
368
- "Möchtest du den Lazy Load auch für Bilder in deinem Theme verwenden? Du "
369
- "musst lediglich ein paar kleinere Modifikationen durchführen. Füge die "
370
- "Klasse \"pb-seo-lazy\" hinzu und erweitere das \"src\" Attribut wie folgt:"
371
-
372
- #: inc/settings.php:306
373
- msgid "REAL SRC HERE"
374
- msgstr "Echter SRC Pfad"
375
-
376
- #: inc/settings.php:326
377
- msgid "WooCommerce settings"
378
- msgstr "WooCommerce Einstellungen"
379
-
380
- #: inc/settings.php:328
381
- msgid ""
382
- "This settings are specially for images inside your WooCommerce Shop. In most "
383
- "cases you need to activate the override to use your custom settings."
384
- msgstr ""
385
- "Diese Einstellungen sind speziell für Bilder innerhalb deines WooCommerce "
386
- "Shops. In dein meisten Fällen muss der Override aktiviert werden, damit "
387
- "diese korrekt funktionieren."
388
-
389
- #: inc/settings.php:344
390
- msgid "WooCommerce"
391
- msgstr "WooCommerce"
392
-
393
- #: inc/settings.php:348
394
- msgid "Use the product name as alt and title for WooCommerce product images"
395
- msgstr ""
396
- "Verwende den Produktnamen als alt und title für WooCommerce Produktbilder."
397
-
398
- #: inc/settings.php:431
399
- msgid "Additional features"
400
- msgstr "Zusatzfunktionen"
401
-
402
- #: inc/settings.php:437
403
- msgid "set title for links"
404
- msgstr "Title für Links setzen"
405
-
406
- #: inc/settings.php:441
407
- msgid ""
408
- "Use the power of PB SEO Friendly Images also for seo friendly links. This "
409
- "will set the title depending on the link text and only if there is no "
410
- "existing title"
411
- msgstr ""
412
- "Nutze die Power von PB SEO Friendly Images ebenfalls für die Titel deiner "
413
- "Links. Das Tool wird nicht vergebene Linktitel automatisch auf Basis der "
414
- "Linktexte oder enthaltener Bilder setzen"
415
-
416
- #: inc/settings.php:448
417
- msgid "disable srcset"
418
- msgstr "srcset ausschalten"
419
-
420
- #: inc/settings.php:452
421
- msgid ""
422
- "disable srcset attribute and responsive images in WordPress if you don't "
423
- "need them"
424
- msgstr ""
425
- "deaktiviere das srcset Attribut und Responsive Bilder in Wordpress, wenn du "
426
- "diese nicht benötigst"
427
-
428
- #: inc/settings.php:472
429
- msgid "Encoding and Parser"
430
- msgstr "Encoding und Parser"
431
-
432
- #: inc/settings.php:474
433
- msgid ""
434
- "Here you can configure the HTML-Parser of the plugin. You <u>only</u> need "
435
- "to change this settings if you have <u>problems with your encoding</u> after "
436
- "activating the plugin."
437
- msgstr ""
438
- "Hier kannst du den HTML-Parser des Plugins konfigurieren. Du solltest diese "
439
- "Einstellungen <u>nur dann ändern</u>, falls du <u>Probleme mit dem "
440
- "Encoding / Umlauten</u> nach Aktivierung des Plugins hast."
441
-
442
- #: inc/settings.php:481
443
- msgid "encoding"
444
- msgstr "Encoding"
445
-
446
- #: inc/settings.php:485
447
- msgid ""
448
- "leave blank to use WordPress default encoding or type in something like "
449
- "\"utf-8\""
450
- msgstr ""
451
- "Lass dieses Feld leer um das WordPress Standard-Encoding zu verwenden oder "
452
- "gib etwas ein wie z.B. „utf-8“"
453
-
454
- #: inc/settings.php:491
455
- msgid "encoding mode"
456
- msgstr "Encoding-Modus"
457
-
458
- #: inc/settings.php:496
459
- msgid "HTML-ENTITIES"
460
- msgstr "HTML-ENTITIES"
461
-
462
- #: inc/settings.php:497
463
- msgid "disable convert encoding"
464
- msgstr "Konvertierung abschalten"
465
-
466
- #. Plugin Name of the plugin/theme
467
- #: inc/settings.php:507
468
- msgid "PB SEO Friendly Images"
469
- msgstr "PB SEO Friendly Images"
470
-
471
- #: inc/settings.php:508
472
- msgid "SEO Friendly Images"
473
- msgstr "SEO Friendly Images"
474
-
475
- #: inc/settings.php:537
476
- msgid "Plugins & Support"
477
- msgstr "Plugins & Support"
478
-
479
- #: inc/settings.php:541
480
- msgid "WordPress Kurs"
481
- msgstr ""
482
-
483
- #: inc/settings.php:542
484
- msgid ""
485
- "Möchtest du mit WordPress richtig durchstarten? In meinem WordPress Kurs "
486
- "erfährst du spannende Tipps und Tricks zu WordPress und SEO!"
487
- msgstr ""
488
-
489
- #: inc/settings.php:545
490
- msgid "Jetzt Kurs ansehen"
491
- msgstr ""
492
-
493
- #: inc/settings.php:553 inc/settings.php:555
494
- msgid "PrimusNote"
495
- msgstr "PrimusNote"
496
-
497
- #: inc/settings.php:555
498
- msgid "Project Management"
499
- msgstr "Projekt-Management"
500
-
501
- #: inc/settings.php:558
502
- msgid ""
503
- "PrimusNote is a Project Management and Team Collaboration software based on "
504
- "WordPress."
505
- msgstr ""
506
- "PrimusNote ist eine Projekt-Management und Team-Kollaborations-Software auf "
507
- "WordPress Basis."
508
-
509
- #: inc/settings.php:559 inc/settings.php:572
510
- msgid "Install Plugin"
511
- msgstr "Plugin installieren"
512
-
513
- #: inc/settings.php:566 inc/settings.php:568
514
- msgid "MailCrypt - AntiSpam Email Encryption"
515
- msgstr "MailCrypt - E-Mail Verschlüsselung"
516
-
517
- #: inc/settings.php:571
518
- msgid ""
519
- "This Plugin provides a Shortcode to encrypt email addresses / links and "
520
- "protect them against spam."
521
- msgstr ""
522
- "Dieses Plugin stellt einen Shortcode und Funktionen für die E-Mail "
523
- "Verschlüsselung zur Verfügung und schützt gegen Spam."
524
-
525
- #: inc/settings.php:577
526
- msgid "Support"
527
- msgstr "Support"
528
-
529
- #: inc/settings.php:578
530
- msgid ""
531
- "Do you need some help with this plugin? I am here to help you. Get in touch:"
532
- msgstr ""
533
- "Benötigst du Unterstützung mit diesem Plugin? Ich bin gerne bereit zu "
534
- "helfen, schreib mir einfach:"
535
-
536
- #: inc/settings.php:582
537
- msgid "Support Forum"
538
- msgstr "Support Forum"
539
-
540
- #: inc/settings.php:584
541
- msgid "Contact Support"
542
- msgstr "Support kontaktieren"
543
-
544
- #: inc/settings.php:586
545
- msgid "Changelog"
546
- msgstr "Changelog"
547
-
548
- #: plugin-update-checker/github-checker.php:119
549
- msgid "There is no changelog available."
550
- msgstr "Es steht kein Änderungsprotokoll zur Verfügung."
551
-
552
- #: plugin-update-checker/plugin-update-checker.php:776
553
- msgid "Check for updates"
554
- msgstr "Auf Aktualisierung prüfen"
555
-
556
- #: plugin-update-checker/plugin-update-checker.php:820
557
- msgid "This plugin is up to date."
558
- msgstr "Dieses Plugin ist auf dem neuesten Stand."
559
-
560
- #: plugin-update-checker/plugin-update-checker.php:822
561
- msgid "A new version of this plugin is available."
562
- msgstr "Eine neue Version dieses Plugins ist verfügbar."
563
-
564
- #: plugin-update-checker/plugin-update-checker.php:824
565
- #, php-format
566
- msgid "Unknown update checker status \"%s\""
567
- msgstr "Unbekannter Aktualisierungs-Status \"%s\""
568
-
569
- #. Plugin URI of the plugin/theme
570
- msgid "https://wordpress.org/extend/plugins/pb-seo-friendly-images/"
571
- msgstr "https://wordpress.org/extend/plugins/pb-seo-friendly-images/"
572
-
573
- #. Description of the plugin/theme
574
- msgid ""
575
- "This plugin is a full-featured solution for SEO friendly images. Optimize "
576
- "\"alt\" and \"title\" attributes for all images and post thumbnails. This "
577
- "plugin helps you to improve your traffic from search engines."
578
- msgstr ""
579
- "PB SEO Friendly Images: Einfach, schnell und automatisch "
580
- "suchmaschinenfreundliche Bilder für WordPress. Simple Optimierung von Alt- "
581
- "und Title Attributen."
582
-
583
- #. Author of the plugin/theme
584
- msgid "Pascal Bajorat"
585
- msgstr "Pascal Bajorat"
586
-
587
- #. Author URI of the plugin/theme
588
- msgid "https://www.pascal-bajorat.com"
589
- msgstr "https://www.pascal-bajorat.com"
590
-
591
- #~ msgid ""
592
- #~ "Do you need some help with this plugin? We are here to help you. Get in "
593
- #~ "touch:"
594
- #~ msgstr ""
595
- #~ "Benötigst du Unterstützung? Wir sind da um zu helfen, nimm Kontakt mit "
596
- #~ "uns auf"
597
-
598
- #~ msgid ""
599
- #~ "PB SEO Friendly Images is a free WordPress Plugin by <a href=\"%s\" "
600
- #~ "target=\"_blank\">Pascal Bajorat</a> and made with %s in Berlin, Germany."
601
- #~ "<br />If you like it and maybe want to <a href=\"%s\" target=\"_blank"
602
- #~ "\">buy me a cup of coffee or a beer</a> I would appreciate that very much."
603
- #~ msgstr ""
604
- #~ "PB SEO Friendly Images ist ein kostenloses WordPress Plugin von <a href="
605
- #~ "\"%s\" target=\"_blank\">Pascal Bajorat</a> und wurde mit viel %s in "
606
- #~ "Berlin entwickelt.<br />Wenn du das Plugin magst würde ich mich freuen, "
607
- #~ "<a href=\"%s\" target=\"_blank\">wenn du mich mit einer kleinen Spende "
608
- #~ "virtuell auf einen Kaffee oder Bier einlädst</a>."
609
-
610
- #~ msgid "http://wordpress.org/extend/plugins/pb-seo-friendly-images/"
611
- #~ msgstr "http://wordpress.org/extend/plugins/pb-seo-friendly-images/"
612
-
613
- #~ msgid "PB SEO Friendly Images Pro"
614
- #~ msgstr "PB SEO Friendly Images Pro"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lang/pb-seo-friendly-images.pot CHANGED
@@ -2,17 +2,18 @@
2
  msgid ""
3
  msgstr ""
4
  "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
5
- "Project-Id-Version: PB SEO Friendly Images Pro\n"
6
- "POT-Creation-Date: 2018-01-21 12:54+0100\n"
7
- "PO-Revision-Date: 2016-12-23 22:36+0100\n"
8
- "Last-Translator: Pascal Bajorat <pascal@pascal-bajorat.com>\n"
9
- "Language-Team: Pascal Bajorat <pascal@pascal-bajorat.com>\n"
10
  "MIME-Version: 1.0\n"
11
  "Content-Type: text/plain; charset=UTF-8\n"
12
  "Content-Transfer-Encoding: 8bit\n"
13
- "X-Generator: Poedit 1.8.12\n"
14
  "X-Poedit-Basepath: ..\n"
15
- "X-Poedit-WPHeader: pb-seo-friendly-images.php\n"
 
16
  "X-Poedit-SourceCharset: UTF-8\n"
17
  "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
18
  "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
@@ -20,466 +21,544 @@ msgstr ""
20
  "X-Poedit-SearchPath-0: .\n"
21
  "X-Poedit-SearchPathExcluded-0: *.js\n"
22
 
23
- #: inc/settings.php:35
24
- #, php-format
25
- msgid ""
26
- "<strong>Hey %s</strong>, we have updated <a href=\"%s\">PB SEO Friendly Images</"
27
- "a>. Visit the <a href=\"%s\">plugin settings page</a> to get deeper insights "
28
- "about the new features. This message will disappear automatically after you've "
29
- "visited the plugin settings."
30
- msgstr ""
31
-
32
- #: inc/settings.php:40
33
- msgid "Close"
34
- msgstr ""
35
-
36
- #: inc/settings.php:58
37
  msgid "Settings"
38
  msgstr ""
39
 
40
- #: inc/settings.php:70
41
  msgid "Get Pro Version"
42
  msgstr ""
43
 
44
- #: inc/settings.php:93
45
  msgid "Image \"alt\" and \"title\" Settings"
46
  msgstr ""
47
 
48
- #: inc/settings.php:97
49
  msgid ""
50
- "PB SEO Friendly Images automatically adds \"alt\" and \"title\" attributes to "
51
- "all images and post thumbnails in your posts. The default options are a good "
52
- "starting point for the optimization and basically fine for most websites."
 
53
  msgstr ""
54
 
55
- #: inc/settings.php:98
56
  msgid "Override feature"
57
  msgstr ""
58
 
59
- #: inc/settings.php:98
60
  msgid ""
61
- "Enable the override means that a possible sync and also hand picked \"alt\" / "
62
- "\"title\" attributes will be overwritten with the selected scheme. If you have "
63
- "good hand picked \"alt\" or \"title\" attributes in your images, I can not "
64
- "recommend to use the override. Automatic sync between \"alt\" and \"title\" will "
65
- "do it's best for you."
66
  msgstr ""
67
 
68
- #: inc/settings.php:101
69
  #, php-format
70
  msgid ""
71
  "PB SEO Friendly Images Pro is a WordPress Plugin by <a href=\"%s\" target="
72
  "\"_blank\">Pascal Bajorat</a> and made with %s in Berlin, Germany."
73
  msgstr ""
74
 
75
- #: inc/settings.php:107
76
  msgid "How it works"
77
  msgstr ""
78
 
79
- #: inc/settings.php:107
80
  msgid ""
81
- "You only need to configure the plugin with the following settings. The plugin "
82
- "will optimize your HTML code on-the-fly. This means, that you see the \"alt\" "
83
- "and \"title\" directly in the HTML code output and not in your media library or "
84
- "editor. This is not a hard rewrite of your media library values. You can change "
85
- "this values without the risk to damage some media library data."
 
86
  msgstr ""
87
 
88
- #: inc/settings.php:114
89
  #, php-format
90
  msgid ""
91
- "Please consider upgrading to <a href=\"%s\" target=\"_blank\">PB SEO Friendly "
92
- "Images Pro</a> if you want to use more features and support the development of "
93
- "this plugin."
94
  msgstr ""
95
 
96
- #: inc/settings.php:117 inc/settings.php:236 inc/settings.php:337
 
97
  msgid "Upgrade now"
98
  msgstr ""
99
 
100
- #: inc/settings.php:124
101
  msgid "optimize images"
102
  msgstr ""
103
 
104
- #: inc/settings.php:129
105
  msgid "post thumbnails and images in post content"
106
  msgstr ""
107
 
108
- #: inc/settings.php:129 inc/settings.php:144 inc/settings.php:360
 
109
  msgid "recommended"
110
  msgstr ""
111
 
112
- #: inc/settings.php:130
113
  msgid "only post thumbnails"
114
  msgstr ""
115
 
116
- #: inc/settings.php:131
117
  msgid "only images in post content"
118
  msgstr ""
119
 
120
- #: inc/settings.php:133
121
  msgid "which images should be optimized"
122
  msgstr ""
123
 
124
- #: inc/settings.php:139 inc/settings.php:355
125
  msgid "sync method"
126
  msgstr ""
127
 
128
- #: inc/settings.php:144 inc/settings.php:360
129
  msgid "alt <=> title"
130
  msgstr ""
131
 
132
- #: inc/settings.php:145 inc/settings.php:361
133
  msgid "alt => title"
134
  msgstr ""
135
 
136
- #: inc/settings.php:146 inc/settings.php:362
137
  msgid "alt <= title"
138
  msgstr ""
139
 
140
- #: inc/settings.php:148 inc/settings.php:364
141
  msgid "select sync method for \"alt\" and \"title\" attribute."
142
  msgstr ""
143
 
144
- #: inc/settings.php:149 inc/settings.php:365
145
  msgid ""
146
- "<code>alt <=> title</code> - if one attribute is set use it also for the other "
147
- "one"
148
  msgstr ""
149
 
150
- #: inc/settings.php:150 inc/settings.php:366
151
  msgid ""
152
  "<code>alt => title</code> - if \"alt\" is set use it for the title attribute"
153
  msgstr ""
154
 
155
- #: inc/settings.php:151 inc/settings.php:367
156
  msgid ""
157
  "<code>alt <= title</code> - if \"title\" is set use it for the alt attribute"
158
  msgstr ""
159
 
160
- #: inc/settings.php:157 inc/settings.php:374
161
  msgid "override \"alt\""
162
  msgstr ""
163
 
164
- #: inc/settings.php:161 inc/settings.php:378
165
  msgid "override existing image alt attributes"
166
  msgstr ""
167
 
168
- #: inc/settings.php:167 inc/settings.php:385
169
  msgid "override \"title\""
170
  msgstr ""
171
 
172
- #: inc/settings.php:171 inc/settings.php:389
173
  msgid "override existing image title attributes"
174
  msgstr ""
175
 
176
- #: inc/settings.php:175
177
  msgid "possible variables:"
178
  msgstr ""
179
 
180
- #: inc/settings.php:176
181
  msgid "replaces post title"
182
  msgstr ""
183
 
184
- #: inc/settings.php:177
185
  msgid "replaces post excerpt"
186
  msgstr ""
187
 
188
- #: inc/settings.php:178
189
  msgid "replaces image filename (without extension)"
190
  msgstr ""
191
 
192
- #: inc/settings.php:179
193
  msgid "replaces post category"
194
  msgstr ""
195
 
196
- #: inc/settings.php:180
197
  msgid "replaces post tags"
198
  msgstr ""
199
 
200
- #: inc/settings.php:181
201
  msgid "replaces attachment title (could be empty if not set)"
202
  msgstr ""
203
 
204
- #: inc/settings.php:182
205
  msgid "replaces attachment alt-text (could be empty if not set)"
206
  msgstr ""
207
 
208
- #: inc/settings.php:183
209
  msgid "replaces attachment caption (could be empty if not set)"
210
  msgstr ""
211
 
212
- #: inc/settings.php:184
213
  msgid "replaces attachment description (could be empty if not set)"
214
  msgstr ""
215
 
216
- #: inc/settings.php:188 inc/settings.php:396
217
  msgid "alt scheme"
218
  msgstr ""
219
 
220
- #: inc/settings.php:192 inc/settings.php:202 inc/settings.php:400
221
- #: inc/settings.php:411 inc/settings.php:496
 
222
  msgid "default"
223
  msgstr ""
224
 
225
- #: inc/settings.php:198 inc/settings.php:407
226
  msgid "title scheme"
227
  msgstr ""
228
 
229
- #: inc/settings.php:221
230
  msgid "Pro Features"
231
  msgstr ""
232
 
233
- #: inc/settings.php:223
234
- msgid "Lazy Load settings"
235
  msgstr ""
236
 
237
- #: inc/settings.php:225
238
  msgid ""
239
- "This function is very useful and it boosts performance by delaying loading of "
240
- "images in long web pages, because images outside of viewport (visible part of "
241
- "web page) won't be loaded until the user scrolls to them."
242
  msgstr ""
243
 
244
- #: inc/settings.php:226
 
245
  msgid ""
246
- "The lazy load is powered by unveil.js, one of the fastest and thinnest lazy "
247
- "loader in the web. The implementation is highly seo compatible with a no js "
248
- "fallback."
 
249
  msgstr ""
250
 
251
- #: inc/settings.php:227
252
  msgid ""
253
- "If enabled the lazy load will be added automatically to images in your post or "
254
- "page content and also to post thumbnails."
255
  msgstr ""
256
 
257
- #: inc/settings.php:233 inc/settings.php:334
 
258
  #, php-format
259
  msgid ""
260
- "Please consider upgrading to <a href=\"%s\" target=\"_blank\">PB SEO Friendly "
261
- "Images Pro</a> if you want to use this feature."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  msgstr ""
263
 
264
- #: inc/settings.php:243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  msgid "enable lazy load"
266
  msgstr ""
267
 
268
- #: inc/settings.php:247
269
  msgid "enable lazy load and boost up your site speed"
270
  msgstr ""
271
 
272
- #: inc/settings.php:254
273
  msgid "enable lazy load for acf"
274
  msgstr ""
275
 
276
- #: inc/settings.php:258
277
  msgid "enable lazy load for AdvancedCustomFields"
278
  msgstr ""
279
 
280
- #: inc/settings.php:265
281
  msgid "lazy load default styles"
282
  msgstr ""
283
 
284
- #: inc/settings.php:269
285
  msgid "enable lazy load default styles"
286
  msgstr ""
287
 
288
- #: inc/settings.php:276
289
  msgid "threshold"
290
  msgstr ""
291
 
292
- #: inc/settings.php:280
293
  msgid ""
294
- "By default, images are only loaded when the user scrolls to them and they became "
295
- "visible on the screen (default value for this field <code>0</code>). If you want "
296
- "your images to load earlier than that, lets say 200px then you need to type in "
297
- "<code>200</code>."
298
  msgstr ""
299
 
300
- #: inc/settings.php:300
301
  msgid "Theme-Integration (only for developers relevant)"
302
  msgstr ""
303
 
304
- #: inc/settings.php:302
305
  msgid ""
306
- "Want to add lazy load to images in your theme? You only need to do some small "
307
- "modifications. Add class \"lazy\" and modify the \"src\" like this:"
308
  msgstr ""
309
 
310
- #: inc/settings.php:306
311
  msgid "REAL SRC HERE"
312
  msgstr ""
313
 
314
- #: inc/settings.php:326
315
  msgid "WooCommerce settings"
316
  msgstr ""
317
 
318
- #: inc/settings.php:328
319
  msgid ""
320
  "This settings are specially for images inside your WooCommerce Shop. In most "
321
  "cases you need to activate the override to use your custom settings."
322
  msgstr ""
323
 
324
- #: inc/settings.php:344
325
  msgid "WooCommerce"
326
  msgstr ""
327
 
328
- #: inc/settings.php:348
329
  msgid "Use the product name as alt and title for WooCommerce product images"
330
  msgstr ""
331
 
332
- #: inc/settings.php:431
333
  msgid "Additional features"
334
  msgstr ""
335
 
336
- #: inc/settings.php:437
337
  msgid "set title for links"
338
  msgstr ""
339
 
340
- #: inc/settings.php:441
341
  msgid ""
342
- "Use the power of PB SEO Friendly Images also for seo friendly links. This will "
343
- "set the title depending on the link text and only if there is no existing title"
 
344
  msgstr ""
345
 
346
- #: inc/settings.php:448
347
  msgid "disable srcset"
348
  msgstr ""
349
 
350
- #: inc/settings.php:452
351
  msgid ""
352
- "disable srcset attribute and responsive images in WordPress if you don't need "
353
- "them"
354
  msgstr ""
355
 
356
- #: inc/settings.php:472
357
  msgid "Encoding and Parser"
358
  msgstr ""
359
 
360
- #: inc/settings.php:474
361
  msgid ""
362
- "Here you can configure the HTML-Parser of the plugin. You <u>only</u> need to "
363
- "change this settings if you have <u>problems with your encoding</u> after "
364
  "activating the plugin."
365
  msgstr ""
366
 
367
- #: inc/settings.php:481
368
  msgid "encoding"
369
  msgstr ""
370
 
371
- #: inc/settings.php:485
372
  msgid ""
373
- "leave blank to use WordPress default encoding or type in something like \"utf-8\""
 
374
  msgstr ""
375
 
376
- #: inc/settings.php:491
377
  msgid "encoding mode"
378
  msgstr ""
379
 
380
- #: inc/settings.php:496
381
  msgid "HTML-ENTITIES"
382
  msgstr ""
383
 
384
- #: inc/settings.php:497
385
  msgid "disable convert encoding"
386
  msgstr ""
387
 
388
  #. Plugin Name of the plugin/theme
389
- #: inc/settings.php:507
390
  msgid "PB SEO Friendly Images"
391
  msgstr ""
392
 
393
- #: inc/settings.php:508
394
  msgid "SEO Friendly Images"
395
  msgstr ""
396
 
397
- #: inc/settings.php:537
398
- msgid "Plugins & Support"
399
  msgstr ""
400
 
401
- #: inc/settings.php:541
402
- msgid "WordPress Kurs"
 
403
  msgstr ""
404
 
405
- #: inc/settings.php:542
406
- msgid ""
407
- "Möchtest du mit WordPress richtig durchstarten? In meinem WordPress Kurs "
408
- "erfährst du spannende Tipps und Tricks zu WordPress und SEO!"
409
  msgstr ""
410
 
411
- #: inc/settings.php:545
412
- msgid "Jetzt Kurs ansehen"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
413
  msgstr ""
414
 
415
- #: inc/settings.php:553 inc/settings.php:555
416
- msgid "PrimusNote"
 
 
417
  msgstr ""
418
 
419
- #: inc/settings.php:555
420
- msgid "Project Management"
 
421
  msgstr ""
422
 
423
- #: inc/settings.php:558
 
 
 
 
 
424
  msgid ""
425
- "PrimusNote is a Project Management and Team Collaboration software based on "
426
- "WordPress."
427
  msgstr ""
428
 
429
- #: inc/settings.php:559 inc/settings.php:572
430
- msgid "Install Plugin"
431
  msgstr ""
432
 
433
- #: inc/settings.php:566 inc/settings.php:568
434
- msgid "MailCrypt - AntiSpam Email Encryption"
 
435
  msgstr ""
436
 
437
- #: inc/settings.php:571
 
 
 
 
438
  msgid ""
439
- "This Plugin provides a Shortcode to encrypt email addresses / links and protect "
440
- "them against spam."
441
  msgstr ""
442
 
443
- #: inc/settings.php:577
444
- msgid "Support"
 
 
 
 
445
  msgstr ""
446
 
447
- #: inc/settings.php:578
448
  msgid ""
449
- "Do you need some help with this plugin? I am here to help you. Get in touch:"
 
 
450
  msgstr ""
451
 
452
- #: inc/settings.php:582
453
- msgid "Support Forum"
454
  msgstr ""
455
 
456
- #: inc/settings.php:584
457
- msgid "Contact Support"
458
  msgstr ""
459
 
460
- #: inc/settings.php:586
461
- msgid "Changelog"
 
 
462
  msgstr ""
463
 
464
- #: plugin-update-checker/github-checker.php:119
465
- msgid "There is no changelog available."
466
  msgstr ""
467
 
468
- #: plugin-update-checker/plugin-update-checker.php:776
469
- msgid "Check for updates"
470
  msgstr ""
471
 
472
- #: plugin-update-checker/plugin-update-checker.php:820
473
- msgid "This plugin is up to date."
 
474
  msgstr ""
475
 
476
- #: plugin-update-checker/plugin-update-checker.php:822
477
- msgid "A new version of this plugin is available."
478
  msgstr ""
479
 
480
- #: plugin-update-checker/plugin-update-checker.php:824
481
- #, php-format
482
- msgid "Unknown update checker status \"%s\""
 
 
 
483
  msgstr ""
484
 
485
  #. Plugin URI of the plugin/theme
@@ -488,9 +567,9 @@ msgstr ""
488
 
489
  #. Description of the plugin/theme
490
  msgid ""
491
- "This plugin is a full-featured solution for SEO friendly images. Optimize \"alt"
492
- "\" and \"title\" attributes for all images and post thumbnails. This plugin "
493
- "helps you to improve your traffic from search engines."
494
  msgstr ""
495
 
496
  #. Author of the plugin/theme
2
  msgid ""
3
  msgstr ""
4
  "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
5
+ "Project-Id-Version: PB SEO Friendly Images\n"
6
+ "POT-Creation-Date: 2019-02-24 17:02+0100\n"
7
+ "PO-Revision-Date: 2019-02-24 12:16+0100\n"
8
+ "Last-Translator: \n"
9
+ "Language-Team: \n"
10
  "MIME-Version: 1.0\n"
11
  "Content-Type: text/plain; charset=UTF-8\n"
12
  "Content-Transfer-Encoding: 8bit\n"
13
+ "X-Generator: Poedit 2.2\n"
14
  "X-Poedit-Basepath: ..\n"
15
+ "X-Poedit-Flags-xgettext: --add-comments=translators:\n"
16
+ "X-Poedit-WPHeader: pb-seo-friendly-images-pro.php\n"
17
  "X-Poedit-SourceCharset: UTF-8\n"
18
  "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
19
  "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
21
  "X-Poedit-SearchPath-0: .\n"
22
  "X-Poedit-SearchPathExcluded-0: *.js\n"
23
 
24
+ #: inc/pbsfi_admin_interface.php:68
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  msgid "Settings"
26
  msgstr ""
27
 
28
+ #: inc/pbsfi_admin_interface.php:80
29
  msgid "Get Pro Version"
30
  msgstr ""
31
 
32
+ #: inc/pbsfi_admin_interface.php:106
33
  msgid "Image \"alt\" and \"title\" Settings"
34
  msgstr ""
35
 
36
+ #: inc/pbsfi_admin_interface.php:110
37
  msgid ""
38
+ "PB SEO Friendly Images automatically adds \"alt\" and \"title\" attributes "
39
+ "to all images and post thumbnails in your posts. The default options are a "
40
+ "good starting point for the optimization and basically fine for most "
41
+ "websites."
42
  msgstr ""
43
 
44
+ #: inc/pbsfi_admin_interface.php:111
45
  msgid "Override feature"
46
  msgstr ""
47
 
48
+ #: inc/pbsfi_admin_interface.php:111
49
  msgid ""
50
+ "Enable the override means that a possible sync and also hand picked \"alt"
51
+ "\" / \"title\" attributes will be overwritten with the selected scheme. If "
52
+ "you have good hand picked \"alt\" or \"title\" attributes in your images, I "
53
+ "can not recommend to use the override. Automatic sync between \"alt\" and "
54
+ "\"title\" will do it's best for you."
55
  msgstr ""
56
 
57
+ #: inc/pbsfi_admin_interface.php:114
58
  #, php-format
59
  msgid ""
60
  "PB SEO Friendly Images Pro is a WordPress Plugin by <a href=\"%s\" target="
61
  "\"_blank\">Pascal Bajorat</a> and made with %s in Berlin, Germany."
62
  msgstr ""
63
 
64
+ #: inc/pbsfi_admin_interface.php:120
65
  msgid "How it works"
66
  msgstr ""
67
 
68
+ #: inc/pbsfi_admin_interface.php:120
69
  msgid ""
70
+ "You only need to configure the plugin with the following settings. The "
71
+ "plugin will optimize your HTML code on-the-fly. This means, that you see the "
72
+ "\"alt\" and \"title\" directly in the HTML code output and not in your media "
73
+ "library or editor. This is not a hard rewrite of your media library values. "
74
+ "You can change this values without the risk to damage some media library "
75
+ "data."
76
  msgstr ""
77
 
78
+ #: inc/pbsfi_admin_interface.php:127
79
  #, php-format
80
  msgid ""
81
+ "Please consider upgrading to <a href=\"%s\" target=\"_blank\">PB SEO "
82
+ "Friendly Images Pro</a> if you want to use more features and support the "
83
+ "development of this plugin."
84
  msgstr ""
85
 
86
+ #: inc/pbsfi_admin_interface.php:131 inc/pbsfi_admin_interface.php:249
87
+ #: inc/pbsfi_admin_interface.php:304 inc/pbsfi_admin_interface.php:405
88
  msgid "Upgrade now"
89
  msgstr ""
90
 
91
+ #: inc/pbsfi_admin_interface.php:138
92
  msgid "optimize images"
93
  msgstr ""
94
 
95
+ #: inc/pbsfi_admin_interface.php:143
96
  msgid "post thumbnails and images in post content"
97
  msgstr ""
98
 
99
+ #: inc/pbsfi_admin_interface.php:143 inc/pbsfi_admin_interface.php:158
100
+ #: inc/pbsfi_admin_interface.php:428
101
  msgid "recommended"
102
  msgstr ""
103
 
104
+ #: inc/pbsfi_admin_interface.php:144
105
  msgid "only post thumbnails"
106
  msgstr ""
107
 
108
+ #: inc/pbsfi_admin_interface.php:145
109
  msgid "only images in post content"
110
  msgstr ""
111
 
112
+ #: inc/pbsfi_admin_interface.php:147
113
  msgid "which images should be optimized"
114
  msgstr ""
115
 
116
+ #: inc/pbsfi_admin_interface.php:153 inc/pbsfi_admin_interface.php:423
117
  msgid "sync method"
118
  msgstr ""
119
 
120
+ #: inc/pbsfi_admin_interface.php:158 inc/pbsfi_admin_interface.php:428
121
  msgid "alt <=> title"
122
  msgstr ""
123
 
124
+ #: inc/pbsfi_admin_interface.php:159 inc/pbsfi_admin_interface.php:429
125
  msgid "alt => title"
126
  msgstr ""
127
 
128
+ #: inc/pbsfi_admin_interface.php:160 inc/pbsfi_admin_interface.php:430
129
  msgid "alt <= title"
130
  msgstr ""
131
 
132
+ #: inc/pbsfi_admin_interface.php:162 inc/pbsfi_admin_interface.php:432
133
  msgid "select sync method for \"alt\" and \"title\" attribute."
134
  msgstr ""
135
 
136
+ #: inc/pbsfi_admin_interface.php:163 inc/pbsfi_admin_interface.php:433
137
  msgid ""
138
+ "<code>alt <=> title</code> - if one attribute is set use it also for the "
139
+ "other one"
140
  msgstr ""
141
 
142
+ #: inc/pbsfi_admin_interface.php:164 inc/pbsfi_admin_interface.php:434
143
  msgid ""
144
  "<code>alt => title</code> - if \"alt\" is set use it for the title attribute"
145
  msgstr ""
146
 
147
+ #: inc/pbsfi_admin_interface.php:165 inc/pbsfi_admin_interface.php:435
148
  msgid ""
149
  "<code>alt <= title</code> - if \"title\" is set use it for the alt attribute"
150
  msgstr ""
151
 
152
+ #: inc/pbsfi_admin_interface.php:171 inc/pbsfi_admin_interface.php:442
153
  msgid "override \"alt\""
154
  msgstr ""
155
 
156
+ #: inc/pbsfi_admin_interface.php:175 inc/pbsfi_admin_interface.php:446
157
  msgid "override existing image alt attributes"
158
  msgstr ""
159
 
160
+ #: inc/pbsfi_admin_interface.php:181 inc/pbsfi_admin_interface.php:453
161
  msgid "override \"title\""
162
  msgstr ""
163
 
164
+ #: inc/pbsfi_admin_interface.php:185 inc/pbsfi_admin_interface.php:457
165
  msgid "override existing image title attributes"
166
  msgstr ""
167
 
168
+ #: inc/pbsfi_admin_interface.php:189
169
  msgid "possible variables:"
170
  msgstr ""
171
 
172
+ #: inc/pbsfi_admin_interface.php:190
173
  msgid "replaces post title"
174
  msgstr ""
175
 
176
+ #: inc/pbsfi_admin_interface.php:191
177
  msgid "replaces post excerpt"
178
  msgstr ""
179
 
180
+ #: inc/pbsfi_admin_interface.php:192
181
  msgid "replaces image filename (without extension)"
182
  msgstr ""
183
 
184
+ #: inc/pbsfi_admin_interface.php:193
185
  msgid "replaces post category"
186
  msgstr ""
187
 
188
+ #: inc/pbsfi_admin_interface.php:194
189
  msgid "replaces post tags"
190
  msgstr ""
191
 
192
+ #: inc/pbsfi_admin_interface.php:195
193
  msgid "replaces attachment title (could be empty if not set)"
194
  msgstr ""
195
 
196
+ #: inc/pbsfi_admin_interface.php:196
197
  msgid "replaces attachment alt-text (could be empty if not set)"
198
  msgstr ""
199
 
200
+ #: inc/pbsfi_admin_interface.php:197
201
  msgid "replaces attachment caption (could be empty if not set)"
202
  msgstr ""
203
 
204
+ #: inc/pbsfi_admin_interface.php:198
205
  msgid "replaces attachment description (could be empty if not set)"
206
  msgstr ""
207
 
208
+ #: inc/pbsfi_admin_interface.php:202 inc/pbsfi_admin_interface.php:464
209
  msgid "alt scheme"
210
  msgstr ""
211
 
212
+ #: inc/pbsfi_admin_interface.php:206 inc/pbsfi_admin_interface.php:216
213
+ #: inc/pbsfi_admin_interface.php:468 inc/pbsfi_admin_interface.php:479
214
+ #: inc/pbsfi_admin_interface.php:564
215
  msgid "default"
216
  msgstr ""
217
 
218
+ #: inc/pbsfi_admin_interface.php:212 inc/pbsfi_admin_interface.php:475
219
  msgid "title scheme"
220
  msgstr ""
221
 
222
+ #: inc/pbsfi_admin_interface.php:235
223
  msgid "Pro Features"
224
  msgstr ""
225
 
226
+ #: inc/pbsfi_admin_interface.php:237
227
+ msgid "Caching"
228
  msgstr ""
229
 
230
+ #: inc/pbsfi_admin_interface.php:239
231
  msgid ""
232
+ "Caching can highly increase the performance of your website with PB SEO "
233
+ "Friendly Images. If you already use a caching plugin you do not need to "
234
+ "enable this function."
235
  msgstr ""
236
 
237
+ #: inc/pbsfi_admin_interface.php:240
238
+ #, php-format
239
  msgid ""
240
+ "We recommend to use <a href=\"%1$s\" target=\"_blank\">WP Rocket</a> as one "
241
+ "of the best Performance and Caching Solutions for WordPress. If you are "
242
+ "interested in a professional and individual Performance-Optimization <a href="
243
+ "\"%2$s\" target=\"_blank\">get a free quote here</a>."
244
  msgstr ""
245
 
246
+ #: inc/pbsfi_admin_interface.php:240 templates/options_page.php:58
247
  msgid ""
248
+ "https://www.pascal-bajorat.com/en/lp/wordpress-performance-optimization/"
 
249
  msgstr ""
250
 
251
+ #: inc/pbsfi_admin_interface.php:246 inc/pbsfi_admin_interface.php:301
252
+ #: inc/pbsfi_admin_interface.php:402
253
  #, php-format
254
  msgid ""
255
+ "Please consider upgrading to <a href=\"%s\" target=\"_blank\">PB SEO "
256
+ "Friendly Images Pro</a> if you want to use this feature."
257
+ msgstr ""
258
+
259
+ #: inc/pbsfi_admin_interface.php:256
260
+ msgid "enable content caching"
261
+ msgstr ""
262
+
263
+ #: inc/pbsfi_admin_interface.php:260
264
+ msgid ""
265
+ "enable content caching and boost up your site speed with PB SEO Friendly "
266
+ "Images"
267
+ msgstr ""
268
+
269
+ #: inc/pbsfi_admin_interface.php:267
270
+ msgid "TTL"
271
+ msgstr ""
272
+
273
+ #: inc/pbsfi_admin_interface.php:271
274
+ msgid "TTL in seconds: 86400 = 24h; 3600 = 1h; 0 = never expire;"
275
+ msgstr ""
276
+
277
+ #: inc/pbsfi_admin_interface.php:291
278
+ msgid "Lazy Load settings"
279
  msgstr ""
280
 
281
+ #: inc/pbsfi_admin_interface.php:293
282
+ msgid ""
283
+ "This function is very useful and it boosts performance by delaying loading "
284
+ "of images in long web pages, because images outside of viewport (visible "
285
+ "part of web page) won't be loaded until the user scrolls to them."
286
+ msgstr ""
287
+
288
+ #: inc/pbsfi_admin_interface.php:294
289
+ msgid ""
290
+ "The lazy load is powered by unveil.js, one of the fastest and thinnest lazy "
291
+ "loader in the web. The implementation is highly seo compatible with a no js "
292
+ "fallback."
293
+ msgstr ""
294
+
295
+ #: inc/pbsfi_admin_interface.php:295
296
+ msgid ""
297
+ "If enabled the lazy load will be added automatically to images in your post "
298
+ "or page content and also to post thumbnails."
299
+ msgstr ""
300
+
301
+ #: inc/pbsfi_admin_interface.php:311
302
  msgid "enable lazy load"
303
  msgstr ""
304
 
305
+ #: inc/pbsfi_admin_interface.php:315
306
  msgid "enable lazy load and boost up your site speed"
307
  msgstr ""
308
 
309
+ #: inc/pbsfi_admin_interface.php:322
310
  msgid "enable lazy load for acf"
311
  msgstr ""
312
 
313
+ #: inc/pbsfi_admin_interface.php:326
314
  msgid "enable lazy load for AdvancedCustomFields"
315
  msgstr ""
316
 
317
+ #: inc/pbsfi_admin_interface.php:333
318
  msgid "lazy load default styles"
319
  msgstr ""
320
 
321
+ #: inc/pbsfi_admin_interface.php:337
322
  msgid "enable lazy load default styles"
323
  msgstr ""
324
 
325
+ #: inc/pbsfi_admin_interface.php:344
326
  msgid "threshold"
327
  msgstr ""
328
 
329
+ #: inc/pbsfi_admin_interface.php:348
330
  msgid ""
331
+ "By default, images are only loaded when the user scrolls to them and they "
332
+ "became visible on the screen (default value for this field <code>0</code>). "
333
+ "If you want your images to load earlier than that, lets say 200px then you "
334
+ "need to type in <code>200</code>."
335
  msgstr ""
336
 
337
+ #: inc/pbsfi_admin_interface.php:368
338
  msgid "Theme-Integration (only for developers relevant)"
339
  msgstr ""
340
 
341
+ #: inc/pbsfi_admin_interface.php:370
342
  msgid ""
343
+ "Want to add lazy load to images in your theme? You only need to do some "
344
+ "small modifications. Add class \"lazy\" and modify the \"src\" like this:"
345
  msgstr ""
346
 
347
+ #: inc/pbsfi_admin_interface.php:374
348
  msgid "REAL SRC HERE"
349
  msgstr ""
350
 
351
+ #: inc/pbsfi_admin_interface.php:394
352
  msgid "WooCommerce settings"
353
  msgstr ""
354
 
355
+ #: inc/pbsfi_admin_interface.php:396
356
  msgid ""
357
  "This settings are specially for images inside your WooCommerce Shop. In most "
358
  "cases you need to activate the override to use your custom settings."
359
  msgstr ""
360
 
361
+ #: inc/pbsfi_admin_interface.php:412
362
  msgid "WooCommerce"
363
  msgstr ""
364
 
365
+ #: inc/pbsfi_admin_interface.php:416
366
  msgid "Use the product name as alt and title for WooCommerce product images"
367
  msgstr ""
368
 
369
+ #: inc/pbsfi_admin_interface.php:499
370
  msgid "Additional features"
371
  msgstr ""
372
 
373
+ #: inc/pbsfi_admin_interface.php:505
374
  msgid "set title for links"
375
  msgstr ""
376
 
377
+ #: inc/pbsfi_admin_interface.php:509
378
  msgid ""
379
+ "Use the power of PB SEO Friendly Images also for seo friendly links. This "
380
+ "will set the title depending on the link text and only if there is no "
381
+ "existing title"
382
  msgstr ""
383
 
384
+ #: inc/pbsfi_admin_interface.php:516
385
  msgid "disable srcset"
386
  msgstr ""
387
 
388
+ #: inc/pbsfi_admin_interface.php:520
389
  msgid ""
390
+ "disable srcset attribute and responsive images in WordPress if you don't "
391
+ "need them"
392
  msgstr ""
393
 
394
+ #: inc/pbsfi_admin_interface.php:540
395
  msgid "Encoding and Parser"
396
  msgstr ""
397
 
398
+ #: inc/pbsfi_admin_interface.php:542
399
  msgid ""
400
+ "Here you can configure the HTML-Parser of the plugin. You <u>only</u> need "
401
+ "to change this settings if you have <u>problems with your encoding</u> after "
402
  "activating the plugin."
403
  msgstr ""
404
 
405
+ #: inc/pbsfi_admin_interface.php:549
406
  msgid "encoding"
407
  msgstr ""
408
 
409
+ #: inc/pbsfi_admin_interface.php:553
410
  msgid ""
411
+ "leave blank to use WordPress default encoding or type in something like "
412
+ "\"utf-8\""
413
  msgstr ""
414
 
415
+ #: inc/pbsfi_admin_interface.php:559
416
  msgid "encoding mode"
417
  msgstr ""
418
 
419
+ #: inc/pbsfi_admin_interface.php:564
420
  msgid "HTML-ENTITIES"
421
  msgstr ""
422
 
423
+ #: inc/pbsfi_admin_interface.php:565
424
  msgid "disable convert encoding"
425
  msgstr ""
426
 
427
  #. Plugin Name of the plugin/theme
428
+ #: inc/pbsfi_admin_interface.php:578 pbseofriendlyimages.php:71
429
  msgid "PB SEO Friendly Images"
430
  msgstr ""
431
 
432
+ #: inc/pbsfi_admin_interface.php:579
433
  msgid "SEO Friendly Images"
434
  msgstr ""
435
 
436
+ #: pbseofriendlyimages.php:197
437
+ msgid "Clear Cache"
438
  msgstr ""
439
 
440
+ #: pbseofriendlyimages.php:305
441
+ #, php-format
442
+ msgid "Can not find: %s"
443
  msgstr ""
444
 
445
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:54
446
+ msgid "View details"
 
 
447
  msgstr ""
448
 
449
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:77
450
+ #, php-format
451
+ msgid "More information about %s"
452
+ msgstr ""
453
+
454
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:128
455
+ msgid "Check for updates"
456
+ msgstr ""
457
+
458
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:213
459
+ #, php-format
460
+ msgctxt "the plugin title"
461
+ msgid "The %s plugin is up to date."
462
+ msgstr ""
463
+
464
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:215
465
+ #, php-format
466
+ msgctxt "the plugin title"
467
+ msgid "A new version of the %s plugin is available."
468
  msgstr ""
469
 
470
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:217
471
+ #, php-format
472
+ msgctxt "the plugin title"
473
+ msgid "Could not determine if updates are available for %s."
474
  msgstr ""
475
 
476
+ #: plugin-update-checker/Puc/v4p5/Plugin/Ui.php:223
477
+ #, php-format
478
+ msgid "Unknown update checker status \"%s\""
479
  msgstr ""
480
 
481
+ #: plugin-update-checker/Puc/v4p5/Vcs/PluginUpdateChecker.php:98
482
+ msgid "There is no changelog available."
483
+ msgstr ""
484
+
485
+ #: templates/options_page.php:11
486
+ #, php-format
487
  msgid ""
488
+ "<strong>Cache cleared!</strong> %d elements are removed from transient cache."
 
489
  msgstr ""
490
 
491
+ #: templates/options_page.php:28
492
+ msgid "Plugins & Support"
493
  msgstr ""
494
 
495
+ #: templates/options_page.php:35 templates/options_page.php:37
496
+ #: templates/options_page.php:52
497
+ msgid "WordPress Kurs"
498
  msgstr ""
499
 
500
+ #: templates/options_page.php:37 templates/options_page.php:54
501
+ msgid "Recommendation"
502
+ msgstr ""
503
+
504
+ #: templates/options_page.php:39
505
  msgid ""
506
+ "Möchtest du mit WordPress richtig durchstarten? In meinem WordPress Kurs "
507
+ "erfährst du spannende Tipps und Tricks zu WordPress und SEO!"
508
  msgstr ""
509
 
510
+ #: templates/options_page.php:43
511
+ msgid "Jetzt Kurs ansehen"
512
+ msgstr ""
513
+
514
+ #: templates/options_page.php:54
515
+ msgid "WordPress Performance"
516
  msgstr ""
517
 
518
+ #: templates/options_page.php:55
519
  msgid ""
520
+ "Do you want a professional and individual performance optimization for your "
521
+ "website? Increase your Google Pagespeed and SEO traffic with our high "
522
+ "performance optimization."
523
  msgstr ""
524
 
525
+ #: templates/options_page.php:59
526
+ msgid "Get a free quote"
527
  msgstr ""
528
 
529
+ #: templates/options_page.php:67 templates/options_page.php:69
530
+ msgid "MailCrypt - AntiSpam Email Encryption"
531
  msgstr ""
532
 
533
+ #: templates/options_page.php:72
534
+ msgid ""
535
+ "This Plugin provides a Shortcode to encrypt email addresses / links and "
536
+ "protect them against spam."
537
  msgstr ""
538
 
539
+ #: templates/options_page.php:75
540
+ msgid "Install Plugin"
541
  msgstr ""
542
 
543
+ #: templates/options_page.php:80
544
+ msgid "Support"
545
  msgstr ""
546
 
547
+ #: templates/options_page.php:81
548
+ msgid ""
549
+ "Do you need some help with this plugin? I am here to help you. Get in touch:"
550
  msgstr ""
551
 
552
+ #: templates/options_page.php:86
553
+ msgid "Support Forum"
554
  msgstr ""
555
 
556
+ #: templates/options_page.php:89
557
+ msgid "Contact Support"
558
+ msgstr ""
559
+
560
+ #: templates/options_page.php:92
561
+ msgid "Changelog"
562
  msgstr ""
563
 
564
  #. Plugin URI of the plugin/theme
567
 
568
  #. Description of the plugin/theme
569
  msgid ""
570
+ "This plugin is a full-featured solution for SEO friendly images. Optimize "
571
+ "\"alt\" and \"title\" attributes for all images and post thumbnails. This "
572
+ "plugin helps you to improve your traffic from search engines."
573
  msgstr ""
574
 
575
  #. Author of the plugin/theme
pb-seo-friendly-images.php CHANGED
@@ -3,522 +3,333 @@
3
  Plugin Name: PB SEO Friendly Images
4
  Plugin URI: https://wordpress.org/extend/plugins/pb-seo-friendly-images/
5
  Description: This plugin is a full-featured solution for SEO friendly images. Optimize "alt" and "title" attributes for all images and post thumbnails. This plugin helps you to improve your traffic from search engines.
6
- Version: 3.1.0
7
  Author: Pascal Bajorat
8
- Author URI: https://www.pascal-bajorat.com
9
  Text Domain: pb-seo-friendly-images
10
  Domain Path: /lang
11
- License: GNU General Public License v.3
12
 
13
- Copyright (c) 2018 by Pascal-Bajorat.com.
14
  */
15
 
16
  /* Security-Check */
17
- if ( !class_exists('WP') ) {
18
- die();
19
- }
20
 
21
- if( ! defined('pbsfi_file') ) {
22
- define('pbsfi_file', __FILE__);
23
- }
24
 
25
- if( ! defined('pbsfi_plugin_path') ) {
26
- define('pbsfi_plugin_path', plugin_dir_path(__FILE__));
27
- }
 
28
 
29
- if( ! defined('pbsfi_plugin_pro_path') ) {
30
- define('pbsfi_plugin_pro_path', pbsfi_plugin_path.'inc'.DIRECTORY_SEPARATOR.'pro.php');
31
- }
32
 
33
- require_once 'inc'.DIRECTORY_SEPARATOR.'pbSettingsFramework.php';
 
34
 
35
- if( !class_exists('pbSEOFriendlyImages') ):
 
36
 
37
- class pbSEOFriendlyImages
38
- {
39
- public static $verMajor = '3.1';
40
- public static $verMinor = '0';
41
 
42
- public static $basename = false;
43
- public static $userSettings = array();
44
- public static $proVersion = false;
45
 
46
- public static $proURL = 'https://goo.gl/0SV2EU'; // fu bit.ly http://bit.ly/seo-friendly-images-pro
47
- public static $proURL2 = 'https://goo.gl/D5YWDj';
48
-
49
- /**
50
- * Init function
51
- */
52
- public static function init()
53
- {
54
- if( isset($_GET['dslc']) ) {
55
- return;
56
- }
57
-
58
- pbSEOFriendlyImages::$basename = plugin_basename(__FILE__);
59
-
60
- // Pro Version file check
61
- if( file_exists(pbsfi_plugin_pro_path) ) {
62
- pbSEOFriendlyImages::$proVersion = true;
63
- }
64
-
65
- /*
66
- * Language file
67
- */
68
- load_plugin_textdomain('pb-seo-friendly-images', false, dirname(pbSEOFriendlyImages::$basename).DIRECTORY_SEPARATOR.'lang'.DIRECTORY_SEPARATOR);
69
-
70
- /*
71
- * Get settings and defaults
72
- */
73
- if( ! is_admin() ) {
74
- pbSEOFriendlyImages::$userSettings = array(
75
- 'optimize_img' => get_option('pbsfi_optimize_img', 'all'),
76
- 'sync_method' => get_option('pbsfi_sync_method', 'both'),
77
- 'override_alt' => get_option('pbsfi_override_alt', false),
78
- 'override_title' => get_option('pbsfi_override_title', false),
79
- 'alt_scheme' => get_option('pbsfi_alt_scheme', '%name - %title'),
80
- 'title_scheme' => get_option('pbsfi_title_scheme', '%title'),
81
- 'enable_lazyload' => get_option('pbsfi_enable_lazyload', true),
82
- 'enable_lazyload_acf' => get_option('pbsfi_enable_lazyload_acf', true),
83
- 'enable_lazyload_styles' => get_option('pbsfi_enable_lazyload_styles', false),
84
- 'lazyload_threshold' => get_option('pbsfi_lazyload_threshold', false),
85
- 'wc_title' => get_option('pbsfi_wc_title', false),
86
- 'wc_sync_method' => get_option('pbsfi_wc_sync_method', false),
87
- 'wc_override_alt' => get_option('pbsfi_wc_override_alt', false),
88
- 'wc_override_title' => get_option('pbsfi_wc_override_title', false),
89
- 'wc_alt_scheme' => get_option('pbsfi_wc_alt_scheme', false),
90
- 'wc_title_scheme' => get_option('pbsfi_wc_title_scheme', false),
91
- 'disable_srcset' => get_option('pbsfi_disable_srcset', false),
92
- 'link_title' => get_option('pbsfi_link_title', false),
93
- 'encoding' => get_option('pbsfi_encoding', false),
94
- 'encoding_mode' => get_option('pbsfi_encoding_mode', false)
95
- );
96
-
97
- // process post thumbnails
98
- if( pbSEOFriendlyImages::$userSettings['optimize_img'] == 'all' || pbSEOFriendlyImages::$userSettings['optimize_img'] == 'thumbs' ) {
99
- add_filter( 'wp_get_attachment_image_attributes', array(__CLASS__, 'addImgTitlePostThumbnail'), 10, 2 );
100
- }
101
-
102
- // process post images
103
- if( pbSEOFriendlyImages::$userSettings['optimize_img'] == 'all' || pbSEOFriendlyImages::$userSettings['optimize_img'] == 'post' ) {
104
- add_filter( 'the_content', array(__CLASS__, 'prepareContentImages'), 999, 1 );
105
-
106
- /*
107
- * Support for AdvancedCustomFields
108
- */
109
- add_filter('acf/load_value/type=textarea', array(__CLASS__, 'prepareContentImages'), 20);
110
- add_filter('acf/load_value/type=wysiwyg', array(__CLASS__, 'prepareContentImages'), 20);
111
-
112
- //add_filter('acf_load_value-text', array(__CLASS__, 'encrypt_mails_in_content'), 20);
113
- add_filter('acf_load_value-textarea', array(__CLASS__, 'prepareContentImages'), 20);
114
- add_filter('acf_load_value-wysiwyg', array(__CLASS__, 'prepareContentImages'), 20);
115
- }
116
- } else {
117
- add_action( 'admin_enqueue_scripts', function(){
118
- wp_register_style(
119
- 'pbsfi-admin-css',
120
- plugins_url(dirname(pbSEOFriendlyImages::$basename)).'/css/admin.css',
121
- false,
122
- pbSEOFriendlyImages::$verMajor.'.'.pbSEOFriendlyImages::$verMinor
123
- );
124
- wp_enqueue_style( 'pbsfi-admin-css' );
125
- } );
126
- }
127
- }
128
 
129
- /**
130
- * get array key
131
- *
132
- * @param $key
133
- * @param $array
134
- * @return bool
135
- */
136
- public static function getArrayKey($key, $array)
137
- {
138
- if( array_key_exists($key, $array) ) {
139
- return $array[$key];
140
- } else {
141
- return false;
142
- }
143
- }
144
 
145
- /**
146
- * Scheme replacements / variables
147
- *
148
- * @param string $content scheme
149
- * @param bool|string $src image url
150
- * @param bool|int $imageID
151
- * @return string
152
- */
153
- public static function convertReplacements( $content, $src=false, $imageID=false )
154
- {
155
- //global $post;
156
- $post = get_post();
157
-
158
- $cats = '';
159
- if ( strrpos( $content, '%category' ) !== false ) {
160
-
161
- if( get_post_type($post) == 'product' ) {
162
- $categories = get_the_terms( $post->ID, 'product_cat' );
163
- if ( ! $categories || is_wp_error( $categories ) ) {
164
- $categories = array();
165
- }
166
-
167
- $categories = array_values( $categories );
168
-
169
- foreach ( array_keys( $categories ) as $key ) {
170
- _make_cat_compat( $categories[$key] );
171
- }
172
- } else {
173
- $categories = get_the_category();
174
- }
175
-
176
- if ( $categories ) {
177
- $i = 0;
178
- foreach ( $categories as $cat ) {
179
- if ( $i == 0 ) {
180
- $cats = $cat->slug . $cats;
181
- } else {
182
- $cats = $cat->slug . ', ' . $cats;
183
- }
184
- ++$i;
185
- }
186
- }
187
- }
188
 
189
- $tags = '';
190
- if ( strrpos( $content, '%tags' ) !== false ) {
191
- $posttags = get_the_tags();
192
-
193
- if ( $posttags ) {
194
- $i = 0;
195
- foreach ( $posttags as $tag ) {
196
- if ( $i == 0 ) {
197
- $tags = $tag->name . $tags;
198
- } else {
199
- $tags = $tag->name . ', ' . $tags;
200
- }
201
- ++$i;
202
- }
203
- }
204
- }
205
 
206
- if( $src ) {
207
- $info = @pathinfo($src);
208
- $src = @basename($src,'.'.$info['extension']);
 
 
 
 
 
209
 
210
- $src = str_replace('-', ' ', $src);
211
- $src = str_replace('_', ' ', $src);
212
- } else {
213
- $src = '';
214
- }
 
 
 
 
 
 
215
 
216
- if( is_numeric($imageID) ) {
217
- $attachment = wp_prepare_attachment_for_js($imageID);
 
 
 
 
218
 
219
- if( is_array($attachment) ) {
220
- $content = str_replace('%media_title', $attachment['title'], $content );
221
- $content = str_replace('%media_alt', $attachment['alt'], $content );
222
- $content = str_replace('%media_caption', $attachment['caption'], $content );
223
- $content = str_replace('%media_description', $attachment['description'], $content );
224
- }
225
- }
226
 
227
- $content = str_replace('%media_title', $post->post_title, $content );
228
- $content = str_replace('%media_alt', $post->post_title, $content );
229
- $content = str_replace('%media_caption', $post->post_title, $content );
230
- $content = str_replace('%media_description', $post->post_title, $content );
231
 
232
- $content = str_replace('%name', $src, $content );
233
- $content = str_replace('%title', $post->post_title, $content );
234
- $content = str_replace('%category', $cats, $content );
235
- $content = str_replace('%tags', $tags, $content );
236
- $content = str_replace('%desc', $post->post_excerpt, $content);
237
 
238
- return $content;
239
- }
240
 
241
- /**
242
- * Process post images
243
- *
244
- *
245
- * @param string $content
246
- * @return string
247
- */
248
- public static function prepareContentImages( $content )
249
- {
250
- if( empty($content) || !class_exists('DOMDocument') )
251
- return $content;
252
-
253
- if(
254
- get_post_type() == 'tribe_events' || // exclude for Events Calendar
255
- is_feed() || // exclude for feeds
256
- strstr( strtolower($content), 'arforms') || // exclude for ARForms
257
- strstr( strtolower($content), 'arf_form') || // exclude for ARForms
258
- strstr( strtolower($content), 'spb_gallery') || // exclude for spb_gallery_widget
259
- isset($_GET['dslc']) // exclude for LiveComposer
260
- ) {
261
- return $content;
262
- }
263
 
264
- if( !empty(pbSEOFriendlyImages::$userSettings['encoding']) ) {
265
- $charset = pbSEOFriendlyImages::$userSettings['encoding'];
266
- } else {
267
- $charset = ( (defined('DB_CHARSET') ) ? DB_CHARSET : 'utf-8' );
268
- }
269
 
270
- $charset = apply_filters('pbsfi-charset', $charset);
271
- $encoding_declaration = sprintf('<?xml encoding="%s" ?>', $charset);
 
272
 
273
- $document = new DOMDocument();
274
- if( function_exists('mb_convert_encoding') && pbSEOFriendlyImages::$userSettings['encoding_mode'] != 'off' ) {
275
- $content = @mb_convert_encoding($content, 'HTML-ENTITIES', $charset);
276
- } else {
277
- $content = $encoding_declaration.$content;
278
- }
279
- @$document->loadHTML($content);
280
 
281
- if( !$document ) {
282
- return $content;
283
  }
284
 
285
- /*
286
- * Recommendation by BasTaller
287
- * @url https://wordpress.org/support/topic/proposal-for-best-replacement/
288
- */
289
- $figTags = $document->getElementsByTagName('figure');
290
-
291
- if( ! $figTags->length ) {
292
- foreach ($figTags as $tag){
293
- $caption = $tag->nodeValue;
294
- $imgTags = $tag->getElementsByTagName('img');
295
-
296
- if( empty($caption) )
297
- continue;
298
-
299
- foreach ($imgTags as $tag) {
300
- $tag->setAttribute('title', $caption);
301
- }
302
- }
303
- }
304
-
305
- $imgTags = $document->getElementsByTagName('img');
306
-
307
- if( ! $imgTags->length )
308
- return $content;
309
-
310
- foreach ($imgTags as $tag) {
311
- $data_src = trim($tag->getAttribute('data-src'));
312
- $src = trim($tag->getAttribute('src'));
313
-
314
- if( !empty($data_src) ) {
315
- $src = $data_src;
316
- }
317
-
318
- $imageID = pbSEOFriendlyImages::getImageID($src);
319
-
320
- /**
321
- * Override Area
322
- */
323
- if( pbSEOFriendlyImages::$userSettings['override_alt'] ) {
324
- $alt = trim(pbSEOFriendlyImages::convertReplacements(
325
- pbSEOFriendlyImages::$userSettings['alt_scheme'],
326
- $src,
327
- $imageID
328
- ));
329
-
330
- $alt = apply_filters('pbsfi-alt', $alt);
331
-
332
- $tag->setAttribute('alt', $alt);
333
- } else {
334
- $alt = trim($tag->getAttribute('alt'));
335
- $alt = apply_filters('pbsfi-alt', $alt);
336
- }
337
-
338
- if( pbSEOFriendlyImages::$userSettings['override_title'] ) {
339
-
340
- $title = trim(pbSEOFriendlyImages::convertReplacements(
341
- pbSEOFriendlyImages::$userSettings['title_scheme'],
342
- $src,
343
- $imageID
344
- ));
345
-
346
- $title = apply_filters('pbsfi-title', $title);
347
-
348
- $tag->setAttribute('title', $title);
349
- } else {
350
- $title = trim($tag->getAttribute('title'));
351
- $title = apply_filters('pbsfi-title', $title);
352
- }
353
-
354
- /**
355
- * Check attributes
356
- */
357
- if( !empty($alt) && empty($title) && (pbSEOFriendlyImages::$userSettings['sync_method'] == 'both' || pbSEOFriendlyImages::$userSettings['sync_method'] == 'alt' ) ) {
358
-
359
- $alt = apply_filters('pbsfi-title', $alt);
360
- $tag->setAttribute('title', $alt);
361
- $title = $alt;
362
-
363
- } else if( empty($alt) && !empty($title) && (pbSEOFriendlyImages::$userSettings['sync_method'] == 'both' || pbSEOFriendlyImages::$userSettings['sync_method'] == 'title' ) ) {
364
-
365
- $title = apply_filters('pbsfi-alt', $title);
366
- $tag->setAttribute('alt', $title);
367
- $alt = $title;
368
-
369
- }
370
-
371
- /**
372
- * set if empty after sync
373
- */
374
- if( empty($alt) ) {
375
- $alt = trim(pbSEOFriendlyImages::convertReplacements(
376
- pbSEOFriendlyImages::$userSettings['alt_scheme'],
377
- $src,
378
- $imageID
379
- ));
380
-
381
- $alt = apply_filters('pbsfi-alt', $alt);
382
- $tag->setAttribute('alt', $alt);
383
- }
384
-
385
- if( empty($title) ) {
386
- $title = trim(pbSEOFriendlyImages::convertReplacements(
387
- pbSEOFriendlyImages::$userSettings['title_scheme'],
388
- $src,
389
- $imageID
390
- ));
391
-
392
- $title = apply_filters('pbsfi-title', $title);
393
- $tag->setAttribute('title', $title);
394
- }
395
  }
396
 
397
- $return = $document->saveHTML();
398
- $return = str_replace($encoding_declaration, '', $return);
399
-
400
- return preg_replace('/^<!DOCTYPE.+?>/', '', str_replace( array('<html>', '</html>', '<body>', '</body>'), array('', '', '', ''), $return));
401
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
 
403
  /**
404
- * Add image title and alt to post thumbnails
405
- *
406
- * @param $attr
407
- * @param null $attachment
408
- * @return mixed
409
  */
410
- public static function addImgTitlePostThumbnail( $attr, $attachment = null )
411
  {
412
- if( empty($attr['alt']) ) {
413
 
414
- $attr['title'] = trim(pbSEOFriendlyImages::convertReplacements(
415
- pbSEOFriendlyImages::$userSettings['title_scheme'],
416
- $attr['src']
417
- ));
418
 
419
- $attr['alt'] = trim(pbSEOFriendlyImages::convertReplacements(
420
- pbSEOFriendlyImages::$userSettings['alt_scheme'],
421
- $attr['src']
422
- ));
423
-
424
- } else {
425
-
426
- if( pbSEOFriendlyImages::$userSettings['sync_method'] == 'both' || pbSEOFriendlyImages::$userSettings['sync_method'] == 'alt' ) {
427
- $attr['title'] = trim( strip_tags($attachment->post_title) );
428
- } else {
429
- $attr['title'] = trim(pbSEOFriendlyImages::convertReplacements(
430
- pbSEOFriendlyImages::$userSettings['title_scheme'],
431
- $attr['src']
432
- ));
433
- }
434
-
435
- }
436
-
437
- $attr['alt'] = apply_filters('pbsfi-alt', $attr['alt']);
438
- $attr['title'] = apply_filters('pbsfi-title', $attr['title']);
439
-
440
- return $attr;
441
  }
442
 
443
- /**
444
- * Get Image ID by URL
445
- *
446
- * @param string $url
447
- * @return int|bool
448
- */
449
- public static function getImageID( $url )
450
  {
451
- global $wpdb;
 
 
452
 
453
- $sql = $wpdb->prepare(
454
- 'SELECT `ID` FROM `'.$wpdb->posts.'` WHERE `guid` = \'%s\';',
455
- esc_sql($url)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
456
  );
457
 
458
- $attachment = $wpdb->get_col($sql);
459
-
460
-
461
- if( is_numeric( pbSEOFriendlyImages::getArrayKey(0, $attachment) ) ) {
462
- return (int) $attachment[0];
463
  }
464
 
465
- return false;
466
- }
467
 
468
- /**
469
- * Uninstall PB SEO Friendly Images
470
- */
471
- public static function uninstall()
472
- {
473
- /* Global */
474
- /** @var object $wpdb */
475
- global $wpdb;
476
 
477
- /* Remove settings */
478
- //delete_option();
479
 
480
- /* Clean DB */
481
- $wpdb->query("OPTIMIZE TABLE `" .$wpdb->options. "`");
 
 
 
 
 
 
 
 
 
 
 
 
 
482
  }
483
  }
484
 
485
- endif; // class_exists
486
-
487
- require_once 'inc'.DIRECTORY_SEPARATOR.'settings.php';
488
- if( file_exists(pbsfi_plugin_pro_path) ) {
489
- require_once pbsfi_plugin_pro_path;
490
- }
491
 
492
- add_action(
493
- 'plugins_loaded',
494
- array(
495
- 'pbSEOFriendlyImages',
496
- 'init'
497
- )
498
- );
499
-
500
- add_action(
501
- 'plugins_loaded',
502
- array(
503
- 'pbSEOFriendlyImagesSettings',
504
- 'addSettings'
505
- )
506
- );
507
-
508
- if( class_exists('pbSEOFriendlyImagesPro') ) {
509
- add_action(
510
- 'plugins_loaded',
511
- array(
512
- 'pbSEOFriendlyImagesPro',
513
- 'init'
514
- )
515
- );
516
  }
517
-
518
- register_uninstall_hook(
519
- __FILE__,
520
- array(
521
- 'pbSEOFriendlyImages',
522
- 'uninstall'
523
- )
524
- );
3
  Plugin Name: PB SEO Friendly Images
4
  Plugin URI: https://wordpress.org/extend/plugins/pb-seo-friendly-images/
5
  Description: This plugin is a full-featured solution for SEO friendly images. Optimize "alt" and "title" attributes for all images and post thumbnails. This plugin helps you to improve your traffic from search engines.
6
+ Version: 4.0.3
7
  Author: Pascal Bajorat
8
+ Author URI: https://www.bajorat-media.com
9
  Text Domain: pb-seo-friendly-images
10
  Domain Path: /lang
11
+ License: GNU General Public License v.3 and Commercial for Pro-Parts
12
 
13
+ Copyright (c) 2020 by Bajorat-Media.com.
14
  */
15
 
16
  /* Security-Check */
17
+ if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
18
 
19
+ if( ! class_exists('pbSEOFriendlyImages') ):
 
 
20
 
21
+ class pbSEOFriendlyImages
22
+ {
23
+ /** @var string Plugin version */
24
+ var $version = '4.0.3';
25
 
26
+ /** @var string DB version */
27
+ var $db_version = '4.0.0';
 
28
 
29
+ /** @var array Plugin Settings */
30
+ var $settings = array();
31
 
32
+ /** @var array Plugin Data */
33
+ var $plugin = array();
34
 
35
+ /** @var string URL to Pro-Version Landingpage */
36
+ var $proURL = 'https://goo.gl/0SV2EU';
 
 
37
 
38
+ /** @var string URL to Pro-Version Cart */
39
+ var $proURL2 = 'https://goo.gl/D5YWDj';
 
40
 
41
+ /** @var string option name */
42
+ var $option_name = 'pb-seo-friendly-images';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
+ /** @var string option name for db version */
45
+ var $option_name_dbv = 'pb-seo-friendly-images-dbv';
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
+ /** @var bool Pro-Version */
48
+ protected $proVersion = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
+ /** @var string path to pro file */
51
+ protected $proPath;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
+ /**
54
+ * Check if Version is Pro (Getter)
55
+ *
56
+ * @return bool
57
+ */
58
+ public function isProVersion() {
59
+ return $this->proVersion;
60
+ }
61
 
62
+ /**
63
+ * Initialize PB SEO Friendly Images
64
+ * @return void
65
+ */
66
+ public function initialize()
67
+ {
68
+ // Plugin Default Data
69
+ $this->plugin = array(
70
+ // basic
71
+ 'name' => __('PB SEO Friendly Images', 'pb-seo-friendly-images'),
72
+ 'version' => $this->version,
73
 
74
+ // urls
75
+ 'file' => __FILE__,
76
+ 'basename' => plugin_basename( __FILE__ ),
77
+ 'path' => plugin_dir_path( __FILE__ ),
78
+ 'url' => plugin_dir_url( __FILE__ ),
79
+ );
80
 
81
+ // Default settings
82
+ $this->settings = array(
 
 
 
 
 
83
 
84
+ );
 
 
 
85
 
86
+ // load plugin textdomain
87
+ $this->load_plugin_textdomain();
 
 
 
88
 
89
+ // load settings
90
+ $this->load_settings();
91
 
92
+ // pro path
93
+ $this->proPath = $this->plugin['path'] . 'inc/pbsfi_pro.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
+ // check if this is pro version and initialize pro class
96
+ if( true === file_exists($this->proPath) ) {
 
 
 
97
 
98
+ // set to true
99
+ $this->proVersion = true;
100
+ $this->settings['proVersion'] = true;
101
 
102
+ // load pro class + extend and manipulate basic version
103
+ new pbsfi_pro( $this );
 
 
 
 
 
104
 
105
+ } else {
106
+ $this->settings['proVersion'] = false;
107
  }
108
 
109
+ // admin bar and post_update is for front- and backend
110
+ if( isset($this->settings['enable_caching']) && $this->settings['enable_caching'] == true ) {
111
+ add_action('admin_bar_menu', [ $this, 'admin_bar_menu' ], 999);
112
+ add_action('post_updated', [ $this, 'clear_cache_for_post' ], 10, 3);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  }
114
 
115
+ try {
116
+ new pbcockpitnotice([
117
+ 'logo' => plugins_url(dirname($this->plugin['basename'])).'/assets/img/bajorat-media-white.svg',
118
+ 'link_de' => 'https://cockpit.bajorat-media.com/infos/?utm_source=pb-seo-friendly-images&utm_medium=banner&utm_campaign=pb-seo-friendly-images',
119
+ 'link_en' => 'https://cockpit.bajorat-media.com/en/infos/?utm_source=pb-seo-friendly-images&utm_medium=banner&utm_campaign=pb-seo-friendly-images',
120
+ 'allowed_screens' => array('settings_page_pb-seo-friendly-images'),
121
+ 'only_on_screens' => $this->settings['proVersion'],
122
+ 'close_on_screens' => $this->settings['proVersion']
123
+ ]);
124
+ } catch (Exception $e) {}
125
+
126
+ if( is_admin() ) {
127
+
128
+ // initialize admin
129
+ $this->initialize_admin();
130
+
131
+ } else {
132
+
133
+ // initialize frontend
134
+ $this->initialize_frontend();
135
+
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Load Plugin Textdomain
141
+ * @return void
142
+ */
143
+ public function load_plugin_textdomain()
144
+ {
145
+ load_plugin_textdomain(
146
+ 'pb-seo-friendly-images',
147
+ false,
148
+ dirname( $this->plugin['basename'] ).'/lang/'
149
+ );
150
+ }
151
+
152
+ /**
153
+ * Load Plugin Settings from Options and maybe convert from older Versions
154
+ * @return void
155
+ */
156
+ public function load_settings()
157
+ {
158
+ $settings_from_option = get_option($this->option_name);
159
+
160
+ if( false === $settings_from_option ) {
161
+ // convert old settings from version previous 4.0.0
162
+ $pbsfi_upgrade = new pbsfi_upgrade( $this );
163
+
164
+ if( true === $pbsfi_upgrade->maybe_do_upgrade() ) {
165
+ $settings_from_option = get_option($this->option_name);
166
+ }
167
+ }
168
+
169
+ if( is_array($settings_from_option) ) {
170
+
171
+ $this->settings = array_merge(
172
+ $this->settings,
173
+ $settings_from_option
174
+ );
175
+
176
+ }
177
+
178
+ }
179
+
180
+ /**
181
+ * initialize admin functions
182
+ * @return void
183
+ */
184
+ public function initialize_admin()
185
+ {
186
+ $admin = new pbsfi_admin_interface( $this );
187
+ $admin->initialize();
188
+ }
189
+
190
+ /**
191
+ * initialize frontend functions
192
+ * @return void
193
+ */
194
+ public function initialize_frontend()
195
+ {
196
+ $frontend = new pbsfi_frontend( $this );
197
+
198
+ add_action('template_redirect', array($frontend, 'initialize'));
199
+ }
200
 
201
  /**
202
+ * AdminBar Menu for Cache
 
 
 
 
203
  */
204
+ public function admin_bar_menu()
205
  {
206
+ global $wp_admin_bar;
207
 
208
+ $menu_id = 'pbsfi';
 
 
 
209
 
210
+ $wp_admin_bar->add_menu(array(
211
+ 'id' => $menu_id,
212
+ 'title' => __('Clear Cache', 'pb-seo-friendly-images'),
213
+ 'href' => admin_url('options-general.php?page=pb-seo-friendly-images&clear_cache=true')
214
+ ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  }
216
 
217
+ public function clear_cache_for_post($post_ID, $post_after, $post_before)
 
 
 
 
 
 
218
  {
219
+ $cache = new pbsfi_cache();
220
+ $cache->clear_post_cache( $post_ID );
221
+ }
222
 
223
+ /**
224
+ * Uninstall PB SEO Friendly Images
225
+ * @return void
226
+ */
227
+ public static function uninstall()
228
+ {
229
+ /* Global */
230
+ /** @var wpdb $wpdb */
231
+ global $wpdb;
232
+
233
+ /** @var pbSEOFriendlyImages $pbSEOFriendlyImages */
234
+ $pbSEOFriendlyImages = new self();
235
+
236
+ /* Remove settings */
237
+ delete_option($pbSEOFriendlyImages->option_name);
238
+
239
+ /* Clean DB */
240
+ $wpdb->query("OPTIMIZE TABLE `" .$wpdb->options. "`");
241
+ }
242
+ } /* end of pbSEOFriendlyImages */
243
+
244
+ /**
245
+ * Initialize pbSEOFriendlyImages Class
246
+ */
247
+ $pbSEOFriendlyImages = new pbSEOFriendlyImages();
248
+
249
+ /**
250
+ * Trigger plugins_loaded hook with method pbSEOFriendlyImages->initialize()
251
+ */
252
+ add_action(
253
+ 'plugins_loaded',
254
+ array(
255
+ $pbSEOFriendlyImages,
256
+ 'initialize'
257
+ )
258
+ );
259
+
260
+ /**
261
+ * Register uninstall hook
262
+ */
263
+ register_uninstall_hook(
264
+ __FILE__,
265
+ array(
266
+ 'pbSEOFriendlyImages',
267
+ 'uninstall'
268
+ )
269
+ );
270
+
271
+ endif;
272
+
273
+ /**
274
+ * Autoloader function
275
+ *
276
+ * @param $class
277
+ *
278
+ * @return WP_Error
279
+ */
280
+
281
+ if( ! function_exists('pbSEOFriendlyImagesAutoload') ) {
282
+
283
+ function pbSEOFriendlyImagesAutoload($class)
284
+ {
285
+ $allowed_classes = array(
286
+ 'pbSettingsFramework_2',
287
+ 'pbsfi_admin_interface',
288
+ 'pbsfi_frontend',
289
+ 'pbsfi_optimizer',
290
+ 'pbsfi_pro',
291
+ 'pbsfi_upgrade',
292
+ 'pbsfi_cache',
293
+ 'pbcockpitnotice'
294
+ );
295
+
296
+ if( 'Puc_v4_Factory' == $class ) {
297
+
298
+ $require_once = sprintf(
299
+ '%s/plugin-update-checker/plugin-update-checker.php',
300
+
301
+ dirname(__FILE__)
302
  );
303
 
304
+ if( file_exists($require_once) ) {
305
+ require_once( $require_once );
 
 
 
306
  }
307
 
 
 
308
 
309
+ } elseif( in_array($class, $allowed_classes) ) {
 
 
 
 
 
 
 
310
 
311
+ $require_once = sprintf(
312
+ '%s/inc/%s.php',
313
 
314
+ dirname(__FILE__),
315
+ $class
316
+ );
317
+
318
+ if( file_exists( $require_once ) ) {
319
+ require_once( $require_once );
320
+ } else {
321
+ return new WP_Error(
322
+ 'broke',
323
+ sprintf(
324
+ esc_html__( 'Can not find: %s', 'pb-seo-friendly-images' ),
325
+ $require_once
326
+ )
327
+ );
328
+ }
329
  }
330
  }
331
 
332
+ /* Autoload Init */
333
+ spl_autoload_register('pbSEOFriendlyImagesAutoload');
 
 
 
 
334
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
  }
 
 
 
 
 
 
 
 
plugin-update-checker/css/puc-debug-bar.css DELETED
@@ -1,62 +0,0 @@
1
- .puc-debug-bar-panel pre {
2
- margin-top: 0;
3
- }
4
-
5
- /* Style the debug data table to match "widefat" table style used by WordPress. */
6
- table.puc-debug-data {
7
- width: 100%;
8
- clear: both;
9
- margin: 0;
10
-
11
- border-spacing: 0;
12
- background-color: #f9f9f9;
13
-
14
- border-radius: 3px;
15
- border: 1px solid #dfdfdf;
16
- border-collapse: separate;
17
- }
18
-
19
- table.puc-debug-data * {
20
- word-wrap: break-word;
21
- }
22
-
23
- table.puc-debug-data th {
24
- width: 11em;
25
- padding: 7px 7px 8px;
26
- text-align: left;
27
-
28
- font-family: "Georgia", "Times New Roman", "Bitstream Charter", "Times", serif;
29
- font-weight: 400;
30
- font-size: 14px;
31
- line-height: 1.3em;
32
- text-shadow: rgba(255, 255, 255, 0.804) 0 1px 0;
33
- }
34
-
35
- table.puc-debug-data td, table.puc-debug-data th {
36
- border-width: 1px 0;
37
- border-style: solid;
38
-
39
- border-top-color: #fff;
40
- border-bottom-color: #dfdfdf;
41
-
42
- text-transform: none;
43
- }
44
-
45
- table.puc-debug-data td {
46
- color: #555;
47
- font-size: 12px;
48
- padding: 4px 7px 2px;
49
- vertical-align: top;
50
- }
51
-
52
- .puc-ajax-response {
53
- border: 1px solid #dfdfdf;
54
- border-radius: 3px;
55
- padding: 0.5em;
56
- margin: 5px 0;
57
- background-color: white;
58
- }
59
-
60
- .puc-ajax-nonce {
61
- display: none;
62
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/debug-bar-panel.php DELETED
@@ -1,146 +0,0 @@
1
- <?php
2
-
3
- if ( !class_exists('PluginUpdateCheckerPanel_3_2', false) && class_exists('Debug_Bar_Panel', false) ) {
4
-
5
- /**
6
- * A Debug Bar panel for the plugin update checker.
7
- */
8
- class PluginUpdateCheckerPanel_3_2 extends Debug_Bar_Panel {
9
- /** @var PluginUpdateChecker_3_2 */
10
- private $updateChecker;
11
-
12
- private $responseBox = '<div class="puc-ajax-response" style="display: none;"></div>';
13
-
14
- public function __construct($updateChecker) {
15
- $this->updateChecker = $updateChecker;
16
- $title = sprintf(
17
- '<span id="puc-debug-menu-link-%s">PUC (%s)</span>',
18
- esc_attr($this->updateChecker->slug),
19
- $this->updateChecker->slug
20
- );
21
- parent::Debug_Bar_Panel($title);
22
- }
23
-
24
- public function render() {
25
- printf(
26
- '<div class="puc-debug-bar-panel" id="puc-debug-bar-panel_%1$s" data-slug="%1$s" data-nonce="%2$s">',
27
- esc_attr($this->updateChecker->slug),
28
- esc_attr(wp_create_nonce('puc-ajax'))
29
- );
30
-
31
- $this->displayConfiguration();
32
- $this->displayStatus();
33
- $this->displayCurrentUpdate();
34
-
35
- echo '</div>';
36
- }
37
-
38
- private function displayConfiguration() {
39
- echo '<h3>Configuration</h3>';
40
- echo '<table class="puc-debug-data">';
41
- $this->row('Plugin file', htmlentities($this->updateChecker->pluginFile));
42
- $this->row('Slug', htmlentities($this->updateChecker->slug));
43
- $this->row('DB option', htmlentities($this->updateChecker->optionName));
44
-
45
- $requestInfoButton = '';
46
- if ( function_exists('get_submit_button') ) {
47
- $requestInfoButton = get_submit_button('Request Info', 'secondary', 'puc-request-info-button', false, array('id' => 'puc-request-info-button-' . $this->updateChecker->slug));
48
- }
49
- $this->row('Metadata URL', htmlentities($this->updateChecker->metadataUrl) . ' ' . $requestInfoButton . $this->responseBox);
50
-
51
- $scheduler = $this->updateChecker->scheduler;
52
- if ( $scheduler->checkPeriod > 0 ) {
53
- $this->row('Automatic checks', 'Every ' . $scheduler->checkPeriod . ' hours');
54
- } else {
55
- $this->row('Automatic checks', 'Disabled');
56
- }
57
-
58
- if ( isset($scheduler->throttleRedundantChecks) ) {
59
- if ( $scheduler->throttleRedundantChecks && ($scheduler->checkPeriod > 0) ) {
60
- $this->row(
61
- 'Throttling',
62
- sprintf(
63
- 'Enabled. If an update is already available, check for updates every %1$d hours instead of every %2$d hours.',
64
- $scheduler->throttledCheckPeriod,
65
- $scheduler->checkPeriod
66
- )
67
- );
68
- } else {
69
- $this->row('Throttling', 'Disabled');
70
- }
71
- }
72
- echo '</table>';
73
- }
74
-
75
- private function displayStatus() {
76
- echo '<h3>Status</h3>';
77
- echo '<table class="puc-debug-data">';
78
- $state = $this->updateChecker->getUpdateState();
79
- $checkNowButton = '';
80
- if ( function_exists('get_submit_button') ) {
81
- $checkNowButton = get_submit_button('Check Now', 'secondary', 'puc-check-now-button', false, array('id' => 'puc-check-now-button-' . $this->updateChecker->slug));
82
- }
83
-
84
- if ( isset($state, $state->lastCheck) ) {
85
- $this->row('Last check', $this->formatTimeWithDelta($state->lastCheck) . ' ' . $checkNowButton . $this->responseBox);
86
- } else {
87
- $this->row('Last check', 'Never');
88
- }
89
-
90
- $nextCheck = wp_next_scheduled($this->updateChecker->scheduler->getCronHookName());
91
- $this->row('Next automatic check', $this->formatTimeWithDelta($nextCheck));
92
-
93
- if ( isset($state, $state->checkedVersion) ) {
94
- $this->row('Checked version', htmlentities($state->checkedVersion));
95
- $this->row('Cached update', $state->update);
96
- }
97
- $this->row('Update checker class', htmlentities(get_class($this->updateChecker)));
98
- echo '</table>';
99
- }
100
-
101
- private function displayCurrentUpdate() {
102
- $update = $this->updateChecker->getUpdate();
103
- if ( $update !== null ) {
104
- echo '<h3>An Update Is Available</h3>';
105
- echo '<table class="puc-debug-data">';
106
- $fields = array('version', 'download_url', 'slug', 'homepage', 'upgrade_notice');
107
- foreach($fields as $field) {
108
- $this->row(ucwords(str_replace('_', ' ', $field)), htmlentities($update->$field));
109
- }
110
- echo '</table>';
111
- } else {
112
- echo '<h3>No updates currently available</h3>';
113
- }
114
- }
115
-
116
- private function formatTimeWithDelta($unixTime) {
117
- if ( empty($unixTime) ) {
118
- return 'Never';
119
- }
120
-
121
- $delta = time() - $unixTime;
122
- $result = human_time_diff(time(), $unixTime);
123
- if ( $delta < 0 ) {
124
- $result = 'after ' . $result;
125
- } else {
126
- $result = $result . ' ago';
127
- }
128
- $result .= ' (' . $this->formatTimestamp($unixTime) . ')';
129
- return $result;
130
- }
131
-
132
- private function formatTimestamp($unixTime) {
133
- return gmdate('Y-m-d H:i:s', $unixTime + (get_option('gmt_offset') * 3600));
134
- }
135
-
136
- private function row($name, $value) {
137
- if ( is_object($value) || is_array($value) ) {
138
- $value = '<pre>' . htmlentities(print_r($value, true)) . '</pre>';
139
- } else if ($value === null) {
140
- $value = '<code>null</code>';
141
- }
142
- printf('<tr><th scope="row">%1$s</th> <td>%2$s</td></tr>', $name, $value);
143
- }
144
- }
145
-
146
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/debug-bar-plugin.php DELETED
@@ -1,102 +0,0 @@
1
- <?php
2
- if ( !class_exists('PucDebugBarPlugin_3_2', false) ) {
3
-
4
- class PucDebugBarPlugin_3_2 {
5
- /** @var PluginUpdateChecker_3_2 */
6
- private $updateChecker;
7
-
8
- public function __construct($updateChecker) {
9
- $this->updateChecker = $updateChecker;
10
-
11
- add_filter('debug_bar_panels', array($this, 'addDebugBarPanel'));
12
- add_action('debug_bar_enqueue_scripts', array($this, 'enqueuePanelDependencies'));
13
-
14
- add_action('wp_ajax_puc_debug_check_now', array($this, 'ajaxCheckNow'));
15
- add_action('wp_ajax_puc_debug_request_info', array($this, 'ajaxRequestInfo'));
16
- }
17
-
18
- /**
19
- * Register the PUC Debug Bar panel.
20
- *
21
- * @param array $panels
22
- * @return array
23
- */
24
- public function addDebugBarPanel($panels) {
25
- require_once dirname(__FILE__) . '/debug-bar-panel.php';
26
- if ( current_user_can('update_plugins') && class_exists('PluginUpdateCheckerPanel_3_2', false) ) {
27
- $panels[] = new PluginUpdateCheckerPanel_3_2($this->updateChecker);
28
- }
29
- return $panels;
30
- }
31
-
32
- /**
33
- * Enqueue our Debug Bar scripts and styles.
34
- */
35
- public function enqueuePanelDependencies() {
36
- wp_enqueue_style(
37
- 'puc-debug-bar-style',
38
- plugins_url( "/css/puc-debug-bar.css", __FILE__ ),
39
- array('debug-bar'),
40
- '20130927'
41
- );
42
-
43
- wp_enqueue_script(
44
- 'puc-debug-bar-js',
45
- plugins_url( "/js/debug-bar.js", __FILE__ ),
46
- array('jquery'),
47
- '20121026'
48
- );
49
- }
50
-
51
- /**
52
- * Run an update check and output the result. Useful for making sure that
53
- * the update checking process works as expected.
54
- */
55
- public function ajaxCheckNow() {
56
- if ( $_POST['slug'] !== $this->updateChecker->slug ) {
57
- return;
58
- }
59
- $this->preAjaxReqest();
60
- $update = $this->updateChecker->checkForUpdates();
61
- if ( $update !== null ) {
62
- echo "An update is available:";
63
- echo '<pre>', htmlentities(print_r($update, true)), '</pre>';
64
- } else {
65
- echo 'No updates found.';
66
- }
67
- exit;
68
- }
69
-
70
- /**
71
- * Request plugin info and output it.
72
- */
73
- public function ajaxRequestInfo() {
74
- if ( $_POST['slug'] !== $this->updateChecker->slug ) {
75
- return;
76
- }
77
- $this->preAjaxReqest();
78
- $info = $this->updateChecker->requestInfo();
79
- if ( $info !== null ) {
80
- echo 'Successfully retrieved plugin info from the metadata URL:';
81
- echo '<pre>', htmlentities(print_r($info, true)), '</pre>';
82
- } else {
83
- echo 'Failed to retrieve plugin info from the metadata URL.';
84
- }
85
- exit;
86
- }
87
-
88
- /**
89
- * Check access permissions and enable error display (for debugging).
90
- */
91
- private function preAjaxReqest() {
92
- if ( !current_user_can('update_plugins') ) {
93
- die('Access denied');
94
- }
95
- check_ajax_referer('puc-ajax');
96
-
97
- error_reporting(E_ALL);
98
- @ini_set('display_errors','On');
99
- }
100
- }
101
-
102
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/github-checker.php DELETED
@@ -1,459 +0,0 @@
1
- <?php
2
-
3
- if ( !class_exists('PucGitHubChecker_3_2', false) ):
4
-
5
- class PucGitHubChecker_3_2 extends PluginUpdateChecker_3_2 {
6
- /**
7
- * @var string GitHub username.
8
- */
9
- protected $userName;
10
- /**
11
- * @var string GitHub repository name.
12
- */
13
- protected $repositoryName;
14
-
15
- /**
16
- * @var string Either a fully qualified repository URL, or just "user/repo-name".
17
- */
18
- protected $repositoryUrl;
19
-
20
- /**
21
- * @var string The branch to use as the latest version. Defaults to "master".
22
- */
23
- protected $branch;
24
-
25
- /**
26
- * @var string GitHub authentication token. Optional.
27
- */
28
- protected $accessToken;
29
-
30
- public function __construct(
31
- $repositoryUrl,
32
- $pluginFile,
33
- $branch = 'master',
34
- $checkPeriod = 12,
35
- $optionName = '',
36
- $muPluginFile = ''
37
- ) {
38
-
39
- $this->repositoryUrl = $repositoryUrl;
40
- $this->branch = empty($branch) ? 'master' : $branch;
41
-
42
- $path = @parse_url($repositoryUrl, PHP_URL_PATH);
43
- if ( preg_match('@^/?(?P<username>[^/]+?)/(?P<repository>[^/#?&]+?)/?$@', $path, $matches) ) {
44
- $this->userName = $matches['username'];
45
- $this->repositoryName = $matches['repository'];
46
- } else {
47
- throw new InvalidArgumentException('Invalid GitHub repository URL: "' . $repositoryUrl . '"');
48
- }
49
-
50
- parent::__construct($repositoryUrl, $pluginFile, '', $checkPeriod, $optionName, $muPluginFile);
51
- }
52
-
53
- /**
54
- * Retrieve details about the latest plugin version from GitHub.
55
- *
56
- * @param array $unusedQueryArgs Unused.
57
- * @return PluginInfo_3_2
58
- */
59
- public function requestInfo($unusedQueryArgs = array()) {
60
- $info = new PluginInfo_3_2();
61
- $info->filename = $this->pluginFile;
62
- $info->slug = $this->slug;
63
-
64
- $this->setInfoFromHeader($this->getPluginHeader(), $info);
65
-
66
- //Figure out which reference (tag or branch) we'll use to get the latest version of the plugin.
67
- $ref = $this->branch;
68
- if ( $this->branch === 'master' ) {
69
- //Use the latest release.
70
- $release = $this->getLatestRelease();
71
- if ( $release !== null ) {
72
- $ref = $release->tag_name;
73
- $info->version = ltrim($release->tag_name, 'v'); //Remove the "v" prefix from "v1.2.3".
74
- $info->last_updated = $release->created_at;
75
- $info->download_url = $release->zipball_url;
76
-
77
- if ( !empty($release->body) ) {
78
- $info->sections['changelog'] = $this->parseMarkdown($release->body);
79
- }
80
- if ( isset($release->assets[0]) ) {
81
- $info->downloaded = $release->assets[0]->download_count;
82
- }
83
- } else {
84
- //Failing that, use the tag with the highest version number.
85
- $tag = $this->getLatestTag();
86
- if ( $tag !== null ) {
87
- $ref = $tag->name;
88
- $info->version = $tag->name;
89
- $info->download_url = $tag->zipball_url;
90
- }
91
- }
92
- }
93
-
94
- if ( empty($info->download_url) ) {
95
- $info->download_url = $this->buildArchiveDownloadUrl($ref);
96
- } else if ( !empty($this->accessToken) ) {
97
- $info->download_url = add_query_arg('access_token', $this->accessToken, $info->download_url);
98
- }
99
-
100
- //Get headers from the main plugin file in this branch/tag. Its "Version" header and other metadata
101
- //are what the WordPress install will actually see after upgrading, so they take precedence over releases/tags.
102
- $mainPluginFile = basename($this->pluginFile);
103
- $remotePlugin = $this->getRemoteFile($mainPluginFile, $ref);
104
- if ( !empty($remotePlugin) ) {
105
- $remoteHeader = $this->getFileHeader($remotePlugin);
106
- $this->setInfoFromHeader($remoteHeader, $info);
107
- }
108
-
109
- //Try parsing readme.txt. If it's formatted according to WordPress.org standards, it will contain
110
- //a lot of useful information like the required/tested WP version, changelog, and so on.
111
- if ( $this->readmeTxtExistsLocally() ) {
112
- $this->setInfoFromRemoteReadme($ref, $info);
113
- }
114
-
115
- //The changelog might be in a separate file.
116
- if ( empty($info->sections['changelog']) ) {
117
- $info->sections['changelog'] = $this->getRemoteChangelog($ref);
118
- if ( empty($info->sections['changelog']) ) {
119
- $info->sections['changelog'] = __('There is no changelog available.', 'plugin-update-checker');
120
- }
121
- }
122
-
123
- if ( empty($info->last_updated) ) {
124
- //Fetch the latest commit that changed the main plugin file and use it as the "last_updated" date.
125
- //It's reasonable to assume that every update will change the version number in that file.
126
- $latestCommit = $this->getLatestCommit($mainPluginFile, $ref);
127
- if ( $latestCommit !== null ) {
128
- $info->last_updated = $latestCommit->commit->author->date;
129
- }
130
- }
131
-
132
- $info = apply_filters('puc_request_info_result-' . $this->slug, $info, null);
133
- return $info;
134
- }
135
-
136
- /**
137
- * Get the latest release from GitHub.
138
- *
139
- * @return StdClass|null
140
- */
141
- protected function getLatestRelease() {
142
- $releases = $this->api('/repos/:user/:repo/releases');
143
- if ( is_wp_error($releases) || !is_array($releases) || !isset($releases[0]) ) {
144
- return null;
145
- }
146
-
147
- $latestRelease = $releases[0];
148
- return $latestRelease;
149
- }
150
-
151
- /**
152
- * Get the tag that looks like the highest version number.
153
- *
154
- * @return StdClass|null
155
- */
156
- protected function getLatestTag() {
157
- $tags = $this->api('/repos/:user/:repo/tags');
158
-
159
- if ( is_wp_error($tags) || empty($tags) || !is_array($tags) ) {
160
- return null;
161
- }
162
-
163
- usort($tags, array($this, 'compareTagNames')); //Sort from highest to lowest.
164
- return $tags[0];
165
- }
166
-
167
- /**
168
- * Compare two GitHub tags as if they were version number.
169
- *
170
- * @param string $tag1
171
- * @param string $tag2
172
- * @return int
173
- */
174
- protected function compareTagNames($tag1, $tag2) {
175
- if ( !isset($tag1->name) ) {
176
- return 1;
177
- }
178
- if ( !isset($tag2->name) ) {
179
- return -1;
180
- }
181
- return -version_compare($tag1->name, $tag2->name);
182
- }
183
-
184
- /**
185
- * Get the latest commit that changed the specified file.
186
- *
187
- * @param string $filename
188
- * @param string $ref Reference name (e.g. branch or tag).
189
- * @return StdClass|null
190
- */
191
- protected function getLatestCommit($filename, $ref = 'master') {
192
- $commits = $this->api(
193
- '/repos/:user/:repo/commits',
194
- array(
195
- 'path' => $filename,
196
- 'sha' => $ref,
197
- )
198
- );
199
- if ( !is_wp_error($commits) && is_array($commits) && isset($commits[0]) ) {
200
- return $commits[0];
201
- }
202
- return null;
203
- }
204
-
205
- protected function getRemoteChangelog($ref = '') {
206
- $filename = $this->getChangelogFilename();
207
- if ( empty($filename) ) {
208
- return null;
209
- }
210
-
211
- $changelog = $this->getRemoteFile($filename, $ref);
212
- if ( $changelog === null ) {
213
- return null;
214
- }
215
- return $this->parseMarkdown($changelog);
216
- }
217
-
218
- protected function getChangelogFilename() {
219
- $pluginDirectory = dirname($this->pluginAbsolutePath);
220
- if ( empty($this->pluginAbsolutePath) || !is_dir($pluginDirectory) || ($pluginDirectory === '.') ) {
221
- return null;
222
- }
223
-
224
- $possibleNames = array('CHANGES.md', 'CHANGELOG.md', 'changes.md', 'changelog.md');
225
- $files = scandir($pluginDirectory);
226
- $foundNames = array_intersect($possibleNames, $files);
227
-
228
- if ( !empty($foundNames) ) {
229
- return reset($foundNames);
230
- }
231
- return null;
232
- }
233
-
234
- /**
235
- * Convert Markdown to HTML.
236
- *
237
- * @param string $markdown
238
- * @return string
239
- */
240
- protected function parseMarkdown($markdown) {
241
- if ( !class_exists('Parsedown', false) ) {
242
- require_once(dirname(__FILE__) . '/vendor/Parsedown' . (version_compare(PHP_VERSION, '5.3.0', '>=') ? '' : 'Legacy') . '.php');
243
- }
244
-
245
- $instance = Parsedown::instance();
246
- return $instance->text($markdown);
247
- }
248
-
249
- /**
250
- * Perform a GitHub API request.
251
- *
252
- * @param string $url
253
- * @param array $queryParams
254
- * @return mixed|WP_Error
255
- */
256
- protected function api($url, $queryParams = array()) {
257
- $variables = array(
258
- 'user' => $this->userName,
259
- 'repo' => $this->repositoryName,
260
- );
261
- foreach ($variables as $name => $value) {
262
- $url = str_replace('/:' . $name, '/' . urlencode($value), $url);
263
- }
264
- $url = 'https://api.github.com' . $url;
265
-
266
- if ( !empty($this->accessToken) ) {
267
- $queryParams['access_token'] = $this->accessToken;
268
- }
269
- if ( !empty($queryParams) ) {
270
- $url = add_query_arg($queryParams, $url);
271
- }
272
-
273
- $response = wp_remote_get($url, array('timeout' => 10));
274
- if ( is_wp_error($response) ) {
275
- return $response;
276
- }
277
-
278
- $code = wp_remote_retrieve_response_code($response);
279
- $body = wp_remote_retrieve_body($response);
280
- if ( $code === 200 ) {
281
- $document = json_decode($body);
282
- return $document;
283
- }
284
-
285
- return new WP_Error(
286
- 'puc-github-http-error',
287
- 'GitHub API error. HTTP status: ' . $code
288
- );
289
- }
290
-
291
- /**
292
- * Set the access token that will be used to make authenticated GitHub API requests.
293
- *
294
- * @param string $accessToken
295
- */
296
- public function setAccessToken($accessToken) {
297
- $this->accessToken = $accessToken;
298
- }
299
-
300
- /**
301
- * Get the contents of a file from a specific branch or tag.
302
- *
303
- * @param string $path File name.
304
- * @param string $ref
305
- * @return null|string Either the contents of the file, or null if the file doesn't exist or there's an error.
306
- */
307
- protected function getRemoteFile($path, $ref = 'master') {
308
- $apiUrl = '/repos/:user/:repo/contents/' . $path;
309
- $response = $this->api($apiUrl, array('ref' => $ref));
310
-
311
- if ( is_wp_error($response) || !isset($response->content) || ($response->encoding !== 'base64') ) {
312
- return null;
313
- }
314
- return base64_decode($response->content);
315
- }
316
-
317
- /**
318
- * Parse plugin metadata from the header comment.
319
- * This is basically a simplified version of the get_file_data() function from /wp-includes/functions.php.
320
- *
321
- * @param $content
322
- * @return array
323
- */
324
- protected function getFileHeader($content) {
325
- $headers = array(
326
- 'Name' => 'Plugin Name',
327
- 'PluginURI' => 'Plugin URI',
328
- 'Version' => 'Version',
329
- 'Description' => 'Description',
330
- 'Author' => 'Author',
331
- 'AuthorURI' => 'Author URI',
332
- 'TextDomain' => 'Text Domain',
333
- 'DomainPath' => 'Domain Path',
334
- 'Network' => 'Network',
335
-
336
- //The newest WordPress version that this plugin requires or has been tested with.
337
- //We support several different formats for compatibility with other libraries.
338
- 'Tested WP' => 'Tested WP',
339
- 'Requires WP' => 'Requires WP',
340
- 'Tested up to' => 'Tested up to',
341
- 'Requires at least' => 'Requires at least',
342
- );
343
-
344
- $content = str_replace("\r", "\n", $content); //Normalize line endings.
345
- $results = array();
346
- foreach ($headers as $field => $name) {
347
- $success = preg_match('/^[ \t\/*#@]*' . preg_quote($name, '/') . ':(.*)$/mi', $content, $matches);
348
- if ( ($success === 1) && $matches[1] ) {
349
- $results[$field] = _cleanup_header_comment($matches[1]);
350
- } else {
351
- $results[$field] = '';
352
- }
353
- }
354
-
355
- return $results;
356
- }
357
-
358
- /**
359
- * Copy plugin metadata from a file header to a PluginInfo object.
360
- *
361
- * @param array $fileHeader
362
- * @param PluginInfo_3_2 $pluginInfo
363
- */
364
- protected function setInfoFromHeader($fileHeader, $pluginInfo) {
365
- $headerToPropertyMap = array(
366
- 'Version' => 'version',
367
- 'Name' => 'name',
368
- 'PluginURI' => 'homepage',
369
- 'Author' => 'author',
370
- 'AuthorName' => 'author',
371
- 'AuthorURI' => 'author_homepage',
372
-
373
- 'Requires WP' => 'requires',
374
- 'Tested WP' => 'tested',
375
- 'Requires at least' => 'requires',
376
- 'Tested up to' => 'tested',
377
- );
378
- foreach ($headerToPropertyMap as $headerName => $property) {
379
- if ( isset($fileHeader[$headerName]) && !empty($fileHeader[$headerName]) ) {
380
- $pluginInfo->$property = $fileHeader[$headerName];
381
- }
382
- }
383
-
384
- if ( !empty($fileHeader['Description']) ) {
385
- $pluginInfo->sections['description'] = $fileHeader['Description'];
386
- }
387
- }
388
-
389
- /**
390
- * Copy plugin metadata from the remote readme.txt file.
391
- *
392
- * @param string $ref GitHub tag or branch where to look for the readme.
393
- * @param PluginInfo_3_2 $pluginInfo
394
- */
395
- protected function setInfoFromRemoteReadme($ref, $pluginInfo) {
396
- $readmeTxt = $this->getRemoteFile('readme.txt', $ref);
397
- if ( empty($readmeTxt) ) {
398
- return;
399
- }
400
-
401
- $readme = $this->parseReadme($readmeTxt);
402
-
403
- if ( isset($readme['sections']) ) {
404
- $pluginInfo->sections = array_merge($pluginInfo->sections, $readme['sections']);
405
- }
406
- if ( !empty($readme['tested_up_to']) ) {
407
- $pluginInfo->tested = $readme['tested_up_to'];
408
- }
409
- if ( !empty($readme['requires_at_least']) ) {
410
- $pluginInfo->requires = $readme['requires_at_least'];
411
- }
412
-
413
- if ( isset($readme['upgrade_notice'], $readme['upgrade_notice'][$pluginInfo->version]) ) {
414
- $pluginInfo->upgrade_notice = $readme['upgrade_notice'][$pluginInfo->version];
415
- }
416
- }
417
-
418
- protected function parseReadme($content) {
419
- if ( !class_exists('PucReadmeParser', false) ) {
420
- require_once(dirname(__FILE__) . '/vendor/readme-parser.php');
421
- }
422
- $parser = new PucReadmeParser();
423
- return $parser->parse_readme_contents($content);
424
- }
425
-
426
- /**
427
- * Check if the currently installed version has a readme.txt file.
428
- *
429
- * @return bool
430
- */
431
- protected function readmeTxtExistsLocally() {
432
- $pluginDirectory = dirname($this->pluginAbsolutePath);
433
- if ( empty($this->pluginAbsolutePath) || !is_dir($pluginDirectory) || ($pluginDirectory === '.') ) {
434
- return false;
435
- }
436
- return is_file($pluginDirectory . '/readme.txt');
437
- }
438
-
439
- /**
440
- * Generate a URL to download a ZIP archive of the specified branch/tag/etc.
441
- *
442
- * @param string $ref
443
- * @return string
444
- */
445
- protected function buildArchiveDownloadUrl($ref = 'master') {
446
- $url = sprintf(
447
- 'https://api.github.com/repos/%1$s/%2$s/zipball/%3$s',
448
- urlencode($this->userName),
449
- urlencode($this->repositoryName),
450
- urlencode($ref)
451
- );
452
- if ( !empty($this->accessToken) ) {
453
- $url = add_query_arg('access_token', $this->accessToken, $url);
454
- }
455
- return $url;
456
- }
457
- }
458
-
459
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/js/debug-bar.js DELETED
@@ -1,52 +0,0 @@
1
- jQuery(function($) {
2
-
3
- function runAjaxAction(button, action) {
4
- button = $(button);
5
- var panel = button.closest('.puc-debug-bar-panel');
6
- var responseBox = button.closest('td').find('.puc-ajax-response');
7
-
8
- responseBox.text('Processing...').show();
9
- $.post(
10
- ajaxurl,
11
- {
12
- action : action,
13
- slug : panel.data('slug'),
14
- _wpnonce: panel.data('nonce')
15
- },
16
- function(data) {
17
- responseBox.html(data);
18
- },
19
- 'html'
20
- );
21
- }
22
-
23
- $('.puc-debug-bar-panel input[name="puc-check-now-button"]').click(function() {
24
- runAjaxAction(this, 'puc_debug_check_now');
25
- return false;
26
- });
27
-
28
- $('.puc-debug-bar-panel input[name="puc-request-info-button"]').click(function() {
29
- runAjaxAction(this, 'puc_debug_request_info');
30
- return false;
31
- });
32
-
33
-
34
- // Debug Bar uses the panel class name as part of its link and container IDs. This means we can
35
- // end up with multiple identical IDs if more than one plugin uses the update checker library.
36
- // Fix it by replacing the class name with the plugin slug.
37
- var panels = $('#debug-menu-targets').find('.puc-debug-bar-panel');
38
- panels.each(function(index) {
39
- var panel = $(this);
40
- var slug = panel.data('slug');
41
- var target = panel.closest('.debug-menu-target');
42
-
43
- //Change the panel wrapper ID.
44
- target.attr('id', 'debug-menu-target-puc-' + slug);
45
-
46
- //Change the menu link ID as well and point it at the new target ID.
47
- $('#puc-debug-menu-link-' + panel.data('slug'))
48
- .closest('.debug-menu-link')
49
- .attr('id', 'debug-menu-link-puc-' + slug)
50
- .attr('href', '#' + target.attr('id'));
51
- });
52
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/languages/plugin-update-checker-de_DE.mo DELETED
Binary file
plugin-update-checker/languages/plugin-update-checker-de_DE.po DELETED
@@ -1,38 +0,0 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: plugin-update-checker\n"
4
- "POT-Creation-Date: 2016-06-29 20:21+0100\n"
5
- "PO-Revision-Date: 2016-06-29 20:23+0100\n"
6
- "Last-Translator: Igor Lückel <info@igorlueckel.de>\n"
7
- "Language-Team: \n"
8
- "MIME-Version: 1.0\n"
9
- "Content-Type: text/plain; charset=UTF-8\n"
10
- "Content-Transfer-Encoding: 8bit\n"
11
- "X-Generator: Poedit 1.8.1\n"
12
- "X-Poedit-Basepath: ..\n"
13
- "Plural-Forms: nplurals=2; plural=(n != 1);\n"
14
- "X-Poedit-SourceCharset: UTF-8\n"
15
- "X-Poedit-KeywordsList: __;_e\n"
16
- "Language: de_DE\n"
17
- "X-Poedit-SearchPath-0: .\n"
18
-
19
- #: github-checker.php:137
20
- msgid "There is no changelog available."
21
- msgstr "Es ist keine Liste von Programmänderungen verfügbar."
22
-
23
- #: plugin-update-checker.php:852
24
- msgid "Check for updates"
25
- msgstr "Nach Update suchen"
26
-
27
- #: plugin-update-checker.php:896
28
- msgid "This plugin is up to date."
29
- msgstr "Das Plugin ist aktuell."
30
-
31
- #: plugin-update-checker.php:898
32
- msgid "A new version of this plugin is available."
33
- msgstr "Es ist eine neue Version für das Plugin verfügbar."
34
-
35
- #: plugin-update-checker.php:900
36
- #, php-format
37
- msgid "Unknown update checker status \"%s\""
38
- msgstr "Unbekannter Update Status \"%s\""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/languages/plugin-update-checker-fa_IR.mo DELETED
Binary file
plugin-update-checker/languages/plugin-update-checker-fa_IR.po DELETED
@@ -1,38 +0,0 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: plugin-update-checker\n"
4
- "POT-Creation-Date: 2016-02-17 14:21+0100\n"
5
- "PO-Revision-Date: 2016-10-28 14:30+0330\n"
6
- "Last-Translator: studio RVOLA <hello@rvola.com>\n"
7
- "Language-Team: Pro Style <info@prostyle.ir>\n"
8
- "Language: fa_IR\n"
9
- "MIME-Version: 1.0\n"
10
- "Content-Type: text/plain; charset=UTF-8\n"
11
- "Content-Transfer-Encoding: 8bit\n"
12
- "X-Generator: Poedit 1.8.8\n"
13
- "X-Poedit-Basepath: ..\n"
14
- "Plural-Forms: nplurals=2; plural=(n > 1);\n"
15
- "X-Poedit-SourceCharset: UTF-8\n"
16
- "X-Poedit-KeywordsList: __;_e\n"
17
- "X-Poedit-SearchPath-0: .\n"
18
-
19
- #: github-checker.php:120
20
- msgid "There is no changelog available."
21
- msgstr "شرحی برای تغییرات یافت نشد"
22
-
23
- #: plugin-update-checker.php:637
24
- msgid "Check for updates"
25
- msgstr "بررسی برای بروزرسانی "
26
-
27
- #: plugin-update-checker.php:681
28
- msgid "This plugin is up to date."
29
- msgstr "شما از آخرین نسخه استفاده میکنید . به‌روز باشید"
30
-
31
- #: plugin-update-checker.php:683
32
- msgid "A new version of this plugin is available."
33
- msgstr "نسخه جدیدی برای افزونه ارائه شده است ."
34
-
35
- #: plugin-update-checker.php:685
36
- #, php-format
37
- msgid "Unknown update checker status \"%s\""
38
- msgstr "وضعیت ناشناخته برای بروزرسانی \"%s\""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/languages/plugin-update-checker-fr_FR.mo DELETED
Binary file
plugin-update-checker/languages/plugin-update-checker-fr_FR.po DELETED
@@ -1,38 +0,0 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: plugin-update-checker\n"
4
- "POT-Creation-Date: 2016-02-17 14:21+0100\n"
5
- "PO-Revision-Date: 2016-08-04 21:08+0200\n"
6
- "Last-Translator: studio RVOLA <hello@rvola.com>\n"
7
- "Language-Team: studio RVOLA <http://www.rvola.com>\n"
8
- "Language: fr_FR\n"
9
- "MIME-Version: 1.0\n"
10
- "Content-Type: text/plain; charset=UTF-8\n"
11
- "Content-Transfer-Encoding: 8bit\n"
12
- "X-Generator: Poedit 1.8.8\n"
13
- "X-Poedit-Basepath: ..\n"
14
- "Plural-Forms: nplurals=2; plural=(n > 1);\n"
15
- "X-Poedit-SourceCharset: UTF-8\n"
16
- "X-Poedit-KeywordsList: __;_e\n"
17
- "X-Poedit-SearchPath-0: .\n"
18
-
19
- #: github-checker.php:120
20
- msgid "There is no changelog available."
21
- msgstr "Il n’y a aucun journal de mise à jour disponible."
22
-
23
- #: plugin-update-checker.php:637
24
- msgid "Check for updates"
25
- msgstr "Vérifier les mises à jour"
26
-
27
- #: plugin-update-checker.php:681
28
- msgid "This plugin is up to date."
29
- msgstr "Cette extension est à jour."
30
-
31
- #: plugin-update-checker.php:683
32
- msgid "A new version of this plugin is available."
33
- msgstr "Une nouvelle version de cette extension est disponible."
34
-
35
- #: plugin-update-checker.php:685
36
- #, php-format
37
- msgid "Unknown update checker status \"%s\""
38
- msgstr "Un problème inconnu est survenu \"%s\""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/languages/plugin-update-checker-hu_HU.mo DELETED
Binary file
plugin-update-checker/languages/plugin-update-checker-hu_HU.po DELETED
@@ -1,41 +0,0 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: plugin-update-checker\n"
4
- "POT-Creation-Date: 2016-01-11 21:23+0100\n"
5
- "PO-Revision-Date: 2016-01-11 21:25+0100\n"
6
- "Last-Translator: Tamás András Horváth <htomy92@gmail.com>\n"
7
- "Language-Team: \n"
8
- "Language: hu_HU\n"
9
- "MIME-Version: 1.0\n"
10
- "Content-Type: text/plain; charset=UTF-8\n"
11
- "Content-Transfer-Encoding: 8bit\n"
12
- "X-Generator: Poedit 1.8.6\n"
13
- "X-Poedit-Basepath: ..\n"
14
- "Plural-Forms: nplurals=2; plural=(n != 1);\n"
15
- "X-Poedit-SourceCharset: UTF-8\n"
16
- "X-Poedit-KeywordsList: __;_e\n"
17
- "X-Poedit-SearchPath-0: .\n"
18
-
19
- #: github-checker.php:137
20
- msgid "There is no changelog available."
21
- msgstr "Nem érhető el a changelog."
22
-
23
- #: plugin-update-checker.php:852
24
- msgid "Check for updates"
25
- msgstr "Frissítés ellenőrzése"
26
-
27
- #: plugin-update-checker.php:896
28
- msgid "This plugin is up to date."
29
- msgstr "Ez a plugin naprakész."
30
-
31
- #: plugin-update-checker.php:898
32
- msgid "A new version of this plugin is available."
33
- msgstr "Új verzió érhető el a kiegészítőhöz"
34
-
35
- #: plugin-update-checker.php:900
36
- #, php-format
37
- msgid "Unknown update checker status \"%s\""
38
- msgstr "Ismeretlen a frissítés ellenőrző státusza \"%s\""
39
-
40
- #~ msgid "Every %d hours"
41
- #~ msgstr "Minden %d órában"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/languages/plugin-update-checker.pot DELETED
@@ -1,39 +0,0 @@
1
- #, fuzzy
2
- msgid ""
3
- msgstr ""
4
- "Project-Id-Version: plugin-update-checker\n"
5
- "POT-Creation-Date: 2016-01-11 21:22+0100\n"
6
- "PO-Revision-Date: 2016-01-10 20:59+0100\n"
7
- "Last-Translator: Tamás András Horváth <htomy92@gmail.com>\n"
8
- "Language-Team: \n"
9
- "Language: en_US\n"
10
- "MIME-Version: 1.0\n"
11
- "Content-Type: text/plain; charset=UTF-8\n"
12
- "Content-Transfer-Encoding: 8bit\n"
13
- "X-Generator: Poedit 1.8.6\n"
14
- "X-Poedit-Basepath: ..\n"
15
- "Plural-Forms: nplurals=2; plural=(n != 1);\n"
16
- "X-Poedit-SourceCharset: UTF-8\n"
17
- "X-Poedit-KeywordsList: __;_e\n"
18
- "X-Poedit-SearchPath-0: .\n"
19
-
20
- #: github-checker.php:137
21
- msgid "There is no changelog available."
22
- msgstr ""
23
-
24
- #: plugin-update-checker.php:852
25
- msgid "Check for updates"
26
- msgstr ""
27
-
28
- #: plugin-update-checker.php:896
29
- msgid "This plugin is up to date."
30
- msgstr ""
31
-
32
- #: plugin-update-checker.php:898
33
- msgid "A new version of this plugin is available."
34
- msgstr ""
35
-
36
- #: plugin-update-checker.php:900
37
- #, php-format
38
- msgid "Unknown update checker status \"%s\""
39
- msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/license.txt DELETED
@@ -1,7 +0,0 @@
1
- Copyright (c) 2014 Jānis Elsts
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
-
5
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
-
7
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 
 
 
 
 
plugin-update-checker/plugin-update-checker.php DELETED
@@ -1,1663 +0,0 @@
1
- <?php
2
- /**
3
- * Plugin Update Checker Library 3.2
4
- * http://w-shadow.com/
5
- *
6
- * Copyright 2016 Janis Elsts
7
- * Released under the MIT license. See license.txt for details.
8
- */
9
-
10
- if ( !class_exists('PluginUpdateChecker_3_2', false) ):
11
-
12
- /**
13
- * A custom plugin update checker.
14
- *
15
- * @author Janis Elsts
16
- * @copyright 2016
17
- * @version 3.2
18
- * @access public
19
- */
20
- class PluginUpdateChecker_3_2 {
21
- public $metadataUrl = ''; //The URL of the plugin's metadata file.
22
- public $pluginAbsolutePath = ''; //Full path of the main plugin file.
23
- public $pluginFile = ''; //Plugin filename relative to the plugins directory. Many WP APIs use this to identify plugins.
24
- public $slug = ''; //Plugin slug.
25
- public $optionName = ''; //Where to store the update info.
26
- public $muPluginFile = ''; //For MU plugins, the plugin filename relative to the mu-plugins directory.
27
-
28
- public $debugMode = false; //Set to TRUE to enable error reporting. Errors are raised using trigger_error()
29
- //and should be logged to the standard PHP error log.
30
- public $scheduler;
31
-
32
- protected $upgraderStatus;
33
-
34
- private $debugBarPlugin = null;
35
- private $cachedInstalledVersion = null;
36
-
37
- private $metadataHost = ''; //The host component of $metadataUrl.
38
-
39
- /**
40
- * Class constructor.
41
- *
42
- * @param string $metadataUrl The URL of the plugin's metadata file.
43
- * @param string $pluginFile Fully qualified path to the main plugin file.
44
- * @param string $slug The plugin's 'slug'. If not specified, the filename part of $pluginFile sans '.php' will be used as the slug.
45
- * @param integer $checkPeriod How often to check for updates (in hours). Defaults to checking every 12 hours. Set to 0 to disable automatic update checks.
46
- * @param string $optionName Where to store book-keeping info about update checks. Defaults to 'external_updates-$slug'.
47
- * @param string $muPluginFile Optional. The plugin filename relative to the mu-plugins directory.
48
- */
49
- public function __construct($metadataUrl, $pluginFile, $slug = '', $checkPeriod = 12, $optionName = '', $muPluginFile = ''){
50
- $this->metadataUrl = $metadataUrl;
51
- $this->pluginAbsolutePath = $pluginFile;
52
- $this->pluginFile = plugin_basename($this->pluginAbsolutePath);
53
- $this->muPluginFile = $muPluginFile;
54
- $this->slug = $slug;
55
- $this->optionName = $optionName;
56
- $this->debugMode = (bool)(constant('WP_DEBUG'));
57
-
58
- //If no slug is specified, use the name of the main plugin file as the slug.
59
- //For example, 'my-cool-plugin/cool-plugin.php' becomes 'cool-plugin'.
60
- if ( empty($this->slug) ){
61
- $this->slug = basename($this->pluginFile, '.php');
62
- }
63
-
64
- //Plugin slugs must be unique.
65
- $slugCheckFilter = 'puc_is_slug_in_use-' . $this->slug;
66
- $slugUsedBy = apply_filters($slugCheckFilter, false);
67
- if ( $slugUsedBy ) {
68
- $this->triggerError(sprintf(
69
- 'Plugin slug "%s" is already in use by %s. Slugs must be unique.',
70
- htmlentities($this->slug),
71
- htmlentities($slugUsedBy)
72
- ), E_USER_ERROR);
73
- }
74
- add_filter($slugCheckFilter, array($this, 'getAbsolutePath'));
75
-
76
-
77
- if ( empty($this->optionName) ){
78
- $this->optionName = 'external_updates-' . $this->slug;
79
- }
80
-
81
- //Backwards compatibility: If the plugin is a mu-plugin but no $muPluginFile is specified, assume
82
- //it's the same as $pluginFile given that it's not in a subdirectory (WP only looks in the base dir).
83
- if ( (strpbrk($this->pluginFile, '/\\') === false) && $this->isUnknownMuPlugin() ) {
84
- $this->muPluginFile = $this->pluginFile;
85
- }
86
-
87
- $this->scheduler = $this->createScheduler($checkPeriod);
88
- $this->upgraderStatus = new PucUpgraderStatus_3_2();
89
-
90
- $this->installHooks();
91
- }
92
-
93
- /**
94
- * Create an instance of the scheduler.
95
- *
96
- * This is implemented as a method to make it possible for plugins to subclass the update checker
97
- * and substitute their own scheduler.
98
- *
99
- * @param int $checkPeriod
100
- * @return PucScheduler_3_2
101
- */
102
- protected function createScheduler($checkPeriod) {
103
- return new PucScheduler_3_2($this, $checkPeriod);
104
- }
105
-
106
- /**
107
- * Install the hooks required to run periodic update checks and inject update info
108
- * into WP data structures.
109
- *
110
- * @return void
111
- */
112
- protected function installHooks(){
113
- //Override requests for plugin information
114
- add_filter('plugins_api', array($this, 'injectInfo'), 20, 3);
115
-
116
- //Insert our update info into the update array maintained by WP.
117
- add_filter('site_transient_update_plugins', array($this,'injectUpdate')); //WP 3.0+
118
- add_filter('transient_update_plugins', array($this,'injectUpdate')); //WP 2.8+
119
- add_filter('site_transient_update_plugins', array($this, 'injectTranslationUpdates'));
120
-
121
- add_filter('plugin_row_meta', array($this, 'addCheckForUpdatesLink'), 10, 2);
122
- add_action('admin_init', array($this, 'handleManualCheck'));
123
- add_action('all_admin_notices', array($this, 'displayManualCheckResult'));
124
-
125
- //Clear the version number cache when something - anything - is upgraded or WP clears the update cache.
126
- add_filter('upgrader_post_install', array($this, 'clearCachedVersion'));
127
- add_action('delete_site_transient_update_plugins', array($this, 'clearCachedVersion'));
128
- //Clear translation updates when WP clears the update cache.
129
- //This needs to be done directly because the library doesn't actually remove obsolete plugin updates,
130
- //it just hides them (see getUpdate()). We can't do that with translations - too much disk I/O.
131
- add_action('delete_site_transient_update_plugins', array($this, 'clearCachedTranslationUpdates'));
132
-
133
- if ( did_action('plugins_loaded') ) {
134
- $this->initDebugBarPanel();
135
- } else {
136
- add_action('plugins_loaded', array($this, 'initDebugBarPanel'));
137
- }
138
-
139
- //Rename the update directory to be the same as the existing directory.
140
- add_filter('upgrader_source_selection', array($this, 'fixDirectoryName'), 10, 3);
141
-
142
- //Enable language support (i18n).
143
- load_plugin_textdomain('plugin-update-checker', false, plugin_basename(dirname(__FILE__)) . '/languages');
144
-
145
- //Allow HTTP requests to the metadata URL even if it's on a local host.
146
- $this->metadataHost = @parse_url($this->metadataUrl, PHP_URL_HOST);
147
- add_filter('http_request_host_is_external', array($this, 'allowMetadataHost'), 10, 2);
148
- }
149
-
150
- /**
151
- * Explicitly allow HTTP requests to the metadata URL.
152
- *
153
- * WordPress has a security feature where the HTTP API will reject all requests that are sent to
154
- * another site hosted on the same server as the current site (IP match), a local host, or a local
155
- * IP, unless the host exactly matches the current site.
156
- *
157
- * This feature is opt-in (at least in WP 4.4). Apparently some people enable it.
158
- *
159
- * That can be a problem when you're developing your plugin and you decide to host the update information
160
- * on the same server as your test site. Update requests will mysteriously fail.
161
- *
162
- * We fix that by adding an exception for the metadata host.
163
- *
164
- * @param bool $allow
165
- * @param string $host
166
- * @return bool
167
- */
168
- public function allowMetadataHost($allow, $host) {
169
- if ( strtolower($host) === strtolower($this->metadataHost) ) {
170
- return true;
171
- }
172
- return $allow;
173
- }
174
-
175
- /**
176
- * Retrieve plugin info from the configured API endpoint.
177
- *
178
- * @uses wp_remote_get()
179
- *
180
- * @param array $queryArgs Additional query arguments to append to the request. Optional.
181
- * @return PluginInfo_3_2
182
- */
183
- public function requestInfo($queryArgs = array()){
184
- //Query args to append to the URL. Plugins can add their own by using a filter callback (see addQueryArgFilter()).
185
- $installedVersion = $this->getInstalledVersion();
186
- $queryArgs['installed_version'] = ($installedVersion !== null) ? $installedVersion : '';
187
- $queryArgs = apply_filters('puc_request_info_query_args-'.$this->slug, $queryArgs);
188
-
189
- //Various options for the wp_remote_get() call. Plugins can filter these, too.
190
- $options = array(
191
- 'timeout' => 10, //seconds
192
- 'headers' => array(
193
- 'Accept' => 'application/json'
194
- ),
195
- );
196
- $options = apply_filters('puc_request_info_options-'.$this->slug, $options);
197
-
198
- //The plugin info should be at 'http://your-api.com/url/here/$slug/info.json'
199
- $url = $this->metadataUrl;
200
- if ( !empty($queryArgs) ){
201
- $url = add_query_arg($queryArgs, $url);
202
- }
203
-
204
- $result = wp_remote_get(
205
- $url,
206
- $options
207
- );
208
-
209
- //Try to parse the response
210
- $status = $this->validateApiResponse($result);
211
- $pluginInfo = null;
212
- if ( !is_wp_error($status) ){
213
- $pluginInfo = PluginInfo_3_2::fromJson($result['body']);
214
- if ( $pluginInfo !== null ) {
215
- $pluginInfo->filename = $this->pluginFile;
216
- $pluginInfo->slug = $this->slug;
217
- }
218
- } else {
219
- $this->triggerError(
220
- sprintf('The URL %s does not point to a valid plugin metadata file. ', $url)
221
- . $status->get_error_message(),
222
- E_USER_WARNING
223
- );
224
- }
225
-
226
- $pluginInfo = apply_filters('puc_request_info_result-'.$this->slug, $pluginInfo, $result);
227
- return $pluginInfo;
228
- }
229
-
230
- /**
231
- * Check if $result is a successful update API response.
232
- *
233
- * @param array|WP_Error $result
234
- * @return true|WP_Error
235
- */
236
- private function validateApiResponse($result) {
237
- if ( is_wp_error($result) ) { /** @var WP_Error $result */
238
- return new WP_Error($result->get_error_code(), 'WP HTTP Error: ' . $result->get_error_message());
239
- }
240
-
241
- if ( !isset($result['response']['code']) ) {
242
- return new WP_Error('puc_no_response_code', 'wp_remote_get() returned an unexpected result.');
243
- }
244
-
245
- if ( $result['response']['code'] !== 200 ) {
246
- return new WP_Error(
247
- 'puc_unexpected_response_code',
248
- 'HTTP response code is ' . $result['response']['code'] . ' (expected: 200)'
249
- );
250
- }
251
-
252
- if ( empty($result['body']) ) {
253
- return new WP_Error('puc_empty_response', 'The metadata file appears to be empty.');
254
- }
255
-
256
- return true;
257
- }
258
-
259
- /**
260
- * Retrieve the latest update (if any) from the configured API endpoint.
261
- *
262
- * @uses PluginUpdateChecker::requestInfo()
263
- *
264
- * @return PluginUpdate_3_2 An instance of PluginUpdate, or NULL when no updates are available.
265
- */
266
- public function requestUpdate(){
267
- //For the sake of simplicity, this function just calls requestInfo()
268
- //and transforms the result accordingly.
269
- $pluginInfo = $this->requestInfo(array('checking_for_updates' => '1'));
270
- if ( $pluginInfo == null ){
271
- return null;
272
- }
273
- $update = PluginUpdate_3_2::fromPluginInfo($pluginInfo);
274
-
275
- //Keep only those translation updates that apply to this site.
276
- $update->translations = $this->filterApplicableTranslations($update->translations);
277
-
278
- return $update;
279
- }
280
-
281
- /**
282
- * Filter a list of translation updates and return a new list that contains only updates
283
- * that apply to the current site.
284
- *
285
- * @param array $translations
286
- * @return array
287
- */
288
- private function filterApplicableTranslations($translations) {
289
- $languages = array_flip(array_values(get_available_languages()));
290
- $installedTranslations = wp_get_installed_translations('plugins');
291
- if ( isset($installedTranslations[$this->slug]) ) {
292
- $installedTranslations = $installedTranslations[$this->slug];
293
- } else {
294
- $installedTranslations = array();
295
- }
296
-
297
- $applicableTranslations = array();
298
- foreach($translations as $translation) {
299
- //Does it match one of the available core languages?
300
- $isApplicable = array_key_exists($translation->language, $languages);
301
- //Is it more recent than an already-installed translation?
302
- if ( isset($installedTranslations[$translation->language]) ) {
303
- $updateTimestamp = strtotime($translation->updated);
304
- $installedTimestamp = strtotime($installedTranslations[$translation->language]['PO-Revision-Date']);
305
- $isApplicable = $updateTimestamp > $installedTimestamp;
306
- }
307
-
308
- if ( $isApplicable ) {
309
- $applicableTranslations[] = $translation;
310
- }
311
- }
312
-
313
- return $applicableTranslations;
314
- }
315
-
316
- /**
317
- * Get the currently installed version of the plugin.
318
- *
319
- * @return string Version number.
320
- */
321
- public function getInstalledVersion(){
322
- if ( isset($this->cachedInstalledVersion) ) {
323
- return $this->cachedInstalledVersion;
324
- }
325
-
326
- $pluginHeader = $this->getPluginHeader();
327
- if ( isset($pluginHeader['Version']) ) {
328
- $this->cachedInstalledVersion = $pluginHeader['Version'];
329
- return $pluginHeader['Version'];
330
- } else {
331
- //This can happen if the filename points to something that is not a plugin.
332
- $this->triggerError(
333
- sprintf(
334
- "Can't to read the Version header for '%s'. The filename is incorrect or is not a plugin.",
335
- $this->pluginFile
336
- ),
337
- E_USER_WARNING
338
- );
339
- return null;
340
- }
341
- }
342
-
343
- /**
344
- * Get plugin's metadata from its file header.
345
- *
346
- * @return array
347
- */
348
- protected function getPluginHeader() {
349
- if ( !is_file($this->pluginAbsolutePath) ) {
350
- //This can happen if the plugin filename is wrong.
351
- $this->triggerError(
352
- sprintf(
353
- "Can't to read the plugin header for '%s'. The file does not exist.",
354
- $this->pluginFile
355
- ),
356
- E_USER_WARNING
357
- );
358
- return array();
359
- }
360
-
361
- if ( !function_exists('get_plugin_data') ){
362
- /** @noinspection PhpIncludeInspection */
363
- require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
364
- }
365
- return get_plugin_data($this->pluginAbsolutePath, false, false);
366
- }
367
-
368
- /**
369
- * Check for plugin updates.
370
- * The results are stored in the DB option specified in $optionName.
371
- *
372
- * @return PluginUpdate_3_2|null
373
- */
374
- public function checkForUpdates(){
375
- $installedVersion = $this->getInstalledVersion();
376
- //Fail silently if we can't find the plugin or read its header.
377
- if ( $installedVersion === null ) {
378
- $this->triggerError(
379
- sprintf('Skipping update check for %s - installed version unknown.', $this->pluginFile),
380
- E_USER_WARNING
381
- );
382
- return null;
383
- }
384
-
385
- $state = $this->getUpdateState();
386
- if ( empty($state) ){
387
- $state = new stdClass;
388
- $state->lastCheck = 0;
389
- $state->checkedVersion = '';
390
- $state->update = null;
391
- }
392
-
393
- $state->lastCheck = time();
394
- $state->checkedVersion = $installedVersion;
395
- $this->setUpdateState($state); //Save before checking in case something goes wrong
396
-
397
- $state->update = $this->requestUpdate();
398
- $this->setUpdateState($state);
399
-
400
- return $this->getUpdate();
401
- }
402
-
403
- /**
404
- * Load the update checker state from the DB.
405
- *
406
- * @return stdClass|null
407
- */
408
- public function getUpdateState() {
409
- $state = get_site_option($this->optionName, null);
410
- if ( empty($state) || !is_object($state)) {
411
- $state = null;
412
- }
413
-
414
- if ( isset($state, $state->update) && is_object($state->update) ) {
415
- $state->update = PluginUpdate_3_2::fromObject($state->update);
416
- }
417
- return $state;
418
- }
419
-
420
-
421
- /**
422
- * Persist the update checker state to the DB.
423
- *
424
- * @param StdClass $state
425
- * @return void
426
- */
427
- private function setUpdateState($state) {
428
- if ( isset($state->update) && is_object($state->update) && method_exists($state->update, 'toStdClass') ) {
429
- $update = $state->update; /** @var PluginUpdate_3_2 $update */
430
- $state->update = $update->toStdClass();
431
- }
432
- update_site_option($this->optionName, $state);
433
- }
434
-
435
- /**
436
- * Reset update checker state - i.e. last check time, cached update data and so on.
437
- *
438
- * Call this when your plugin is being uninstalled, or if you want to
439
- * clear the update cache.
440
- */
441
- public function resetUpdateState() {
442
- delete_site_option($this->optionName);
443
- }
444
-
445
- /**
446
- * Intercept plugins_api() calls that request information about our plugin and
447
- * use the configured API endpoint to satisfy them.
448
- *
449
- * @see plugins_api()
450
- *
451
- * @param mixed $result
452
- * @param string $action
453
- * @param array|object $args
454
- * @return mixed
455
- */
456
- public function injectInfo($result, $action = null, $args = null){
457
- $relevant = ($action == 'plugin_information') && isset($args->slug) && (
458
- ($args->slug == $this->slug) || ($args->slug == dirname($this->pluginFile))
459
- );
460
- if ( !$relevant ) {
461
- return $result;
462
- }
463
-
464
- $pluginInfo = $this->requestInfo();
465
- $pluginInfo = apply_filters('puc_pre_inject_info-' . $this->slug, $pluginInfo);
466
- if ( $pluginInfo ) {
467
- return $pluginInfo->toWpFormat();
468
- }
469
-
470
- return $result;
471
- }
472
-
473
- /**
474
- * Insert the latest update (if any) into the update list maintained by WP.
475
- *
476
- * @param StdClass $updates Update list.
477
- * @return StdClass Modified update list.
478
- */
479
- public function injectUpdate($updates){
480
- //Is there an update to insert?
481
- $update = $this->getUpdate();
482
-
483
- //No update notifications for mu-plugins unless explicitly enabled. The MU plugin file
484
- //is usually different from the main plugin file so the update wouldn't show up properly anyway.
485
- if ( $this->isUnknownMuPlugin() ) {
486
- $update = null;
487
- }
488
-
489
- if ( !empty($update) ) {
490
- //Let plugins filter the update info before it's passed on to WordPress.
491
- $update = apply_filters('puc_pre_inject_update-' . $this->slug, $update);
492
- $updates = $this->addUpdateToList($updates, $update);
493
- } else {
494
- //Clean up any stale update info.
495
- $updates = $this->removeUpdateFromList($updates);
496
- }
497
-
498
- return $updates;
499
- }
500
-
501
- /**
502
- * @param StdClass|null $updates
503
- * @param PluginUpdate_3_2 $updateToAdd
504
- * @return StdClass
505
- */
506
- private function addUpdateToList($updates, $updateToAdd) {
507
- if ( !is_object($updates) ) {
508
- $updates = new stdClass();
509
- $updates->response = array();
510
- }
511
-
512
- $wpUpdate = $updateToAdd->toWpFormat();
513
- $pluginFile = $this->pluginFile;
514
-
515
- if ( $this->isMuPlugin() ) {
516
- //WP does not support automatic update installation for mu-plugins, but we can still display a notice.
517
- $wpUpdate->package = null;
518
- $pluginFile = $this->muPluginFile;
519
- }
520
- $updates->response[$pluginFile] = $wpUpdate;
521
- return $updates;
522
- }
523
-
524
- /**
525
- * @param stdClass|null $updates
526
- * @return stdClass|null
527
- */
528
- private function removeUpdateFromList($updates) {
529
- if ( isset($updates, $updates->response) ) {
530
- unset($updates->response[$this->pluginFile]);
531
- if ( !empty($this->muPluginFile) ) {
532
- unset($updates->response[$this->muPluginFile]);
533
- }
534
- }
535
- return $updates;
536
- }
537
-
538
- /**
539
- * Insert translation updates into the list maintained by WordPress.
540
- *
541
- * @param stdClass $updates
542
- * @return stdClass
543
- */
544
- public function injectTranslationUpdates($updates) {
545
- $translationUpdates = $this->getTranslationUpdates();
546
- if ( empty($translationUpdates) ) {
547
- return $updates;
548
- }
549
-
550
- //Being defensive.
551
- if ( !is_object($updates) ) {
552
- $updates = new stdClass();
553
- }
554
- if ( !isset($updates->translations) ) {
555
- $updates->translations = array();
556
- }
557
-
558
- //In case there's a name collision with a plugin hosted on wordpress.org,
559
- //remove any preexisting updates that match our plugin.
560
- $translationType = 'plugin';
561
- $filteredTranslations = array();
562
- foreach($updates->translations as $translation) {
563
- if ( ($translation['type'] === $translationType) && ($translation['slug'] === $this->slug) ) {
564
- continue;
565
- }
566
- $filteredTranslations[] = $translation;
567
- }
568
- $updates->translations = $filteredTranslations;
569
-
570
- //Add our updates to the list.
571
- foreach($translationUpdates as $update) {
572
- $convertedUpdate = array_merge(
573
- array(
574
- 'type' => $translationType,
575
- 'slug' => $this->slug,
576
- 'autoupdate' => 0,
577
- //AFAICT, WordPress doesn't actually use the "version" field for anything.
578
- //But lets make sure it's there, just in case.
579
- 'version' => isset($update->version) ? $update->version : ('1.' . strtotime($update->updated)),
580
- ),
581
- (array)$update
582
- );
583
-
584
- $updates->translations[] = $convertedUpdate;
585
- }
586
-
587
- return $updates;
588
- }
589
-
590
- /**
591
- * Rename the update directory to match the existing plugin directory.
592
- *
593
- * When WordPress installs a plugin or theme update, it assumes that the ZIP file will contain
594
- * exactly one directory, and that the directory name will be the same as the directory where
595
- * the plugin/theme is currently installed.
596
- *
597
- * GitHub and other repositories provide ZIP downloads, but they often use directory names like
598
- * "project-branch" or "project-tag-hash". We need to change the name to the actual plugin folder.
599
- *
600
- * This is a hook callback. Don't call it from a plugin.
601
- *
602
- * @param string $source The directory to copy to /wp-content/plugins. Usually a subdirectory of $remoteSource.
603
- * @param string $remoteSource WordPress has extracted the update to this directory.
604
- * @param WP_Upgrader $upgrader
605
- * @return string|WP_Error
606
- */
607
- public function fixDirectoryName($source, $remoteSource, $upgrader) {
608
- global $wp_filesystem; /** @var WP_Filesystem_Base $wp_filesystem */
609
-
610
- //Basic sanity checks.
611
- if ( !isset($source, $remoteSource, $upgrader, $upgrader->skin, $wp_filesystem) ) {
612
- return $source;
613
- }
614
-
615
- //If WordPress is upgrading anything other than our plugin, leave the directory name unchanged.
616
- if ( !$this->isPluginBeingUpgraded($upgrader) ) {
617
- return $source;
618
- }
619
-
620
- //Rename the source to match the existing plugin directory.
621
- $pluginDirectoryName = dirname($this->pluginFile);
622
- if ( $pluginDirectoryName === '.' ) {
623
- return $source;
624
- }
625
- $correctedSource = trailingslashit($remoteSource) . $pluginDirectoryName . '/';
626
- if ( $source !== $correctedSource ) {
627
- //The update archive should contain a single directory that contains the rest of plugin files. Otherwise,
628
- //WordPress will try to copy the entire working directory ($source == $remoteSource). We can't rename
629
- //$remoteSource because that would break WordPress code that cleans up temporary files after update.
630
- if ( $this->isBadDirectoryStructure($remoteSource) ) {
631
- return new WP_Error(
632
- 'puc-incorrect-directory-structure',
633
- sprintf(
634
- 'The directory structure of the update is incorrect. All plugin files should be inside ' .
635
- 'a directory named <span class="code">%s</span>, not at the root of the ZIP file.',
636
- htmlentities($this->slug)
637
- )
638
- );
639
- }
640
-
641
- /** @var WP_Upgrader_Skin $upgrader->skin */
642
- $upgrader->skin->feedback(sprintf(
643
- 'Renaming %s to %s&#8230;',
644
- '<span class="code">' . basename($source) . '</span>',
645
- '<span class="code">' . $pluginDirectoryName . '</span>'
646
- ));
647
-
648
- if ( $wp_filesystem->move($source, $correctedSource, true) ) {
649
- $upgrader->skin->feedback('Plugin directory successfully renamed.');
650
- return $correctedSource;
651
- } else {
652
- return new WP_Error(
653
- 'puc-rename-failed',
654
- 'Unable to rename the update to match the existing plugin directory.'
655
- );
656
- }
657
- }
658
-
659
- return $source;
660
- }
661
-
662
- /**
663
- * Check for incorrect update directory structure. An update must contain a single directory,
664
- * all other files should be inside that directory.
665
- *
666
- * @param string $remoteSource Directory path.
667
- * @return bool
668
- */
669
- private function isBadDirectoryStructure($remoteSource) {
670
- global $wp_filesystem; /** @var WP_Filesystem_Base $wp_filesystem */
671
-
672
- $sourceFiles = $wp_filesystem->dirlist($remoteSource);
673
- if ( is_array($sourceFiles) ) {
674
- $sourceFiles = array_keys($sourceFiles);
675
- $firstFilePath = trailingslashit($remoteSource) . $sourceFiles[0];
676
- return (count($sourceFiles) > 1) || (!$wp_filesystem->is_dir($firstFilePath));
677
- }
678
-
679
- //Assume it's fine.
680
- return false;
681
- }
682
-
683
- /**
684
- * Is there and update being installed RIGHT NOW, for this specific plugin?
685
- *
686
- * @param WP_Upgrader|null $upgrader The upgrader that's performing the current update.
687
- * @return bool
688
- */
689
- public function isPluginBeingUpgraded($upgrader = null) {
690
- return $this->upgraderStatus->isPluginBeingUpgraded($this->pluginFile, $upgrader);
691
- }
692
-
693
- /**
694
- * Get the details of the currently available update, if any.
695
- *
696
- * If no updates are available, or if the last known update version is below or equal
697
- * to the currently installed version, this method will return NULL.
698
- *
699
- * Uses cached update data. To retrieve update information straight from
700
- * the metadata URL, call requestUpdate() instead.
701
- *
702
- * @return PluginUpdate_3_2|null
703
- */
704
- public function getUpdate() {
705
- $state = $this->getUpdateState(); /** @var StdClass $state */
706
-
707
- //Is there an update available?
708
- if ( isset($state, $state->update) ) {
709
- $update = $state->update;
710
- //Check if the update is actually newer than the currently installed version.
711
- $installedVersion = $this->getInstalledVersion();
712
- if ( ($installedVersion !== null) && version_compare($update->version, $installedVersion, '>') ){
713
- $update->filename = $this->pluginFile;
714
- return $update;
715
- }
716
- }
717
- return null;
718
- }
719
-
720
- /**
721
- * Get a list of available translation updates.
722
- *
723
- * This method will return an empty array if there are no updates.
724
- * Uses cached update data.
725
- *
726
- * @return array
727
- */
728
- public function getTranslationUpdates() {
729
- $state = $this->getUpdateState();
730
- if ( isset($state, $state->update, $state->update->translations) ) {
731
- return $state->update->translations;
732
- }
733
- return array();
734
- }
735
-
736
- /**
737
- * Remove all cached translation updates.
738
- *
739
- * @see wp_clean_update_cache
740
- */
741
- public function clearCachedTranslationUpdates() {
742
- $state = $this->getUpdateState();
743
- if ( isset($state, $state->update, $state->update->translations) ) {
744
- $state->update->translations = array();
745
- $this->setUpdateState($state);
746
- }
747
- }
748
-
749
- /**
750
- * Add a "Check for updates" link to the plugin row in the "Plugins" page. By default,
751
- * the new link will appear after the "Visit plugin site" link.
752
- *
753
- * You can change the link text by using the "puc_manual_check_link-$slug" filter.
754
- * Returning an empty string from the filter will disable the link.
755
- *
756
- * @param array $pluginMeta Array of meta links.
757
- * @param string $pluginFile
758
- * @return array
759
- */
760
- public function addCheckForUpdatesLink($pluginMeta, $pluginFile) {
761
- $isRelevant = ($pluginFile == $this->pluginFile)
762
- || (!empty($this->muPluginFile) && $pluginFile == $this->muPluginFile);
763
-
764
- if ( $isRelevant && current_user_can('update_plugins') ) {
765
- $linkUrl = wp_nonce_url(
766
- add_query_arg(
767
- array(
768
- 'puc_check_for_updates' => 1,
769
- 'puc_slug' => $this->slug,
770
- ),
771
- self_admin_url('plugins.php')
772
- ),
773
- 'puc_check_for_updates'
774
- );
775
-
776
- $linkText = apply_filters('puc_manual_check_link-' . $this->slug, __('Check for updates', 'plugin-update-checker'));
777
- if ( !empty($linkText) ) {
778
- $pluginMeta[] = sprintf('<a href="%s">%s</a>', esc_attr($linkUrl), $linkText);
779
- }
780
- }
781
- return $pluginMeta;
782
- }
783
-
784
- /**
785
- * Check for updates when the user clicks the "Check for updates" link.
786
- * @see self::addCheckForUpdatesLink()
787
- *
788
- * @return void
789
- */
790
- public function handleManualCheck() {
791
- $shouldCheck =
792
- isset($_GET['puc_check_for_updates'], $_GET['puc_slug'])
793
- && $_GET['puc_slug'] == $this->slug
794
- && current_user_can('update_plugins')
795
- && check_admin_referer('puc_check_for_updates');
796
-
797
- if ( $shouldCheck ) {
798
- $update = $this->checkForUpdates();
799
- $status = ($update === null) ? 'no_update' : 'update_available';
800
- wp_redirect(add_query_arg(
801
- array(
802
- 'puc_update_check_result' => $status,
803
- 'puc_slug' => $this->slug,
804
- ),
805
- self_admin_url('plugins.php')
806
- ));
807
- }
808
- }
809
-
810
- /**
811
- * Display the results of a manual update check.
812
- * @see self::handleManualCheck()
813
- *
814
- * You can change the result message by using the "puc_manual_check_message-$slug" filter.
815
- */
816
- public function displayManualCheckResult() {
817
- if ( isset($_GET['puc_update_check_result'], $_GET['puc_slug']) && ($_GET['puc_slug'] == $this->slug) ) {
818
- $status = strval($_GET['puc_update_check_result']);
819
- if ( $status == 'no_update' ) {
820
- $message = __('This plugin is up to date.', 'plugin-update-checker');
821
- } else if ( $status == 'update_available' ) {
822
- $message = __('A new version of this plugin is available.', 'plugin-update-checker');
823
- } else {
824
- $message = sprintf(__('Unknown update checker status "%s"', 'plugin-update-checker'), htmlentities($status));
825
- }
826
- printf(
827
- '<div class="updated notice is-dismissible"><p>%s</p></div>',
828
- apply_filters('puc_manual_check_message-' . $this->slug, $message, $status)
829
- );
830
- }
831
- }
832
-
833
- /**
834
- * Check if the plugin file is inside the mu-plugins directory.
835
- *
836
- * @return bool
837
- */
838
- protected function isMuPlugin() {
839
- static $cachedResult = null;
840
-
841
- if ( $cachedResult === null ) {
842
- //Convert both paths to the canonical form before comparison.
843
- $muPluginDir = realpath(WPMU_PLUGIN_DIR);
844
- $pluginPath = realpath($this->pluginAbsolutePath);
845
-
846
- $cachedResult = (strpos($pluginPath, $muPluginDir) === 0);
847
- }
848
-
849
- return $cachedResult;
850
- }
851
-
852
- /**
853
- * MU plugins are partially supported, but only when we know which file in mu-plugins
854
- * corresponds to this plugin.
855
- *
856
- * @return bool
857
- */
858
- protected function isUnknownMuPlugin() {
859
- return empty($this->muPluginFile) && $this->isMuPlugin();
860
- }
861
-
862
- /**
863
- * Clear the cached plugin version. This method can be set up as a filter (hook) and will
864
- * return the filter argument unmodified.
865
- *
866
- * @param mixed $filterArgument
867
- * @return mixed
868
- */
869
- public function clearCachedVersion($filterArgument = null) {
870
- $this->cachedInstalledVersion = null;
871
- return $filterArgument;
872
- }
873
-
874
- /**
875
- * Get absolute path to the main plugin file.
876
- *
877
- * @return string
878
- */
879
- public function getAbsolutePath() {
880
- return $this->pluginAbsolutePath;
881
- }
882
-
883
- /**
884
- * Register a callback for filtering query arguments.
885
- *
886
- * The callback function should take one argument - an associative array of query arguments.
887
- * It should return a modified array of query arguments.
888
- *
889
- * @uses add_filter() This method is a convenience wrapper for add_filter().
890
- *
891
- * @param callable $callback
892
- * @return void
893
- */
894
- public function addQueryArgFilter($callback){
895
- add_filter('puc_request_info_query_args-'.$this->slug, $callback);
896
- }
897
-
898
- /**
899
- * Register a callback for filtering arguments passed to wp_remote_get().
900
- *
901
- * The callback function should take one argument - an associative array of arguments -
902
- * and return a modified array or arguments. See the WP documentation on wp_remote_get()
903
- * for details on what arguments are available and how they work.
904
- *
905
- * @uses add_filter() This method is a convenience wrapper for add_filter().
906
- *
907
- * @param callable $callback
908
- * @return void
909
- */
910
- public function addHttpRequestArgFilter($callback){
911
- add_filter('puc_request_info_options-'.$this->slug, $callback);
912
- }
913
-
914
- /**
915
- * Register a callback for filtering the plugin info retrieved from the external API.
916
- *
917
- * The callback function should take two arguments. If the plugin info was retrieved
918
- * successfully, the first argument passed will be an instance of PluginInfo. Otherwise,
919
- * it will be NULL. The second argument will be the corresponding return value of
920
- * wp_remote_get (see WP docs for details).
921
- *
922
- * The callback function should return a new or modified instance of PluginInfo or NULL.
923
- *
924
- * @uses add_filter() This method is a convenience wrapper for add_filter().
925
- *
926
- * @param callable $callback
927
- * @return void
928
- */
929
- public function addResultFilter($callback){
930
- add_filter('puc_request_info_result-'.$this->slug, $callback, 10, 2);
931
- }
932
-
933
- /**
934
- * Register a callback for one of the update checker filters.
935
- *
936
- * Identical to add_filter(), except it automatically adds the "puc_" prefix
937
- * and the "-$plugin_slug" suffix to the filter name. For example, "request_info_result"
938
- * becomes "puc_request_info_result-your_plugin_slug".
939
- *
940
- * @param string $tag
941
- * @param callable $callback
942
- * @param int $priority
943
- * @param int $acceptedArgs
944
- */
945
- public function addFilter($tag, $callback, $priority = 10, $acceptedArgs = 1) {
946
- add_filter('puc_' . $tag . '-' . $this->slug, $callback, $priority, $acceptedArgs);
947
- }
948
-
949
- /**
950
- * Initialize the update checker Debug Bar plugin/add-on thingy.
951
- */
952
- public function initDebugBarPanel() {
953
- $debugBarPlugin = dirname(__FILE__) . '/debug-bar-plugin.php';
954
- if ( class_exists('Debug_Bar', false) && file_exists($debugBarPlugin) ) {
955
- /** @noinspection PhpIncludeInspection */
956
- require_once $debugBarPlugin;
957
- $this->debugBarPlugin = new PucDebugBarPlugin_3_2($this);
958
- }
959
- }
960
-
961
- /**
962
- * Trigger a PHP error, but only when $debugMode is enabled.
963
- *
964
- * @param string $message
965
- * @param int $errorType
966
- */
967
- protected function triggerError($message, $errorType) {
968
- if ( $this->debugMode ) {
969
- trigger_error($message, $errorType);
970
- }
971
- }
972
- }
973
-
974
- endif;
975
-
976
- if ( !class_exists('PluginInfo_3_2', false) ):
977
-
978
- /**
979
- * A container class for holding and transforming various plugin metadata.
980
- *
981
- * @author Janis Elsts
982
- * @copyright 2016
983
- * @version 3.2
984
- * @access public
985
- */
986
- class PluginInfo_3_2 {
987
- //Most fields map directly to the contents of the plugin's info.json file.
988
- //See the relevant docs for a description of their meaning.
989
- public $name;
990
- public $slug;
991
- public $version;
992
- public $homepage;
993
- public $sections = array();
994
- public $banners;
995
- public $translations = array();
996
- public $download_url;
997
-
998
- public $author;
999
- public $author_homepage;
1000
-
1001
- public $requires;
1002
- public $tested;
1003
- public $upgrade_notice;
1004
-
1005
- public $rating;
1006
- public $num_ratings;
1007
- public $downloaded;
1008
- public $active_installs;
1009
- public $last_updated;
1010
-
1011
- public $id = 0; //The native WP.org API returns numeric plugin IDs, but they're not used for anything.
1012
-
1013
- public $filename; //Plugin filename relative to the plugins directory.
1014
-
1015
- /**
1016
- * Create a new instance of PluginInfo from JSON-encoded plugin info
1017
- * returned by an external update API.
1018
- *
1019
- * @param string $json Valid JSON string representing plugin info.
1020
- * @return PluginInfo_3_2|null New instance of PluginInfo, or NULL on error.
1021
- */
1022
- public static function fromJson($json){
1023
- /** @var StdClass $apiResponse */
1024
- $apiResponse = json_decode($json);
1025
- if ( empty($apiResponse) || !is_object($apiResponse) ){
1026
- trigger_error(
1027
- "Failed to parse plugin metadata. Try validating your .json file with http://jsonlint.com/",
1028
- E_USER_NOTICE
1029
- );
1030
- return null;
1031
- }
1032
-
1033
- $valid = self::validateMetadata($apiResponse);
1034
- if ( is_wp_error($valid) ){
1035
- trigger_error($valid->get_error_message(), E_USER_NOTICE);
1036
- return null;
1037
- }
1038
-
1039
- $info = new self();
1040
- foreach(get_object_vars($apiResponse) as $key => $value){
1041
- $info->$key = $value;
1042
- }
1043
-
1044
- //json_decode decodes assoc. arrays as objects. We want it as an array.
1045
- $info->sections = (array)$info->sections;
1046
-
1047
- return $info;
1048
- }
1049
-
1050
- /**
1051
- * Very, very basic validation.
1052
- *
1053
- * @param StdClass $apiResponse
1054
- * @return bool|WP_Error
1055
- */
1056
- protected static function validateMetadata($apiResponse) {
1057
- if (
1058
- !isset($apiResponse->name, $apiResponse->version)
1059
- || empty($apiResponse->name)
1060
- || empty($apiResponse->version)
1061
- ) {
1062
- return new WP_Error(
1063
- 'puc-invalid-metadata',
1064
- "The plugin metadata file does not contain the required 'name' and/or 'version' keys."
1065
- );
1066
- }
1067
- return true;
1068
- }
1069
-
1070
-
1071
- /**
1072
- * Transform plugin info into the format used by the native WordPress.org API
1073
- *
1074
- * @return object
1075
- */
1076
- public function toWpFormat(){
1077
- $info = new stdClass;
1078
-
1079
- //The custom update API is built so that many fields have the same name and format
1080
- //as those returned by the native WordPress.org API. These can be assigned directly.
1081
- $sameFormat = array(
1082
- 'name', 'slug', 'version', 'requires', 'tested', 'rating', 'upgrade_notice',
1083
- 'num_ratings', 'downloaded', 'active_installs', 'homepage', 'last_updated',
1084
- );
1085
- foreach($sameFormat as $field){
1086
- if ( isset($this->$field) ) {
1087
- $info->$field = $this->$field;
1088
- } else {
1089
- $info->$field = null;
1090
- }
1091
- }
1092
-
1093
- //Other fields need to be renamed and/or transformed.
1094
- $info->download_link = $this->download_url;
1095
- $info->author = $this->getFormattedAuthor();
1096
- $info->sections = array_merge(array('description' => ''), $this->sections);
1097
-
1098
- if ( !empty($this->banners) ) {
1099
- //WP expects an array with two keys: "high" and "low". Both are optional.
1100
- //Docs: https://wordpress.org/plugins/about/faq/#banners
1101
- $info->banners = is_object($this->banners) ? get_object_vars($this->banners) : $this->banners;
1102
- $info->banners = array_intersect_key($info->banners, array('high' => true, 'low' => true));
1103
- }
1104
-
1105
- return $info;
1106
- }
1107
-
1108
- protected function getFormattedAuthor() {
1109
- if ( !empty($this->author_homepage) ){
1110
- return sprintf('<a href="%s">%s</a>', $this->author_homepage, $this->author);
1111
- }
1112
- return $this->author;
1113
- }
1114
- }
1115
-
1116
- endif;
1117
-
1118
- if ( !class_exists('PluginUpdate_3_2', false) ):
1119
-
1120
- /**
1121
- * A simple container class for holding information about an available update.
1122
- *
1123
- * @author Janis Elsts
1124
- * @copyright 2016
1125
- * @version 3.2
1126
- * @access public
1127
- */
1128
- class PluginUpdate_3_2 {
1129
- public $id = 0;
1130
- public $slug;
1131
- public $version;
1132
- public $homepage;
1133
- public $download_url;
1134
- public $upgrade_notice;
1135
- public $tested;
1136
- public $translations = array();
1137
- public $filename; //Plugin filename relative to the plugins directory.
1138
-
1139
- private static $fields = array(
1140
- 'id', 'slug', 'version', 'homepage', 'tested',
1141
- 'download_url', 'upgrade_notice', 'filename',
1142
- 'translations'
1143
- );
1144
-
1145
- /**
1146
- * Create a new instance of PluginUpdate from its JSON-encoded representation.
1147
- *
1148
- * @param string $json
1149
- * @return PluginUpdate_3_2|null
1150
- */
1151
- public static function fromJson($json){
1152
- //Since update-related information is simply a subset of the full plugin info,
1153
- //we can parse the update JSON as if it was a plugin info string, then copy over
1154
- //the parts that we care about.
1155
- $pluginInfo = PluginInfo_3_2::fromJson($json);
1156
- if ( $pluginInfo != null ) {
1157
- return self::fromPluginInfo($pluginInfo);
1158
- } else {
1159
- return null;
1160
- }
1161
- }
1162
-
1163
- /**
1164
- * Create a new instance of PluginUpdate based on an instance of PluginInfo.
1165
- * Basically, this just copies a subset of fields from one object to another.
1166
- *
1167
- * @param PluginInfo_3_2 $info
1168
- * @return PluginUpdate_3_2
1169
- */
1170
- public static function fromPluginInfo($info){
1171
- return self::fromObject($info);
1172
- }
1173
-
1174
- /**
1175
- * Create a new instance of PluginUpdate by copying the necessary fields from
1176
- * another object.
1177
- *
1178
- * @param StdClass|PluginInfo_3_2|PluginUpdate_3_2 $object The source object.
1179
- * @return PluginUpdate_3_2 The new copy.
1180
- */
1181
- public static function fromObject($object) {
1182
- $update = new self();
1183
- $fields = self::$fields;
1184
- if ( !empty($object->slug) ) {
1185
- $fields = apply_filters('puc_retain_fields-' . $object->slug, $fields);
1186
- }
1187
- foreach($fields as $field){
1188
- if (property_exists($object, $field)) {
1189
- $update->$field = $object->$field;
1190
- }
1191
- }
1192
- return $update;
1193
- }
1194
-
1195
- /**
1196
- * Create an instance of StdClass that can later be converted back to
1197
- * a PluginUpdate. Useful for serialization and caching, as it avoids
1198
- * the "incomplete object" problem if the cached value is loaded before
1199
- * this class.
1200
- *
1201
- * @return StdClass
1202
- */
1203
- public function toStdClass() {
1204
- $object = new stdClass();
1205
- $fields = self::$fields;
1206
- if ( !empty($this->slug) ) {
1207
- $fields = apply_filters('puc_retain_fields-' . $this->slug, $fields);
1208
- }
1209
- foreach($fields as $field){
1210
- if (property_exists($this, $field)) {
1211
- $object->$field = $this->$field;
1212
- }
1213
- }
1214
- return $object;
1215
- }
1216
-
1217
-
1218
- /**
1219
- * Transform the update into the format used by WordPress native plugin API.
1220
- *
1221
- * @return object
1222
- */
1223
- public function toWpFormat(){
1224
- $update = new stdClass;
1225
-
1226
- $update->id = $this->id;
1227
- $update->slug = $this->slug;
1228
- $update->new_version = $this->version;
1229
- $update->url = $this->homepage;
1230
- $update->package = $this->download_url;
1231
- $update->tested = $this->tested;
1232
- $update->plugin = $this->filename;
1233
-
1234
- if ( !empty($this->upgrade_notice) ){
1235
- $update->upgrade_notice = $this->upgrade_notice;
1236
- }
1237
-
1238
- return $update;
1239
- }
1240
- }
1241
-
1242
- endif;
1243
-
1244
- if ( !class_exists('PucScheduler_3_2', false) ):
1245
-
1246
- /**
1247
- * The scheduler decides when and how often to check for updates.
1248
- * It calls @see PluginUpdateChecker::checkForUpdates() to perform the actual checks.
1249
- *
1250
- * @version 3.2
1251
- */
1252
- class PucScheduler_3_2 {
1253
- public $checkPeriod = 12; //How often to check for updates (in hours).
1254
- public $throttleRedundantChecks = false; //Check less often if we already know that an update is available.
1255
- public $throttledCheckPeriod = 72;
1256
-
1257
- /**
1258
- * @var PluginUpdateChecker_3_2
1259
- */
1260
- protected $updateChecker;
1261
-
1262
- private $cronHook = null;
1263
-
1264
- /**
1265
- * Scheduler constructor.
1266
- *
1267
- * @param PluginUpdateChecker_3_2 $updateChecker
1268
- * @param int $checkPeriod How often to check for updates (in hours).
1269
- */
1270
- public function __construct($updateChecker, $checkPeriod) {
1271
- $this->updateChecker = $updateChecker;
1272
- $this->checkPeriod = $checkPeriod;
1273
-
1274
- //Set up the periodic update checks
1275
- $this->cronHook = 'check_plugin_updates-' . $this->updateChecker->slug;
1276
- if ( $this->checkPeriod > 0 ){
1277
-
1278
- //Trigger the check via Cron.
1279
- //Try to use one of the default schedules if possible as it's less likely to conflict
1280
- //with other plugins and their custom schedules.
1281
- $defaultSchedules = array(
1282
- 1 => 'hourly',
1283
- 12 => 'twicedaily',
1284
- 24 => 'daily',
1285
- );
1286
- if ( array_key_exists($this->checkPeriod, $defaultSchedules) ) {
1287
- $scheduleName = $defaultSchedules[$this->checkPeriod];
1288
- } else {
1289
- //Use a custom cron schedule.
1290
- $scheduleName = 'every' . $this->checkPeriod . 'hours';
1291
- add_filter('cron_schedules', array($this, '_addCustomSchedule'));
1292
- }
1293
-
1294
- if ( !wp_next_scheduled($this->cronHook) && !defined('WP_INSTALLING') ) {
1295
- wp_schedule_event(time(), $scheduleName, $this->cronHook);
1296
- }
1297
- add_action($this->cronHook, array($this, 'maybeCheckForUpdates'));
1298
-
1299
- register_deactivation_hook($this->updateChecker->pluginFile, array($this, '_removeUpdaterCron'));
1300
-
1301
- //In case Cron is disabled or unreliable, we also manually trigger
1302
- //the periodic checks while the user is browsing the Dashboard.
1303
- add_action( 'admin_init', array($this, 'maybeCheckForUpdates') );
1304
-
1305
- //Like WordPress itself, we check more often on certain pages.
1306
- /** @see wp_update_plugins */
1307
- add_action('load-update-core.php', array($this, 'maybeCheckForUpdates'));
1308
- add_action('load-plugins.php', array($this, 'maybeCheckForUpdates'));
1309
- add_action('load-update.php', array($this, 'maybeCheckForUpdates'));
1310
- //This hook fires after a bulk update is complete.
1311
- add_action('upgrader_process_complete', array($this, 'maybeCheckForUpdates'), 11, 0);
1312
-
1313
- } else {
1314
- //Periodic checks are disabled.
1315
- wp_clear_scheduled_hook($this->cronHook);
1316
- }
1317
- }
1318
-
1319
- /**
1320
- * Check for updates if the configured check interval has already elapsed.
1321
- * Will use a shorter check interval on certain admin pages like "Dashboard -> Updates" or when doing cron.
1322
- *
1323
- * You can override the default behaviour by using the "puc_check_now-$slug" filter.
1324
- * The filter callback will be passed three parameters:
1325
- * - Current decision. TRUE = check updates now, FALSE = don't check now.
1326
- * - Last check time as a Unix timestamp.
1327
- * - Configured check period in hours.
1328
- * Return TRUE to check for updates immediately, or FALSE to cancel.
1329
- *
1330
- * This method is declared public because it's a hook callback. Calling it directly is not recommended.
1331
- */
1332
- public function maybeCheckForUpdates(){
1333
- if ( empty($this->checkPeriod) ){
1334
- return;
1335
- }
1336
-
1337
- $state = $this->updateChecker->getUpdateState();
1338
- $shouldCheck =
1339
- empty($state) ||
1340
- !isset($state->lastCheck) ||
1341
- ( (time() - $state->lastCheck) >= $this->getEffectiveCheckPeriod() );
1342
-
1343
- //Let plugin authors substitute their own algorithm.
1344
- $shouldCheck = apply_filters(
1345
- 'puc_check_now-' . $this->updateChecker->slug,
1346
- $shouldCheck,
1347
- (!empty($state) && isset($state->lastCheck)) ? $state->lastCheck : 0,
1348
- $this->checkPeriod
1349
- );
1350
-
1351
- if ( $shouldCheck ) {
1352
- $this->updateChecker->checkForUpdates();
1353
- }
1354
- }
1355
-
1356
- /**
1357
- * Calculate the actual check period based on the current status and environment.
1358
- *
1359
- * @return int Check period in seconds.
1360
- */
1361
- protected function getEffectiveCheckPeriod() {
1362
- $currentFilter = current_filter();
1363
- if ( in_array($currentFilter, array('load-update-core.php', 'upgrader_process_complete')) ) {
1364
- //Check more often when the user visits "Dashboard -> Updates" or does a bulk update.
1365
- $period = 60;
1366
- } else if ( in_array($currentFilter, array('load-plugins.php', 'load-update.php')) ) {
1367
- //Also check more often on the "Plugins" page and /wp-admin/update.php.
1368
- $period = 3600;
1369
- } else if ( $this->throttleRedundantChecks && ($this->updateChecker->getUpdate() !== null) ) {
1370
- //Check less frequently if it's already known that an update is available.
1371
- $period = $this->throttledCheckPeriod * 3600;
1372
- } else if ( defined('DOING_CRON') && constant('DOING_CRON') ) {
1373
- //WordPress cron schedules are not exact, so lets do an update check even
1374
- //if slightly less than $checkPeriod hours have elapsed since the last check.
1375
- $cronFuzziness = 20 * 60;
1376
- $period = $this->checkPeriod * 3600 - $cronFuzziness;
1377
- } else {
1378
- $period = $this->checkPeriod * 3600;
1379
- }
1380
-
1381
- return $period;
1382
- }
1383
-
1384
- /**
1385
- * Add our custom schedule to the array of Cron schedules used by WP.
1386
- *
1387
- * @param array $schedules
1388
- * @return array
1389
- */
1390
- public function _addCustomSchedule($schedules){
1391
- if ( $this->checkPeriod && ($this->checkPeriod > 0) ){
1392
- $scheduleName = 'every' . $this->checkPeriod . 'hours';
1393
- $schedules[$scheduleName] = array(
1394
- 'interval' => $this->checkPeriod * 3600,
1395
- 'display' => sprintf('Every %d hours', $this->checkPeriod),
1396
- );
1397
- }
1398
- return $schedules;
1399
- }
1400
-
1401
- /**
1402
- * Remove the scheduled cron event that the library uses to check for updates.
1403
- *
1404
- * @return void
1405
- */
1406
- public function _removeUpdaterCron(){
1407
- wp_clear_scheduled_hook($this->cronHook);
1408
- }
1409
-
1410
- /**
1411
- * Get the name of the update checker's WP-cron hook. Mostly useful for debugging.
1412
- *
1413
- * @return string
1414
- */
1415
- public function getCronHookName() {
1416
- return $this->cronHook;
1417
- }
1418
- }
1419
-
1420
- endif;
1421
-
1422
-
1423
- if ( !class_exists('PucUpgraderStatus_3_2', false) ):
1424
-
1425
- /**
1426
- * A utility class that helps figure out which plugin WordPress is upgrading.
1427
- *
1428
- * It may seem strange to have an separate class just for that, but the task is surprisingly complicated.
1429
- * Core classes like Plugin_Upgrader don't expose the plugin file name during an in-progress update (AFAICT).
1430
- * This class uses a few workarounds and heuristics to get the file name.
1431
- */
1432
- class PucUpgraderStatus_3_2 {
1433
- private $upgradedPluginFile = null; //The plugin that is currently being upgraded by WordPress.
1434
-
1435
- public function __construct() {
1436
- //Keep track of which plugin WordPress is currently upgrading.
1437
- add_filter('upgrader_pre_install', array($this, 'setUpgradedPlugin'), 10, 2);
1438
- add_filter('upgrader_package_options', array($this, 'setUpgradedPluginFromOptions'), 10, 1);
1439
- add_filter('upgrader_post_install', array($this, 'clearUpgradedPlugin'), 10, 1);
1440
- add_action('upgrader_process_complete', array($this, 'clearUpgradedPlugin'), 10, 1);
1441
- }
1442
-
1443
- /**
1444
- * Is there and update being installed RIGHT NOW, for a specific plugin?
1445
- *
1446
- * Caution: This method is unreliable. WordPress doesn't make it easy to figure out what it is upgrading,
1447
- * and upgrader implementations are liable to change without notice.
1448
- *
1449
- * @param string $pluginFile The plugin to check.
1450
- * @param WP_Upgrader|null $upgrader The upgrader that's performing the current update.
1451
- * @return bool True if the plugin identified by $pluginFile is being upgraded.
1452
- */
1453
- public function isPluginBeingUpgraded($pluginFile, $upgrader = null) {
1454
- if ( isset($upgrader) ) {
1455
- $upgradedPluginFile = $this->getPluginBeingUpgradedBy($upgrader);
1456
- if ( !empty($upgradedPluginFile) ) {
1457
- $this->upgradedPluginFile = $upgradedPluginFile;
1458
- }
1459
- }
1460
- return ( !empty($this->upgradedPluginFile) && ($this->upgradedPluginFile === $pluginFile) );
1461
- }
1462
-
1463
- /**
1464
- * Get the file name of the plugin that's currently being upgraded.
1465
- *
1466
- * @param Plugin_Upgrader|WP_Upgrader $upgrader
1467
- * @return string|null
1468
- */
1469
- private function getPluginBeingUpgradedBy($upgrader) {
1470
- if ( !isset($upgrader, $upgrader->skin) ) {
1471
- return null;
1472
- }
1473
-
1474
- //Figure out which plugin is being upgraded.
1475
- $pluginFile = null;
1476
- $skin = $upgrader->skin;
1477
- if ( $skin instanceof Plugin_Upgrader_Skin ) {
1478
- if ( isset($skin->plugin) && is_string($skin->plugin) && ($skin->plugin !== '') ) {
1479
- $pluginFile = $skin->plugin;
1480
- }
1481
- } elseif ( isset($skin->plugin_info) && is_array($skin->plugin_info) ) {
1482
- //This case is tricky because Bulk_Plugin_Upgrader_Skin (etc) doesn't actually store the plugin
1483
- //filename anywhere. Instead, it has the plugin headers in $plugin_info. So the best we can
1484
- //do is compare those headers to the headers of installed plugins.
1485
- $pluginFile = $this->identifyPluginByHeaders($skin->plugin_info);
1486
- }
1487
-
1488
- return $pluginFile;
1489
- }
1490
-
1491
- /**
1492
- * Identify an installed plugin based on its headers.
1493
- *
1494
- * @param array $searchHeaders The plugin file header to look for.
1495
- * @return string|null Plugin basename ("foo/bar.php"), or NULL if we can't identify the plugin.
1496
- */
1497
- private function identifyPluginByHeaders($searchHeaders) {
1498
- if ( !function_exists('get_plugins') ){
1499
- /** @noinspection PhpIncludeInspection */
1500
- require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
1501
- }
1502
-
1503
- $installedPlugins = get_plugins();
1504
- $matches = array();
1505
- foreach($installedPlugins as $pluginBasename => $headers) {
1506
- $diff1 = array_diff_assoc($headers, $searchHeaders);
1507
- $diff2 = array_diff_assoc($searchHeaders, $headers);
1508
- if ( empty($diff1) && empty($diff2) ) {
1509
- $matches[] = $pluginBasename;
1510
- }
1511
- }
1512
-
1513
- //It's possible (though very unlikely) that there could be two plugins with identical
1514
- //headers. In that case, we can't unambiguously identify the plugin that's being upgraded.
1515
- if ( count($matches) !== 1 ) {
1516
- return null;
1517
- }
1518
-
1519
- return reset($matches);
1520
- }
1521
-
1522
- /**
1523
- * @access private
1524
- *
1525
- * @param mixed $input
1526
- * @param array $hookExtra
1527
- * @return mixed Returns $input unaltered.
1528
- */
1529
- public function setUpgradedPlugin($input, $hookExtra) {
1530
- if (!empty($hookExtra['plugin']) && is_string($hookExtra['plugin'])) {
1531
- $this->upgradedPluginFile = $hookExtra['plugin'];
1532
- } else {
1533
- $this->upgradedPluginFile = null;
1534
- }
1535
- return $input;
1536
- }
1537
-
1538
- /**
1539
- * @access private
1540
- *
1541
- * @param array $options
1542
- * @return array
1543
- */
1544
- public function setUpgradedPluginFromOptions($options) {
1545
- if (isset($options['hook_extra']['plugin']) && is_string($options['hook_extra']['plugin'])) {
1546
- $this->upgradedPluginFile = $options['hook_extra']['plugin'];
1547
- } else {
1548
- $this->upgradedPluginFile = null;
1549
- }
1550
- return $options;
1551
- }
1552
-
1553
- /**
1554
- * @access private
1555
- *
1556
- * @param mixed $input
1557
- * @return mixed Returns $input unaltered.
1558
- */
1559
- public function clearUpgradedPlugin($input = null) {
1560
- $this->upgradedPluginFile = null;
1561
- return $input;
1562
- }
1563
- }
1564
-
1565
- endif;
1566
-
1567
-
1568
- if ( !class_exists('PucFactory', false) ):
1569
-
1570
- /**
1571
- * A factory that builds instances of other classes from this library.
1572
- *
1573
- * When multiple versions of the same class have been loaded (e.g. PluginUpdateChecker 1.2
1574
- * and 1.3), this factory will always use the latest available version. Register class
1575
- * versions by calling {@link PucFactory::addVersion()}.
1576
- *
1577
- * At the moment it can only build instances of the PluginUpdateChecker class. Other classes
1578
- * are intended mainly for internal use and refer directly to specific implementations. If you
1579
- * want to instantiate one of them anyway, you can use {@link PucFactory::getLatestClassVersion()}
1580
- * to get the class name and then create it with <code>new $class(...)</code>.
1581
- */
1582
- class PucFactory {
1583
- protected static $classVersions = array();
1584
- protected static $sorted = false;
1585
-
1586
- /**
1587
- * Create a new instance of PluginUpdateChecker.
1588
- *
1589
- * @see PluginUpdateChecker::__construct()
1590
- *
1591
- * @param $metadataUrl
1592
- * @param $pluginFile
1593
- * @param string $slug
1594
- * @param int $checkPeriod
1595
- * @param string $optionName
1596
- * @param string $muPluginFile
1597
- * @return PluginUpdateChecker_3_2
1598
- */
1599
- public static function buildUpdateChecker($metadataUrl, $pluginFile, $slug = '', $checkPeriod = 12, $optionName = '', $muPluginFile = '') {
1600
- $class = self::getLatestClassVersion('PluginUpdateChecker');
1601
- return new $class($metadataUrl, $pluginFile, $slug, $checkPeriod, $optionName, $muPluginFile);
1602
- }
1603
-
1604
- /**
1605
- * Get the specific class name for the latest available version of a class.
1606
- *
1607
- * @param string $class
1608
- * @return string|null
1609
- */
1610
- public static function getLatestClassVersion($class) {
1611
- if ( !self::$sorted ) {
1612
- self::sortVersions();
1613
- }
1614
-
1615
- if ( isset(self::$classVersions[$class]) ) {
1616
- return reset(self::$classVersions[$class]);
1617
- } else {
1618
- return null;
1619
- }
1620
- }
1621
-
1622
- /**
1623
- * Sort available class versions in descending order (i.e. newest first).
1624
- */
1625
- protected static function sortVersions() {
1626
- foreach ( self::$classVersions as $class => $versions ) {
1627
- uksort($versions, array(__CLASS__, 'compareVersions'));
1628
- self::$classVersions[$class] = $versions;
1629
- }
1630
- self::$sorted = true;
1631
- }
1632
-
1633
- protected static function compareVersions($a, $b) {
1634
- return -version_compare($a, $b);
1635
- }
1636
-
1637
- /**
1638
- * Register a version of a class.
1639
- *
1640
- * @access private This method is only for internal use by the library.
1641
- *
1642
- * @param string $generalClass Class name without version numbers, e.g. 'PluginUpdateChecker'.
1643
- * @param string $versionedClass Actual class name, e.g. 'PluginUpdateChecker_1_2'.
1644
- * @param string $version Version number, e.g. '1.2'.
1645
- */
1646
- public static function addVersion($generalClass, $versionedClass, $version) {
1647
- if ( !isset(self::$classVersions[$generalClass]) ) {
1648
- self::$classVersions[$generalClass] = array();
1649
- }
1650
- self::$classVersions[$generalClass][$version] = $versionedClass;
1651
- self::$sorted = false;
1652
- }
1653
- }
1654
-
1655
- endif;
1656
-
1657
- require_once(dirname(__FILE__) . '/github-checker.php');
1658
-
1659
- //Register classes defined in this file with the factory.
1660
- PucFactory::addVersion('PluginUpdateChecker', 'PluginUpdateChecker_3_2', '3.2');
1661
- PucFactory::addVersion('PluginUpdate', 'PluginUpdate_3_2', '3.2');
1662
- PucFactory::addVersion('PluginInfo', 'PluginInfo_3_2', '3.2');
1663
- PucFactory::addVersion('PucGitHubChecker', 'PucGitHubChecker_3_2', '3.2');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/vendor/Parsedown.php DELETED
@@ -1,1538 +0,0 @@
1
- <?php
2
-
3
- #
4
- #
5
- # Parsedown
6
- # http://parsedown.org
7
- #
8
- # (c) Emanuil Rusev
9
- # http://erusev.com
10
- #
11
- # For the full license information, view the LICENSE file that was distributed
12
- # with this source code.
13
- #
14
- #
15
-
16
- class Parsedown
17
- {
18
- # ~
19
-
20
- const version = '1.6.0';
21
-
22
- # ~
23
-
24
- function text($text)
25
- {
26
- # make sure no definitions are set
27
- $this->DefinitionData = array();
28
-
29
- # standardize line breaks
30
- $text = str_replace(array("\r\n", "\r"), "\n", $text);
31
-
32
- # remove surrounding line breaks
33
- $text = trim($text, "\n");
34
-
35
- # split text into lines
36
- $lines = explode("\n", $text);
37
-
38
- # iterate through lines to identify blocks
39
- $markup = $this->lines($lines);
40
-
41
- # trim line breaks
42
- $markup = trim($markup, "\n");
43
-
44
- return $markup;
45
- }
46
-
47
- #
48
- # Setters
49
- #
50
-
51
- function setBreaksEnabled($breaksEnabled)
52
- {
53
- $this->breaksEnabled = $breaksEnabled;
54
-
55
- return $this;
56
- }
57
-
58
- protected $breaksEnabled;
59
-
60
- function setMarkupEscaped($markupEscaped)
61
- {
62
- $this->markupEscaped = $markupEscaped;
63
-
64
- return $this;
65
- }
66
-
67
- protected $markupEscaped;
68
-
69
- function setUrlsLinked($urlsLinked)
70
- {
71
- $this->urlsLinked = $urlsLinked;
72
-
73
- return $this;
74
- }
75
-
76
- protected $urlsLinked = true;
77
-
78
- #
79
- # Lines
80
- #
81
-
82
- protected $BlockTypes = array(
83
- '#' => array('Header'),
84
- '*' => array('Rule', 'List'),
85
- '+' => array('List'),
86
- '-' => array('SetextHeader', 'Table', 'Rule', 'List'),
87
- '0' => array('List'),
88
- '1' => array('List'),
89
- '2' => array('List'),
90
- '3' => array('List'),
91
- '4' => array('List'),
92
- '5' => array('List'),
93
- '6' => array('List'),
94
- '7' => array('List'),
95
- '8' => array('List'),
96
- '9' => array('List'),
97
- ':' => array('Table'),
98
- '<' => array('Comment', 'Markup'),
99
- '=' => array('SetextHeader'),
100
- '>' => array('Quote'),
101
- '[' => array('Reference'),
102
- '_' => array('Rule'),
103
- '`' => array('FencedCode'),
104
- '|' => array('Table'),
105
- '~' => array('FencedCode'),
106
- );
107
-
108
- # ~
109
-
110
- protected $unmarkedBlockTypes = array(
111
- 'Code',
112
- );
113
-
114
- #
115
- # Blocks
116
- #
117
-
118
- protected function lines(array $lines)
119
- {
120
- $CurrentBlock = null;
121
-
122
- foreach ($lines as $line)
123
- {
124
- if (chop($line) === '')
125
- {
126
- if (isset($CurrentBlock))
127
- {
128
- $CurrentBlock['interrupted'] = true;
129
- }
130
-
131
- continue;
132
- }
133
-
134
- if (strpos($line, "\t") !== false)
135
- {
136
- $parts = explode("\t", $line);
137
-
138
- $line = $parts[0];
139
-
140
- unset($parts[0]);
141
-
142
- foreach ($parts as $part)
143
- {
144
- $shortage = 4 - mb_strlen($line, 'utf-8') % 4;
145
-
146
- $line .= str_repeat(' ', $shortage);
147
- $line .= $part;
148
- }
149
- }
150
-
151
- $indent = 0;
152
-
153
- while (isset($line[$indent]) and $line[$indent] === ' ')
154
- {
155
- $indent ++;
156
- }
157
-
158
- $text = $indent > 0 ? substr($line, $indent) : $line;
159
-
160
- # ~
161
-
162
- $Line = array('body' => $line, 'indent' => $indent, 'text' => $text);
163
-
164
- # ~
165
-
166
- if (isset($CurrentBlock['continuable']))
167
- {
168
- $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock);
169
-
170
- if (isset($Block))
171
- {
172
- $CurrentBlock = $Block;
173
-
174
- continue;
175
- }
176
- else
177
- {
178
- if ($this->isBlockCompletable($CurrentBlock['type']))
179
- {
180
- $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
181
- }
182
- }
183
- }
184
-
185
- # ~
186
-
187
- $marker = $text[0];
188
-
189
- # ~
190
-
191
- $blockTypes = $this->unmarkedBlockTypes;
192
-
193
- if (isset($this->BlockTypes[$marker]))
194
- {
195
- foreach ($this->BlockTypes[$marker] as $blockType)
196
- {
197
- $blockTypes []= $blockType;
198
- }
199
- }
200
-
201
- #
202
- # ~
203
-
204
- foreach ($blockTypes as $blockType)
205
- {
206
- $Block = $this->{'block'.$blockType}($Line, $CurrentBlock);
207
-
208
- if (isset($Block))
209
- {
210
- $Block['type'] = $blockType;
211
-
212
- if ( ! isset($Block['identified']))
213
- {
214
- $Blocks []= $CurrentBlock;
215
-
216
- $Block['identified'] = true;
217
- }
218
-
219
- if ($this->isBlockContinuable($blockType))
220
- {
221
- $Block['continuable'] = true;
222
- }
223
-
224
- $CurrentBlock = $Block;
225
-
226
- continue 2;
227
- }
228
- }
229
-
230
- # ~
231
-
232
- if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted']))
233
- {
234
- $CurrentBlock['element']['text'] .= "\n".$text;
235
- }
236
- else
237
- {
238
- $Blocks []= $CurrentBlock;
239
-
240
- $CurrentBlock = $this->paragraph($Line);
241
-
242
- $CurrentBlock['identified'] = true;
243
- }
244
- }
245
-
246
- # ~
247
-
248
- if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type']))
249
- {
250
- $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
251
- }
252
-
253
- # ~
254
-
255
- $Blocks []= $CurrentBlock;
256
-
257
- unset($Blocks[0]);
258
-
259
- # ~
260
-
261
- $markup = '';
262
-
263
- foreach ($Blocks as $Block)
264
- {
265
- if (isset($Block['hidden']))
266
- {
267
- continue;
268
- }
269
-
270
- $markup .= "\n";
271
- $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
272
- }
273
-
274
- $markup .= "\n";
275
-
276
- # ~
277
-
278
- return $markup;
279
- }
280
-
281
- protected function isBlockContinuable($Type)
282
- {
283
- return method_exists($this, 'block'.$Type.'Continue');
284
- }
285
-
286
- protected function isBlockCompletable($Type)
287
- {
288
- return method_exists($this, 'block'.$Type.'Complete');
289
- }
290
-
291
- #
292
- # Code
293
-
294
- protected function blockCode($Line, $Block = null)
295
- {
296
- if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted']))
297
- {
298
- return;
299
- }
300
-
301
- if ($Line['indent'] >= 4)
302
- {
303
- $text = substr($Line['body'], 4);
304
-
305
- $Block = array(
306
- 'element' => array(
307
- 'name' => 'pre',
308
- 'handler' => 'element',
309
- 'text' => array(
310
- 'name' => 'code',
311
- 'text' => $text,
312
- ),
313
- ),
314
- );
315
-
316
- return $Block;
317
- }
318
- }
319
-
320
- protected function blockCodeContinue($Line, $Block)
321
- {
322
- if ($Line['indent'] >= 4)
323
- {
324
- if (isset($Block['interrupted']))
325
- {
326
- $Block['element']['text']['text'] .= "\n";
327
-
328
- unset($Block['interrupted']);
329
- }
330
-
331
- $Block['element']['text']['text'] .= "\n";
332
-
333
- $text = substr($Line['body'], 4);
334
-
335
- $Block['element']['text']['text'] .= $text;
336
-
337
- return $Block;
338
- }
339
- }
340
-
341
- protected function blockCodeComplete($Block)
342
- {
343
- $text = $Block['element']['text']['text'];
344
-
345
- $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
346
-
347
- $Block['element']['text']['text'] = $text;
348
-
349
- return $Block;
350
- }
351
-
352
- #
353
- # Comment
354
-
355
- protected function blockComment($Line)
356
- {
357
- if ($this->markupEscaped)
358
- {
359
- return;
360
- }
361
-
362
- if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!')
363
- {
364
- $Block = array(
365
- 'markup' => $Line['body'],
366
- );
367
-
368
- if (preg_match('/-->$/', $Line['text']))
369
- {
370
- $Block['closed'] = true;
371
- }
372
-
373
- return $Block;
374
- }
375
- }
376
-
377
- protected function blockCommentContinue($Line, array $Block)
378
- {
379
- if (isset($Block['closed']))
380
- {
381
- return;
382
- }
383
-
384
- $Block['markup'] .= "\n" . $Line['body'];
385
-
386
- if (preg_match('/-->$/', $Line['text']))
387
- {
388
- $Block['closed'] = true;
389
- }
390
-
391
- return $Block;
392
- }
393
-
394
- #
395
- # Fenced Code
396
-
397
- protected function blockFencedCode($Line)
398
- {
399
- if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches))
400
- {
401
- $Element = array(
402
- 'name' => 'code',
403
- 'text' => '',
404
- );
405
-
406
- if (isset($matches[1]))
407
- {
408
- $class = 'language-'.$matches[1];
409
-
410
- $Element['attributes'] = array(
411
- 'class' => $class,
412
- );
413
- }
414
-
415
- $Block = array(
416
- 'char' => $Line['text'][0],
417
- 'element' => array(
418
- 'name' => 'pre',
419
- 'handler' => 'element',
420
- 'text' => $Element,
421
- ),
422
- );
423
-
424
- return $Block;
425
- }
426
- }
427
-
428
- protected function blockFencedCodeContinue($Line, $Block)
429
- {
430
- if (isset($Block['complete']))
431
- {
432
- return;
433
- }
434
-
435
- if (isset($Block['interrupted']))
436
- {
437
- $Block['element']['text']['text'] .= "\n";
438
-
439
- unset($Block['interrupted']);
440
- }
441
-
442
- if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))
443
- {
444
- $Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1);
445
-
446
- $Block['complete'] = true;
447
-
448
- return $Block;
449
- }
450
-
451
- $Block['element']['text']['text'] .= "\n".$Line['body'];;
452
-
453
- return $Block;
454
- }
455
-
456
- protected function blockFencedCodeComplete($Block)
457
- {
458
- $text = $Block['element']['text']['text'];
459
-
460
- $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
461
-
462
- $Block['element']['text']['text'] = $text;
463
-
464
- return $Block;
465
- }
466
-
467
- #
468
- # Header
469
-
470
- protected function blockHeader($Line)
471
- {
472
- if (isset($Line['text'][1]))
473
- {
474
- $level = 1;
475
-
476
- while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')
477
- {
478
- $level ++;
479
- }
480
-
481
- if ($level > 6)
482
- {
483
- return;
484
- }
485
-
486
- $text = trim($Line['text'], '# ');
487
-
488
- $Block = array(
489
- 'element' => array(
490
- 'name' => 'h' . min(6, $level),
491
- 'text' => $text,
492
- 'handler' => 'line',
493
- ),
494
- );
495
-
496
- return $Block;
497
- }
498
- }
499
-
500
- #
501
- # List
502
-
503
- protected function blockList($Line)
504
- {
505
- list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');
506
-
507
- if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches))
508
- {
509
- $Block = array(
510
- 'indent' => $Line['indent'],
511
- 'pattern' => $pattern,
512
- 'element' => array(
513
- 'name' => $name,
514
- 'handler' => 'elements',
515
- ),
516
- );
517
-
518
- $Block['li'] = array(
519
- 'name' => 'li',
520
- 'handler' => 'li',
521
- 'text' => array(
522
- $matches[2],
523
- ),
524
- );
525
-
526
- $Block['element']['text'] []= & $Block['li'];
527
-
528
- return $Block;
529
- }
530
- }
531
-
532
- protected function blockListContinue($Line, array $Block)
533
- {
534
- if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches))
535
- {
536
- if (isset($Block['interrupted']))
537
- {
538
- $Block['li']['text'] []= '';
539
-
540
- unset($Block['interrupted']);
541
- }
542
-
543
- unset($Block['li']);
544
-
545
- $text = isset($matches[1]) ? $matches[1] : '';
546
-
547
- $Block['li'] = array(
548
- 'name' => 'li',
549
- 'handler' => 'li',
550
- 'text' => array(
551
- $text,
552
- ),
553
- );
554
-
555
- $Block['element']['text'] []= & $Block['li'];
556
-
557
- return $Block;
558
- }
559
-
560
- if ($Line['text'][0] === '[' and $this->blockReference($Line))
561
- {
562
- return $Block;
563
- }
564
-
565
- if ( ! isset($Block['interrupted']))
566
- {
567
- $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
568
-
569
- $Block['li']['text'] []= $text;
570
-
571
- return $Block;
572
- }
573
-
574
- if ($Line['indent'] > 0)
575
- {
576
- $Block['li']['text'] []= '';
577
-
578
- $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
579
-
580
- $Block['li']['text'] []= $text;
581
-
582
- unset($Block['interrupted']);
583
-
584
- return $Block;
585
- }
586
- }
587
-
588
- #
589
- # Quote
590
-
591
- protected function blockQuote($Line)
592
- {
593
- if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
594
- {
595
- $Block = array(
596
- 'element' => array(
597
- 'name' => 'blockquote',
598
- 'handler' => 'lines',
599
- 'text' => (array) $matches[1],
600
- ),
601
- );
602
-
603
- return $Block;
604
- }
605
- }
606
-
607
- protected function blockQuoteContinue($Line, array $Block)
608
- {
609
- if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
610
- {
611
- if (isset($Block['interrupted']))
612
- {
613
- $Block['element']['text'] []= '';
614
-
615
- unset($Block['interrupted']);
616
- }
617
-
618
- $Block['element']['text'] []= $matches[1];
619
-
620
- return $Block;
621
- }
622
-
623
- if ( ! isset($Block['interrupted']))
624
- {
625
- $Block['element']['text'] []= $Line['text'];
626
-
627
- return $Block;
628
- }
629
- }
630
-
631
- #
632
- # Rule
633
-
634
- protected function blockRule($Line)
635
- {
636
- if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text']))
637
- {
638
- $Block = array(
639
- 'element' => array(
640
- 'name' => 'hr'
641
- ),
642
- );
643
-
644
- return $Block;
645
- }
646
- }
647
-
648
- #
649
- # Setext
650
-
651
- protected function blockSetextHeader($Line, array $Block = null)
652
- {
653
- if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
654
- {
655
- return;
656
- }
657
-
658
- if (chop($Line['text'], $Line['text'][0]) === '')
659
- {
660
- $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
661
-
662
- return $Block;
663
- }
664
- }
665
-
666
- #
667
- # Markup
668
-
669
- protected function blockMarkup($Line)
670
- {
671
- if ($this->markupEscaped)
672
- {
673
- return;
674
- }
675
-
676
- if (preg_match('/^<(\w*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
677
- {
678
- $element = strtolower($matches[1]);
679
-
680
- if (in_array($element, $this->textLevelElements))
681
- {
682
- return;
683
- }
684
-
685
- $Block = array(
686
- 'name' => $matches[1],
687
- 'depth' => 0,
688
- 'markup' => $Line['text'],
689
- );
690
-
691
- $length = strlen($matches[0]);
692
-
693
- $remainder = substr($Line['text'], $length);
694
-
695
- if (trim($remainder) === '')
696
- {
697
- if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
698
- {
699
- $Block['closed'] = true;
700
-
701
- $Block['void'] = true;
702
- }
703
- }
704
- else
705
- {
706
- if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
707
- {
708
- return;
709
- }
710
-
711
- if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder))
712
- {
713
- $Block['closed'] = true;
714
- }
715
- }
716
-
717
- return $Block;
718
- }
719
- }
720
-
721
- protected function blockMarkupContinue($Line, array $Block)
722
- {
723
- if (isset($Block['closed']))
724
- {
725
- return;
726
- }
727
-
728
- if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open
729
- {
730
- $Block['depth'] ++;
731
- }
732
-
733
- if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close
734
- {
735
- if ($Block['depth'] > 0)
736
- {
737
- $Block['depth'] --;
738
- }
739
- else
740
- {
741
- $Block['closed'] = true;
742
- }
743
- }
744
-
745
- if (isset($Block['interrupted']))
746
- {
747
- $Block['markup'] .= "\n";
748
-
749
- unset($Block['interrupted']);
750
- }
751
-
752
- $Block['markup'] .= "\n".$Line['body'];
753
-
754
- return $Block;
755
- }
756
-
757
- #
758
- # Reference
759
-
760
- protected function blockReference($Line)
761
- {
762
- if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches))
763
- {
764
- $id = strtolower($matches[1]);
765
-
766
- $Data = array(
767
- 'url' => $matches[2],
768
- 'title' => null,
769
- );
770
-
771
- if (isset($matches[3]))
772
- {
773
- $Data['title'] = $matches[3];
774
- }
775
-
776
- $this->DefinitionData['Reference'][$id] = $Data;
777
-
778
- $Block = array(
779
- 'hidden' => true,
780
- );
781
-
782
- return $Block;
783
- }
784
- }
785
-
786
- #
787
- # Table
788
-
789
- protected function blockTable($Line, array $Block = null)
790
- {
791
- if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
792
- {
793
- return;
794
- }
795
-
796
- if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '')
797
- {
798
- $alignments = array();
799
-
800
- $divider = $Line['text'];
801
-
802
- $divider = trim($divider);
803
- $divider = trim($divider, '|');
804
-
805
- $dividerCells = explode('|', $divider);
806
-
807
- foreach ($dividerCells as $dividerCell)
808
- {
809
- $dividerCell = trim($dividerCell);
810
-
811
- if ($dividerCell === '')
812
- {
813
- continue;
814
- }
815
-
816
- $alignment = null;
817
-
818
- if ($dividerCell[0] === ':')
819
- {
820
- $alignment = 'left';
821
- }
822
-
823
- if (substr($dividerCell, - 1) === ':')
824
- {
825
- $alignment = $alignment === 'left' ? 'center' : 'right';
826
- }
827
-
828
- $alignments []= $alignment;
829
- }
830
-
831
- # ~
832
-
833
- $HeaderElements = array();
834
-
835
- $header = $Block['element']['text'];
836
-
837
- $header = trim($header);
838
- $header = trim($header, '|');
839
-
840
- $headerCells = explode('|', $header);
841
-
842
- foreach ($headerCells as $index => $headerCell)
843
- {
844
- $headerCell = trim($headerCell);
845
-
846
- $HeaderElement = array(
847
- 'name' => 'th',
848
- 'text' => $headerCell,
849
- 'handler' => 'line',
850
- );
851
-
852
- if (isset($alignments[$index]))
853
- {
854
- $alignment = $alignments[$index];
855
-
856
- $HeaderElement['attributes'] = array(
857
- 'style' => 'text-align: '.$alignment.';',
858
- );
859
- }
860
-
861
- $HeaderElements []= $HeaderElement;
862
- }
863
-
864
- # ~
865
-
866
- $Block = array(
867
- 'alignments' => $alignments,
868
- 'identified' => true,
869
- 'element' => array(
870
- 'name' => 'table',
871
- 'handler' => 'elements',
872
- ),
873
- );
874
-
875
- $Block['element']['text'] []= array(
876
- 'name' => 'thead',
877
- 'handler' => 'elements',
878
- );
879
-
880
- $Block['element']['text'] []= array(
881
- 'name' => 'tbody',
882
- 'handler' => 'elements',
883
- 'text' => array(),
884
- );
885
-
886
- $Block['element']['text'][0]['text'] []= array(
887
- 'name' => 'tr',
888
- 'handler' => 'elements',
889
- 'text' => $HeaderElements,
890
- );
891
-
892
- return $Block;
893
- }
894
- }
895
-
896
- protected function blockTableContinue($Line, array $Block)
897
- {
898
- if (isset($Block['interrupted']))
899
- {
900
- return;
901
- }
902
-
903
- if ($Line['text'][0] === '|' or strpos($Line['text'], '|'))
904
- {
905
- $Elements = array();
906
-
907
- $row = $Line['text'];
908
-
909
- $row = trim($row);
910
- $row = trim($row, '|');
911
-
912
- preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);
913
-
914
- foreach ($matches[0] as $index => $cell)
915
- {
916
- $cell = trim($cell);
917
-
918
- $Element = array(
919
- 'name' => 'td',
920
- 'handler' => 'line',
921
- 'text' => $cell,
922
- );
923
-
924
- if (isset($Block['alignments'][$index]))
925
- {
926
- $Element['attributes'] = array(
927
- 'style' => 'text-align: '.$Block['alignments'][$index].';',
928
- );
929
- }
930
-
931
- $Elements []= $Element;
932
- }
933
-
934
- $Element = array(
935
- 'name' => 'tr',
936
- 'handler' => 'elements',
937
- 'text' => $Elements,
938
- );
939
-
940
- $Block['element']['text'][1]['text'] []= $Element;
941
-
942
- return $Block;
943
- }
944
- }
945
-
946
- #
947
- # ~
948
- #
949
-
950
- protected function paragraph($Line)
951
- {
952
- $Block = array(
953
- 'element' => array(
954
- 'name' => 'p',
955
- 'text' => $Line['text'],
956
- 'handler' => 'line',
957
- ),
958
- );
959
-
960
- return $Block;
961
- }
962
-
963
- #
964
- # Inline Elements
965
- #
966
-
967
- protected $InlineTypes = array(
968
- '"' => array('SpecialCharacter'),
969
- '!' => array('Image'),
970
- '&' => array('SpecialCharacter'),
971
- '*' => array('Emphasis'),
972
- ':' => array('Url'),
973
- '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'),
974
- '>' => array('SpecialCharacter'),
975
- '[' => array('Link'),
976
- '_' => array('Emphasis'),
977
- '`' => array('Code'),
978
- '~' => array('Strikethrough'),
979
- '\\' => array('EscapeSequence'),
980
- );
981
-
982
- # ~
983
-
984
- protected $inlineMarkerList = '!"*_&[:<>`~\\';
985
-
986
- #
987
- # ~
988
- #
989
-
990
- public function line($text)
991
- {
992
- $markup = '';
993
-
994
- # $excerpt is based on the first occurrence of a marker
995
-
996
- while ($excerpt = strpbrk($text, $this->inlineMarkerList))
997
- {
998
- $marker = $excerpt[0];
999
-
1000
- $markerPosition = strpos($text, $marker);
1001
-
1002
- $Excerpt = array('text' => $excerpt, 'context' => $text);
1003
-
1004
- foreach ($this->InlineTypes[$marker] as $inlineType)
1005
- {
1006
- $Inline = $this->{'inline'.$inlineType}($Excerpt);
1007
-
1008
- if ( ! isset($Inline))
1009
- {
1010
- continue;
1011
- }
1012
-
1013
- # makes sure that the inline belongs to "our" marker
1014
-
1015
- if (isset($Inline['position']) and $Inline['position'] > $markerPosition)
1016
- {
1017
- continue;
1018
- }
1019
-
1020
- # sets a default inline position
1021
-
1022
- if ( ! isset($Inline['position']))
1023
- {
1024
- $Inline['position'] = $markerPosition;
1025
- }
1026
-
1027
- # the text that comes before the inline
1028
- $unmarkedText = substr($text, 0, $Inline['position']);
1029
-
1030
- # compile the unmarked text
1031
- $markup .= $this->unmarkedText($unmarkedText);
1032
-
1033
- # compile the inline
1034
- $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
1035
-
1036
- # remove the examined text
1037
- $text = substr($text, $Inline['position'] + $Inline['extent']);
1038
-
1039
- continue 2;
1040
- }
1041
-
1042
- # the marker does not belong to an inline
1043
-
1044
- $unmarkedText = substr($text, 0, $markerPosition + 1);
1045
-
1046
- $markup .= $this->unmarkedText($unmarkedText);
1047
-
1048
- $text = substr($text, $markerPosition + 1);
1049
- }
1050
-
1051
- $markup .= $this->unmarkedText($text);
1052
-
1053
- return $markup;
1054
- }
1055
-
1056
- #
1057
- # ~
1058
- #
1059
-
1060
- protected function inlineCode($Excerpt)
1061
- {
1062
- $marker = $Excerpt['text'][0];
1063
-
1064
- if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
1065
- {
1066
- $text = $matches[2];
1067
- $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
1068
- $text = preg_replace("/[ ]*\n/", ' ', $text);
1069
-
1070
- return array(
1071
- 'extent' => strlen($matches[0]),
1072
- 'element' => array(
1073
- 'name' => 'code',
1074
- 'text' => $text,
1075
- ),
1076
- );
1077
- }
1078
- }
1079
-
1080
- protected function inlineEmailTag($Excerpt)
1081
- {
1082
- if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
1083
- {
1084
- $url = $matches[1];
1085
-
1086
- if ( ! isset($matches[2]))
1087
- {
1088
- $url = 'mailto:' . $url;
1089
- }
1090
-
1091
- return array(
1092
- 'extent' => strlen($matches[0]),
1093
- 'element' => array(
1094
- 'name' => 'a',
1095
- 'text' => $matches[1],
1096
- 'attributes' => array(
1097
- 'href' => $url,
1098
- ),
1099
- ),
1100
- );
1101
- }
1102
- }
1103
-
1104
- protected function inlineEmphasis($Excerpt)
1105
- {
1106
- if ( ! isset($Excerpt['text'][1]))
1107
- {
1108
- return;
1109
- }
1110
-
1111
- $marker = $Excerpt['text'][0];
1112
-
1113
- if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches))
1114
- {
1115
- $emphasis = 'strong';
1116
- }
1117
- elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches))
1118
- {
1119
- $emphasis = 'em';
1120
- }
1121
- else
1122
- {
1123
- return;
1124
- }
1125
-
1126
- return array(
1127
- 'extent' => strlen($matches[0]),
1128
- 'element' => array(
1129
- 'name' => $emphasis,
1130
- 'handler' => 'line',
1131
- 'text' => $matches[1],
1132
- ),
1133
- );
1134
- }
1135
-
1136
- protected function inlineEscapeSequence($Excerpt)
1137
- {
1138
- if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters))
1139
- {
1140
- return array(
1141
- 'markup' => $Excerpt['text'][1],
1142
- 'extent' => 2,
1143
- );
1144
- }
1145
- }
1146
-
1147
- protected function inlineImage($Excerpt)
1148
- {
1149
- if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[')
1150
- {
1151
- return;
1152
- }
1153
-
1154
- $Excerpt['text']= substr($Excerpt['text'], 1);
1155
-
1156
- $Link = $this->inlineLink($Excerpt);
1157
-
1158
- if ($Link === null)
1159
- {
1160
- return;
1161
- }
1162
-
1163
- $Inline = array(
1164
- 'extent' => $Link['extent'] + 1,
1165
- 'element' => array(
1166
- 'name' => 'img',
1167
- 'attributes' => array(
1168
- 'src' => $Link['element']['attributes']['href'],
1169
- 'alt' => $Link['element']['text'],
1170
- ),
1171
- ),
1172
- );
1173
-
1174
- $Inline['element']['attributes'] += $Link['element']['attributes'];
1175
-
1176
- unset($Inline['element']['attributes']['href']);
1177
-
1178
- return $Inline;
1179
- }
1180
-
1181
- protected function inlineLink($Excerpt)
1182
- {
1183
- $Element = array(
1184
- 'name' => 'a',
1185
- 'handler' => 'line',
1186
- 'text' => null,
1187
- 'attributes' => array(
1188
- 'href' => null,
1189
- 'title' => null,
1190
- ),
1191
- );
1192
-
1193
- $extent = 0;
1194
-
1195
- $remainder = $Excerpt['text'];
1196
-
1197
- if (preg_match('/\[((?:[^][]|(?R))*)\]/', $remainder, $matches))
1198
- {
1199
- $Element['text'] = $matches[1];
1200
-
1201
- $extent += strlen($matches[0]);
1202
-
1203
- $remainder = substr($remainder, $extent);
1204
- }
1205
- else
1206
- {
1207
- return;
1208
- }
1209
-
1210
- if (preg_match('/^[(]((?:[^ ()]|[(][^ )]+[)])+)(?:[ ]+("[^"]*"|\'[^\']*\'))?[)]/', $remainder, $matches))
1211
- {
1212
- $Element['attributes']['href'] = $matches[1];
1213
-
1214
- if (isset($matches[2]))
1215
- {
1216
- $Element['attributes']['title'] = substr($matches[2], 1, - 1);
1217
- }
1218
-
1219
- $extent += strlen($matches[0]);
1220
- }
1221
- else
1222
- {
1223
- if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
1224
- {
1225
- $definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
1226
- $definition = strtolower($definition);
1227
-
1228
- $extent += strlen($matches[0]);
1229
- }
1230
- else
1231
- {
1232
- $definition = strtolower($Element['text']);
1233
- }
1234
-
1235
- if ( ! isset($this->DefinitionData['Reference'][$definition]))
1236
- {
1237
- return;
1238
- }
1239
-
1240
- $Definition = $this->DefinitionData['Reference'][$definition];
1241
-
1242
- $Element['attributes']['href'] = $Definition['url'];
1243
- $Element['attributes']['title'] = $Definition['title'];
1244
- }
1245
-
1246
- $Element['attributes']['href'] = str_replace(array('&', '<'), array('&amp;', '&lt;'), $Element['attributes']['href']);
1247
-
1248
- return array(
1249
- 'extent' => $extent,
1250
- 'element' => $Element,
1251
- );
1252
- }
1253
-
1254
- protected function inlineMarkup($Excerpt)
1255
- {
1256
- if ($this->markupEscaped or strpos($Excerpt['text'], '>') === false)
1257
- {
1258
- return;
1259
- }
1260
-
1261
- if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w*[ ]*>/s', $Excerpt['text'], $matches))
1262
- {
1263
- return array(
1264
- 'markup' => $matches[0],
1265
- 'extent' => strlen($matches[0]),
1266
- );
1267
- }
1268
-
1269
- if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches))
1270
- {
1271
- return array(
1272
- 'markup' => $matches[0],
1273
- 'extent' => strlen($matches[0]),
1274
- );
1275
- }
1276
-
1277
- if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
1278
- {
1279
- return array(
1280
- 'markup' => $matches[0],
1281
- 'extent' => strlen($matches[0]),
1282
- );
1283
- }
1284
- }
1285
-
1286
- protected function inlineSpecialCharacter($Excerpt)
1287
- {
1288
- if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text']))
1289
- {
1290
- return array(
1291
- 'markup' => '&amp;',
1292
- 'extent' => 1,
1293
- );
1294
- }
1295
-
1296
- $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
1297
-
1298
- if (isset($SpecialCharacter[$Excerpt['text'][0]]))
1299
- {
1300
- return array(
1301
- 'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';',
1302
- 'extent' => 1,
1303
- );
1304
- }
1305
- }
1306
-
1307
- protected function inlineStrikethrough($Excerpt)
1308
- {
1309
- if ( ! isset($Excerpt['text'][1]))
1310
- {
1311
- return;
1312
- }
1313
-
1314
- if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches))
1315
- {
1316
- return array(
1317
- 'extent' => strlen($matches[0]),
1318
- 'element' => array(
1319
- 'name' => 'del',
1320
- 'text' => $matches[1],
1321
- 'handler' => 'line',
1322
- ),
1323
- );
1324
- }
1325
- }
1326
-
1327
- protected function inlineUrl($Excerpt)
1328
- {
1329
- if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/')
1330
- {
1331
- return;
1332
- }
1333
-
1334
- if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))
1335
- {
1336
- $Inline = array(
1337
- 'extent' => strlen($matches[0][0]),
1338
- 'position' => $matches[0][1],
1339
- 'element' => array(
1340
- 'name' => 'a',
1341
- 'text' => $matches[0][0],
1342
- 'attributes' => array(
1343
- 'href' => $matches[0][0],
1344
- ),
1345
- ),
1346
- );
1347
-
1348
- return $Inline;
1349
- }
1350
- }
1351
-
1352
- protected function inlineUrlTag($Excerpt)
1353
- {
1354
- if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))
1355
- {
1356
- $url = str_replace(array('&', '<'), array('&amp;', '&lt;'), $matches[1]);
1357
-
1358
- return array(
1359
- 'extent' => strlen($matches[0]),
1360
- 'element' => array(
1361
- 'name' => 'a',
1362
- 'text' => $url,
1363
- 'attributes' => array(
1364
- 'href' => $url,
1365
- ),
1366
- ),
1367
- );
1368
- }
1369
- }
1370
-
1371
- # ~
1372
-
1373
- protected function unmarkedText($text)
1374
- {
1375
- if ($this->breaksEnabled)
1376
- {
1377
- $text = preg_replace('/[ ]*\n/', "<br />\n", $text);
1378
- }
1379
- else
1380
- {
1381
- $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "<br />\n", $text);
1382
- $text = str_replace(" \n", "\n", $text);
1383
- }
1384
-
1385
- return $text;
1386
- }
1387
-
1388
- #
1389
- # Handlers
1390
- #
1391
-
1392
- protected function element(array $Element)
1393
- {
1394
- $markup = '<'.$Element['name'];
1395
-
1396
- if (isset($Element['attributes']))
1397
- {
1398
- foreach ($Element['attributes'] as $name => $value)
1399
- {
1400
- if ($value === null)
1401
- {
1402
- continue;
1403
- }
1404
-
1405
- $markup .= ' '.$name.'="'.$value.'"';
1406
- }
1407
- }
1408
-
1409
- if (isset($Element['text']))
1410
- {
1411
- $markup .= '>';
1412
-
1413
- if (isset($Element['handler']))
1414
- {
1415
- $markup .= $this->{$Element['handler']}($Element['text']);
1416
- }
1417
- else
1418
- {
1419
- $markup .= $Element['text'];
1420
- }
1421
-
1422
- $markup .= '</'.$Element['name'].'>';
1423
- }
1424
- else
1425
- {
1426
- $markup .= ' />';
1427
- }
1428
-
1429
- return $markup;
1430
- }
1431
-
1432
- protected function elements(array $Elements)
1433
- {
1434
- $markup = '';
1435
-
1436
- foreach ($Elements as $Element)
1437
- {
1438
- $markup .= "\n" . $this->element($Element);
1439
- }
1440
-
1441
- $markup .= "\n";
1442
-
1443
- return $markup;
1444
- }
1445
-
1446
- # ~
1447
-
1448
- protected function li($lines)
1449
- {
1450
- $markup = $this->lines($lines);
1451
-
1452
- $trimmedMarkup = trim($markup);
1453
-
1454
- if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '<p>')
1455
- {
1456
- $markup = $trimmedMarkup;
1457
- $markup = substr($markup, 3);
1458
-
1459
- $position = strpos($markup, "</p>");
1460
-
1461
- $markup = substr_replace($markup, '', $position, 4);
1462
- }
1463
-
1464
- return $markup;
1465
- }
1466
-
1467
- #
1468
- # Deprecated Methods
1469
- #
1470
-
1471
- function parse($text)
1472
- {
1473
- $markup = $this->text($text);
1474
-
1475
- return $markup;
1476
- }
1477
-
1478
- #
1479
- # Static Methods
1480
- #
1481
-
1482
- static function instance($name = 'default')
1483
- {
1484
- if (isset(self::$instances[$name]))
1485
- {
1486
- return self::$instances[$name];
1487
- }
1488
-
1489
- $instance = new static();
1490
-
1491
- self::$instances[$name] = $instance;
1492
-
1493
- return $instance;
1494
- }
1495
-
1496
- private static $instances = array();
1497
-
1498
- #
1499
- # Fields
1500
- #
1501
-
1502
- protected $DefinitionData;
1503
-
1504
- #
1505
- # Read-Only
1506
-
1507
- protected $specialCharacters = array(
1508
- '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|',
1509
- );
1510
-
1511
- protected $StrongRegex = array(
1512
- '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',
1513
- '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us',
1514
- );
1515
-
1516
- protected $EmRegex = array(
1517
- '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s',
1518
- '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us',
1519
- );
1520
-
1521
- protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?';
1522
-
1523
- protected $voidElements = array(
1524
- 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source',
1525
- );
1526
-
1527
- protected $textLevelElements = array(
1528
- 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',
1529
- 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
1530
- 'i', 'rp', 'del', 'code', 'strike', 'marquee',
1531
- 'q', 'rt', 'ins', 'font', 'strong',
1532
- 's', 'tt', 'sub', 'mark',
1533
- 'u', 'xm', 'sup', 'nobr',
1534
- 'var', 'ruby',
1535
- 'wbr', 'span',
1536
- 'time',
1537
- );
1538
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/vendor/ParsedownLegacy.php DELETED
@@ -1,1535 +0,0 @@
1
- <?php
2
-
3
- #
4
- #
5
- # Parsedown
6
- # http://parsedown.org
7
- #
8
- # (c) Emanuil Rusev
9
- # http://erusev.com
10
- #
11
- # For the full license information, view the LICENSE file that was distributed
12
- # with this source code.
13
- #
14
- #
15
-
16
- class Parsedown
17
- {
18
- # ~
19
-
20
- const version = '1.5.0';
21
-
22
- # ~
23
-
24
- function text($text)
25
- {
26
- # make sure no definitions are set
27
- $this->DefinitionData = array();
28
-
29
- # standardize line breaks
30
- $text = str_replace(array("\r\n", "\r"), "\n", $text);
31
-
32
- # remove surrounding line breaks
33
- $text = trim($text, "\n");
34
-
35
- # split text into lines
36
- $lines = explode("\n", $text);
37
-
38
- # iterate through lines to identify blocks
39
- $markup = $this->lines($lines);
40
-
41
- # trim line breaks
42
- $markup = trim($markup, "\n");
43
-
44
- return $markup;
45
- }
46
-
47
- #
48
- # Setters
49
- #
50
-
51
- function setBreaksEnabled($breaksEnabled)
52
- {
53
- $this->breaksEnabled = $breaksEnabled;
54
-
55
- return $this;
56
- }
57
-
58
- protected $breaksEnabled;
59
-
60
- function setMarkupEscaped($markupEscaped)
61
- {
62
- $this->markupEscaped = $markupEscaped;
63
-
64
- return $this;
65
- }
66
-
67
- protected $markupEscaped;
68
-
69
- function setUrlsLinked($urlsLinked)
70
- {
71
- $this->urlsLinked = $urlsLinked;
72
-
73
- return $this;
74
- }
75
-
76
- protected $urlsLinked = true;
77
-
78
- #
79
- # Lines
80
- #
81
-
82
- protected $BlockTypes = array(
83
- '#' => array('Header'),
84
- '*' => array('Rule', 'List'),
85
- '+' => array('List'),
86
- '-' => array('SetextHeader', 'Table', 'Rule', 'List'),
87
- '0' => array('List'),
88
- '1' => array('List'),
89
- '2' => array('List'),
90
- '3' => array('List'),
91
- '4' => array('List'),
92
- '5' => array('List'),
93
- '6' => array('List'),
94
- '7' => array('List'),
95
- '8' => array('List'),
96
- '9' => array('List'),
97
- ':' => array('Table'),
98
- '<' => array('Comment', 'Markup'),
99
- '=' => array('SetextHeader'),
100
- '>' => array('Quote'),
101
- '[' => array('Reference'),
102
- '_' => array('Rule'),
103
- '`' => array('FencedCode'),
104
- '|' => array('Table'),
105
- '~' => array('FencedCode'),
106
- );
107
-
108
- # ~
109
-
110
- protected $DefinitionTypes = array(
111
- '[' => array('Reference'),
112
- );
113
-
114
- # ~
115
-
116
- protected $unmarkedBlockTypes = array(
117
- 'Code',
118
- );
119
-
120
- #
121
- # Blocks
122
- #
123
-
124
- private function lines(array $lines)
125
- {
126
- $CurrentBlock = null;
127
-
128
- foreach ($lines as $line)
129
- {
130
- if (chop($line) === '')
131
- {
132
- if (isset($CurrentBlock))
133
- {
134
- $CurrentBlock['interrupted'] = true;
135
- }
136
-
137
- continue;
138
- }
139
-
140
- if (strpos($line, "\t") !== false)
141
- {
142
- $parts = explode("\t", $line);
143
-
144
- $line = $parts[0];
145
-
146
- unset($parts[0]);
147
-
148
- foreach ($parts as $part)
149
- {
150
- $shortage = 4 - mb_strlen($line, 'utf-8') % 4;
151
-
152
- $line .= str_repeat(' ', $shortage);
153
- $line .= $part;
154
- }
155
- }
156
-
157
- $indent = 0;
158
-
159
- while (isset($line[$indent]) and $line[$indent] === ' ')
160
- {
161
- $indent ++;
162
- }
163
-
164
- $text = $indent > 0 ? substr($line, $indent) : $line;
165
-
166
- # ~
167
-
168
- $Line = array('body' => $line, 'indent' => $indent, 'text' => $text);
169
-
170
- # ~
171
-
172
- if (isset($CurrentBlock['incomplete']))
173
- {
174
- $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock);
175
-
176
- if (isset($Block))
177
- {
178
- $CurrentBlock = $Block;
179
-
180
- continue;
181
- }
182
- else
183
- {
184
- if (method_exists($this, 'block'.$CurrentBlock['type'].'Complete'))
185
- {
186
- $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
187
- }
188
-
189
- unset($CurrentBlock['incomplete']);
190
- }
191
- }
192
-
193
- # ~
194
-
195
- $marker = $text[0];
196
-
197
- # ~
198
-
199
- $blockTypes = $this->unmarkedBlockTypes;
200
-
201
- if (isset($this->BlockTypes[$marker]))
202
- {
203
- foreach ($this->BlockTypes[$marker] as $blockType)
204
- {
205
- $blockTypes []= $blockType;
206
- }
207
- }
208
-
209
- #
210
- # ~
211
-
212
- foreach ($blockTypes as $blockType)
213
- {
214
- $Block = $this->{'block'.$blockType}($Line, $CurrentBlock);
215
-
216
- if (isset($Block))
217
- {
218
- $Block['type'] = $blockType;
219
-
220
- if ( ! isset($Block['identified']))
221
- {
222
- $Blocks []= $CurrentBlock;
223
-
224
- $Block['identified'] = true;
225
- }
226
-
227
- if (method_exists($this, 'block'.$blockType.'Continue'))
228
- {
229
- $Block['incomplete'] = true;
230
- }
231
-
232
- $CurrentBlock = $Block;
233
-
234
- continue 2;
235
- }
236
- }
237
-
238
- # ~
239
-
240
- if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted']))
241
- {
242
- $CurrentBlock['element']['text'] .= "\n".$text;
243
- }
244
- else
245
- {
246
- $Blocks []= $CurrentBlock;
247
-
248
- $CurrentBlock = $this->paragraph($Line);
249
-
250
- $CurrentBlock['identified'] = true;
251
- }
252
- }
253
-
254
- # ~
255
-
256
- if (isset($CurrentBlock['incomplete']) and method_exists($this, 'block'.$CurrentBlock['type'].'Complete'))
257
- {
258
- $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
259
- }
260
-
261
- # ~
262
-
263
- $Blocks []= $CurrentBlock;
264
-
265
- unset($Blocks[0]);
266
-
267
- # ~
268
-
269
- $markup = '';
270
-
271
- foreach ($Blocks as $Block)
272
- {
273
- if (isset($Block['hidden']))
274
- {
275
- continue;
276
- }
277
-
278
- $markup .= "\n";
279
- $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
280
- }
281
-
282
- $markup .= "\n";
283
-
284
- # ~
285
-
286
- return $markup;
287
- }
288
-
289
- #
290
- # Code
291
-
292
- protected function blockCode($Line, $Block = null)
293
- {
294
- if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted']))
295
- {
296
- return;
297
- }
298
-
299
- if ($Line['indent'] >= 4)
300
- {
301
- $text = substr($Line['body'], 4);
302
-
303
- $Block = array(
304
- 'element' => array(
305
- 'name' => 'pre',
306
- 'handler' => 'element',
307
- 'text' => array(
308
- 'name' => 'code',
309
- 'text' => $text,
310
- ),
311
- ),
312
- );
313
-
314
- return $Block;
315
- }
316
- }
317
-
318
- protected function blockCodeContinue($Line, $Block)
319
- {
320
- if ($Line['indent'] >= 4)
321
- {
322
- if (isset($Block['interrupted']))
323
- {
324
- $Block['element']['text']['text'] .= "\n";
325
-
326
- unset($Block['interrupted']);
327
- }
328
-
329
- $Block['element']['text']['text'] .= "\n";
330
-
331
- $text = substr($Line['body'], 4);
332
-
333
- $Block['element']['text']['text'] .= $text;
334
-
335
- return $Block;
336
- }
337
- }
338
-
339
- protected function blockCodeComplete($Block)
340
- {
341
- $text = $Block['element']['text']['text'];
342
-
343
- $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
344
-
345
- $Block['element']['text']['text'] = $text;
346
-
347
- return $Block;
348
- }
349
-
350
- #
351
- # Comment
352
-
353
- protected function blockComment($Line)
354
- {
355
- if ($this->markupEscaped)
356
- {
357
- return;
358
- }
359
-
360
- if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!')
361
- {
362
- $Block = array(
363
- 'markup' => $Line['body'],
364
- );
365
-
366
- if (preg_match('/-->$/', $Line['text']))
367
- {
368
- $Block['closed'] = true;
369
- }
370
-
371
- return $Block;
372
- }
373
- }
374
-
375
- protected function blockCommentContinue($Line, array $Block)
376
- {
377
- if (isset($Block['closed']))
378
- {
379
- return;
380
- }
381
-
382
- $Block['markup'] .= "\n" . $Line['body'];
383
-
384
- if (preg_match('/-->$/', $Line['text']))
385
- {
386
- $Block['closed'] = true;
387
- }
388
-
389
- return $Block;
390
- }
391
-
392
- #
393
- # Fenced Code
394
-
395
- protected function blockFencedCode($Line)
396
- {
397
- if (preg_match('/^(['.$Line['text'][0].']{3,})[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches))
398
- {
399
- $Element = array(
400
- 'name' => 'code',
401
- 'text' => '',
402
- );
403
-
404
- if (isset($matches[2]))
405
- {
406
- $class = 'language-'.$matches[2];
407
-
408
- $Element['attributes'] = array(
409
- 'class' => $class,
410
- );
411
- }
412
-
413
- $Block = array(
414
- 'char' => $Line['text'][0],
415
- 'element' => array(
416
- 'name' => 'pre',
417
- 'handler' => 'element',
418
- 'text' => $Element,
419
- ),
420
- );
421
-
422
- return $Block;
423
- }
424
- }
425
-
426
- protected function blockFencedCodeContinue($Line, $Block)
427
- {
428
- if (isset($Block['complete']))
429
- {
430
- return;
431
- }
432
-
433
- if (isset($Block['interrupted']))
434
- {
435
- $Block['element']['text']['text'] .= "\n";
436
-
437
- unset($Block['interrupted']);
438
- }
439
-
440
- if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))
441
- {
442
- $Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1);
443
-
444
- $Block['complete'] = true;
445
-
446
- return $Block;
447
- }
448
-
449
- $Block['element']['text']['text'] .= "\n".$Line['body'];;
450
-
451
- return $Block;
452
- }
453
-
454
- protected function blockFencedCodeComplete($Block)
455
- {
456
- $text = $Block['element']['text']['text'];
457
-
458
- $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
459
-
460
- $Block['element']['text']['text'] = $text;
461
-
462
- return $Block;
463
- }
464
-
465
- #
466
- # Header
467
-
468
- protected function blockHeader($Line)
469
- {
470
- if (isset($Line['text'][1]))
471
- {
472
- $level = 1;
473
-
474
- while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')
475
- {
476
- $level ++;
477
- }
478
-
479
- if ($level > 6)
480
- {
481
- return;
482
- }
483
-
484
- $text = trim($Line['text'], '# ');
485
-
486
- $Block = array(
487
- 'element' => array(
488
- 'name' => 'h' . min(6, $level),
489
- 'text' => $text,
490
- 'handler' => 'line',
491
- ),
492
- );
493
-
494
- return $Block;
495
- }
496
- }
497
-
498
- #
499
- # List
500
-
501
- protected function blockList($Line)
502
- {
503
- list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');
504
-
505
- if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches))
506
- {
507
- $Block = array(
508
- 'indent' => $Line['indent'],
509
- 'pattern' => $pattern,
510
- 'element' => array(
511
- 'name' => $name,
512
- 'handler' => 'elements',
513
- ),
514
- );
515
-
516
- $Block['li'] = array(
517
- 'name' => 'li',
518
- 'handler' => 'li',
519
- 'text' => array(
520
- $matches[2],
521
- ),
522
- );
523
-
524
- $Block['element']['text'] []= & $Block['li'];
525
-
526
- return $Block;
527
- }
528
- }
529
-
530
- protected function blockListContinue($Line, array $Block)
531
- {
532
- if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches))
533
- {
534
- if (isset($Block['interrupted']))
535
- {
536
- $Block['li']['text'] []= '';
537
-
538
- unset($Block['interrupted']);
539
- }
540
-
541
- unset($Block['li']);
542
-
543
- $text = isset($matches[1]) ? $matches[1] : '';
544
-
545
- $Block['li'] = array(
546
- 'name' => 'li',
547
- 'handler' => 'li',
548
- 'text' => array(
549
- $text,
550
- ),
551
- );
552
-
553
- $Block['element']['text'] []= & $Block['li'];
554
-
555
- return $Block;
556
- }
557
-
558
- if ($Line['text'][0] === '[' and $this->blockReference($Line))
559
- {
560
- return $Block;
561
- }
562
-
563
- if ( ! isset($Block['interrupted']))
564
- {
565
- $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
566
-
567
- $Block['li']['text'] []= $text;
568
-
569
- return $Block;
570
- }
571
-
572
- if ($Line['indent'] > 0)
573
- {
574
- $Block['li']['text'] []= '';
575
-
576
- $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
577
-
578
- $Block['li']['text'] []= $text;
579
-
580
- unset($Block['interrupted']);
581
-
582
- return $Block;
583
- }
584
- }
585
-
586
- #
587
- # Quote
588
-
589
- protected function blockQuote($Line)
590
- {
591
- if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
592
- {
593
- $Block = array(
594
- 'element' => array(
595
- 'name' => 'blockquote',
596
- 'handler' => 'lines',
597
- 'text' => (array) $matches[1],
598
- ),
599
- );
600
-
601
- return $Block;
602
- }
603
- }
604
-
605
- protected function blockQuoteContinue($Line, array $Block)
606
- {
607
- if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
608
- {
609
- if (isset($Block['interrupted']))
610
- {
611
- $Block['element']['text'] []= '';
612
-
613
- unset($Block['interrupted']);
614
- }
615
-
616
- $Block['element']['text'] []= $matches[1];
617
-
618
- return $Block;
619
- }
620
-
621
- if ( ! isset($Block['interrupted']))
622
- {
623
- $Block['element']['text'] []= $Line['text'];
624
-
625
- return $Block;
626
- }
627
- }
628
-
629
- #
630
- # Rule
631
-
632
- protected function blockRule($Line)
633
- {
634
- if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text']))
635
- {
636
- $Block = array(
637
- 'element' => array(
638
- 'name' => 'hr'
639
- ),
640
- );
641
-
642
- return $Block;
643
- }
644
- }
645
-
646
- #
647
- # Setext
648
-
649
- protected function blockSetextHeader($Line, array $Block = null)
650
- {
651
- if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
652
- {
653
- return;
654
- }
655
-
656
- if (chop($Line['text'], $Line['text'][0]) === '')
657
- {
658
- $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
659
-
660
- return $Block;
661
- }
662
- }
663
-
664
- #
665
- # Markup
666
-
667
- protected function blockMarkup($Line)
668
- {
669
- if ($this->markupEscaped)
670
- {
671
- return;
672
- }
673
-
674
- if (preg_match('/^<(\w*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
675
- {
676
- if (in_array($matches[1], $this->textLevelElements))
677
- {
678
- return;
679
- }
680
-
681
- $Block = array(
682
- 'name' => $matches[1],
683
- 'depth' => 0,
684
- 'markup' => $Line['text'],
685
- );
686
-
687
- $length = strlen($matches[0]);
688
-
689
- $remainder = substr($Line['text'], $length);
690
-
691
- if (trim($remainder) === '')
692
- {
693
- if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
694
- {
695
- $Block['closed'] = true;
696
-
697
- $Block['void'] = true;
698
- }
699
- }
700
- else
701
- {
702
- if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
703
- {
704
- return;
705
- }
706
-
707
- if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder))
708
- {
709
- $Block['closed'] = true;
710
- }
711
- }
712
-
713
- return $Block;
714
- }
715
- }
716
-
717
- protected function blockMarkupContinue($Line, array $Block)
718
- {
719
- if (isset($Block['closed']))
720
- {
721
- return;
722
- }
723
-
724
- if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open
725
- {
726
- $Block['depth'] ++;
727
- }
728
-
729
- if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close
730
- {
731
- if ($Block['depth'] > 0)
732
- {
733
- $Block['depth'] --;
734
- }
735
- else
736
- {
737
- $Block['closed'] = true;
738
- }
739
-
740
- $Block['markup'] .= $matches[1];
741
- }
742
-
743
- if (isset($Block['interrupted']))
744
- {
745
- $Block['markup'] .= "\n";
746
-
747
- unset($Block['interrupted']);
748
- }
749
-
750
- $Block['markup'] .= "\n".$Line['body'];
751
-
752
- return $Block;
753
- }
754
-
755
- #
756
- # Reference
757
-
758
- protected function blockReference($Line)
759
- {
760
- if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches))
761
- {
762
- $id = strtolower($matches[1]);
763
-
764
- $Data = array(
765
- 'url' => $matches[2],
766
- 'title' => null,
767
- );
768
-
769
- if (isset($matches[3]))
770
- {
771
- $Data['title'] = $matches[3];
772
- }
773
-
774
- $this->DefinitionData['Reference'][$id] = $Data;
775
-
776
- $Block = array(
777
- 'hidden' => true,
778
- );
779
-
780
- return $Block;
781
- }
782
- }
783
-
784
- #
785
- # Table
786
-
787
- protected function blockTable($Line, array $Block = null)
788
- {
789
- if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
790
- {
791
- return;
792
- }
793
-
794
- if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '')
795
- {
796
- $alignments = array();
797
-
798
- $divider = $Line['text'];
799
-
800
- $divider = trim($divider);
801
- $divider = trim($divider, '|');
802
-
803
- $dividerCells = explode('|', $divider);
804
-
805
- foreach ($dividerCells as $dividerCell)
806
- {
807
- $dividerCell = trim($dividerCell);
808
-
809
- if ($dividerCell === '')
810
- {
811
- continue;
812
- }
813
-
814
- $alignment = null;
815
-
816
- if ($dividerCell[0] === ':')
817
- {
818
- $alignment = 'left';
819
- }
820
-
821
- if (substr($dividerCell, - 1) === ':')
822
- {
823
- $alignment = $alignment === 'left' ? 'center' : 'right';
824
- }
825
-
826
- $alignments []= $alignment;
827
- }
828
-
829
- # ~
830
-
831
- $HeaderElements = array();
832
-
833
- $header = $Block['element']['text'];
834
-
835
- $header = trim($header);
836
- $header = trim($header, '|');
837
-
838
- $headerCells = explode('|', $header);
839
-
840
- foreach ($headerCells as $index => $headerCell)
841
- {
842
- $headerCell = trim($headerCell);
843
-
844
- $HeaderElement = array(
845
- 'name' => 'th',
846
- 'text' => $headerCell,
847
- 'handler' => 'line',
848
- );
849
-
850
- if (isset($alignments[$index]))
851
- {
852
- $alignment = $alignments[$index];
853
-
854
- $HeaderElement['attributes'] = array(
855
- 'style' => 'text-align: '.$alignment.';',
856
- );
857
- }
858
-
859
- $HeaderElements []= $HeaderElement;
860
- }
861
-
862
- # ~
863
-
864
- $Block = array(
865
- 'alignments' => $alignments,
866
- 'identified' => true,
867
- 'element' => array(
868
- 'name' => 'table',
869
- 'handler' => 'elements',
870
- ),
871
- );
872
-
873
- $Block['element']['text'] []= array(
874
- 'name' => 'thead',
875
- 'handler' => 'elements',
876
- );
877
-
878
- $Block['element']['text'] []= array(
879
- 'name' => 'tbody',
880
- 'handler' => 'elements',
881
- 'text' => array(),
882
- );
883
-
884
- $Block['element']['text'][0]['text'] []= array(
885
- 'name' => 'tr',
886
- 'handler' => 'elements',
887
- 'text' => $HeaderElements,
888
- );
889
-
890
- return $Block;
891
- }
892
- }
893
-
894
- protected function blockTableContinue($Line, array $Block)
895
- {
896
- if (isset($Block['interrupted']))
897
- {
898
- return;
899
- }
900
-
901
- if ($Line['text'][0] === '|' or strpos($Line['text'], '|'))
902
- {
903
- $Elements = array();
904
-
905
- $row = $Line['text'];
906
-
907
- $row = trim($row);
908
- $row = trim($row, '|');
909
-
910
- preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);
911
-
912
- foreach ($matches[0] as $index => $cell)
913
- {
914
- $cell = trim($cell);
915
-
916
- $Element = array(
917
- 'name' => 'td',
918
- 'handler' => 'line',
919
- 'text' => $cell,
920
- );
921
-
922
- if (isset($Block['alignments'][$index]))
923
- {
924
- $Element['attributes'] = array(
925
- 'style' => 'text-align: '.$Block['alignments'][$index].';',
926
- );
927
- }
928
-
929
- $Elements []= $Element;
930
- }
931
-
932
- $Element = array(
933
- 'name' => 'tr',
934
- 'handler' => 'elements',
935
- 'text' => $Elements,
936
- );
937
-
938
- $Block['element']['text'][1]['text'] []= $Element;
939
-
940
- return $Block;
941
- }
942
- }
943
-
944
- #
945
- # ~
946
- #
947
-
948
- protected function paragraph($Line)
949
- {
950
- $Block = array(
951
- 'element' => array(
952
- 'name' => 'p',
953
- 'text' => $Line['text'],
954
- 'handler' => 'line',
955
- ),
956
- );
957
-
958
- return $Block;
959
- }
960
-
961
- #
962
- # Inline Elements
963
- #
964
-
965
- protected $InlineTypes = array(
966
- '"' => array('SpecialCharacter'),
967
- '!' => array('Image'),
968
- '&' => array('SpecialCharacter'),
969
- '*' => array('Emphasis'),
970
- ':' => array('Url'),
971
- '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'),
972
- '>' => array('SpecialCharacter'),
973
- '[' => array('Link'),
974
- '_' => array('Emphasis'),
975
- '`' => array('Code'),
976
- '~' => array('Strikethrough'),
977
- '\\' => array('EscapeSequence'),
978
- );
979
-
980
- # ~
981
-
982
- protected $inlineMarkerList = '!"*_&[:<>`~\\';
983
-
984
- #
985
- # ~
986
- #
987
-
988
- public function line($text)
989
- {
990
- $markup = '';
991
-
992
- $unexaminedText = $text;
993
-
994
- $markerPosition = 0;
995
-
996
- while ($excerpt = strpbrk($unexaminedText, $this->inlineMarkerList))
997
- {
998
- $marker = $excerpt[0];
999
-
1000
- $markerPosition += strpos($unexaminedText, $marker);
1001
-
1002
- $Excerpt = array('text' => $excerpt, 'context' => $text);
1003
-
1004
- foreach ($this->InlineTypes[$marker] as $inlineType)
1005
- {
1006
- $Inline = $this->{'inline'.$inlineType}($Excerpt);
1007
-
1008
- if ( ! isset($Inline))
1009
- {
1010
- continue;
1011
- }
1012
-
1013
- if (isset($Inline['position']) and $Inline['position'] > $markerPosition) # position is ahead of marker
1014
- {
1015
- continue;
1016
- }
1017
-
1018
- if ( ! isset($Inline['position']))
1019
- {
1020
- $Inline['position'] = $markerPosition;
1021
- }
1022
-
1023
- $unmarkedText = substr($text, 0, $Inline['position']);
1024
-
1025
- $markup .= $this->unmarkedText($unmarkedText);
1026
-
1027
- $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
1028
-
1029
- $text = substr($text, $Inline['position'] + $Inline['extent']);
1030
-
1031
- $unexaminedText = $text;
1032
-
1033
- $markerPosition = 0;
1034
-
1035
- continue 2;
1036
- }
1037
-
1038
- $unexaminedText = substr($excerpt, 1);
1039
-
1040
- $markerPosition ++;
1041
- }
1042
-
1043
- $markup .= $this->unmarkedText($text);
1044
-
1045
- return $markup;
1046
- }
1047
-
1048
- #
1049
- # ~
1050
- #
1051
-
1052
- protected function inlineCode($Excerpt)
1053
- {
1054
- $marker = $Excerpt['text'][0];
1055
-
1056
- if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
1057
- {
1058
- $text = $matches[2];
1059
- $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
1060
- $text = preg_replace("/[ ]*\n/", ' ', $text);
1061
-
1062
- return array(
1063
- 'extent' => strlen($matches[0]),
1064
- 'element' => array(
1065
- 'name' => 'code',
1066
- 'text' => $text,
1067
- ),
1068
- );
1069
- }
1070
- }
1071
-
1072
- protected function inlineEmailTag($Excerpt)
1073
- {
1074
- if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
1075
- {
1076
- $url = $matches[1];
1077
-
1078
- if ( ! isset($matches[2]))
1079
- {
1080
- $url = 'mailto:' . $url;
1081
- }
1082
-
1083
- return array(
1084
- 'extent' => strlen($matches[0]),
1085
- 'element' => array(
1086
- 'name' => 'a',
1087
- 'text' => $matches[1],
1088
- 'attributes' => array(
1089
- 'href' => $url,
1090
- ),
1091
- ),
1092
- );
1093
- }
1094
- }
1095
-
1096
- protected function inlineEmphasis($Excerpt)
1097
- {
1098
- if ( ! isset($Excerpt['text'][1]))
1099
- {
1100
- return;
1101
- }
1102
-
1103
- $marker = $Excerpt['text'][0];
1104
-
1105
- if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches))
1106
- {
1107
- $emphasis = 'strong';
1108
- }
1109
- elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches))
1110
- {
1111
- $emphasis = 'em';
1112
- }
1113
- else
1114
- {
1115
- return;
1116
- }
1117
-
1118
- return array(
1119
- 'extent' => strlen($matches[0]),
1120
- 'element' => array(
1121
- 'name' => $emphasis,
1122
- 'handler' => 'line',
1123
- 'text' => $matches[1],
1124
- ),
1125
- );
1126
- }
1127
-
1128
- protected function inlineEscapeSequence($Excerpt)
1129
- {
1130
- if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters))
1131
- {
1132
- return array(
1133
- 'markup' => $Excerpt['text'][1],
1134
- 'extent' => 2,
1135
- );
1136
- }
1137
- }
1138
-
1139
- protected function inlineImage($Excerpt)
1140
- {
1141
- if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[')
1142
- {
1143
- return;
1144
- }
1145
-
1146
- $Excerpt['text']= substr($Excerpt['text'], 1);
1147
-
1148
- $Link = $this->inlineLink($Excerpt);
1149
-
1150
- if ($Link === null)
1151
- {
1152
- return;
1153
- }
1154
-
1155
- $Inline = array(
1156
- 'extent' => $Link['extent'] + 1,
1157
- 'element' => array(
1158
- 'name' => 'img',
1159
- 'attributes' => array(
1160
- 'src' => $Link['element']['attributes']['href'],
1161
- 'alt' => $Link['element']['text'],
1162
- ),
1163
- ),
1164
- );
1165
-
1166
- $Inline['element']['attributes'] += $Link['element']['attributes'];
1167
-
1168
- unset($Inline['element']['attributes']['href']);
1169
-
1170
- return $Inline;
1171
- }
1172
-
1173
- protected function inlineLink($Excerpt)
1174
- {
1175
- $Element = array(
1176
- 'name' => 'a',
1177
- 'handler' => 'line',
1178
- 'text' => null,
1179
- 'attributes' => array(
1180
- 'href' => null,
1181
- 'title' => null,
1182
- ),
1183
- );
1184
-
1185
- $extent = 0;
1186
-
1187
- $remainder = $Excerpt['text'];
1188
-
1189
- if (preg_match('/\[((?:[^][]|(?R))*)\]/', $remainder, $matches))
1190
- {
1191
- $Element['text'] = $matches[1];
1192
-
1193
- $extent += strlen($matches[0]);
1194
-
1195
- $remainder = substr($remainder, $extent);
1196
- }
1197
- else
1198
- {
1199
- return;
1200
- }
1201
-
1202
- if (preg_match('/^[(]((?:[^ (]|[(][^ )]+[)])+)(?:[ ]+("[^"]+"|\'[^\']+\'))?[)]/', $remainder, $matches))
1203
- {
1204
- $Element['attributes']['href'] = $matches[1];
1205
-
1206
- if (isset($matches[2]))
1207
- {
1208
- $Element['attributes']['title'] = substr($matches[2], 1, - 1);
1209
- }
1210
-
1211
- $extent += strlen($matches[0]);
1212
- }
1213
- else
1214
- {
1215
- if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
1216
- {
1217
- $definition = $matches[1] ? $matches[1] : $Element['text'];
1218
- $definition = strtolower($definition);
1219
-
1220
- $extent += strlen($matches[0]);
1221
- }
1222
- else
1223
- {
1224
- $definition = strtolower($Element['text']);
1225
- }
1226
-
1227
- if ( ! isset($this->DefinitionData['Reference'][$definition]))
1228
- {
1229
- return;
1230
- }
1231
-
1232
- $Definition = $this->DefinitionData['Reference'][$definition];
1233
-
1234
- $Element['attributes']['href'] = $Definition['url'];
1235
- $Element['attributes']['title'] = $Definition['title'];
1236
- }
1237
-
1238
- $Element['attributes']['href'] = str_replace(array('&', '<'), array('&amp;', '&lt;'), $Element['attributes']['href']);
1239
-
1240
- return array(
1241
- 'extent' => $extent,
1242
- 'element' => $Element,
1243
- );
1244
- }
1245
-
1246
- protected function inlineMarkup($Excerpt)
1247
- {
1248
- if ($this->markupEscaped or strpos($Excerpt['text'], '>') === false)
1249
- {
1250
- return;
1251
- }
1252
-
1253
- if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w*[ ]*>/s', $Excerpt['text'], $matches))
1254
- {
1255
- return array(
1256
- 'markup' => $matches[0],
1257
- 'extent' => strlen($matches[0]),
1258
- );
1259
- }
1260
-
1261
- if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches))
1262
- {
1263
- return array(
1264
- 'markup' => $matches[0],
1265
- 'extent' => strlen($matches[0]),
1266
- );
1267
- }
1268
-
1269
- if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
1270
- {
1271
- return array(
1272
- 'markup' => $matches[0],
1273
- 'extent' => strlen($matches[0]),
1274
- );
1275
- }
1276
- }
1277
-
1278
- protected function inlineSpecialCharacter($Excerpt)
1279
- {
1280
- if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text']))
1281
- {
1282
- return array(
1283
- 'markup' => '&amp;',
1284
- 'extent' => 1,
1285
- );
1286
- }
1287
-
1288
- $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
1289
-
1290
- if (isset($SpecialCharacter[$Excerpt['text'][0]]))
1291
- {
1292
- return array(
1293
- 'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';',
1294
- 'extent' => 1,
1295
- );
1296
- }
1297
- }
1298
-
1299
- protected function inlineStrikethrough($Excerpt)
1300
- {
1301
- if ( ! isset($Excerpt['text'][1]))
1302
- {
1303
- return;
1304
- }
1305
-
1306
- if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches))
1307
- {
1308
- return array(
1309
- 'extent' => strlen($matches[0]),
1310
- 'element' => array(
1311
- 'name' => 'del',
1312
- 'text' => $matches[1],
1313
- 'handler' => 'line',
1314
- ),
1315
- );
1316
- }
1317
- }
1318
-
1319
- protected function inlineUrl($Excerpt)
1320
- {
1321
- if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/')
1322
- {
1323
- return;
1324
- }
1325
-
1326
- if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))
1327
- {
1328
- $Inline = array(
1329
- 'extent' => strlen($matches[0][0]),
1330
- 'position' => $matches[0][1],
1331
- 'element' => array(
1332
- 'name' => 'a',
1333
- 'text' => $matches[0][0],
1334
- 'attributes' => array(
1335
- 'href' => $matches[0][0],
1336
- ),
1337
- ),
1338
- );
1339
-
1340
- return $Inline;
1341
- }
1342
- }
1343
-
1344
- protected function inlineUrlTag($Excerpt)
1345
- {
1346
- if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))
1347
- {
1348
- $url = str_replace(array('&', '<'), array('&amp;', '&lt;'), $matches[1]);
1349
-
1350
- return array(
1351
- 'extent' => strlen($matches[0]),
1352
- 'element' => array(
1353
- 'name' => 'a',
1354
- 'text' => $url,
1355
- 'attributes' => array(
1356
- 'href' => $url,
1357
- ),
1358
- ),
1359
- );
1360
- }
1361
- }
1362
-
1363
- #
1364
- # ~
1365
-
1366
- protected $unmarkedInlineTypes = array("\n" => 'Break', '://' => 'Url');
1367
-
1368
- # ~
1369
-
1370
- protected function unmarkedText($text)
1371
- {
1372
- if ($this->breaksEnabled)
1373
- {
1374
- $text = preg_replace('/[ ]*\n/', "<br />\n", $text);
1375
- }
1376
- else
1377
- {
1378
- $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "<br />\n", $text);
1379
- $text = str_replace(" \n", "\n", $text);
1380
- }
1381
-
1382
- return $text;
1383
- }
1384
-
1385
- #
1386
- # Handlers
1387
- #
1388
-
1389
- protected function element(array $Element)
1390
- {
1391
- $markup = '<'.$Element['name'];
1392
-
1393
- if (isset($Element['attributes']))
1394
- {
1395
- foreach ($Element['attributes'] as $name => $value)
1396
- {
1397
- if ($value === null)
1398
- {
1399
- continue;
1400
- }
1401
-
1402
- $markup .= ' '.$name.'="'.$value.'"';
1403
- }
1404
- }
1405
-
1406
- if (isset($Element['text']))
1407
- {
1408
- $markup .= '>';
1409
-
1410
- if (isset($Element['handler']))
1411
- {
1412
- $markup .= $this->$Element['handler']($Element['text']);
1413
- }
1414
- else
1415
- {
1416
- $markup .= $Element['text'];
1417
- }
1418
-
1419
- $markup .= '</'.$Element['name'].'>';
1420
- }
1421
- else
1422
- {
1423
- $markup .= ' />';
1424
- }
1425
-
1426
- return $markup;
1427
- }
1428
-
1429
- protected function elements(array $Elements)
1430
- {
1431
- $markup = '';
1432
-
1433
- foreach ($Elements as $Element)
1434
- {
1435
- $markup .= "\n" . $this->element($Element);
1436
- }
1437
-
1438
- $markup .= "\n";
1439
-
1440
- return $markup;
1441
- }
1442
-
1443
- # ~
1444
-
1445
- protected function li($lines)
1446
- {
1447
- $markup = $this->lines($lines);
1448
-
1449
- $trimmedMarkup = trim($markup);
1450
-
1451
- if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '<p>')
1452
- {
1453
- $markup = $trimmedMarkup;
1454
- $markup = substr($markup, 3);
1455
-
1456
- $position = strpos($markup, "</p>");
1457
-
1458
- $markup = substr_replace($markup, '', $position, 4);
1459
- }
1460
-
1461
- return $markup;
1462
- }
1463
-
1464
- #
1465
- # Deprecated Methods
1466
- #
1467
-
1468
- function parse($text)
1469
- {
1470
- $markup = $this->text($text);
1471
-
1472
- return $markup;
1473
- }
1474
-
1475
- #
1476
- # Static Methods
1477
- #
1478
-
1479
- static function instance($name = 'default')
1480
- {
1481
- if (isset(self::$instances[$name]))
1482
- {
1483
- return self::$instances[$name];
1484
- }
1485
-
1486
- $instance = new self();
1487
-
1488
- self::$instances[$name] = $instance;
1489
-
1490
- return $instance;
1491
- }
1492
-
1493
- private static $instances = array();
1494
-
1495
- #
1496
- # Fields
1497
- #
1498
-
1499
- protected $DefinitionData;
1500
-
1501
- #
1502
- # Read-Only
1503
-
1504
- protected $specialCharacters = array(
1505
- '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|',
1506
- );
1507
-
1508
- protected $StrongRegex = array(
1509
- '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',
1510
- '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us',
1511
- );
1512
-
1513
- protected $EmRegex = array(
1514
- '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s',
1515
- '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us',
1516
- );
1517
-
1518
- protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?';
1519
-
1520
- protected $voidElements = array(
1521
- 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source',
1522
- );
1523
-
1524
- protected $textLevelElements = array(
1525
- 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',
1526
- 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
1527
- 'i', 'rp', 'del', 'code', 'strike', 'marquee',
1528
- 'q', 'rt', 'ins', 'font', 'strong',
1529
- 's', 'tt', 'sub', 'mark',
1530
- 'u', 'xm', 'sup', 'nobr',
1531
- 'var', 'ruby',
1532
- 'wbr', 'span',
1533
- 'time',
1534
- );
1535
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-update-checker/vendor/readme-parser.php DELETED
@@ -1,331 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * This is a slightly modified version of github.com/markjaquith/WordPress-Plugin-Readme-Parser
5
- * It uses Parsedown instead of the "Markdown Extra" parser.
6
- */
7
-
8
- Class PucReadmeParser {
9
-
10
- function __construct() {
11
- // This space intentially blank
12
- }
13
-
14
- function parse_readme( $file ) {
15
- $file_contents = @implode('', @file($file));
16
- return $this->parse_readme_contents( $file_contents );
17
- }
18
-
19
- function parse_readme_contents( $file_contents ) {
20
- $file_contents = str_replace(array("\r\n", "\r"), "\n", $file_contents);
21
- $file_contents = trim($file_contents);
22
- if ( 0 === strpos( $file_contents, "\xEF\xBB\xBF" ) )
23
- $file_contents = substr( $file_contents, 3 );
24
-
25
- // Markdown transformations
26
- $file_contents = preg_replace( "|^###([^#]+)#*?\s*?\n|im", '=$1='."\n", $file_contents );
27
- $file_contents = preg_replace( "|^##([^#]+)#*?\s*?\n|im", '==$1=='."\n", $file_contents );
28
- $file_contents = preg_replace( "|^#([^#]+)#*?\s*?\n|im", '===$1==='."\n", $file_contents );
29
-
30
- // === Plugin Name ===
31
- // Must be the very first thing.
32
- if ( !preg_match('|^===(.*)===|', $file_contents, $_name) )
33
- return array(); // require a name
34
- $name = trim($_name[1], '=');
35
- $name = $this->sanitize_text( $name );
36
-
37
- $file_contents = $this->chop_string( $file_contents, $_name[0] );
38
-
39
-
40
- // Requires at least: 1.5
41
- if ( preg_match('|Requires at least:(.*)|i', $file_contents, $_requires_at_least) )
42
- $requires_at_least = $this->sanitize_text($_requires_at_least[1]);
43
- else
44
- $requires_at_least = NULL;
45
-
46
-
47
- // Tested up to: 2.1
48
- if ( preg_match('|Tested up to:(.*)|i', $file_contents, $_tested_up_to) )
49
- $tested_up_to = $this->sanitize_text( $_tested_up_to[1] );
50
- else
51
- $tested_up_to = NULL;
52
-
53
-
54
- // Stable tag: 10.4-ride-the-fire-eagle-danger-day
55
- if ( preg_match('|Stable tag:(.*)|i', $file_contents, $_stable_tag) )
56
- $stable_tag = $this->sanitize_text( $_stable_tag[1] );
57
- else
58
- $stable_tag = NULL; // we assume trunk, but don't set it here to tell the difference between specified trunk and default trunk
59
-
60
-
61
- // Tags: some tag, another tag, we like tags
62
- if ( preg_match('|Tags:(.*)|i', $file_contents, $_tags) ) {
63
- $tags = preg_split('|,[\s]*?|', trim($_tags[1]));
64
- foreach ( array_keys($tags) as $t )
65
- $tags[$t] = $this->sanitize_text( $tags[$t] );
66
- } else {
67
- $tags = array();
68
- }
69
-
70
-
71
- // Contributors: markjaquith, mdawaffe, zefrank
72
- $contributors = array();
73
- if ( preg_match('|Contributors:(.*)|i', $file_contents, $_contributors) ) {
74
- $temp_contributors = preg_split('|,[\s]*|', trim($_contributors[1]));
75
- foreach ( array_keys($temp_contributors) as $c ) {
76
- $tmp_sanitized = $this->user_sanitize( $temp_contributors[$c] );
77
- if ( strlen(trim($tmp_sanitized)) > 0 )
78
- $contributors[$c] = $tmp_sanitized;
79
- unset($tmp_sanitized);
80
- }
81
- }
82
-
83
-
84
- // Donate Link: URL
85
- if ( preg_match('|Donate link:(.*)|i', $file_contents, $_donate_link) )
86
- $donate_link = esc_url( $_donate_link[1] );
87
- else
88
- $donate_link = NULL;
89
-
90
-
91
- // togs, conts, etc are optional and order shouldn't matter. So we chop them only after we've grabbed their values.
92
- foreach ( array('tags', 'contributors', 'requires_at_least', 'tested_up_to', 'stable_tag', 'donate_link') as $chop ) {
93
- if ( $$chop ) {
94
- $_chop = '_' . $chop;
95
- $file_contents = $this->chop_string( $file_contents, ${$_chop}[0] );
96
- }
97
- }
98
-
99
- $file_contents = trim($file_contents);
100
-
101
-
102
- // short-description fu
103
- if ( !preg_match('/(^(.*?))^[\s]*=+?[\s]*.+?[\s]*=+?/ms', $file_contents, $_short_description) )
104
- $_short_description = array( 1 => &$file_contents, 2 => &$file_contents );
105
- $short_desc_filtered = $this->sanitize_text( $_short_description[2] );
106
- $short_desc_length = strlen($short_desc_filtered);
107
- $short_description = substr($short_desc_filtered, 0, 150);
108
- if ( $short_desc_length > strlen($short_description) )
109
- $truncated = true;
110
- else
111
- $truncated = false;
112
- if ( $_short_description[1] )
113
- $file_contents = $this->chop_string( $file_contents, $_short_description[1] ); // yes, the [1] is intentional
114
-
115
- // == Section ==
116
- // Break into sections
117
- // $_sections[0] will be the title of the first section, $_sections[1] will be the content of the first section
118
- // the array alternates from there: title2, content2, title3, content3... and so forth
119
- $_sections = preg_split('/^[\s]*==[\s]*(.+?)[\s]*==/m', $file_contents, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
120
-
121
- $sections = array();
122
- for ( $i=1; $i <= count($_sections); $i +=2 ) {
123
- $_sections[$i] = preg_replace('/(^[\s]*)=[\s]+(.+?)[\s]+=/m', '$1<h4>$2</h4>', $_sections[$i]);
124
- $_sections[$i] = $this->filter_text( $_sections[$i], true );
125
- $title = $this->sanitize_text( $_sections[$i-1] );
126
- $sections[str_replace(' ', '_', strtolower($title))] = array('title' => $title, 'content' => $_sections[$i]);
127
- }
128
-
129
-
130
- // Special sections
131
- // This is where we nab our special sections, so we can enforce their order and treat them differently, if needed
132
- // upgrade_notice is not a section, but parse it like it is for now
133
- $final_sections = array();
134
- foreach ( array('description', 'installation', 'frequently_asked_questions', 'screenshots', 'changelog', 'change_log', 'upgrade_notice') as $special_section ) {
135
- if ( isset($sections[$special_section]) ) {
136
- $final_sections[$special_section] = $sections[$special_section]['content'];
137
- unset($sections[$special_section]);
138
- }
139
- }
140
- if ( isset($final_sections['change_log']) && empty($final_sections['changelog']) )
141
- $final_sections['changelog'] = $final_sections['change_log'];
142
-
143
-
144
- $final_screenshots = array();
145
- if ( isset($final_sections['screenshots']) ) {
146
- preg_match_all('|<li>(.*?)</li>|s', $final_sections['screenshots'], $screenshots, PREG_SET_ORDER);
147
- if ( $screenshots ) {
148
- foreach ( (array) $screenshots as $ss )
149
- $final_screenshots[] = $ss[1];
150
- }
151
- }
152
-
153
- // Parse the upgrade_notice section specially:
154
- // 1.0 => blah, 1.1 => fnord
155
- $upgrade_notice = array();
156
- if ( isset($final_sections['upgrade_notice']) ) {
157
- $split = preg_split( '#<h4>(.*?)</h4>#', $final_sections['upgrade_notice'], -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
158
- for ( $i = 0; $i < count( $split ); $i += 2 )
159
- $upgrade_notice[$this->sanitize_text( $split[$i] )] = substr( $this->sanitize_text( $split[$i + 1] ), 0, 300 );
160
- unset( $final_sections['upgrade_notice'] );
161
- }
162
-
163
- // No description?
164
- // No problem... we'll just fall back to the old style of description
165
- // We'll even let you use markup this time!
166
- $excerpt = false;
167
- if ( !isset($final_sections['description']) ) {
168
- $final_sections = array_merge(array('description' => $this->filter_text( $_short_description[2], true )), $final_sections);
169
- $excerpt = true;
170
- }
171
-
172
-
173
- // dump the non-special sections into $remaining_content
174
- // their order will be determined by their original order in the readme.txt
175
- $remaining_content = '';
176
- foreach ( $sections as $s_name => $s_data ) {
177
- $remaining_content .= "\n<h3>{$s_data['title']}</h3>\n{$s_data['content']}";
178
- }
179
- $remaining_content = trim($remaining_content);
180
-
181
-
182
- // All done!
183
- // $r['tags'] and $r['contributors'] are simple arrays
184
- // $r['sections'] is an array with named elements
185
- $r = array(
186
- 'name' => $name,
187
- 'tags' => $tags,
188
- 'requires_at_least' => $requires_at_least,
189
- 'tested_up_to' => $tested_up_to,
190
- 'stable_tag' => $stable_tag,
191
- 'contributors' => $contributors,
192
- 'donate_link' => $donate_link,
193
- 'short_description' => $short_description,
194
- 'screenshots' => $final_screenshots,
195
- 'is_excerpt' => $excerpt,
196
- 'is_truncated' => $truncated,
197
- 'sections' => $final_sections,
198
- 'remaining_content' => $remaining_content,
199
- 'upgrade_notice' => $upgrade_notice
200
- );
201
-
202
- return $r;
203
- }
204
-
205
- function chop_string( $string, $chop ) { // chop a "prefix" from a string: Agressive! uses strstr not 0 === strpos
206
- if ( $_string = strstr($string, $chop) ) {
207
- $_string = substr($_string, strlen($chop));
208
- return trim($_string);
209
- } else {
210
- return trim($string);
211
- }
212
- }
213
-
214
- function user_sanitize( $text, $strict = false ) { // whitelisted chars
215
- if ( function_exists('user_sanitize') ) // bbPress native
216
- return user_sanitize( $text, $strict );
217
-
218
- if ( $strict ) {
219
- $text = preg_replace('/[^a-z0-9-]/i', '', $text);
220
- $text = preg_replace('|-+|', '-', $text);
221
- } else {
222
- $text = preg_replace('/[^a-z0-9_-]/i', '', $text);
223
- }
224
- return $text;
225
- }
226
-
227
- function sanitize_text( $text ) { // not fancy
228
- $text = strip_tags($text);
229
- $text = esc_html($text);
230
- $text = trim($text);
231
- return $text;
232
- }
233
-
234
- function filter_text( $text, $markdown = false ) { // fancy, Markdown
235
- $text = trim($text);
236
-
237
- $text = call_user_func( array( __CLASS__, 'code_trick' ), $text, $markdown ); // A better parser than Markdown's for: backticks -> CODE
238
-
239
- if ( $markdown ) { // Parse markdown.
240
- if ( !class_exists('Parsedown', false) ) {
241
- require_once(dirname(__FILE__) . '/Parsedown' . (version_compare(PHP_VERSION, '5.3.0', '>=') ? '' : 'Legacy') . '.php');
242
- }
243
- $instance = Parsedown::instance();
244
- $text = $instance->text($text);
245
- }
246
-
247
- $allowed = array(
248
- 'a' => array(
249
- 'href' => array(),
250
- 'title' => array(),
251
- 'rel' => array()),
252
- 'blockquote' => array('cite' => array()),
253
- 'br' => array(),
254
- 'p' => array(),
255
- 'code' => array(),
256
- 'pre' => array(),
257
- 'em' => array(),
258
- 'strong' => array(),
259
- 'ul' => array(),
260
- 'ol' => array(),
261
- 'li' => array(),
262
- 'h3' => array(),
263
- 'h4' => array()
264
- );
265
-
266
- $text = balanceTags($text);
267
-
268
- $text = wp_kses( $text, $allowed );
269
- $text = trim($text);
270
- return $text;
271
- }
272
-
273
- function code_trick( $text, $markdown ) { // Don't use bbPress native function - it's incompatible with Markdown
274
- // If doing markdown, first take any user formatted code blocks and turn them into backticks so that
275
- // markdown will preserve things like underscores in code blocks
276
- if ( $markdown )
277
- $text = preg_replace_callback("!(<pre><code>|<code>)(.*?)(</code></pre>|</code>)!s", array( __CLASS__,'decodeit'), $text);
278
-
279
- $text = str_replace(array("\r\n", "\r"), "\n", $text);
280
- if ( !$markdown ) {
281
- // This gets the "inline" code blocks, but can't be used with Markdown.
282
- $text = preg_replace_callback("|(`)(.*?)`|", array( __CLASS__, 'encodeit'), $text);
283
- // This gets the "block level" code blocks and converts them to PRE CODE
284
- $text = preg_replace_callback("!(^|\n)`(.*?)`!s", array( __CLASS__, 'encodeit'), $text);
285
- } else {
286
- // Markdown can do inline code, we convert bbPress style block level code to Markdown style
287
- $text = preg_replace_callback("!(^|\n)([ \t]*?)`(.*?)`!s", array( __CLASS__, 'indent'), $text);
288
- }
289
- return $text;
290
- }
291
-
292
- function indent( $matches ) {
293
- $text = $matches[3];
294
- $text = preg_replace('|^|m', $matches[2] . ' ', $text);
295
- return $matches[1] . $text;
296
- }
297
-
298
- function encodeit( $matches ) {
299
- if ( function_exists('encodeit') ) // bbPress native
300
- return encodeit( $matches );
301
-
302
- $text = trim($matches[2]);
303
- $text = htmlspecialchars($text, ENT_QUOTES);
304
- $text = str_replace(array("\r\n", "\r"), "\n", $text);
305
- $text = preg_replace("|\n\n\n+|", "\n\n", $text);
306
- $text = str_replace('&amp;lt;', '&lt;', $text);
307
- $text = str_replace('&amp;gt;', '&gt;', $text);
308
- $text = "<code>$text</code>";
309
- if ( "`" != $matches[1] )
310
- $text = "<pre>$text</pre>";
311
- return $text;
312
- }
313
-
314
- function decodeit( $matches ) {
315
- if ( function_exists('decodeit') ) // bbPress native
316
- return decodeit( $matches );
317
-
318
- $text = $matches[2];
319
- $trans_table = array_flip(get_html_translation_table(HTML_ENTITIES));
320
- $text = strtr($text, $trans_table);
321
- $text = str_replace('<br />', '', $text);
322
- $text = str_replace('&#38;', '&', $text);
323
- $text = str_replace('&#39;', "'", $text);
324
- if ( '<pre><code>' == $matches[1] )
325
- $text = "\n$text\n";
326
- return "`$text`";
327
- }
328
-
329
- } // end class
330
-
331
- Class Automattic_Readme extends PucReadmeParser {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: pascalbajorat
3
  Donate link: https://www.pascal-bajorat.com/spenden/
4
  Tags: seo, images, Post, admin, google, attachment, optimize, photo, picture, image, media, photos, pictures, alt, title, lazy, load
5
- Requires at least: 3.0
6
- Tested up to: 4.9.6
7
- Stable tag: 3.1.0
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -47,6 +47,19 @@ Want to add lazy load to images in your theme? You only need to do some small mo
47
 
48
  == Changelog ==
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  = 3.1.0 =
51
  * serveral bugs are fixed and code was optimized
52
  * improved image and figure handling - Thanks to BasTaller (@bastaller)
2
  Contributors: pascalbajorat
3
  Donate link: https://www.pascal-bajorat.com/spenden/
4
  Tags: seo, images, Post, admin, google, attachment, optimize, photo, picture, image, media, photos, pictures, alt, title, lazy, load
5
+ Requires at least: 5.0
6
+ Tested up to: 5.3.9
7
+ Stable tag: 4.0.3
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
47
 
48
  == Changelog ==
49
 
50
+ = 4.0.3 =
51
+ * Bugfix & Optimization
52
+
53
+ = 4.0.2 =
54
+ * Bugfix & Optimization
55
+
56
+ = 4.0.1 =
57
+ * Bugfix
58
+
59
+ = 4.0.0 =
60
+ * Complete Rewrite of the plugin
61
+ * Please make sure to backup your files before you run this update. If you have any problems you can switch to an older version, have a look at the download archive.
62
+
63
  = 3.1.0 =
64
  * serveral bugs are fixed and code was optimized
65
  * improved image and figure handling - Thanks to BasTaller (@bastaller)
templates/options_page.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wrap pb-wp-app-wrapper">
2
+ <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
3
+
4
+ <?php
5
+ if( isset($_GET['clear_cache']) && $_GET['clear_cache'] === 'true' ) {
6
+ $cache = new pbsfi_cache();
7
+ $clear_cache = $cache->clear_cache();
8
+
9
+ ?>
10
+ <div class="notice notice-success is-dismissible">
11
+ <p><?php echo sprintf(__( '<strong>Cache cleared!</strong> %d elements are removed from transient cache.', 'pb-seo-friendly-images' ), $clear_cache); ?></p>
12
+ </div>
13
+ <?php
14
+ }
15
+ ?>
16
+
17
+ <div class="pb-wrapper">
18
+ <div class="pb-main">
19
+ <form action="<?php echo admin_url('options.php') ?>" method="post" target="_self">
20
+ <?php
21
+ settings_fields('pb-seo-friendly-images');
22
+ $this->settingsFramework->doSettingsSections('pb-seo-friendly-images');
23
+ submit_button();
24
+ ?>
25
+ </form>
26
+ </div>
27
+ <div class="pb-sidebar">
28
+ <h3><?php esc_html_e('Plugins & Support', 'pb-seo-friendly-images') ?></h3>
29
+
30
+ <?php if (strstr(get_locale(), 'de')): ?>
31
+ <div class="pb-support-box">
32
+ <h4>
33
+ <span class="icon">
34
+ <img src="<?php echo plugins_url('assets/img/check.png', $this->pbSEOFriendlyImages->plugin['file']); ?>"
35
+ alt="<?php _e('WordPress Kurs', 'pb-seo-friendly-images') ?>"/>
36
+ </span>
37
+ <span class="text"><?php _e('Recommendation', 'pb-seo-friendly-images'); ?>:<br /><?php _e('WordPress Kurs', 'pb-seo-friendly-images') ?></span>
38
+ </h4>
39
+ <p><?php _e('Möchtest du mit WordPress richtig durchstarten? In meinem WordPress Kurs erfährst du spannende Tipps und Tricks zu WordPress und SEO!', 'pb-seo-friendly-images') ?></p>
40
+
41
+ <p>
42
+ <a href="https://www.bajorat-media.com/lp/wordpress-kurs/?utm_source=pb-seo-friendly-images&utm_medium=banner&utm_campaign=pb-seo-friendly-images" class="button"
43
+ target="_blank"><?php _e('Jetzt Kurs ansehen', 'pb-seo-friendly-images') ?></a>
44
+ </p>
45
+ </div>
46
+ <?php endif; ?>
47
+
48
+ <div class="pb-support-box">
49
+ <h4>
50
+ <span class="icon">
51
+ <img src="<?php echo plugins_url('assets/img/check.png', $this->pbSEOFriendlyImages->plugin['file']); ?>"
52
+ alt="<?php _e('WordPress Kurs', 'pb-seo-friendly-images') ?>"/>
53
+ </span>
54
+ <span class="text"><?php _e('Recommendation', 'pb-seo-friendly-images'); ?>:<br /><?php _e('WordPress Performance', 'pb-seo-friendly-images'); ?></h4></span>
55
+ <p><?php _e('Do you want a professional and individual performance optimization for your website? Increase your Google Pagespeed and SEO traffic with our high performance optimization.', 'pb-seo-friendly-images') ?></p>
56
+
57
+ <p>
58
+ <a href="<?php echo esc_url(__('https://www.pascal-bajorat.com/en/lp/wordpress-performance-optimization/', 'pb-seo-friendly-images')); ?>?utm_source=pb-seo-friendly-images&utm_medium=banner&utm_campaign=pb-seo-friendly-images" class="button"
59
+ target="_blank"><?php _e('Get a free quote', 'pb-seo-friendly-images') ?></a>
60
+ </p>
61
+ </div>
62
+
63
+ <div class="pb-plugin-box">
64
+ <h4>
65
+ <span class="icon">
66
+ <img src="<?php echo plugins_url('assets/img/mailcrypt.png', $this->pbSEOFriendlyImages->plugin['file']); ?>"
67
+ alt="<?php _e('MailCrypt - AntiSpam Email Encryption', 'pb-seo-friendly-images') ?>"/>
68
+ </span>
69
+ <span class="text"><?php _e('MailCrypt - AntiSpam Email Encryption', 'pb-seo-friendly-images') ?></span>
70
+ </h4>
71
+ <div class="desc">
72
+ <p><?php _e('This Plugin provides a Shortcode to encrypt email addresses / links and protect them against spam.', 'pb-seo-friendly-images') ?></p>
73
+ <p>
74
+ <a href="<?php echo admin_url('plugin-install.php?s=PB+MailCrypt+-+AntiSpam+Email+Encryption&tab=search&type=term') ?>"
75
+ class="button"><?php _e('Install Plugin', 'pb-seo-friendly-images') ?></a></p>
76
+ </div>
77
+ </div>
78
+
79
+ <div class="pb-support-box">
80
+ <h4><?php _e('Support', 'pb-seo-friendly-images') ?></h4>
81
+ <p><?php _e('Do you need some help with this plugin? I am here to help you. Get in touch:', 'pb-seo-friendly-images') ?></p>
82
+
83
+ <p>
84
+ <?php if (!$this->pbSEOFriendlyImages->isProVersion()): ?>
85
+ <a href="https://wordpress.org/support/plugin/pb-seo-friendly-images" class="button"
86
+ target="_blank"><?php _e('Support Forum', 'pb-seo-friendly-images') ?></a>
87
+ <?php else: ?>
88
+ <a href="https://codecanyon.net/item/seo-friendly-images-pro-for-wordpress/19296704/support?ref=Pascal-Bajorat"
89
+ class="button" target="_blank"><?php _e('Contact Support', 'pb-seo-friendly-images') ?></a>
90
+ <?php endif; ?>
91
+ &nbsp;<a href="https://wordpress.org/plugins/pb-seo-friendly-images/#developers" class="button"
92
+ target="_blank"><?php _e('Changelog', 'pb-seo-friendly-images') ?></a>
93
+ </p>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ </div>
98
+ <script>
99
+ jQuery(document).ready(function () {
100
+
101
+ var $wc_setting_elements = jQuery('#pbsfi_wc_sync_method, label[for="pbsfi_wc_sync_method"], #pbsfi_wc_override_alt, label[for="pbsfi_wc_override_alt"], #pbsfi_wc_override_title, label[for="pbsfi_wc_override_title"], #pbsfi_wc_alt_scheme, label[for="pbsfi_wc_alt_scheme"], #pbsfi_wc_title_scheme, label[for="pbsfi_wc_title_scheme"]');
102
+
103
+ if (jQuery('#pbsfi_wc_title').is(':checked')) {
104
+ console.log('fade out');
105
+ $wc_setting_elements.css('opacity', .4);
106
+ }
107
+
108
+ jQuery('#pbsfi_wc_title').on('change', function (e) {
109
+ if (jQuery(this).is(':checked')) {
110
+ $wc_setting_elements.css('opacity', .4);
111
+ } else {
112
+ $wc_setting_elements.css('opacity', 1);
113
+ }
114
+ });
115
+ });
116
+ </script>