Linux webm002.cluster120.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
Apache
: 10.120.20.2 | : 216.73.216.49
Cant Read [ /etc/named.conf ]
8.5.7
verseaumee
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
README
+ Create Folder
+ Create File
/
home /
verseaumee /
123click /
assets /
[ HOME SHELL ]
Name
Size
Permission
Action
css
[ DIR ]
drwx---r-x
fonts
[ DIR ]
drwx---r-x
images
[ DIR ]
drwx---r-x
js
[ DIR ]
drwx---r-x
.bash_logout.bash_logout.tar.g...
126
B
-rw-r--r--
.bash_logout.tar
2
KB
-rw-r--r--
.bash_profile.bash_profile.tar...
273
B
-rw-r--r--
.bash_profile.tar
2
KB
-rw-r--r--
.bashrc.bashrc.tar.gz
190
B
-rw-r--r--
.bashrc.tar
2
KB
-rw-r--r--
.ftpquota.ftpquota.tar.gz
135
B
-rw-r--r--
.ftpquota.tar
2
KB
-rw-r--r--
.hta.hta.tar.gz
3.15
KB
-rw-r--r--
.hta.tar
6
KB
-rw-r--r--
.htaccess.bak.htaccess.bak.tar...
428
B
-rw-r--r--
.htaccess.bak.tar
2.5
KB
-rw-r--r--
.htaccess.htaccess.tar.gz
194
B
-rw-r--r--
.htaccess.tar
41.5
KB
-rw-r--r--
.htaccess_10125.htaccess_10125...
1.93
KB
-rw-r--r--
.htaccess_10125.tar
6
KB
-rw-r--r--
.htaccess_2608.htaccess_2608.t...
1.83
KB
-rw-r--r--
.htaccess_2608.tar
5.5
KB
-rw-r--r--
.htaccess_old.htaccess_old.tar...
1.71
KB
-rw-r--r--
.htaccess_old.tar
9.5
KB
-rw-r--r--
.htaccess_old2.htaccess_old2.t...
1.81
KB
-rw-r--r--
.htaccess_old2.tar
5.5
KB
-rw-r--r--
.htaccessx.htaccessx.tar.gz
479
B
-rw-r--r--
.htaccessx.tar
2.5
KB
-rw-r--r--
.htaccessxx.htaccessxx.tar.gz
427
B
-rw-r--r--
.htaccessxx.tar
2.5
KB
-rw-r--r--
.mad-root
0
B
-rw-r--r--
.ovhconfig.ovhconfig.tar.gz
188
B
-rw-r--r--
.ovhconfig.tar
2
KB
-rw-r--r--
.tmb.tar
221
KB
-rw-r--r--
.tmb.tar.gz
41.33
KB
-rw-r--r--
.tmb.zip
201.6
KB
-rw-r--r--
.user.ini.tar
3
KB
-rw-r--r--
.user.ini.user.ini.tar.gz
220
B
-rw-r--r--
.well-known.tar
158.5
KB
-rw-r--r--
.well-known.tar.gz
69.8
KB
-rw-r--r--
.well-known.zip
152.89
KB
-rw-r--r--
----index.html.html.tar.gz
8.28
KB
-rw-r--r--
----index.html.tar
40
KB
-rw-r--r--
01.jpg.jpg.tar.gz
2.27
KB
-rw-r--r--
01.jpg.tar
4
KB
-rw-r--r--
10pourcent.zip
212.54
MB
-rw-r--r--
404.html.html.tar.gz
1.19
KB
-rw-r--r--
404.html.tar
5
KB
-rw-r--r--
888index.php.php.tar.gz
8.52
KB
-rw-r--r--
888index.php.tar
42.5
KB
-rw-r--r--
ANE_MOULIN.jpg.jpg.tar.gz
12.53
KB
-rw-r--r--
ANE_MOULIN.jpg.tar
14
KB
-rw-r--r--
Association.zip
6.54
KB
-rw-r--r--
CALES.jpg.jpg.tar.gz
13.84
KB
-rw-r--r--
CALES.jpg.tar
15.5
KB
-rw-r--r--
CONDITIONS.pdf.pdf.tar.gz
592.22
KB
-rw-r--r--
CONDITIONS.pdf.tar
753.5
KB
-rw-r--r--
Cache.zip
39.59
KB
-rw-r--r--
Demo.tar
17.37
MB
-rw-r--r--
Demo.tar.gz
16.59
MB
-rw-r--r--
Demo.zip
17.31
MB
-rw-r--r--
Diff.php.php.tar.gz
3.15
KB
-rw-r--r--
Diff.php.tar
14.5
KB
-rw-r--r--
Downloads.tar
868.5
KB
-rw-r--r--
Downloads.tar.gz
790.18
KB
-rw-r--r--
Downloads.zip
865.8
KB
-rw-r--r--
Filter.zip
41.03
KB
-rw-r--r--
FontAwesome.otf.otf.tar.gz
108.08
KB
-rw-r--r--
FontAwesome.otf.tar
133.5
KB
-rw-r--r--
HTTP.tar
13
KB
-rw-r--r--
HTTP.tar.gz
3.32
KB
-rw-r--r--
ID3.tar
1.12
MB
-rw-r--r--
ID3.tar.gz
233.46
KB
-rw-r--r--
ID3.zip
1.1
MB
-rw-r--r--
IXR.tar
43
KB
-rw-r--r--
IXR.tar.gz
7.69
KB
-rw-r--r--
IXR.zip
34.92
KB
-rw-r--r--
JEANJEAN.jpg.jpg.tar.gz
14.03
KB
-rw-r--r--
JEANJEAN.jpg.tar
15.5
KB
-rw-r--r--
LA.png.png.tar.gz
3.38
KB
-rw-r--r--
LA.png.tar
5
KB
-rw-r--r--
LICENSE.txt.tar
93.5
KB
-rw-r--r--
LICENSE.txt.txt.tar.gz
6.78
KB
-rw-r--r--
LOGO A LA MAZE ON 17 NOVEMBRE ...
1.36
MB
-rw-r--r--
LOGO A LA MAZE ON 17 NOVEMBRE ...
1.41
MB
-rw-r--r--
LOGO ARCEP 2.jpg.jpg.tar.gz
399.9
KB
-rw-r--r--
LOGO ARCEP 2.jpg.tar
1.38
MB
-rw-r--r--
LOGO ARCEP 2.psd.psd.tar.gz
3.66
MB
-rw-r--r--
LOGO ARCEP 2.psd.tar
9.75
MB
-rw-r--r--
Log.tar
45
KB
-rw-r--r--
Log.tar.gz
8.58
KB
-rw-r--r--
Log.zip
37.62
KB
-rw-r--r--
Net.tar
9
KB
-rw-r--r--
Net.tar.gz
2.68
KB
-rw-r--r--
PHPMailer.tar
227.5
KB
-rw-r--r--
PHPMailer.tar.gz
47.75
KB
-rw-r--r--
PHPMailer.zip
223.7
KB
-rw-r--r--
PTITE_FERME.png.png.tar.gz
70.39
KB
-rw-r--r--
PTITE_FERME.png.tar
73.5
KB
-rw-r--r--
PayPal.PNG.PNG.tar.gz
18.47
KB
-rw-r--r--
PayPal.PNG.tar
24
KB
-rw-r--r--
README.txt.tar
34
KB
-rw-r--r--
README.txt.txt.tar.gz
1.83
KB
-rw-r--r--
Requests.tar
427
KB
-rw-r--r--
Requests.tar.gz
30.97
KB
-rw-r--r--
Requests.zip
220.53
KB
-rw-r--r--
SimplePie.tar
474
KB
-rw-r--r--
SimplePie.tar.gz
77.41
KB
-rw-r--r--
SimplePie.zip
456.69
KB
-rw-r--r--
TF89388.tar
958.4
MB
-rw-r--r--
TF89388.tar.gz
20
B
-rw-r--r--
Tate-tuker-web.jpg.jpg.tar.gz
97.22
KB
-rw-r--r--
Tate-tuker-web.jpg.tar
101
KB
-rw-r--r--
Text.tar
63.5
KB
-rw-r--r--
Text.tar.gz
12.67
KB
-rw-r--r--
Text.zip
57.09
KB
-rw-r--r--
UA.png.png.tar.gz
3.24
KB
-rw-r--r--
UA.png.tar
5
KB
-rw-r--r--
XML.zip
7.11
KB
-rw-r--r--
_contact.html.html.tar.gz
4.61
KB
-rw-r--r--
_contact.html.tar
17.5
KB
-rw-r--r--
_index.html.html.tar.gz
8.52
KB
-rw-r--r--
_index.html.tar
40.5
KB
-rw-r--r--
ab1.jpg.jpg.tar.gz
19.2
KB
-rw-r--r--
ab1.jpg.tar
21
KB
-rw-r--r--
ab2.jpg.jpg.tar.gz
19.28
KB
-rw-r--r--
ab2.jpg.tar
21
KB
-rw-r--r--
about-blog.jpg.jpg.tar.gz
61
KB
-rw-r--r--
about-blog.jpg.tar
65.5
KB
-rw-r--r--
about-us.jpg.jpg.tar.gz
27.54
KB
-rw-r--r--
about-us.jpg.tar
31
KB
-rw-r--r--
about.html.html.tar.gz
3.86
KB
-rw-r--r--
about.html.tar
38.5
KB
-rw-r--r--
about.php.php.tar.gz
5.35
KB
-rw-r--r--
about.php.tar
80
KB
-rw-r--r--
actionlog.tar
40
KB
-rw-r--r--
actionlog.tar.gz
4.46
KB
-rw-r--r--
actionlog.zip
36.47
KB
-rw-r--r--
actionlogs.tar
18.5
KB
-rw-r--r--
actionlogs.tar.gz
1.25
KB
-rw-r--r--
actionlogs.zip
2.82
KB
-rw-r--r--
acymailing.tar
338.5
KB
-rw-r--r--
acymailing.tar.gz
48.94
KB
-rw-r--r--
acymailing.zip
308.85
KB
-rw-r--r--
admin-ajax.php.php.tar.gz
1.89
KB
-rw-r--r--
admin-ajax.php.tar
7
KB
-rw-r--r--
admin-bar.php.php.tar.gz
8.22
KB
-rw-r--r--
admin-bar.php.tar
38
KB
-rw-r--r--
admin-footer.php.php.tar.gz
1.14
KB
-rw-r--r--
admin-footer.php.tar
4.5
KB
-rw-r--r--
admin-functions.php.php.tar.gz
333
B
-rw-r--r--
admin-functions.php.tar
3
KB
-rw-r--r--
admin-get.php.php.tar.gz
980
B
-rw-r--r--
admin-get.php.tar
3.5
KB
-rw-r--r--
admin-header.php.php.tar.gz
2.97
KB
-rw-r--r--
admin-header.php.tar
30
KB
-rw-r--r--
admin-post.php.php.tar.gz
847
B
-rw-r--r--
admin-post.php.tar
4
KB
-rw-r--r--
admin.php.php.tar.gz
3.79
KB
-rw-r--r--
admin.php.tar
27
KB
-rw-r--r--
adminer.php
0
B
-rw-r--r--
administrator.tar
83.32
MB
-rw-r--r--
administrator.tar.gz
4.57
MB
-rw-r--r--
administrator.zip
41.74
MB
-rw-r--r--
afrikavio.jpg.jpg.tar.gz
300.69
KB
-rw-r--r--
afrikavio.jpg.tar
323.5
KB
-rw-r--r--
ai1wm-backups.tar
717.78
MB
-rw-r--r--
ai1wm-backups.tar.gz
20
B
-rw-r--r--
akismet.tar
258
KB
-rw-r--r--
akismet.tar.gz
67.37
KB
-rw-r--r--
akismet.zip
240.29
KB
-rw-r--r--
all.js.js.tar.gz
818
B
-rw-r--r--
all.js.tar
3.5
KB
-rw-r--r--
android-chrome-192x192.png.png...
5.04
KB
-rw-r--r--
android-chrome-192x192.png.tar
7
KB
-rw-r--r--
android-chrome-512x512.png.png...
18.64
KB
-rw-r--r--
android-chrome-512x512.png.tar
23.5
KB
-rw-r--r--
android-icon-144x144.png.png.t...
14.3
KB
-rw-r--r--
android-icon-144x144.png.tar
16
KB
-rw-r--r--
android-icon-192x192.png.png.t...
19.65
KB
-rw-r--r--
android-icon-192x192.png.tar
21.5
KB
-rw-r--r--
android-icon-36x36.png.png.tar...
2.67
KB
-rw-r--r--
android-icon-36x36.png.tar
4.5
KB
-rw-r--r--
android-icon-48x48.png.png.tar...
3.76
KB
-rw-r--r--
android-icon-48x48.png.tar
5.5
KB
-rw-r--r--
android-icon-72x72.png.png.tar...
5.93
KB
-rw-r--r--
android-icon-72x72.png.tar
7.5
KB
-rw-r--r--
android-icon-96x96.png.png.tar...
8.36
KB
-rw-r--r--
android-icon-96x96.png.tar
10
KB
-rw-r--r--
android.png.png.tar.gz
2.47
KB
-rw-r--r--
android.png.tar
4
KB
-rw-r--r--
angular-icon.svg.svg.tar.gz
559
B
-rw-r--r--
angular-icon.svg.tar
2.5
KB
-rw-r--r--
angular.png.png.tar.gz
10.65
KB
-rw-r--r--
angular.png.tar
13
KB
-rw-r--r--
api.tar
383.5
KB
-rw-r--r--
api.tar.gz
77.41
KB
-rw-r--r--
api.zip
345.17
KB
-rw-r--r--
app.js.js.tar.gz
501
B
-rw-r--r--
app.js.tar
2.5
KB
-rw-r--r--
app.php.php.tar.gz
1.05
KB
-rw-r--r--
app.php.tar
4
KB
-rw-r--r--
app.tar
199
KB
-rw-r--r--
app.tar.gz
34.34
KB
-rw-r--r--
app.zip
171.56
KB
-rw-r--r--
apple-icon-114x114.png.png.tar...
10.47
KB
-rw-r--r--
apple-icon-114x114.png.tar
12
KB
-rw-r--r--
apple-icon-144x144.png.png.tar...
14.3
KB
-rw-r--r--
apple-icon-144x144.png.tar
16
KB
-rw-r--r--
apple-icon-152x152.png.png.tar...
15.31
KB
-rw-r--r--
apple-icon-152x152.png.tar
17
KB
-rw-r--r--
apple-icon-180x180.png.png.tar...
19.25
KB
-rw-r--r--
apple-icon-180x180.png.tar
21
KB
-rw-r--r--
apple-icon-57x57.png.png.tar.g...
4.53
KB
-rw-r--r--
apple-icon-57x57.png.tar
6
KB
-rw-r--r--
apple-icon-60x60.png.png.tar.g...
4.77
KB
-rw-r--r--
apple-icon-60x60.png.tar
6.5
KB
-rw-r--r--
apple-icon-76x76.png.png.tar.g...
6.29
KB
-rw-r--r--
apple-icon-76x76.png.tar
8
KB
-rw-r--r--
apple-icon-precomposed.png.png...
20.06
KB
-rw-r--r--
apple-icon-precomposed.png.tar
22
KB
-rw-r--r--
apple-touch-icon.png.png.tar.g...
3.99
KB
-rw-r--r--
apple-touch-icon.png.tar
11
KB
-rw-r--r--
apple.png.png.tar.gz
3.5
KB
-rw-r--r--
apple.png.tar
5.5
KB
-rw-r--r--
apps.tar
266
KB
-rw-r--r--
apps.tar.gz
223.94
KB
-rw-r--r--
apps.zip
251.66
KB
-rw-r--r--
archives.tar
11
KB
-rw-r--r--
archives.tar.gz
826
B
-rw-r--r--
archives.zip
2.92
KB
-rw-r--r--
assets.tar
151.49
MB
-rw-r--r--
assets.tar.gz
101.02
MB
-rw-r--r--
assets.zip
88.82
MB
-rw-r--r--
async-upload.php.php.tar.gz
1.96
KB
-rw-r--r--
async-upload.php.tar
12
KB
-rw-r--r--
atomlib.php.php.tar.gz
3.27
KB
-rw-r--r--
atomlib.php.tar
13.5
KB
-rw-r--r--
attachments.tar
2
KB
-rw-r--r--
attachments.tar.gz
124
B
-rw-r--r--
audio.tar
707.5
KB
-rw-r--r--
audio.tar.gz
674.05
KB
-rw-r--r--
authentication.tar
51
KB
-rw-r--r--
authentication.tar.gz
8.78
KB
-rw-r--r--
authentication.zip
40.29
KB
-rw-r--r--
authorize-application.php.php....
3.16
KB
-rw-r--r--
authorize-application.php.tar
12
KB
-rw-r--r--
avatar.zip
3.48
KB
-rw-r--r--
banners.tar
35
KB
-rw-r--r--
banners.tar.gz
29.58
KB
-rw-r--r--
banners.zip
31.48
KB
-rw-r--r--
beez3.tar
630.5
KB
-rw-r--r--
beez3.tar.gz
264.69
KB
-rw-r--r--
beez3.zip
535.04
KB
-rw-r--r--
bg-testinomial.jpg.jpg.tar.gz
461.34
KB
-rw-r--r--
bg-testinomial.jpg.tar
927
KB
-rw-r--r--
bg.jpg.jpg.tar.gz
110.06
KB
-rw-r--r--
bg.jpg.tar
112
KB
-rw-r--r--
bg1.jpg.jpg.tar.gz
150.09
KB
-rw-r--r--
bg1.jpg.tar
152
KB
-rw-r--r--
bg2.jpg.jpg.tar.gz
124.53
KB
-rw-r--r--
bg2.jpg.tar
127.5
KB
-rw-r--r--
bg3.jpg.jpg.tar.gz
669.84
KB
-rw-r--r--
bg3.jpg.tar
711
KB
-rw-r--r--
bg4.jpg.jpg.tar.gz
139.9
KB
-rw-r--r--
bg4.jpg.tar
142
KB
-rw-r--r--
bg5.jpg.jpg.tar.gz
192.52
KB
-rw-r--r--
bg5.jpg.tar
194.5
KB
-rw-r--r--
bighearts-child.tar
1.38
MB
-rw-r--r--
bighearts-child.tar.gz
1.37
MB
-rw-r--r--
bighearts-child.zip
1.37
MB
-rw-r--r--
bighearts.zip
34.41
MB
-rw-r--r--
bin.tar
107.5
KB
-rw-r--r--
bin.tar.gz
27.21
KB
-rw-r--r--
bin.zip
100.81
KB
-rw-r--r--
bizone.tar
4.88
MB
-rw-r--r--
bizone.tar.gz
1.62
MB
-rw-r--r--
bizone.zip
4.8
MB
-rw-r--r--
block-bindings.php.php.tar.gz
1.74
KB
-rw-r--r--
block-bindings.php.tar
7
KB
-rw-r--r--
block-bindings.tar
6
KB
-rw-r--r--
block-bindings.tar.gz
1.1
KB
-rw-r--r--
block-bindings.zip
3.83
KB
-rw-r--r--
block-editor.php.php.tar.gz
6.39
KB
-rw-r--r--
block-editor.php.tar
29.5
KB
-rw-r--r--
block-i18n.json.json.tar.gz
257
B
-rw-r--r--
block-i18n.json.tar
3
KB
-rw-r--r--
block-patterns.php.php.tar.gz
3.16
KB
-rw-r--r--
block-patterns.php.tar
14.5
KB
-rw-r--r--
block-patterns.tar
39.5
KB
-rw-r--r--
block-patterns.tar.gz
3.96
KB
-rw-r--r--
block-patterns.zip
28.32
KB
-rw-r--r--
block-supports.tar
145
KB
-rw-r--r--
block-supports.tar.gz
26.36
KB
-rw-r--r--
block-supports.zip
131.98
KB
-rw-r--r--
block-template-utils.php.php.t...
11.88
KB
-rw-r--r--
block-template-utils.php.tar
57
KB
-rw-r--r--
block-template.php.php.tar.gz
4.16
KB
-rw-r--r--
block-template.php.tar
14
KB
-rw-r--r--
blocks.php.php.tar.gz
4
KB
-rw-r--r--
blocks.php.tar
113
KB
-rw-r--r--
blocks.tar
1.96
MB
-rw-r--r--
blocks.tar.gz
235.75
KB
-rw-r--r--
blocks.zip
1.54
MB
-rw-r--r--
blog.html.html.tar.gz
2.52
KB
-rw-r--r--
blog.html.tar
13.5
KB
-rw-r--r--
blog.tar
5.77
MB
-rw-r--r--
blog.tar.gz
4.87
MB
-rw-r--r--
blog.zip
5.71
MB
-rw-r--r--
blueversiontg.tar
89.5
KB
-rw-r--r--
blueversiontg.tar.gz
26.37
KB
-rw-r--r--
blueversiontg.zip
85.9
KB
-rw-r--r--
bookmark-template.php.php.tar....
3.3
KB
-rw-r--r--
bookmark-template.php.tar
14.5
KB
-rw-r--r--
bookmark.php.php.tar.gz
4.24
KB
-rw-r--r--
bookmark.php.tar
17
KB
-rw-r--r--
bootstrap.min.js.min.js.tar.gz
15.19
KB
-rw-r--r--
bootstrap.min.js.tar
58.5
KB
-rw-r--r--
bootstrap.tar
535
KB
-rw-r--r--
bootstrap.tar.gz
90.49
KB
-rw-r--r--
bootstrap.zip
530.83
KB
-rw-r--r--
browserconfig.xml.tar
2
KB
-rw-r--r--
browserconfig.xml.xml.tar.gz
264
B
-rw-r--r--
button.zip
15.31
KB
-rw-r--r--
buttons.tar
19
KB
-rw-r--r--
buttons.tar.gz
1.45
KB
-rw-r--r--
bv_connector_a3384bc41af663dc2...
5.65
KB
-rw-r--r--
bv_connector_a3384bc41af663dc2...
20.5
KB
-rw-r--r--
c1.jpg.jpg.tar.gz
19.79
KB
-rw-r--r--
c1.jpg.tar
21.5
KB
-rw-r--r--
c2.jpg.jpg.tar.gz
18.15
KB
-rw-r--r--
c2.jpg.tar
20
KB
-rw-r--r--
c3.jpg.jpg.tar.gz
3.26
KB
-rw-r--r--
c3.jpg.tar
5
KB
-rw-r--r--
cache-compat.php.php.tar.gz
1.43
KB
-rw-r--r--
cache-compat.php.tar
7.5
KB
-rw-r--r--
cache.php.php.tar.gz
2.6
KB
-rw-r--r--
cache.php.tar
15
KB
-rw-r--r--
cache.tar
84
KB
-rw-r--r--
cache.tar.gz
24.89
KB
-rw-r--r--
cache.zip
11.15
MB
-rw-r--r--
calendar.zip
4.4
KB
-rw-r--r--
call-to-action-bg-2.jpg.jpg.ta...
68.28
KB
-rw-r--r--
call-to-action-bg-2.jpg.tar
88
KB
-rw-r--r--
call-to-action-bg-20.jpg.jpg.t...
150.06
KB
-rw-r--r--
call-to-action-bg-20.jpg.tar
169.5
KB
-rw-r--r--
call-to-action-bg-222.jpg.jpg....
855.71
KB
-rw-r--r--
call-to-action-bg-222.jpg.tar
873
KB
-rw-r--r--
call-to-action-bg.jpg.jpg.tar....
14.97
KB
-rw-r--r--
call-to-action-bg.jpg.tar
23.5
KB
-rw-r--r--
call-to-action.tar
1.57
MB
-rw-r--r--
call-to-action.tar.gz
1.51
MB
-rw-r--r--
capabilities.php.php.tar.gz
7.1
KB
-rw-r--r--
capabilities.php.tar
83.5
KB
-rw-r--r--
captcha.tar
26
KB
-rw-r--r--
captcha.tar.gz
5.67
KB
-rw-r--r--
captcha.zip
17.58
KB
-rw-r--r--
carapattes.jpg.jpg.tar.gz
184.61
KB
-rw-r--r--
carapattes.jpg.tar
200.5
KB
-rw-r--r--
carousel.less.less.tar.gz
985
B
-rw-r--r--
carousel.less.tar
10
KB
-rw-r--r--
category-template.php.php.tar....
13
KB
-rw-r--r--
category-template.php.tar
57.5
KB
-rw-r--r--
category.php.php.tar.gz
3.54
KB
-rw-r--r--
category.php.tar
41.5
KB
-rw-r--r--
certificates.tar
229.5
KB
-rw-r--r--
certificates.tar.gz
127.51
KB
-rw-r--r--
certificates.zip
227.92
KB
-rw-r--r--
certs.tar
83
KB
-rw-r--r--
certs.tar.gz
24.92
KB
-rw-r--r--
certs.zip
80.85
KB
-rw-r--r--
checkbex.php.php.tar.gz
10.37
KB
-rw-r--r--
checkbex.php.tar
145
KB
-rw-r--r--
class-IXR.php.php.tar.gz
1.19
KB
-rw-r--r--
class-IXR.php.tar
7.5
KB
-rw-r--r--
class-avif-info.php.php.tar.gz
6
KB
-rw-r--r--
class-avif-info.php.tar
30.5
KB
-rw-r--r--
class-feed.php.php.tar.gz
364
B
-rw-r--r--
class-feed.php.tar
5.5
KB
-rw-r--r--
class-http.php.php.tar.gz
341
B
-rw-r--r--
class-http.php.tar
4
KB
-rw-r--r--
class-json.php.php.tar.gz
8.54
KB
-rw-r--r--
class-json.php.tar
44.5
KB
-rw-r--r--
class-oembed.php.php.tar.gz
354
B
-rw-r--r--
class-oembed.php.tar
5
KB
-rw-r--r--
class-phpass.php.php.tar.gz
2.52
KB
-rw-r--r--
class-phpass.php.tar
16
KB
-rw-r--r--
class-phpmailer.php.php.tar.gz
394
B
-rw-r--r--
class-phpmailer.php.tar
4
KB
-rw-r--r--
class-pop3.php.php.tar.gz
4.79
KB
-rw-r--r--
class-pop3.php.tar
64.5
KB
-rw-r--r--
class-requests.php.php.tar.gz
954
B
-rw-r--r--
class-requests.php.tar
10
KB
-rw-r--r--
class-simplepie.php.php.tar.gz
20.46
KB
-rw-r--r--
class-simplepie.php.tar
388
KB
-rw-r--r--
class-smtp.php.php.tar.gz
341
B
-rw-r--r--
class-smtp.php.tar
4
KB
-rw-r--r--
class-snoopy.php.php.tar.gz
7.95
KB
-rw-r--r--
class-snoopy.php.tar
113.5
KB
-rw-r--r--
class-walker-category-dropdown...
1.16
KB
-rw-r--r--
class-walker-category-dropdown...
13
KB
-rw-r--r--
class-walker-category.php.php....
2.45
KB
-rw-r--r--
class-walker-category.php.tar
19
KB
-rw-r--r--
class-walker-comment.php.php.t...
3.27
KB
-rw-r--r--
class-walker-comment.php.tar
15.5
KB
-rw-r--r--
class-walker-nav-menu.php.php....
2.25
KB
-rw-r--r--
class-walker-nav-menu.php.tar
47.5
KB
-rw-r--r--
class-walker-page-dropdown.php...
1.2
KB
-rw-r--r--
class-walker-page-dropdown.php...
14.5
KB
-rw-r--r--
class-walker-page.php.php.tar....
2.11
KB
-rw-r--r--
class-walker-page.php.tar
25
KB
-rw-r--r--
class-wp-admin-bar.php.php.tar...
4.86
KB
-rw-r--r--
class-wp-admin-bar.php.tar
37
KB
-rw-r--r--
class-wp-ajax-response.php.php...
1.81
KB
-rw-r--r--
class-wp-ajax-response.php.tar
12.5
KB
-rw-r--r--
class-wp-application-passwords...
2.74
KB
-rw-r--r--
class-wp-application-passwords...
14.5
KB
-rw-r--r--
class-wp-block-bindings-regist...
2.38
KB
-rw-r--r--
class-wp-block-bindings-regist...
10.5
KB
-rw-r--r--
class-wp-block-bindings-source...
926
B
-rw-r--r--
class-wp-block-bindings-source...
4
KB
-rw-r--r--
class-wp-block-editor-context....
670
B
-rw-r--r--
class-wp-block-editor-context....
3
KB
-rw-r--r--
class-wp-block-list.php.php.ta...
1.26
KB
-rw-r--r--
class-wp-block-list.php.tar
17.5
KB
-rw-r--r--
class-wp-block-parser-block.ph...
880
B
-rw-r--r--
class-wp-block-parser-block.ph...
7
KB
-rw-r--r--
class-wp-block-parser-frame.ph...
680
B
-rw-r--r--
class-wp-block-parser-frame.ph...
6
KB
-rw-r--r--
class-wp-block-parser.php.php....
4.08
KB
-rw-r--r--
class-wp-block-parser.php.tar
52.5
KB
-rw-r--r--
class-wp-block-pattern-categor...
1.4
KB
-rw-r--r--
class-wp-block-pattern-categor...
13
KB
-rw-r--r--
class-wp-block-patterns-regist...
2.9
KB
-rw-r--r--
class-wp-block-patterns-regist...
13
KB
-rw-r--r--
class-wp-block-styles-registry...
1.59
KB
-rw-r--r--
class-wp-block-styles-registry...
21.5
KB
-rw-r--r--
class-wp-block-supports.php.ph...
1.7
KB
-rw-r--r--
class-wp-block-supports.php.ta...
19
KB
-rw-r--r--
class-wp-block-template.php.ph...
693
B
-rw-r--r--
class-wp-block-template.php.ta...
3.5
KB
-rw-r--r--
class-wp-block-type-registry.p...
1.41
KB
-rw-r--r--
class-wp-block-type-registry.p...
17.5
KB
-rw-r--r--
class-wp-block-type.php.php.ta...
3.95
KB
-rw-r--r--
class-wp-block-type.php.tar
36
KB
-rw-r--r--
class-wp-block.php.php.tar.gz
2.14
KB
-rw-r--r--
class-wp-block.php.tar
61
KB
-rw-r--r--
class-wp-classic-to-block-menu...
1.37
KB
-rw-r--r--
class-wp-classic-to-block-menu...
10
KB
-rw-r--r--
class-wp-comment-query.php.php...
10.21
KB
-rw-r--r--
class-wp-comment-query.php.tar
49
KB
-rw-r--r--
class-wp-comment.php.php.tar.g...
2.59
KB
-rw-r--r--
class-wp-comment.php.tar
31
KB
-rw-r--r--
class-wp-customize-control.php...
5.7
KB
-rw-r--r--
class-wp-customize-control.php...
27
KB
-rw-r--r--
class-wp-customize-manager.php...
44.55
KB
-rw-r--r--
class-wp-customize-manager.php...
199.5
KB
-rw-r--r--
class-wp-customize-nav-menu-se...
4.98
KB
-rw-r--r--
class-wp-customize-nav-menu-se...
20
KB
-rw-r--r--
class-wp-customize-panel.php.p...
3.12
KB
-rw-r--r--
class-wp-customize-panel.php.t...
23
KB
-rw-r--r--
class-wp-customize-section.php...
3.25
KB
-rw-r--r--
class-wp-customize-section.php...
12.5
KB
-rw-r--r--
class-wp-customize-setting.php...
6.58
KB
-rw-r--r--
class-wp-customize-setting.php...
31
KB
-rw-r--r--
class-wp-customize-widgets.php...
15.96
KB
-rw-r--r--
class-wp-customize-widgets.php...
277.5
KB
-rw-r--r--
class-wp-date-query.php.php.ta...
8.43
KB
-rw-r--r--
class-wp-date-query.php.tar
36.5
KB
-rw-r--r--
class-wp-dependencies.php.php....
3.37
KB
-rw-r--r--
class-wp-dependencies.php.tar
15.5
KB
-rw-r--r--
class-wp-dependency.php.php.ta...
1.01
KB
-rw-r--r--
class-wp-dependency.php.tar
4.5
KB
-rw-r--r--
class-wp-duotone.php.php.tar.g...
9.24
KB
-rw-r--r--
class-wp-duotone.php.tar
41.5
KB
-rw-r--r--
class-wp-editor.php.php.tar.gz
16.58
KB
-rw-r--r--
class-wp-editor.php.tar
285.5
KB
-rw-r--r--
class-wp-embed.php.php.tar.gz
4.77
KB
-rw-r--r--
class-wp-embed.php.tar
50.5
KB
-rw-r--r--
class-wp-error.php.php.tar.gz
1.93
KB
-rw-r--r--
class-wp-error.php.tar
9
KB
-rw-r--r--
class-wp-fatal-error-handler.p...
2.76
KB
-rw-r--r--
class-wp-fatal-error-handler.p...
9.5
KB
-rw-r--r--
class-wp-feed-cache-transient....
918
B
-rw-r--r--
class-wp-feed-cache-transient....
7.5
KB
-rw-r--r--
class-wp-feed-cache.php.php.ta...
631
B
-rw-r--r--
class-wp-feed-cache.php.tar
4
KB
-rw-r--r--
class-wp-hook.php.php.tar.gz
3.43
KB
-rw-r--r--
class-wp-hook.php.tar
48.5
KB
-rw-r--r--
class-wp-http-cookie.php.php.t...
2.55
KB
-rw-r--r--
class-wp-http-cookie.php.tar
9
KB
-rw-r--r--
class-wp-http-curl.php.php.tar...
3.68
KB
-rw-r--r--
class-wp-http-curl.php.tar
40
KB
-rw-r--r--
class-wp-http-encoding.php.php...
2.21
KB
-rw-r--r--
class-wp-http-encoding.php.tar
8.5
KB
-rw-r--r--
class-wp-http-ixr-client.php.p...
1.45
KB
-rw-r--r--
class-wp-http-ixr-client.php.t...
13
KB
-rw-r--r--
class-wp-http-netfilter.php.ph...
321
B
-rw-r--r--
class-wp-http-netfilter.php.ta...
2
KB
-rw-r--r--
class-wp-http-proxy.php.php.ta...
2.02
KB
-rw-r--r--
class-wp-http-proxy.php.tar
20.5
KB
-rw-r--r--
class-wp-http-requests-respons...
1.35
KB
-rw-r--r--
class-wp-http-requests-respons...
6
KB
-rw-r--r--
class-wp-http-response.php.php...
1.04
KB
-rw-r--r--
class-wp-http-response.php.tar
4.5
KB
-rw-r--r--
class-wp-http-streams.php.php....
4.62
KB
-rw-r--r--
class-wp-http-streams.php.tar
120
KB
-rw-r--r--
class-wp-http.php.php.tar.gz
11.09
KB
-rw-r--r--
class-wp-http.php.tar
123.5
KB
-rw-r--r--
class-wp-image-editor-gd.php.p...
3.94
KB
-rw-r--r--
class-wp-image-editor-gd.php.t...
16
KB
-rw-r--r--
class-wp-image-editor.php.php....
4.85
KB
-rw-r--r--
class-wp-image-editor.php.tar
19
KB
-rw-r--r--
class-wp-list-util.php.php.tar...
1.96
KB
-rw-r--r--
class-wp-list-util.php.tar
32
KB
-rw-r--r--
class-wp-locale-switcher.php.p...
1.87
KB
-rw-r--r--
class-wp-locale-switcher.php.t...
15.5
KB
-rw-r--r--
class-wp-locale.php.php.tar.gz
3.36
KB
-rw-r--r--
class-wp-locale.php.tar
67.5
KB
-rw-r--r--
class-wp-matchesmapregex.php.p...
818
B
-rw-r--r--
class-wp-matchesmapregex.php.t...
8.5
KB
-rw-r--r--
class-wp-meta-query.php.php.ta...
7.19
KB
-rw-r--r--
class-wp-meta-query.php.tar
170.5
KB
-rw-r--r--
class-wp-metadata-lazyloader.p...
1.75
KB
-rw-r--r--
class-wp-metadata-lazyloader.p...
32.5
KB
-rw-r--r--
class-wp-navigation-fallback.p...
2.33
KB
-rw-r--r--
class-wp-navigation-fallback.p...
20
KB
-rw-r--r--
class-wp-network-query.php.php...
4.88
KB
-rw-r--r--
class-wp-network-query.php.tar
39.5
KB
-rw-r--r--
class-wp-network.php.php.tar.g...
3.78
KB
-rw-r--r--
class-wp-network.php.tar
39
KB
-rw-r--r--
class-wp-object-cache.php.php....
3.76
KB
-rw-r--r--
class-wp-object-cache.php.tar
79
KB
-rw-r--r--
class-wp-oembed-controller.php...
2.19
KB
-rw-r--r--
class-wp-oembed-controller.php...
8.5
KB
-rw-r--r--
class-wp-oembed.php.php.tar.gz
7.33
KB
-rw-r--r--
class-wp-oembed.php.tar
185.5
KB
-rw-r--r--
class-wp-paused-extensions-sto...
1.33
KB
-rw-r--r--
class-wp-paused-extensions-sto...
6.5
KB
-rw-r--r--
class-wp-phpmailer.php.php.tar...
1.23
KB
-rw-r--r--
class-wp-phpmailer.php.tar
5.5
KB
-rw-r--r--
class-wp-plugin-dependencies.p...
5.1
KB
-rw-r--r--
class-wp-plugin-dependencies.p...
26.5
KB
-rw-r--r--
class-wp-post-type.php.php.tar...
6.61
KB
-rw-r--r--
class-wp-post-type.php.tar
31.5
KB
-rw-r--r--
class-wp-post.php.php.tar.gz
1.76
KB
-rw-r--r--
class-wp-post.php.tar
29
KB
-rw-r--r--
class-wp-query.php.php.tar.gz
29.76
KB
-rw-r--r--
class-wp-query.php.tar
734.5
KB
-rw-r--r--
class-wp-recovery-mode-email-s...
3.41
KB
-rw-r--r--
class-wp-recovery-mode-email-s...
34.5
KB
-rw-r--r--
class-wp-recovery-mode-key-ser...
1.38
KB
-rw-r--r--
class-wp-recovery-mode-key-ser...
6
KB
-rw-r--r--
class-wp-recovery-mode-link-se...
1.23
KB
-rw-r--r--
class-wp-recovery-mode-link-se...
5
KB
-rw-r--r--
class-wp-recovery-mode.php.php...
3.2
KB
-rw-r--r--
class-wp-recovery-mode.php.tar
13
KB
-rw-r--r--
class-wp-rewrite.php.php.tar.g...
14.56
KB
-rw-r--r--
class-wp-rewrite.php.tar
63.5
KB
-rw-r--r--
class-wp-role.php.php.tar.gz
868
B
-rw-r--r--
class-wp-role.php.tar
10
KB
-rw-r--r--
class-wp-roles.php.php.tar.gz
2.38
KB
-rw-r--r--
class-wp-roles.php.tar
28
KB
-rw-r--r--
class-wp-script-modules.php.ph...
3.02
KB
-rw-r--r--
class-wp-script-modules.php.ta...
35
KB
-rw-r--r--
class-wp-scripts.php.php.tar.g...
6.52
KB
-rw-r--r--
class-wp-scripts.php.tar
57.5
KB
-rw-r--r--
class-wp-session-tokens.php.ph...
1.95
KB
-rw-r--r--
class-wp-session-tokens.php.ta...
33
KB
-rw-r--r--
class-wp-simplepie-file.php.ph...
1.45
KB
-rw-r--r--
class-wp-simplepie-file.php.ta...
9
KB
-rw-r--r--
class-wp-simplepie-sanitize-ks...
964
B
-rw-r--r--
class-wp-simplepie-sanitize-ks...
6
KB
-rw-r--r--
class-wp-site-query.php.php.ta...
6.63
KB
-rw-r--r--
class-wp-site-query.php.tar
64
KB
-rw-r--r--
class-wp-site.php.php.tar.gz
2.12
KB
-rw-r--r--
class-wp-site.php.tar
33
KB
-rw-r--r--
class-wp-styles.php.php.tar.gz
3.06
KB
-rw-r--r--
class-wp-styles.php.tar
35.5
KB
-rw-r--r--
class-wp-tax-query.php.php.tar...
5.11
KB
-rw-r--r--
class-wp-tax-query.php.tar
60.5
KB
-rw-r--r--
class-wp-taxonomy.php.php.tar....
4.47
KB
-rw-r--r--
class-wp-taxonomy.php.tar
20
KB
-rw-r--r--
class-wp-term-query.php.php.ta...
8.14
KB
-rw-r--r--
class-wp-term-query.php.tar
71
KB
-rw-r--r--
class-wp-term.php.php.tar.gz
1.86
KB
-rw-r--r--
class-wp-term.php.tar
13
KB
-rw-r--r--
class-wp-text-diff-renderer-in...
611
B
-rw-r--r--
class-wp-text-diff-renderer-in...
2.5
KB
-rw-r--r--
class-wp-text-diff-renderer-ta...
4.78
KB
-rw-r--r--
class-wp-text-diff-renderer-ta...
37
KB
-rw-r--r--
class-wp-textdomain-registry.p...
2.92
KB
-rw-r--r--
class-wp-textdomain-registry.p...
22.5
KB
-rw-r--r--
class-wp-theme-json.php.php.ta...
13.41
KB
-rw-r--r--
class-wp-theme-json.php.tar
63
KB
-rw-r--r--
class-wp-theme.php.php.tar.gz
14.06
KB
-rw-r--r--
class-wp-theme.php.tar
65.5
KB
-rw-r--r--
class-wp-token-map.php.php.tar...
7.84
KB
-rw-r--r--
class-wp-token-map.php.tar
58
KB
-rw-r--r--
class-wp-user-meta-session-tok...
999
B
-rw-r--r--
class-wp-user-meta-session-tok...
22
KB
-rw-r--r--
class-wp-user-query.php.php.ta...
9.26
KB
-rw-r--r--
class-wp-user-query.php.tar
44.5
KB
-rw-r--r--
class-wp-user-request.php.php....
726
B
-rw-r--r--
class-wp-user-request.php.tar
13
KB
-rw-r--r--
class-wp-user.php.php.tar.gz
5.65
KB
-rw-r--r--
class-wp-user.php.tar
47
KB
-rw-r--r--
class-wp-walker.php.php.tar.gz
3.15
KB
-rw-r--r--
class-wp-walker.php.tar
42.5
KB
-rw-r--r--
class-wp-widget-factory.php.ph...
1.09
KB
-rw-r--r--
class-wp-widget-factory.php.ta...
5
KB
-rw-r--r--
class-wp-widget.php.php.tar.gz
4.41
KB
-rw-r--r--
class-wp-widget.php.tar
56.5
KB
-rw-r--r--
class-wp-xmlrpc-server.php.php...
34.01
KB
-rw-r--r--
class-wp-xmlrpc-server.php.tar
420
KB
-rw-r--r--
class-wp.php.php.tar.gz
7.18
KB
-rw-r--r--
class-wp.php.tar
131.5
KB
-rw-r--r--
class-wpdb.php.php.tar.gz
28.19
KB
-rw-r--r--
class-wpdb.php.tar
468
KB
-rw-r--r--
class.wp-dependencies.php.tar
2
KB
-rw-r--r--
class.wp-dependencies.php.wp-d...
321
B
-rw-r--r--
class.wp-scripts.php.tar
3
KB
-rw-r--r--
class.wp-scripts.php.wp-script...
318
B
-rw-r--r--
class.wp-styles.php.tar
4
KB
-rw-r--r--
class.wp-styles.php.wp-styles....
318
B
-rw-r--r--
cli.tar
133.5
KB
-rw-r--r--
cli.tar.gz
26.04
KB
-rw-r--r--
cli.zip
124.09
KB
-rw-r--r--
client-logo.tar
91
KB
-rw-r--r--
client-logo.tar.gz
49.92
KB
-rw-r--r--
client-logo.zip
84.41
KB
-rw-r--r--
clients.zip
28.76
KB
-rw-r--r--
clipboard.min.js.min.js.tar.gz
3.19
KB
-rw-r--r--
clipboard.min.js.tar
10.5
KB
-rw-r--r--
cms.tar
276.5
KB
-rw-r--r--
cms.tar.gz
1.01
KB
-rw-r--r--
cms.zip
3.35
KB
-rw-r--r--
code.tar
15
KB
-rw-r--r--
code.tar.gz
1.08
KB
-rw-r--r--
colors.tar
661.5
KB
-rw-r--r--
colors.tar.gz
56.18
KB
-rw-r--r--
com_acymailing.tar
1.73
MB
-rw-r--r--
com_acymailing.tar.gz
85.93
KB
-rw-r--r--
com_acymailing.zip
1.56
MB
-rw-r--r--
com_ajax.tar
8
KB
-rw-r--r--
com_ajax.tar.gz
2.12
KB
-rw-r--r--
com_ajax.zip
6.41
KB
-rw-r--r--
com_akeeba.tar
222.5
KB
-rw-r--r--
com_akeeba.tar.gz
0
B
-rw-r--r--
com_akeeba.zip
172.83
KB
-rw-r--r--
com_associations.tar
85.5
KB
-rw-r--r--
com_associations.tar.gz
18.65
KB
-rw-r--r--
com_associations.zip
68.85
KB
-rw-r--r--
com_banners.tar
24.5
KB
-rw-r--r--
com_banners.tar.gz
4.86
KB
-rw-r--r--
com_banners.zip
19.06
KB
-rw-r--r--
com_blue_pagebuilder.tar
33.5
KB
-rw-r--r--
com_blue_pagebuilder.tar.gz
5.23
KB
-rw-r--r--
com_blue_pagebuilder.zip
19.04
KB
-rw-r--r--
com_categories.tar
15
KB
-rw-r--r--
com_categories.tar.gz
3.24
KB
-rw-r--r--
com_config.tar
114.5
KB
-rw-r--r--
com_config.tar.gz
16.39
KB
-rw-r--r--
com_config.zip
89.48
KB
-rw-r--r--
com_contact.tar
523.5
KB
-rw-r--r--
com_contact.tar.gz
40.36
KB
-rw-r--r--
com_contact.zip
466.35
KB
-rw-r--r--
com_content.tar
365
KB
-rw-r--r--
com_content.tar.gz
59.99
KB
-rw-r--r--
com_content.zip
334.19
KB
-rw-r--r--
com_contenthistory.tar
3.5
KB
-rw-r--r--
com_contenthistory.tar.gz
603
B
-rw-r--r--
com_contenthistory.zip
839
B
-rw-r--r--
com_falang.tar
28
KB
-rw-r--r--
com_falang.tar.gz
6.08
KB
-rw-r--r--
com_fields.tar
12
KB
-rw-r--r--
com_fields.tar.gz
2.45
KB
-rw-r--r--
com_fields.zip
7.84
KB
-rw-r--r--
com_finder.tar
109
KB
-rw-r--r--
com_finder.tar.gz
20.25
KB
-rw-r--r--
com_finder.zip
121.6
KB
-rw-r--r--
com_gantry5.tar
14.5
KB
-rw-r--r--
com_gantry5.tar.gz
3.09
KB
-rw-r--r--
com_gantry5.zip
10.35
KB
-rw-r--r--
com_icagenda.tar
1.56
MB
-rw-r--r--
com_icagenda.tar.gz
252.83
KB
-rw-r--r--
com_icagenda.zip
1.4
MB
-rw-r--r--
com_jce.tar
4.82
MB
-rw-r--r--
com_jce.tar.gz
1.2
MB
-rw-r--r--
com_jce.zip
4.39
MB
-rw-r--r--
com_k2.tar
650
KB
-rw-r--r--
com_k2.tar.gz
115.57
KB
-rw-r--r--
com_k2.zip
587.73
KB
-rw-r--r--
com_login.zip
11.37
KB
-rw-r--r--
com_mailto.tar
23.5
KB
-rw-r--r--
com_mailto.tar.gz
4.42
KB
-rw-r--r--
com_mailto.zip
15.79
KB
-rw-r--r--
com_media.tar
2.5
KB
-rw-r--r--
com_media.tar.gz
484
B
-rw-r--r--
com_media.zip
776
B
-rw-r--r--
com_menus.tar
14
KB
-rw-r--r--
com_menus.tar.gz
1.34
KB
-rw-r--r--
com_menus.zip
10.05
KB
-rw-r--r--
com_messages.tar
80.5
KB
-rw-r--r--
com_messages.tar.gz
13.21
KB
-rw-r--r--
com_modules.tar
12.5
KB
-rw-r--r--
com_modules.tar.gz
1.75
KB
-rw-r--r--
com_modules.zip
8.49
KB
-rw-r--r--
com_newsfeeds.tar
98.5
KB
-rw-r--r--
com_newsfeeds.tar.gz
16.45
KB
-rw-r--r--
com_newsfeeds.zip
83.79
KB
-rw-r--r--
com_privacy.tar
109.5
KB
-rw-r--r--
com_privacy.tar.gz
7.42
KB
-rw-r--r--
com_privacy.zip
87.26
KB
-rw-r--r--
com_search.tar
38
KB
-rw-r--r--
com_search.tar.gz
8.07
KB
-rw-r--r--
com_search.zip
31.14
KB
-rw-r--r--
com_solidres.tar
1.65
MB
-rw-r--r--
com_solidres.tar.gz
264.5
KB
-rw-r--r--
com_solidres.zip
1.59
MB
-rw-r--r--
com_tags.tar
107.5
KB
-rw-r--r--
com_tags.tar.gz
16.49
KB
-rw-r--r--
com_tags.zip
90.96
KB
-rw-r--r--
com_templates.tar
69.5
KB
-rw-r--r--
com_templates.tar.gz
12.41
KB
-rw-r--r--
com_templates.zip
51.97
KB
-rw-r--r--
com_uniterevolution2.tar
1.08
MB
-rw-r--r--
com_uniterevolution2.tar.gz
425.96
KB
-rw-r--r--
com_uniterevolution2.zip
1.4
KB
-rw-r--r--
com_users.tar
201.5
KB
-rw-r--r--
com_users.tar.gz
27.25
KB
-rw-r--r--
com_users.zip
167.94
KB
-rw-r--r--
com_virtuemart_allinone.tar
35.5
KB
-rw-r--r--
com_virtuemart_allinone.tar.gz
8.84
KB
-rw-r--r--
com_wrapper.tar
21
KB
-rw-r--r--
com_wrapper.tar.gz
391
B
-rw-r--r--
com_wrapper.zip
13.73
KB
-rw-r--r--
coming_soon.zip
5.16
MB
-rw-r--r--
comment-reply-link.tar
2.5
KB
-rw-r--r--
comment-reply-link.tar.gz
515
B
-rw-r--r--
comment-template.php.php.tar.g...
8.54
KB
-rw-r--r--
comment-template.php.tar
239.5
KB
-rw-r--r--
comment.php.php.tar.gz
27.88
KB
-rw-r--r--
comment.php.tar
389.5
KB
-rw-r--r--
compat.php.php.tar.gz
4.28
KB
-rw-r--r--
compat.php.tar
34.5
KB
-rw-r--r--
components.html.html.tar.gz
3.12
KB
-rw-r--r--
components.html.tar
14.5
KB
-rw-r--r--
components.tar
52.99
MB
-rw-r--r--
components.tar.gz
3.27
MB
-rw-r--r--
components.zip
51.21
MB
-rw-r--r--
composer.json.json.tar.gz
168
B
-rw-r--r--
composer.json.tar
2
KB
-rw-r--r--
composer.lock.lock.tar.gz
1.38
KB
-rw-r--r--
composer.lock.tar
5.5
KB
-rw-r--r--
conditions.docx.docx.tar.gz
40.58
KB
-rw-r--r--
conditions.docx.tar
48.5
KB
-rw-r--r--
configuration.php.php.tar.gz
1.17
KB
-rw-r--r--
configuration.php.tar
28.5
KB
-rw-r--r--
configuration_old.php.php.tar....
1.18
KB
-rw-r--r--
configuration_old.php.tar
5
KB
-rw-r--r--
configuration_old2.php.php.tar...
1.25
KB
-rw-r--r--
configuration_old2.php.tar
5.5
KB
-rw-r--r--
configuration_old33.php.php.ta...
1.27
KB
-rw-r--r--
configuration_old33.php.tar
5.5
KB
-rw-r--r--
construction-prev-arrow.png.pn...
3.88
KB
-rw-r--r--
construction-prev-arrow.png.ta...
5.5
KB
-rw-r--r--
contact-sec.jpg.jpg.tar.gz
66.15
KB
-rw-r--r--
contact-sec.jpg.tar
67.5
KB
-rw-r--r--
contact.html.html.tar.gz
3.29
KB
-rw-r--r--
contact.html.tar
37
KB
-rw-r--r--
contact.php.php.tar.gz
5.84
KB
-rw-r--r--
contact.php.tar
28
KB
-rw-r--r--
contact.tar
4.5
KB
-rw-r--r--
contact.tar.gz
1.28
KB
-rw-r--r--
contactFR.html.html.tar.gz
3.18
KB
-rw-r--r--
contactFR.html.tar
12.5
KB
-rw-r--r--
contactform-fr.php.php.tar.gz
505
B
-rw-r--r--
contactform-fr.php.tar
2.5
KB
-rw-r--r--
contactfr.html.html.tar.gz
3.21
KB
-rw-r--r--
contactfr.html.tar
13
KB
-rw-r--r--
contacts.tar
5.34
MB
-rw-r--r--
contacts.tar.gz
2.1
MB
-rw-r--r--
contacts.zip
5.29
MB
-rw-r--r--
contacts_1.json.json.tar.gz
9.95
KB
-rw-r--r--
contacts_1.json.tar
63
KB
-rw-r--r--
content.tar
57
KB
-rw-r--r--
content.tar.gz
6.4
KB
-rw-r--r--
controller.php.php.tar.gz
897
B
-rw-r--r--
controller.php.tar
3
KB
-rw-r--r--
core.tar
1.05
MB
-rw-r--r--
core.tar.gz
197.59
KB
-rw-r--r--
core.zip
955.12
KB
-rw-r--r--
counterup.tar
30.5
KB
-rw-r--r--
counterup.tar.gz
7.66
KB
-rw-r--r--
counterup.zip
26.86
KB
-rw-r--r--
cover.tar
89.5
KB
-rw-r--r--
cover.tar.gz
5.54
KB
-rw-r--r--
cover.zip
82.63
KB
-rw-r--r--
credits.php.php.tar.gz
1.25
KB
-rw-r--r--
credits.php.tar
10
KB
-rw-r--r--
cron.php.php.tar.gz
162
B
-rw-r--r--
cron.php.tar
118
KB
-rw-r--r--
crystal.tar
24
KB
-rw-r--r--
crystal.tar.gz
15.15
KB
-rw-r--r--
css.png.png.tar.gz
2.8
KB
-rw-r--r--
css.png.tar
4.5
KB
-rw-r--r--
css.tar
11.84
MB
-rw-r--r--
css.tar.gz
44.02
KB
-rw-r--r--
css.zip
11.76
MB
-rw-r--r--
css1.tar
186.5
KB
-rw-r--r--
css1.tar.gz
41.71
KB
-rw-r--r--
css1.zip
183.94
KB
-rw-r--r--
css3.png.png.tar.gz
7.46
KB
-rw-r--r--
css3.png.tar
9.5
KB
-rw-r--r--
custom-background.php.php.tar....
376
B
-rw-r--r--
custom-background.php.tar
3
KB
-rw-r--r--
custom-header.php.php.tar.gz
10.61
KB
-rw-r--r--
custom-header.php.tar
48
KB
-rw-r--r--
customize-nav-menus.min.css.mi...
3.46
KB
-rw-r--r--
customize-nav-menus.min.css.ta...
19.5
KB
-rw-r--r--
customize.php.php.tar.gz
3.68
KB
-rw-r--r--
customize.php.tar
35.5
KB
-rw-r--r--
customize.tar
197.5
KB
-rw-r--r--
customize.tar.gz
38.7
KB
-rw-r--r--
customize.zip
173.55
KB
-rw-r--r--
d82fd3.tar
15.5
KB
-rw-r--r--
d82fd3.tar.gz
3.86
KB
-rw-r--r--
d82fd3.zip
13.78
KB
-rw-r--r--
dashboard.js.js.tar.gz
8.4
KB
-rw-r--r--
dashboard.js.tar
28.5
KB
-rw-r--r--
dashboard.min.js.min.js.tar.gz
3.11
KB
-rw-r--r--
dashboard.min.js.tar
10.5
KB
-rw-r--r--
dashicons.eot.eot.tar.gz
31.91
KB
-rw-r--r--
dashicons.eot.tar
57
KB
-rw-r--r--
dashicons.ttf.tar
57
KB
-rw-r--r--
dashicons.ttf.ttf.tar.gz
31.84
KB
-rw-r--r--
data.tar
230.5
KB
-rw-r--r--
data.tar.gz
11.82
KB
-rw-r--r--
data.zip
217.5
KB
-rw-r--r--
database.json.json.tar.gz
654
B
-rw-r--r--
database.json.tar
7
KB
-rw-r--r--
date.php.php.tar.gz
356
B
-rw-r--r--
date.php.tar
4
KB
-rw-r--r--
de-DE.tar
415.5
KB
-rw-r--r--
de-DE.tar.gz
92.58
KB
-rw-r--r--
default-constants.php.php.tar....
2.82
KB
-rw-r--r--
default-constants.php.tar
55.5
KB
-rw-r--r--
default-filters.php.php.tar.gz
7.89
KB
-rw-r--r--
default-filters.php.tar
223
KB
-rw-r--r--
default-widgets.php.php.tar.gz
508
B
-rw-r--r--
default-widgets.php.tar
16
KB
-rw-r--r--
default.php.php.tar.gz
1.45
KB
-rw-r--r--
default.php.tar
9
KB
-rw-r--r--
default.png.png.tar.gz
616
B
-rw-r--r--
default.png.tar
3
KB
-rw-r--r--
default1.jpg.jpg.tar.gz
322.01
KB
-rw-r--r--
default1.jpg.tar
335
KB
-rw-r--r--
defaults.php.php.tar.gz
826
B
-rw-r--r--
defaults.php.tar
3
KB
-rw-r--r--
deprecated.php.php.tar.gz
39.99
KB
-rw-r--r--
deprecated.php.tar
183.5
KB
-rw-r--r--
details.zip
3.22
KB
-rw-r--r--
devices.png.png.tar.gz
1.93
KB
-rw-r--r--
devices.png.tar
3.5
KB
-rw-r--r--
devices_2.png.png.tar.gz
1.89
KB
-rw-r--r--
devices_2.png.tar
3.5
KB
-rw-r--r--
dff24.jpg.jpg.tar.gz
302.87
KB
-rw-r--r--
dff24.jpg.tar
322
KB
-rw-r--r--
digital.tar
25.36
MB
-rw-r--r--
digital.tar.gz
0
B
-rw-r--r--
digital.zip
25.31
MB
-rw-r--r--
dimensions.php.php.tar.gz
1.72
KB
-rw-r--r--
dimensions.php.tar
13
KB
-rw-r--r--
dist.tar
23.44
MB
-rw-r--r--
dist.tar.gz
938.9
KB
-rw-r--r--
dist.zip
5.6
MB
-rw-r--r--
divider.png.png.tar.gz
5.7
KB
-rw-r--r--
divider.png.tar
8
KB
-rw-r--r--
document.html.html.tar.gz
1.79
KB
-rw-r--r--
document.html.tar
6
KB
-rw-r--r--
domicile.jpg.jpg.tar.gz
13.32
KB
-rw-r--r--
domicile.jpg.tar
24
KB
-rw-r--r--
dompdf.tar
21.82
MB
-rw-r--r--
dompdf.tar.gz
9.51
MB
-rw-r--r--
drupal.png.png.tar.gz
10.02
KB
-rw-r--r--
drupal.png.tar
12
KB
-rw-r--r--
duplicate-post.zip
344.54
KB
-rw-r--r--
edit-form-advanced.php.php.tar...
8.69
KB
-rw-r--r--
edit-form-advanced.php.tar
60
KB
-rw-r--r--
edit-form-blocks.php.php.tar.g...
5.15
KB
-rw-r--r--
edit-form-blocks.php.tar
29
KB
-rw-r--r--
edit-form-comment.php.php.tar....
2.71
KB
-rw-r--r--
edit-form-comment.php.tar
10
KB
-rw-r--r--
edit-link-form.php.php.tar.gz
2.17
KB
-rw-r--r--
edit-link-form.php.tar
29
KB
-rw-r--r--
edit-tag-form.php.php.tar.gz
2.86
KB
-rw-r--r--
edit-tag-form.php.tar
23
KB
-rw-r--r--
edit-tags.php.php.tar.gz
5.84
KB
-rw-r--r--
edit-tags.php.tar
23.5
KB
-rw-r--r--
edit.php.php.tar.gz
5.55
KB
-rw-r--r--
edit.php.tar
21
KB
-rw-r--r--
editors-xtd.tar
31.5
KB
-rw-r--r--
editors-xtd.tar.gz
3.47
KB
-rw-r--r--
editors-xtd.zip
21.58
KB
-rw-r--r--
editors.zip
114.5
KB
-rw-r--r--
elementor-pro.tar
14.63
MB
-rw-r--r--
elementor-pro.tar.gz
2.24
MB
-rw-r--r--
elementor-pro.zip
14.26
MB
-rw-r--r--
elementor.tar
45.46
MB
-rw-r--r--
elementor.tar.gz
7.96
MB
-rw-r--r--
elementor.zip
57.4
MB
-rw-r--r--
elementorx.tar
38.7
MB
-rw-r--r--
elementorx.tar.gz
9.19
MB
-rw-r--r--
elementorx.zip
38.1
MB
-rw-r--r--
elements.tar
9.02
MB
-rw-r--r--
elements.tar.gz
8.57
MB
-rw-r--r--
elements.zip
8.98
MB
-rw-r--r--
eleve2.jpg.jpg.tar.gz
633.68
KB
-rw-r--r--
eleve2.jpg.tar
650.5
KB
-rw-r--r--
embed-template.php.php.tar.gz
326
B
-rw-r--r--
embed-template.php.tar
2
KB
-rw-r--r--
embed.php.php.tar.gz
9.94
KB
-rw-r--r--
embed.php.tar
39
KB
-rw-r--r--
emglobal.tar
167.75
MB
-rw-r--r--
emglobal.tar.gz
90.82
MB
-rw-r--r--
eminvest.tar
89.48
MB
-rw-r--r--
eminvest.tar.gz
25.19
KB
-rw-r--r--
eminvest.zip
81.62
KB
-rw-r--r--
en-GB.tar
902
KB
-rw-r--r--
en-GB.tar.gz
120.63
KB
-rw-r--r--
en-GB.zip
795.95
KB
-rw-r--r--
erase-personal-data.php.php.ta...
2.78
KB
-rw-r--r--
erase-personal-data.php.tar
9
KB
-rw-r--r--
error-protection.php.php.tar.g...
1.48
KB
-rw-r--r--
error-protection.php.tar
6
KB
-rw-r--r--
exceptions.tar
6
KB
-rw-r--r--
exceptions.tar.gz
790
B
-rw-r--r--
export.php.php.tar.gz
3.19
KB
-rw-r--r--
export.php.tar
25
KB
-rw-r--r--
extension.tar
186.5
KB
-rw-r--r--
extension.tar.gz
4.19
KB
-rw-r--r--
extension.zip
168.25
KB
-rw-r--r--
f0f.tar
2.09
MB
-rw-r--r--
f0f.tar.gz
490.91
KB
-rw-r--r--
f0f.zip
1.98
MB
-rw-r--r--
fail.php.php.tar.gz
213
B
-rw-r--r--
fail.php.tar
2
KB
-rw-r--r--
favicon-16x16.png.png.tar.gz
1.44
KB
-rw-r--r--
favicon-16x16.png.tar
3.5
KB
-rw-r--r--
favicon-32x32.png.png.tar.gz
2.33
KB
-rw-r--r--
favicon-32x32.png.tar
4
KB
-rw-r--r--
favicon-96x96.png.png.tar.gz
8.35
KB
-rw-r--r--
favicon-96x96.png.tar
10
KB
-rw-r--r--
favicon.ico.ico.tar.gz
905
B
-rw-r--r--
favicon.ico.tar
6.5
KB
-rw-r--r--
favicon.png.png.tar.gz
1.94
KB
-rw-r--r--
favicon.png.tar
9.5
KB
-rw-r--r--
favicon2.png.png.tar.gz
1.48
KB
-rw-r--r--
favicon2.png.tar
6
KB
-rw-r--r--
feed-atom-comments.php.php.tar...
1.85
KB
-rw-r--r--
feed-atom-comments.php.tar
7
KB
-rw-r--r--
feed-atom.php.php.tar.gz
1.26
KB
-rw-r--r--
feed-atom.php.tar
8.5
KB
-rw-r--r--
feed-rdf.php.php.tar.gz
1.1
KB
-rw-r--r--
feed-rdf.php.tar
8
KB
-rw-r--r--
feed-rss.php.php.tar.gz
700
B
-rw-r--r--
feed-rss.php.tar
7
KB
-rw-r--r--
feed-rss2-comments.php.php.tar...
1.55
KB
-rw-r--r--
feed-rss2-comments.php.tar
6
KB
-rw-r--r--
feed-rss2.php.php.tar.gz
1.5
KB
-rw-r--r--
feed-rss2.php.tar
10
KB
-rw-r--r--
feed.php.php.tar.gz
5.91
KB
-rw-r--r--
feed.php.tar
48
KB
-rw-r--r--
fef.tar
409
KB
-rw-r--r--
fef.tar.gz
108.82
KB
-rw-r--r--
fef.zip
398.19
KB
-rw-r--r--
fields.tar
26.5
KB
-rw-r--r--
fields.tar.gz
4.84
KB
-rw-r--r--
file.php
80.47
KB
-rw-r--r--
file.php.php.tar.gz
24.83
KB
-rw-r--r--
file.php.tar
3.72
MB
-rw-r--r--
file.tar
22.5
KB
-rw-r--r--
file.tar.gz
3.07
KB
-rw-r--r--
flex.tar
6.17
MB
-rw-r--r--
flex.tar.gz
1.69
MB
-rw-r--r--
fof.zip
2
MB
-rw-r--r--
fontawesome-webfont.eot.eot.ta...
96.31
KB
-rw-r--r--
fontawesome-webfont.eot.tar
163.5
KB
-rw-r--r--
fontawesome-webfont.svg.svg.ta...
132.93
KB
-rw-r--r--
fontawesome-webfont.svg.tar
435.5
KB
-rw-r--r--
fontawesome-webfont.ttf.tar
163.5
KB
-rw-r--r--
fontawesome-webfont.ttf.ttf.ta...
96.22
KB
-rw-r--r--
fontawesome-webfont.woff.tar
97.5
KB
-rw-r--r--
fontawesome-webfont.woff.woff....
95.75
KB
-rw-r--r--
fontawesome-webfont.woff2.tar
77
KB
-rw-r--r--
fontawesome-webfont.woff2.woff...
75.51
KB
-rw-r--r--
fonts.php.php.tar.gz
2.69
KB
-rw-r--r--
fonts.php.tar
11
KB
-rw-r--r--
fonts.tar
2.93
MB
-rw-r--r--
fonts.tar.gz
608.17
KB
-rw-r--r--
fonts.zip
2.91
MB
-rw-r--r--
footnotes.zip
3.27
KB
-rw-r--r--
form.tar
2.5
KB
-rw-r--r--
form.tar.gz
475
B
-rw-r--r--
form.zip
1.14
KB
-rw-r--r--
formatting.php.php.tar.gz
65.1
KB
-rw-r--r--
formatting.php.tar
329.5
KB
-rw-r--r--
forms-rtl.min.css.min.css.tar....
6.69
KB
-rw-r--r--
forms-rtl.min.css.tar
29.5
KB
-rw-r--r--
fr-FR.zip
432.44
KB
-rw-r--r--
framework.php.php.tar.gz
1.38
KB
-rw-r--r--
framework.php.tar
14
KB
-rw-r--r--
freeform.zip
41.54
KB
-rw-r--r--
freepik_edit_3d-model-octane-r...
573.77
KB
-rw-r--r--
freepik_edit_3d-model-octane-r...
646
KB
-rw-r--r--
full-responsive.png.png.tar.gz
1.11
MB
-rw-r--r--
full-responsive.png.tar
1.12
MB
-rw-r--r--
functions.php.php.tar.gz
71.93
KB
-rw-r--r--
functions.php.tar
557.5
KB
-rw-r--r--
functions.wp-scripts.php.tar
16
KB
-rw-r--r--
functions.wp-scripts.php.wp-sc...
3.98
KB
-rw-r--r--
functions.wp-styles.php.tar
19
KB
-rw-r--r--
functions.wp-styles.php.wp-sty...
2.29
KB
-rw-r--r--
gallery.tar
1.24
MB
-rw-r--r--
gallery.tar.gz
933.8
KB
-rw-r--r--
gallery.zip
1.23
MB
-rw-r--r--
gantry.zip
42.42
KB
-rw-r--r--
gantry5.tar
9.78
MB
-rw-r--r--
gantry5.tar.gz
521.58
KB
-rw-r--r--
gantry5.zip
6.48
MB
-rw-r--r--
general-template.php.php.tar.g...
34.11
KB
-rw-r--r--
general-template.php.tar
490.5
KB
-rw-r--r--
genieprevention.jpg.jpg.tar.gz
224.21
KB
-rw-r--r--
genieprevention.jpg.tar
250.5
KB
-rw-r--r--
genieprevention.png.png.tar.gz
1.14
MB
-rw-r--r--
genieprevention.png.tar
1.17
MB
-rw-r--r--
genieprevention.tar
127.85
MB
-rw-r--r--
genieprevention.tar.gz
59.62
MB
-rw-r--r--
getid3.lib.php.lib.php.tar.gz
12.36
KB
-rw-r--r--
getid3.lib.php.tar
55
KB
-rw-r--r--
global-styles-and-settings.php...
5.27
KB
-rw-r--r--
global-styles-and-settings.php...
22.5
KB
-rw-r--r--
google-map.tar
15
KB
-rw-r--r--
google-map.tar.gz
4.24
KB
-rw-r--r--
google-map.zip
12.63
KB
-rw-r--r--
google13cccd2253d2ff59.html.ht...
151
B
-rw-r--r--
google13cccd2253d2ff59.html.ta...
2
KB
-rw-r--r--
google9d63adf694ce55d9.html.ht...
155
B
-rw-r--r--
google9d63adf694ce55d9.html.ta...
2
KB
-rw-r--r--
googleaa8106a26df5450e.html.ht...
152
B
-rw-r--r--
googleaa8106a26df5450e.html.ta...
2
KB
-rw-r--r--
grid1.jpg.jpg.tar.gz
39.16
KB
-rw-r--r--
grid1.jpg.tar
40.5
KB
-rw-r--r--
group.tar
21
KB
-rw-r--r--
group.tar.gz
1.69
KB
-rw-r--r--
group.zip
10.62
KB
-rw-r--r--
header.php.php.tar.gz
989
B
-rw-r--r--
header.php.tar
4
KB
-rw-r--r--
headers.tar
153.5
KB
-rw-r--r--
headers.tar.gz
147.74
KB
-rw-r--r--
headers.zip
149.11
KB
-rw-r--r--
heading.php.php.tar.gz
700
B
-rw-r--r--
heading.php.tar
3
KB
-rw-r--r--
help.tar
8
KB
-rw-r--r--
help.tar.gz
1.14
KB
-rw-r--r--
help.zip
5.76
KB
-rw-r--r--
helpers.tar
14
KB
-rw-r--r--
helpers.tar.gz
2.92
KB
-rw-r--r--
hightlight.css.css.tar.gz
541
B
-rw-r--r--
hightlight.css.tar
2.5
KB
-rw-r--r--
hikashoppayment.tar
1.63
MB
-rw-r--r--
hikashoppayment.tar.gz
433.55
KB
-rw-r--r--
hikashoppayment.zip
1.45
MB
-rw-r--r--
home-link.tar
3
KB
-rw-r--r--
home-link.tar.gz
598
B
-rw-r--r--
home-link.zip
1.25
KB
-rw-r--r--
hover.css.css.tar.gz
4.2
KB
-rw-r--r--
hover.css.tar
47
KB
-rw-r--r--
htaccess.txt.tar
28.5
KB
-rw-r--r--
htaccess.txt.txt.tar.gz
1.53
KB
-rw-r--r--
html-api.tar
535.5
KB
-rw-r--r--
html-api.tar.gz
90.01
KB
-rw-r--r--
html-api.zip
526.46
KB
-rw-r--r--
html.png.png.tar.gz
5.08
KB
-rw-r--r--
html.png.tar
7
KB
-rw-r--r--
html.tar
33.5
KB
-rw-r--r--
html.tar.gz
966
B
-rw-r--r--
http.php.php.tar.gz
5.53
KB
-rw-r--r--
http.php.tar
52
KB
-rw-r--r--
http:.tar
82
KB
-rw-r--r--
http:.tar.gz
24.81
KB
-rw-r--r--
http:.zip
80.62
KB
-rw-r--r--
https-migration.php.php.tar.gz
1.65
KB
-rw-r--r--
https-migration.php.tar
12
KB
-rw-r--r--
https:.tar
82
KB
-rw-r--r--
https:.tar.gz
24.81
KB
-rw-r--r--
https:.zip
80.62
KB
-rw-r--r--
ibd.html.tar
1.5
KB
-rw-r--r--
icagenda.tar
14
KB
-rw-r--r--
icagenda.tar.gz
3.01
KB
-rw-r--r--
icon_fonts.tar
3.44
MB
-rw-r--r--
icon_fonts.tar.gz
1.48
MB
-rw-r--r--
icon_fonts.zip
3.43
MB
-rw-r--r--
ident.tar
1.84
MB
-rw-r--r--
ident.tar.gz
1.69
MB
-rw-r--r--
ident.zip
1.84
MB
-rw-r--r--
identification_qr_code_joe007....
426.41
KB
-rw-r--r--
identification_qr_code_joe007....
452.5
KB
-rw-r--r--
identification_qrcode_suly007....
425.82
KB
-rw-r--r--
identification_qrcode_suly007....
452
KB
-rw-r--r--
idna_convert.zip
142.7
KB
-rw-r--r--
image.php.php.tar.gz
4.05
KB
-rw-r--r--
image.php.tar
13.5
KB
-rw-r--r--
images.jfif.jfif.tar.gz
3.66
KB
-rw-r--r--
images.jfif.tar
5.5
KB
-rw-r--r--
images.tar
185.22
MB
-rw-r--r--
images.tar.gz
9.73
MB
-rw-r--r--
images.zip
204.64
MB
-rw-r--r--
img.tar
1.83
MB
-rw-r--r--
img.tar.gz
638.06
KB
-rw-r--r--
img.zip
1.77
MB
-rw-r--r--
import.php.php.tar.gz
2.68
KB
-rw-r--r--
import.php.tar
17.5
KB
-rw-r--r--
include-component.tar
342.5
KB
-rw-r--r--
include-component.tar.gz
319.18
KB
-rw-r--r--
includes.tar
2.8
MB
-rw-r--r--
includes.tar.gz
26.35
KB
-rw-r--r--
includes.zip
2.99
MB
-rw-r--r--
index-home.html.html.tar.gz
4.34
KB
-rw-r--r--
index-home.html.tar
22
KB
-rw-r--r--
index-slides.html.html.tar.gz
7.51
KB
-rw-r--r--
index-slides.html.tar
40.5
KB
-rw-r--r--
index-static.html.html.tar.gz
7.41
KB
-rw-r--r--
index-static.html.tar
40
KB
-rw-r--r--
index-text.html.html.tar.gz
6.78
KB
-rw-r--r--
index-text.html.tar
41.5
KB
-rw-r--r--
index.html.html.tar.gz
7.33
KB
-rw-r--r--
index.html.tar
99
KB
-rw-r--r--
index.jpg.jpg.tar.gz
11.13
KB
-rw-r--r--
index.jpg.tar
13
KB
-rw-r--r--
index.php.php.tar.gz
351
B
-rw-r--r--
index.php.tar
83.5
KB
-rw-r--r--
index.php0.php0.tar.gz
855
B
-rw-r--r--
index.php0.tar
3
KB
-rw-r--r--
index5.php.php.tar.gz
353
B
-rw-r--r--
index5.php.tar
2
KB
-rw-r--r--
indexFR.html.html.tar.gz
5.82
KB
-rw-r--r--
indexFR.html.tar
27.5
KB
-rw-r--r--
index_files.tar
1.22
MB
-rw-r--r--
index_files.tar.gz
838.85
KB
-rw-r--r--
index_files.zip
1.21
MB
-rw-r--r--
indexfr.html.html.tar.gz
6.01
KB
-rw-r--r--
indexfr.html.tar
29.5
KB
-rw-r--r--
indexx.html.html.tar.gz
2.01
KB
-rw-r--r--
indexx.html.tar
8
KB
-rw-r--r--
indexx.php.php.tar.gz
357
B
-rw-r--r--
indexx.php.tar
2
KB
-rw-r--r--
install-helper.php.php.tar.gz
1.97
KB
-rw-r--r--
install-helper.php.tar
37.5
KB
-rw-r--r--
install.html.html.tar.gz
160
B
-rw-r--r--
install.html.tar
2
KB
-rw-r--r--
install.php.php.tar.gz
5.21
KB
-rw-r--r--
install.php.tar
72.5
KB
-rw-r--r--
installer.tar
74
KB
-rw-r--r--
installer.tar.gz
14.3
KB
-rw-r--r--
installer.zip
70.91
KB
-rw-r--r--
interactivity-api.tar
57.5
KB
-rw-r--r--
interactivity-api.tar.gz
13.26
KB
-rw-r--r--
interactivity-api.zip
54.55
KB
-rw-r--r--
ion.rangeSlider.min.css.rangeS...
1.05
KB
-rw-r--r--
ion.rangeSlider.min.css.tar
5
KB
-rw-r--r--
ionicons.css.css.tar.gz
8.76
KB
-rw-r--r--
ionicons.css.tar
57.5
KB
-rw-r--r--
ionicons.eot.eot.tar.gz
67.46
KB
-rw-r--r--
ionicons.eot.tar
119.5
KB
-rw-r--r--
ionicons.min.css.min.css.tar.g...
8.19
KB
-rw-r--r--
ionicons.min.css.tar
52
KB
-rw-r--r--
ionicons.svg.svg.tar.gz
100.45
KB
-rw-r--r--
ionicons.svg.tar
328
KB
-rw-r--r--
ionicons.ttf.tar
186
KB
-rw-r--r--
ionicons.ttf.ttf.tar.gz
107.36
KB
-rw-r--r--
ionicons.woff.tar
68
KB
-rw-r--r--
ionicons.woff.woff.tar.gz
65.47
KB
-rw-r--r--
it_sanctum.tar
7.63
MB
-rw-r--r--
it_sanctum.tar.gz
3.36
MB
-rw-r--r--
it_sanctum.zip
7.36
MB
-rw-r--r--
java.png.png.tar.gz
4.57
KB
-rw-r--r--
java.png.tar
6
KB
-rw-r--r--
jce.tar
285
KB
-rw-r--r--
jce.tar.gz
258.77
KB
-rw-r--r--
jce.zip
263.86
KB
-rw-r--r--
jcrop.zip
24.83
KB
-rw-r--r--
joomla.png.png.tar.gz
10.05
KB
-rw-r--r--
joomla.png.tar
12
KB
-rw-r--r--
joomla.tar
2.09
MB
-rw-r--r--
joomla.tar.gz
34.7
KB
-rw-r--r--
joomla.zip
1.86
MB
-rw-r--r--
joomla_black.png.png.tar.gz
5.04
KB
-rw-r--r--
joomla_black.png.tar
6.5
KB
-rw-r--r--
jquery-1.10.2.js.10.2.js.tar.g...
79.27
KB
-rw-r--r--
jquery-1.10.2.js.tar
268.5
KB
-rw-r--r--
jquery-1.7.2.js.7.2.js.tar.gz
32.95
KB
-rw-r--r--
jquery-1.7.2.js.tar
94.5
KB
-rw-r--r--
jquery-3.1.1.min.js.1.1.min.js...
29.5
KB
-rw-r--r--
jquery-3.1.1.min.js.tar
86.5
KB
-rw-r--r--
jquery-3.3.1.min.js.3.1.min.js...
23.63
KB
-rw-r--r--
jquery-3.3.1.min.js.tar
70
KB
-rw-r--r--
jquery.prettyPhoto.js.prettyPh...
6.23
KB
-rw-r--r--
jquery.prettyPhoto.js.tar
37.5
KB
-rw-r--r--
jquery.quicksand.js.quicksand....
3.32
KB
-rw-r--r--
jquery.quicksand.js.tar
16
KB
-rw-r--r--
jquery.tar
1.31
MB
-rw-r--r--
jquery.tar.gz
354.74
KB
-rw-r--r--
js.png.png.tar.gz
5.12
KB
-rw-r--r--
js.png.tar
7
KB
-rw-r--r--
js.tar
28.98
MB
-rw-r--r--
js.tar.gz
88.56
KB
-rw-r--r--
js.zip
28.81
MB
-rw-r--r--
jui.tar
1.93
MB
-rw-r--r--
jui.tar.gz
608.39
KB
-rw-r--r--
jui.zip
1.86
MB
-rw-r--r--
jw_allvideos.tar
8.5
KB
-rw-r--r--
jw_allvideos.tar.gz
6.89
KB
-rw-r--r--
jw_allvideos.zip
6.93
KB
-rw-r--r--
k2.tar
19.06
MB
-rw-r--r--
k2.tar.gz
12.15
MB
-rw-r--r--
k2.zip
20.62
MB
-rw-r--r--
keychain.php.php.tar.gz
2.5
KB
-rw-r--r--
keychain.php.tar
10
KB
-rw-r--r--
keys.tar
83
KB
-rw-r--r--
keys.tar.gz
24.92
KB
-rw-r--r--
keys.zip
80.85
KB
-rw-r--r--
kses.php.php.tar.gz
15.21
KB
-rw-r--r--
kses.php.tar
137
KB
-rw-r--r--
l10n.php.php.tar.gz
10.36
KB
-rw-r--r--
l10n.php.tar
123
KB
-rw-r--r--
l10n.tar
35.5
KB
-rw-r--r--
l10n.tar.gz
6.3
KB
-rw-r--r--
l10n.zip
31.37
KB
-rw-r--r--
langmetadata.xml.tar
4
KB
-rw-r--r--
langmetadata.xml.xml.tar.gz
602
B
-rw-r--r--
language.tar
4.46
MB
-rw-r--r--
language.tar.gz
712.33
KB
-rw-r--r--
language.zip
901.86
KB
-rw-r--r--
languages.tar
45.74
MB
-rw-r--r--
languages.tar.gz
10.09
MB
-rw-r--r--
languages.zip
45.4
MB
-rw-r--r--
latest-posts.tar
18
KB
-rw-r--r--
latest-posts.tar.gz
1.95
KB
-rw-r--r--
latest-posts.zip
12.74
KB
-rw-r--r--
layerslider.tar
742.5
KB
-rw-r--r--
layerslider.tar.gz
377.05
KB
-rw-r--r--
layerslider.zip
702.11
KB
-rw-r--r--
layouts.tar
576
KB
-rw-r--r--
layouts.tar.gz
64.14
KB
-rw-r--r--
layouts.zip
472.05
KB
-rw-r--r--
libraries.tar
65.01
MB
-rw-r--r--
libraries.tar.gz
3.69
MB
-rw-r--r--
libraries.zip
65.53
MB
-rw-r--r--
library.tar
2
KB
-rw-r--r--
library.tar.gz
263
B
-rw-r--r--
license.txt.tar
241
KB
-rw-r--r--
license.txt.txt.tar.gz
7.23
KB
-rw-r--r--
link-add.php.php.tar.gz
590
B
-rw-r--r--
link-add.php.tar
2.5
KB
-rw-r--r--
link-manager.php.php.tar.gz
1.88
KB
-rw-r--r--
link-manager.php.tar
6
KB
-rw-r--r--
link-parse-opml.php.php.tar.gz
1.09
KB
-rw-r--r--
link-parse-opml.php.tar
4.5
KB
-rw-r--r--
link-template.php.php.tar.gz
25.97
KB
-rw-r--r--
link-template.php.tar
154
KB
-rw-r--r--
link.php.php.tar.gz
1.15
KB
-rw-r--r--
link.php.tar
4.5
KB
-rw-r--r--
list.php.php.tar.gz
699
B
-rw-r--r--
list.php.tar
3
KB
-rw-r--r--
load-scripts.php.php.tar.gz
939
B
-rw-r--r--
load-scripts.php.tar
6.5
KB
-rw-r--r--
load-styles.php.php.tar.gz
1.14
KB
-rw-r--r--
load-styles.php.tar
8
KB
-rw-r--r--
load.php.php.tar.gz
14.85
KB
-rw-r--r--
load.php.tar
56
KB
-rw-r--r--
loader.gif.gif.tar.gz
2.23
KB
-rw-r--r--
loader.gif.tar
4
KB
-rw-r--r--
loader.php.php.tar.gz
5.63
KB
-rw-r--r--
loader.php.tar
24
KB
-rw-r--r--
locale.php.php.tar.gz
245
B
-rw-r--r--
locale.php.tar
4
KB
-rw-r--r--
location.pdf.pdf.tar.gz
475.03
KB
-rw-r--r--
location.pdf.tar
495
KB
-rw-r--r--
log.tar
82
KB
-rw-r--r--
log.tar.gz
24.81
KB
-rw-r--r--
log.zip
80.62
KB
-rw-r--r--
login.tar
101.44
MB
-rw-r--r--
login.tar.gz
45.21
MB
-rw-r--r--
login.zip
96.15
MB
-rw-r--r--
loginout.zip
1.15
KB
-rw-r--r--
logo ala maze.ai.ai.tar.gz
1.36
MB
-rw-r--r--
logo ala maze.ai.tar
1.42
MB
-rw-r--r--
logo-white.png.png.tar.gz
4.59
KB
-rw-r--r--
logo-white.png.tar
6
KB
-rw-r--r--
logo.png.png.tar.gz
92.76
KB
-rw-r--r--
logo.png.tar
211.5
KB
-rw-r--r--
logo.tar
497
KB
-rw-r--r--
logo.tar.gz
96
B
-rw-r--r--
logo.zip
493.46
KB
-rw-r--r--
logo2.png.png.tar.gz
3.13
KB
-rw-r--r--
logo2.png.tar
4.5
KB
-rw-r--r--
logo_2x.png.png.tar.gz
1.9
KB
-rw-r--r--
logo_2x.png.tar
3.5
KB
-rw-r--r--
logo_sticky.png.png.tar.gz
1.24
KB
-rw-r--r--
logo_sticky.png.tar
3
KB
-rw-r--r--
logoindex2.png.png.tar.gz
3.89
KB
-rw-r--r--
logoindex2.png.tar
10
KB
-rw-r--r--
logos.tar
1.5
KB
-rw-r--r--
logos.tar.gz
97
B
-rw-r--r--
logowhite.png.png.tar.gz
3.98
KB
-rw-r--r--
logowhite.png.tar
6
KB
-rw-r--r--
logrotation.zip
8.03
KB
-rw-r--r--
logs.tar
117.5
KB
-rw-r--r--
logs.tar.gz
25.54
KB
-rw-r--r--
logs.zip
353.88
KB
-rw-r--r--
magento.png.png.tar.gz
50.73
KB
-rw-r--r--
magento.png.tar
60.5
KB
-rw-r--r--
mailto.tar
2
KB
-rw-r--r--
mailto.tar.gz
208
B
-rw-r--r--
mailto.zip
284
B
-rw-r--r--
main-banner_old2.jpg.jpg.tar.g...
61.7
KB
-rw-r--r--
main-banner_old2.jpg.tar
95.5
KB
-rw-r--r--
main.css.css.tar.gz
2.27
KB
-rw-r--r--
main.css.tar
10.5
KB
-rw-r--r--
main.js.js.tar.gz
1.83
KB
-rw-r--r--
main.js.tar
7
KB
-rw-r--r--
main.min.css.min.css.tar.gz
1.97
KB
-rw-r--r--
main.min.css.tar
8
KB
-rw-r--r--
main.min.js.min.js.tar.gz
1.66
KB
-rw-r--r--
main.min.js.tar
6
KB
-rw-r--r--
maint.tar
9
KB
-rw-r--r--
maint.tar.gz
2.66
KB
-rw-r--r--
maint.zip
7.56
KB
-rw-r--r--
manifest.json.json.tar.gz
294
B
-rw-r--r--
manifest.json.tar
2.5
KB
-rw-r--r--
mapmarker_func.jquery.js.jquer...
317
B
-rw-r--r--
mapmarker_func.jquery.js.tar
2
KB
-rw-r--r--
maps.tar
79.5
KB
-rw-r--r--
maps.tar.gz
19.9
KB
-rw-r--r--
maps.zip
77.71
KB
-rw-r--r--
media-audiovideo.js.js.tar.gz
6.02
KB
-rw-r--r--
media-audiovideo.js.tar
28.5
KB
-rw-r--r--
media-button-2x.png.png.tar.gz
1007
B
-rw-r--r--
media-button-2x.png.tar
2.5
KB
-rw-r--r--
media-button-image.gif.gif.tar...
325
B
-rw-r--r--
media-button-image.gif.tar
2
KB
-rw-r--r--
media-button-other.gif.gif.tar...
409
B
-rw-r--r--
media-button-other.gif.tar
2
KB
-rw-r--r--
media-button.png.png.tar.gz
475
B
-rw-r--r--
media-button.png.tar
2
KB
-rw-r--r--
media-new.php.php.tar.gz
1.57
KB
-rw-r--r--
media-new.php.tar
9
KB
-rw-r--r--
media-template.php.php.tar.gz
11.15
KB
-rw-r--r--
media-template.php.tar
184.5
KB
-rw-r--r--
media-text.tar
22
KB
-rw-r--r--
media-text.tar.gz
2.2
KB
-rw-r--r--
media-text.zip
15.34
KB
-rw-r--r--
media-upload.php.php.tar.gz
1.46
KB
-rw-r--r--
media-upload.php.tar
13
KB
-rw-r--r--
media.php.php.tar.gz
36.43
KB
-rw-r--r--
media.php.tar
368.5
KB
-rw-r--r--
media.tar
76.18
MB
-rw-r--r--
media.tar.gz
16.27
MB
-rw-r--r--
media.zip
69.29
MB
-rw-r--r--
mediaelement.tar
2.19
MB
-rw-r--r--
mediaelement.tar.gz
154.85
KB
-rw-r--r--
mediaelement.zip
2.17
MB
-rw-r--r--
member.jpg.jpg.tar.gz
8.99
KB
-rw-r--r--
member.jpg.tar
11
KB
-rw-r--r--
menu-header.php.php.tar.gz
2.89
KB
-rw-r--r--
menu-header.php.tar
11.5
KB
-rw-r--r--
menu.php.php.tar.gz
4.47
KB
-rw-r--r--
menu.php.tar
18.5
KB
-rw-r--r--
menu.tar
5.5
KB
-rw-r--r--
menu.tar.gz
1.26
KB
-rw-r--r--
meta-boxes.php.php.tar.gz
12.82
KB
-rw-r--r--
meta-boxes.php.tar
185.5
KB
-rw-r--r--
meta.php.php.tar.gz
9.97
KB
-rw-r--r--
meta.php.tar
290
KB
-rw-r--r--
metismenujs.tar
77
KB
-rw-r--r--
metismenujs.tar.gz
16.01
KB
-rw-r--r--
middletv.tar
17.4
MB
-rw-r--r--
middletv.tar.gz
9.32
MB
-rw-r--r--
middletv.zip
17.23
MB
-rw-r--r--
missing.tar
2.5
KB
-rw-r--r--
missing.tar.gz
396
B
-rw-r--r--
mod_acymailing.zip
60.47
KB
-rw-r--r--
mod_articles_latest.tar
13
KB
-rw-r--r--
mod_articles_latest.tar.gz
2.95
KB
-rw-r--r--
mod_articles_latest.zip
9.55
KB
-rw-r--r--
mod_articles_news.tar
23.5
KB
-rw-r--r--
mod_articles_news.tar.gz
4.22
KB
-rw-r--r--
mod_articles_popular.zip
9.37
KB
-rw-r--r--
mod_breadcrumbs.tar
13
KB
-rw-r--r--
mod_breadcrumbs.tar.gz
2.95
KB
-rw-r--r--
mod_breadcrumbs.zip
9.32
KB
-rw-r--r--
mod_custom.tar
7
KB
-rw-r--r--
mod_custom.tar.gz
1.57
KB
-rw-r--r--
mod_custom.zip
4.06
KB
-rw-r--r--
mod_falang.tar
50.5
KB
-rw-r--r--
mod_falang.tar.gz
9.35
KB
-rw-r--r--
mod_falang.zip
44.2
KB
-rw-r--r--
mod_feed.zip
10.14
KB
-rw-r--r--
mod_finder.tar
18
KB
-rw-r--r--
mod_finder.tar.gz
4.23
KB
-rw-r--r--
mod_hikashop_filter.tar
15
KB
-rw-r--r--
mod_hikashop_filter.tar.gz
2.09
KB
-rw-r--r--
mod_k2_tools.tar
88
KB
-rw-r--r--
mod_k2_tools.tar.gz
13.73
KB
-rw-r--r--
mod_k2_tools.zip
79.47
KB
-rw-r--r--
mod_languages.tar
18.5
KB
-rw-r--r--
mod_languages.tar.gz
3.59
KB
-rw-r--r--
mod_languages.zip
14.83
KB
-rw-r--r--
mod_multilangstatus.tar
8
KB
-rw-r--r--
mod_multilangstatus.tar.gz
1.17
KB
-rw-r--r--
mod_privacy_dashboard.tar
10.5
KB
-rw-r--r--
mod_privacy_dashboard.tar.gz
2.18
KB
-rw-r--r--
mod_privacy_dashboard.zip
6.72
KB
-rw-r--r--
mod_related_items.zip
8.91
KB
-rw-r--r--
mod_search.tar
13
KB
-rw-r--r--
mod_search.tar.gz
2.86
KB
-rw-r--r--
mod_search.zip
9.7
KB
-rw-r--r--
mod_spsimpleportfolio.tar
25.5
KB
-rw-r--r--
mod_spsimpleportfolio.tar.gz
5.22
KB
-rw-r--r--
mod_sr_currency.tar
30.5
KB
-rw-r--r--
mod_sr_currency.tar.gz
3.72
KB
-rw-r--r--
mod_stats.tar
16.5
KB
-rw-r--r--
mod_stats.tar.gz
2.36
KB
-rw-r--r--
mod_stats.zip
12.43
KB
-rw-r--r--
mod_submenu.tar
7
KB
-rw-r--r--
mod_submenu.tar.gz
1.56
KB
-rw-r--r--
mod_syndicate.tar
8.5
KB
-rw-r--r--
mod_syndicate.tar.gz
1.77
KB
-rw-r--r--
mod_syndicate.zip
5.02
KB
-rw-r--r--
mod_tags_popular.zip
13.4
KB
-rw-r--r--
mod_tags_similar.tar
14
KB
-rw-r--r--
mod_tags_similar.tar.gz
3.23
KB
-rw-r--r--
mod_tags_similar.zip
11.02
KB
-rw-r--r--
mod_users_latest.tar
9
KB
-rw-r--r--
mod_users_latest.tar.gz
2.01
KB
-rw-r--r--
mod_users_latest.zip
5.81
KB
-rw-r--r--
mod_wrapper.tar
11
KB
-rw-r--r--
mod_wrapper.tar.gz
2.21
KB
-rw-r--r--
mod_wrapper.zip
7.83
KB
-rw-r--r--
modal.zip
17.12
KB
-rw-r--r--
models.tar
6.5
KB
-rw-r--r--
models.tar.gz
1.57
KB
-rw-r--r--
moderation.php.php.tar.gz
303
B
-rw-r--r--
moderation.php.tar
2
KB
-rw-r--r--
modules.tar
2.56
MB
-rw-r--r--
modules.tar.gz
87.17
KB
-rw-r--r--
modules.zip
3.04
MB
-rw-r--r--
more.zip
4.38
KB
-rw-r--r--
ms-admin.php.php.tar.gz
263
B
-rw-r--r--
ms-admin.php.tar
2
KB
-rw-r--r--
ms-blogs.php.php.tar.gz
6.12
KB
-rw-r--r--
ms-blogs.php.tar
27
KB
-rw-r--r--
ms-default-constants.php.php.t...
1.66
KB
-rw-r--r--
ms-default-constants.php.tar
23
KB
-rw-r--r--
ms-default-filters.php.php.tar...
1.8
KB
-rw-r--r--
ms-default-filters.php.tar
27.5
KB
-rw-r--r--
ms-delete-site.php.php.tar.gz
1.87
KB
-rw-r--r--
ms-delete-site.php.tar
11
KB
-rw-r--r--
ms-deprecated.php.php.tar.gz
6.25
KB
-rw-r--r--
ms-deprecated.php.tar
23
KB
-rw-r--r--
ms-edit.php.php.tar.gz
280
B
-rw-r--r--
ms-edit.php.tar
3
KB
-rw-r--r--
ms-files.php.php.tar.gz
1.22
KB
-rw-r--r--
ms-files.php.tar
8
KB
-rw-r--r--
ms-functions.php.php.tar.gz
19.22
KB
-rw-r--r--
ms-functions.php.tar
91
KB
-rw-r--r--
ms-icon-144x144.png.png.tar.gz
14.3
KB
-rw-r--r--
ms-icon-144x144.png.tar
16
KB
-rw-r--r--
ms-icon-150x150.png.png.tar.gz
14.94
KB
-rw-r--r--
ms-icon-150x150.png.tar
16.5
KB
-rw-r--r--
ms-icon-310x310.png.png.tar.gz
43.67
KB
-rw-r--r--
ms-icon-310x310.png.tar
45.5
KB
-rw-r--r--
ms-icon-70x70.png.png.tar.gz
5.71
KB
-rw-r--r--
ms-icon-70x70.png.tar
7.5
KB
-rw-r--r--
ms-load.php.php.tar.gz
6.03
KB
-rw-r--r--
ms-load.php.tar
40.5
KB
-rw-r--r--
ms-network.php.php.tar.gz
1.47
KB
-rw-r--r--
ms-network.php.tar
10
KB
-rw-r--r--
ms-options.php.php.tar.gz
282
B
-rw-r--r--
ms-options.php.tar
2
KB
-rw-r--r--
ms-settings.php.php.tar.gz
1.62
KB
-rw-r--r--
ms-settings.php.tar
11
KB
-rw-r--r--
ms-site.php.php.tar.gz
9.44
KB
-rw-r--r--
ms-site.php.tar
41
KB
-rw-r--r--
ms-sites.php.php.tar.gz
273
B
-rw-r--r--
ms-sites.php.tar
3
KB
-rw-r--r--
ms-upgrade-network.php.php.tar...
281
B
-rw-r--r--
ms-upgrade-network.php.tar
2
KB
-rw-r--r--
ms-users.php.php.tar.gz
274
B
-rw-r--r--
ms-users.php.tar
3
KB
-rw-r--r--
mu-plugins.tar
2.5
KB
-rw-r--r--
mu-plugins.tar.gz
393
B
-rw-r--r--
mu-plugins.zip
791
B
-rw-r--r--
my-music.online.tar
636.9
MB
-rw-r--r--
my-music.online.tar.gz
20
B
-rw-r--r--
my-sites.php.php.tar.gz
2.04
KB
-rw-r--r--
my-sites.php.tar
6.5
KB
-rw-r--r--
mymusicpromo-online.zip
53.39
MB
-rw-r--r--
mysql.png.png.tar.gz
4.7
KB
-rw-r--r--
mysql.png.tar
7
KB
-rw-r--r--
nav-menu-template.php.php.tar....
6.24
KB
-rw-r--r--
nav-menu-template.php.tar
76.5
KB
-rw-r--r--
nav-menu.php.php.tar.gz
9.58
KB
-rw-r--r--
nav-menu.php.tar
45
KB
-rw-r--r--
nav-menus.php.php.tar.gz
10.56
KB
-rw-r--r--
nav-menus.php.tar
50
KB
-rw-r--r--
navigation-link.tar
19.5
KB
-rw-r--r--
navigation-link.tar.gz
1.97
KB
-rw-r--r--
navigation-submenu.zip
9.26
KB
-rw-r--r--
navigation.zip
131.13
KB
-rw-r--r--
network.php.php.tar.gz
2.23
KB
-rw-r--r--
network.php.tar
7
KB
-rw-r--r--
network.tar
145.5
KB
-rw-r--r--
network.tar.gz
27.6
KB
-rw-r--r--
network.zip
127.06
KB
-rw-r--r--
networks.php.php.tar.gz
1.07
KB
-rw-r--r--
networks.php.tar
3.5
KB
-rw-r--r--
newsletter.php.php.tar.gz
1.39
KB
-rw-r--r--
newsletter.php.tar
4
KB
-rw-r--r--
nl-NL.tar
354.5
KB
-rw-r--r--
nl-NL.tar.gz
79.1
KB
-rw-r--r--
nl-NL.zip
304
KB
-rw-r--r--
node.png.png.tar.gz
51.8
KB
-rw-r--r--
node.png.tar
57.5
KB
-rw-r--r--
node2.png.png.tar.gz
26.86
KB
-rw-r--r--
node2.png.tar
32
KB
-rw-r--r--
odfiafrica.jpg.jpg.tar.gz
384.95
KB
-rw-r--r--
odfiafrica.jpg.tar
417
KB
-rw-r--r--
onepage-slider.html.html.tar.g...
6.99
KB
-rw-r--r--
onepage-slider.html.tar
42.5
KB
-rw-r--r--
onepage-text.html.html.tar.gz
6.9
KB
-rw-r--r--
onepage-text.html.tar
42
KB
-rw-r--r--
option.php.php.tar.gz
13.11
KB
-rw-r--r--
option.php.tar
532.5
KB
-rw-r--r--
options-discussion.php.php.tar...
4.27
KB
-rw-r--r--
options-discussion.php.tar
82
KB
-rw-r--r--
options-general.php.php.tar.gz
6.41
KB
-rw-r--r--
options-general.php.tar
83
KB
-rw-r--r--
options-head.php.php.tar.gz
464
B
-rw-r--r--
options-head.php.tar
2.5
KB
-rw-r--r--
options-permalink.php.php.tar....
5.59
KB
-rw-r--r--
options-permalink.php.tar
88.5
KB
-rw-r--r--
options-privacy.php.php.tar.gz
2.71
KB
-rw-r--r--
options-privacy.php.tar
41
KB
-rw-r--r--
options-reading.php.php.tar.gz
3.1
KB
-rw-r--r--
options-reading.php.tar
12
KB
-rw-r--r--
options-writing.php.php.tar.gz
3.05
KB
-rw-r--r--
options-writing.php.tar
21
KB
-rw-r--r--
options.php.php.tar.gz
4.51
KB
-rw-r--r--
options.php.tar
56.5
KB
-rw-r--r--
overrider.tar
12.5
KB
-rw-r--r--
overrider.tar.gz
2.86
KB
-rw-r--r--
overrider.zip
9.83
KB
-rw-r--r--
overrides.tar
3
KB
-rw-r--r--
overrides.tar.gz
269
B
-rw-r--r--
overrides.zip
512
B
-rw-r--r--
owl.carousel.js.carousel.js.ta...
17.24
KB
-rw-r--r--
owl.carousel.js.tar
79
KB
-rw-r--r--
owl.carousel.min.js.carousel.m...
10.39
KB
-rw-r--r--
owl.carousel.min.js.tar
89
KB
-rw-r--r--
p1.jpg.jpg.tar.gz
237.02
KB
-rw-r--r--
p1.jpg.tar
243.5
KB
-rw-r--r--
p2.jpg.jpg.tar.gz
283.15
KB
-rw-r--r--
p2.jpg.tar
285
KB
-rw-r--r--
p3.jpg.jpg.tar.gz
287.59
KB
-rw-r--r--
p3.jpg.tar
289.5
KB
-rw-r--r--
p4.jpg.jpg.tar.gz
394.73
KB
-rw-r--r--
p4.jpg.tar
396.5
KB
-rw-r--r--
p5.jpg.jpg.tar.gz
177.65
KB
-rw-r--r--
p5.jpg.tar
181
KB
-rw-r--r--
p6.jpg.jpg.tar.gz
601.57
KB
-rw-r--r--
p6.jpg.tar
603
KB
-rw-r--r--
packageinstaller.zip
11.38
KB
-rw-r--r--
page-list-item.tar
3
KB
-rw-r--r--
page-list-item.tar.gz
576
B
-rw-r--r--
page-list.tar
15
KB
-rw-r--r--
page-list.tar.gz
1.39
KB
-rw-r--r--
pagebuilder.tar
6.09
MB
-rw-r--r--
pagebuilder.tar.gz
5.84
MB
-rw-r--r--
paralax-index1_old.jpg.jpg.tar...
794.32
KB
-rw-r--r--
paralax-index1_old.jpg.tar
807.5
KB
-rw-r--r--
particles.min.js.min.js.tar.gz
5.91
KB
-rw-r--r--
particles.min.js.tar
24.5
KB
-rw-r--r--
pattern.png.png.tar.gz
2.75
KB
-rw-r--r--
pattern.png.tar
4.5
KB
-rw-r--r--
pattern.svg.svg.tar.gz
17.24
KB
-rw-r--r--
pattern.svg.tar
53
KB
-rw-r--r--
pattern.zip
478
B
-rw-r--r--
payeer_1314567119.txt.tar
2
KB
-rw-r--r--
payeer_1314567119.txt.txt.tar....
128
B
-rw-r--r--
payments.png.png.tar.gz
10.04
KB
-rw-r--r--
payments.png.tar
11.5
KB
-rw-r--r--
payments_2x.png.png.tar.gz
31.26
KB
-rw-r--r--
payments_2x.png.tar
33
KB
-rw-r--r--
paypal_bt.png.png.tar.gz
13.5
KB
-rw-r--r--
paypal_bt.png.tar
15
KB
-rw-r--r--
paypaladvanced_2_6279148dd013c...
334
B
-rw-r--r--
paypaladvanced_2_6279148dd013c...
2.5
KB
-rw-r--r--
paypaladvanced_cancel_2.php.ph...
316
B
-rw-r--r--
paypaladvanced_cancel_2.php.ta...
2.5
KB
-rw-r--r--
paypaladvanced_return_2.php.ph...
316
B
-rw-r--r--
paypaladvanced_return_2.php.ta...
2.5
KB
-rw-r--r--
php-compat.tar
3
KB
-rw-r--r--
php-compat.tar.gz
649
B
-rw-r--r--
php-compat.zip
1.38
KB
-rw-r--r--
php-encryption.tar
26
KB
-rw-r--r--
php-encryption.tar.gz
6.52
KB
-rw-r--r--
php-encryption.zip
24.3
KB
-rw-r--r--
php.ini.ini.tar.gz
244
B
-rw-r--r--
php.ini.tar
3
KB
-rw-r--r--
php.png.png.tar.gz
4.91
KB
-rw-r--r--
php.png.tar
6.5
KB
-rw-r--r--
php_mail.log.log.tar.gz
6.45
KB
-rw-r--r--
php_mail.log.tar
100.5
KB
-rw-r--r--
pickapp.tar
83.5
KB
-rw-r--r--
pickapp.tar.gz
25.16
KB
-rw-r--r--
plg_installer_webinstaller.tar
34.5
KB
-rw-r--r--
plg_installer_webinstaller.tar...
6.53
KB
-rw-r--r--
plg_installer_webinstaller.zip
31.15
KB
-rw-r--r--
plg_media-action_crop.tar
19
KB
-rw-r--r--
plg_media-action_crop.tar.gz
4.14
KB
-rw-r--r--
plg_media-action_crop.zip
14.32
KB
-rw-r--r--
plg_media-action_resize.tar
15
KB
-rw-r--r--
plg_media-action_resize.tar.gz
3.31
KB
-rw-r--r--
plg_media-action_resize.zip
10.3
KB
-rw-r--r--
plg_media-action_rotate.tar
17
KB
-rw-r--r--
plg_media-action_rotate.tar.gz
3.98
KB
-rw-r--r--
plg_media-action_rotate.zip
12.17
KB
-rw-r--r--
plg_quickicon_extensionupdate....
3.5
KB
-rw-r--r--
plg_quickicon_extensionupdate....
791
B
-rw-r--r--
plg_quickicon_extensionupdate....
7.69
KB
-rw-r--r--
plg_quickicon_joomlaupdate.tar
4
KB
-rw-r--r--
plg_quickicon_joomlaupdate.tar...
890
B
-rw-r--r--
plg_quickicon_privacycheck.tar
3.5
KB
-rw-r--r--
plg_quickicon_privacycheck.tar...
860
B
-rw-r--r--
plg_quickicon_privacycheck.zip
2.12
KB
-rw-r--r--
plg_solidres_limitbooking.tar
6
KB
-rw-r--r--
plg_solidres_limitbooking.tar....
1.18
KB
-rw-r--r--
plg_system_highlight.tar
2
KB
-rw-r--r--
plg_system_highlight.tar.gz
166
B
-rw-r--r--
plg_system_highlight.zip
241
B
-rw-r--r--
plg_system_stats.tar
4
KB
-rw-r--r--
plg_system_stats.tar.gz
841
B
-rw-r--r--
plg_system_stats.zip
2.31
KB
-rw-r--r--
plg_twofactorauth_totp.tar
117
KB
-rw-r--r--
plg_twofactorauth_totp.tar.gz
49.11
KB
-rw-r--r--
plg_twofactorauth_totp.zip
113.39
KB
-rw-r--r--
pluggable-deprecated.php.php.t...
1.97
KB
-rw-r--r--
pluggable-deprecated.php.tar
8
KB
-rw-r--r--
pluggable.php.php.tar.gz
23.38
KB
-rw-r--r--
pluggable.php.tar
213
KB
-rw-r--r--
plugin-editor.php.php.tar.gz
4.7
KB
-rw-r--r--
plugin-editor.php.tar
15
KB
-rw-r--r--
plugin-install.php.php.tar.gz
2.64
KB
-rw-r--r--
plugin-install.php.tar
30
KB
-rw-r--r--
plugin.php.php.tar.gz
7.14
KB
-rw-r--r--
plugin.php.tar
36.5
KB
-rw-r--r--
plugin.tar
366
KB
-rw-r--r--
plugin.tar.gz
90.03
KB
-rw-r--r--
plugins.php.php.tar.gz
1.08
KB
-rw-r--r--
plugins.php.tar
86
KB
-rw-r--r--
plugins.tar
239.95
MB
-rw-r--r--
plugins.tar.gz
1.59
MB
-rw-r--r--
plugins.zip
715.26
MB
-rw-r--r--
plugins1.tar
9.22
MB
-rw-r--r--
plugins1.tar.gz
4.62
MB
-rw-r--r--
plugins1.zip
9.2
MB
-rw-r--r--
plupload.tar
486.5
KB
-rw-r--r--
plupload.tar.gz
134.75
KB
-rw-r--r--
pomo.tar
59
KB
-rw-r--r--
pomo.tar.gz
11.77
KB
-rw-r--r--
pomo.zip
54
KB
-rw-r--r--
popper.min.js.min.js.tar.gz
7.4
KB
-rw-r--r--
popper.min.js.tar
22.5
KB
-rw-r--r--
popup_img.jpg.jpg.tar.gz
17.31
KB
-rw-r--r--
popup_img.jpg.tar
19
KB
-rw-r--r--
portfolio.html.html.tar.gz
3.03
KB
-rw-r--r--
portfolio.html.tar
17.5
KB
-rw-r--r--
post-comments-form.zip
10.75
KB
-rw-r--r--
post-content.zip
2.05
KB
-rw-r--r--
post-excerpt.php.php.tar.gz
1.45
KB
-rw-r--r--
post-excerpt.php.tar
5
KB
-rw-r--r--
post-excerpt.tar
11
KB
-rw-r--r--
post-excerpt.tar.gz
919
B
-rw-r--r--
post-formats.php.php.tar.gz
1.97
KB
-rw-r--r--
post-formats.php.tar
16
KB
-rw-r--r--
post-new.php.php.tar.gz
1.13
KB
-rw-r--r--
post-new.php.tar
15
KB
-rw-r--r--
post-template.php.php.tar.gz
15.54
KB
-rw-r--r--
post-template.php.tar
67
KB
-rw-r--r--
post-template.tar
16
KB
-rw-r--r--
post-template.tar.gz
1.44
KB
-rw-r--r--
post-template.zip
9.12
KB
-rw-r--r--
post-thumbnail-template.php.ph...
2.5
KB
-rw-r--r--
post-thumbnail-template.php.ta...
33.5
KB
-rw-r--r--
post.php.php.tar.gz
3.01
KB
-rw-r--r--
post.php.tar
1.12
MB
-rw-r--r--
postnews.php.php.tar.gz
2.34
KB
-rw-r--r--
postnews.php.tar
4
KB
-rw-r--r--
posts.tar
1.41
MB
-rw-r--r--
posts.tar.gz
1.36
MB
-rw-r--r--
posts.zip
1.4
MB
-rw-r--r--
powered_by.png.png.tar.gz
2.3
KB
-rw-r--r--
powered_by.png.tar
8
KB
-rw-r--r--
premium-addons-elementor.tar
69.5
KB
-rw-r--r--
premium-addons-elementor.tar.g...
8.32
KB
-rw-r--r--
premium-addons-elementor.zip
90.58
KB
-rw-r--r--
press-this.php.php.tar.gz
1.07
KB
-rw-r--r--
press-this.php.tar
7
KB
-rw-r--r--
prestashop.png.png.tar.gz
9.5
KB
-rw-r--r--
prestashop.png.tar
11
KB
-rw-r--r--
prev-blue.png.png.tar.gz
3.8
KB
-rw-r--r--
prev-blue.png.tar
5.5
KB
-rw-r--r--
prev-dark.png.png.tar.gz
3.78
KB
-rw-r--r--
prev-dark.png.tar
5.5
KB
-rw-r--r--
prev-green.png.png.tar.gz
3.88
KB
-rw-r--r--
prev-green.png.tar
5.5
KB
-rw-r--r--
prev-orange.png.png.tar.gz
3.87
KB
-rw-r--r--
prev-orange.png.tar
5.5
KB
-rw-r--r--
prev.png.png.tar.gz
3.88
KB
-rw-r--r--
prev.png.tar
10
KB
-rw-r--r--
preview.html.html.tar.gz
1.56
KB
-rw-r--r--
preview.html.tar
8.5
KB
-rw-r--r--
pricing.html.html.tar.gz
3.05
KB
-rw-r--r--
pricing.html.tar
14.5
KB
-rw-r--r--
privacy-policy-guide.php.php.t...
1.52
KB
-rw-r--r--
privacy-policy-guide.php.tar
19
KB
-rw-r--r--
privacy.php.php.tar.gz
1.12
KB
-rw-r--r--
privacy.php.tar
14.5
KB
-rw-r--r--
privacy.tar
62
KB
-rw-r--r--
privacy.tar.gz
7.92
KB
-rw-r--r--
privacy.zip
49.12
KB
-rw-r--r--
privacyconsent.tar
32
KB
-rw-r--r--
privacyconsent.tar.gz
7.52
KB
-rw-r--r--
privacyconsent.zip
28.66
KB
-rw-r--r--
product_edit_dimensions.php.ph...
1.11
KB
-rw-r--r--
product_edit_dimensions.php.ta...
5
KB
-rw-r--r--
profile.php.php.tar.gz
314
B
-rw-r--r--
profile.php.tar
4
KB
-rw-r--r--
promo_bg.jpg.jpg.tar.gz
7.8
KB
-rw-r--r--
promo_bg.jpg.tar
19
KB
-rw-r--r--
promotions.tar
16
KB
-rw-r--r--
promotions.tar.gz
2.24
KB
-rw-r--r--
promotions.zip
10.77
KB
-rw-r--r--
protostar.tar
430.5
KB
-rw-r--r--
protostar.tar.gz
213.28
KB
-rw-r--r--
protostar.zip
408.12
KB
-rw-r--r--
providers.zip
17.7
KB
-rw-r--r--
ptitsanes.jpg.jpg.tar.gz
207.01
KB
-rw-r--r--
ptitsanes.jpg.tar
234.5
KB
-rw-r--r--
ptitsanes.png.png.tar.gz
1.09
MB
-rw-r--r--
ptitsanes.png.tar
1.11
MB
-rw-r--r--
pullquote.tar
19.5
KB
-rw-r--r--
pullquote.tar.gz
1.48
KB
-rw-r--r--
pullquote.zip
18.03
KB
-rw-r--r--
pwnkit
0
B
-rwxr-xr-x
python.png.png.tar.gz
9.74
KB
-rw-r--r--
python.png.tar
12
KB
-rw-r--r--
q1.php.php.tar.gz
740
B
-rw-r--r--
q1.php.tar
8
KB
-rw-r--r--
qlf.txt.tar
2
KB
-rw-r--r--
qlf.txt.txt.tar.gz
120
B
-rw-r--r--
quaadra.tar
3.29
MB
-rw-r--r--
quaadra.tar.gz
2.6
MB
-rw-r--r--
query-no-results.tar
2.5
KB
-rw-r--r--
query-no-results.tar.gz
500
B
-rw-r--r--
query-pagination-next.zip
1.17
KB
-rw-r--r--
query.php.php.tar.gz
4.82
KB
-rw-r--r--
query.php.tar
183.5
KB
-rw-r--r--
query.zip
14.91
KB
-rw-r--r--
quickicon.tar
87
KB
-rw-r--r--
quickicon.tar.gz
10.07
KB
-rw-r--r--
quickicon.zip
69.9
KB
-rw-r--r--
quote.zip
7.6
KB
-rw-r--r--
readme.html.html.tar.gz
3.03
KB
-rw-r--r--
readme.html.tar
28
KB
-rw-r--r--
readme.txt.tar
6.5
KB
-rw-r--r--
readme.txt.txt.tar.gz
2.08
KB
-rw-r--r--
realex_hpp_api.tar
271.5
KB
-rw-r--r--
realex_hpp_api.tar.gz
53.14
KB
-rw-r--r--
registration-functions.php.php...
273
B
-rw-r--r--
registration-functions.php.tar
3
KB
-rw-r--r--
registration.php.php.tar.gz
266
B
-rw-r--r--
registration.php.tar
3
KB
-rw-r--r--
remember.tar
7.5
KB
-rw-r--r--
remember.tar.gz
1.93
KB
-rw-r--r--
remember.zip
4.68
KB
-rw-r--r--
rest-api.php.php.tar.gz
20.51
KB
-rw-r--r--
rest-api.php.tar
98
KB
-rw-r--r--
rest-api.tar
997
KB
-rw-r--r--
rest-api.tar.gz
168.1
KB
-rw-r--r--
rest-api.zip
965.07
KB
-rw-r--r--
retina-replace.js.js.tar.gz
1.39
KB
-rw-r--r--
retina-replace.js.tar
5
KB
-rw-r--r--
retina-replace.min.js.min.js.t...
1.08
KB
-rw-r--r--
retina-replace.min.js.tar
4
KB
-rw-r--r--
revision.php.php.tar.gz
2.11
KB
-rw-r--r--
revision.php.tar
38.5
KB
-rw-r--r--
rewrite.php.php.tar.gz
5.84
KB
-rw-r--r--
rewrite.php.tar
21
KB
-rw-r--r--
ribbon.png.png.tar.gz
12.26
KB
-rw-r--r--
ribbon.png.tar
14
KB
-rw-r--r--
rick.jpg.jpg.tar.gz
105.81
KB
-rw-r--r--
rick.jpg.tar
112.5
KB
-rw-r--r--
robots-template.php.php.tar.gz
1.31
KB
-rw-r--r--
robots-template.php.tar
13
KB
-rw-r--r--
robots.txt.dist.tar
8.5
KB
-rw-r--r--
robots.txt.dist.txt.dist.tar.g...
492
B
-rw-r--r--
robots.txt.tar
10
KB
-rw-r--r--
robots.txt.txt.tar.gz
213
B
-rw-r--r--
router.php.php.tar.gz
3.1
KB
-rw-r--r--
router.php.tar
16.5
KB
-rw-r--r--
royalkarukera.jpg.jpg.tar.gz
295.82
KB
-rw-r--r--
royalkarukera.jpg.tar
330.5
KB
-rw-r--r--
royalkarukera.png.png.tar.gz
1.45
MB
-rw-r--r--
royalkarukera.png.tar
1.48
MB
-rw-r--r--
royalkarukera.tar
165.02
MB
-rw-r--r--
royalkarukera.tar.gz
70.64
MB
-rw-r--r--
royalkarukerda.jpg.jpg.tar.gz
292.85
KB
-rw-r--r--
royalkarukerda.jpg.tar
326
KB
-rw-r--r--
rss-functions.php.php.tar.gz
312
B
-rw-r--r--
rss-functions.php.tar
2
KB
-rw-r--r--
rss.php.php.tar.gz
6.66
KB
-rw-r--r--
rss.php.tar
48
KB
-rw-r--r--
s1.PNG.PNG.tar.gz
1003.13
KB
-rw-r--r--
s1.PNG.tar
1005
KB
-rw-r--r--
s2.PNG.PNG.tar.gz
409.52
KB
-rw-r--r--
s2.PNG.tar
415
KB
-rw-r--r--
s3.PNG.PNG.tar.gz
753.06
KB
-rw-r--r--
s3.PNG.tar
757
KB
-rw-r--r--
s4.PNG.PNG.tar.gz
674.01
KB
-rw-r--r--
s4.PNG.tar
682.5
KB
-rw-r--r--
sampledata.tar
577
KB
-rw-r--r--
sampledata.tar.gz
5.79
KB
-rw-r--r--
sampledata.zip
1.18
MB
-rw-r--r--
script-loader.php.php.tar.gz
30.55
KB
-rw-r--r--
script-loader.php.tar
529
KB
-rw-r--r--
script-modules.php.php.tar.gz
1.16
KB
-rw-r--r--
script-modules.php.tar
7.5
KB
-rw-r--r--
script.js.js.tar.gz
739
B
-rw-r--r--
script.js.tar
3
KB
-rw-r--r--
scss.tar
143.5
KB
-rw-r--r--
scss.tar.gz
33.94
KB
-rw-r--r--
scss.zip
128.81
KB
-rw-r--r--
search.php.php.tar.gz
870
B
-rw-r--r--
search.php.tar
3
KB
-rw-r--r--
search.tar
57
KB
-rw-r--r--
search.tar.gz
7.01
KB
-rw-r--r--
search.zip
83.69
KB
-rw-r--r--
searchtools.zip
10.7
KB
-rw-r--r--
semantic.css.css.tar.gz
112.76
KB
-rw-r--r--
semantic.css.tar
735
KB
-rw-r--r--
semantic.js.js.tar.gz
113.67
KB
-rw-r--r--
semantic.js.tar
713
KB
-rw-r--r--
semantic.min.js.min.js.tar.gz
67.58
KB
-rw-r--r--
semantic.min.js.tar
270.5
KB
-rw-r--r--
sendmail.php.php.tar.gz
568
B
-rw-r--r--
sendmail.php.tar
2.5
KB
-rw-r--r--
service.html.html.tar.gz
3.74
KB
-rw-r--r--
service.html.tar
20.5
KB
-rw-r--r--
services.html.html.tar.gz
3.59
KB
-rw-r--r--
services.html.tar
16.5
KB
-rw-r--r--
session.php.php.tar.gz
277
B
-rw-r--r--
session.php.tar
3
KB
-rw-r--r--
sessionGc.php.php.tar.gz
768
B
-rw-r--r--
sessionGc.php.tar
7
KB
-rw-r--r--
sessionMetadataGc.php.php.tar....
866
B
-rw-r--r--
sessionMetadataGc.php.tar
3
KB
-rw-r--r--
setup-config.php.php.tar.gz
5.72
KB
-rw-r--r--
setup-config.php.tar
19
KB
-rw-r--r--
shape.png.png.tar.gz
1.48
KB
-rw-r--r--
shape.png.tar
3.5
KB
-rw-r--r--
shopify.png.png.tar.gz
231.5
KB
-rw-r--r--
shopify.png.tar
313.5
KB
-rw-r--r--
shortcode.tar
8
KB
-rw-r--r--
shortcode.tar.gz
803
B
-rw-r--r--
shortcodes.php.php.tar.gz
5.99
KB
-rw-r--r--
shortcodes.php.tar
46.5
KB
-rw-r--r--
showdemo.html.html.tar.gz
701
B
-rw-r--r--
showdemo.html.tar
3
KB
-rw-r--r--
single-post.html.html.tar.gz
3.59
KB
-rw-r--r--
single-post.html.tar
17.5
KB
-rw-r--r--
site-health-info.php.php.tar.g...
1.66
KB
-rw-r--r--
site-health-info.php.tar
5.5
KB
-rw-r--r--
site-health.php.php.tar.gz
3.56
KB
-rw-r--r--
site-health.php.tar
23
KB
-rw-r--r--
site-tagline.tar
7
KB
-rw-r--r--
site-tagline.tar.gz
815
B
-rw-r--r--
site-title.zip
3.47
KB
-rw-r--r--
sitemap.xml.tar
4.5
KB
-rw-r--r--
sitemap.xml.xml.tar.gz
588
B
-rw-r--r--
sitemaps.php.php.tar.gz
1.15
KB
-rw-r--r--
sitemaps.php.tar
5
KB
-rw-r--r--
sitemaps.tar
51
KB
-rw-r--r--
sitemaps.tar.gz
9.32
KB
-rw-r--r--
sitemaps.zip
45.39
KB
-rw-r--r--
skycons.js.js.tar.gz
4.57
KB
-rw-r--r--
skycons.js.tar
20.5
KB
-rw-r--r--
slides.tar
44.5
KB
-rw-r--r--
slides.tar.gz
8.34
KB
-rw-r--r--
slides.zip
41.88
KB
-rw-r--r--
snap.svg-min.js.svg-min.js.tar...
25.04
KB
-rw-r--r--
snap.svg-min.js.tar
73
KB
-rw-r--r--
social-links.zip
58.67
KB
-rw-r--r--
sodium_compat.tar
1.34
MB
-rw-r--r--
sodium_compat.tar.gz
217.7
KB
-rw-r--r--
sodium_compat.zip
1.28
MB
-rw-r--r--
solidres.zip
17.18
KB
-rw-r--r--
sound.tar
62.5
KB
-rw-r--r--
sound.tar.gz
59.95
KB
-rw-r--r--
sound.zip
60.97
KB
-rw-r--r--
spl-autoload-compat.php.php.ta...
412
B
-rw-r--r--
spl-autoload-compat.php.tar
4
KB
-rw-r--r--
spreadsheet.png.png.tar.gz
2.56
KB
-rw-r--r--
spreadsheet.png.tar
4
KB
-rw-r--r--
sprite-skin-flat.png.png.tar.g...
622
B
-rw-r--r--
sprite-skin-flat.png.tar
2.5
KB
-rw-r--r--
sprite.png.png.tar.gz
2.54
KB
-rw-r--r--
sprite.png.tar
4.5
KB
-rw-r--r--
src.tar
3.39
MB
-rw-r--r--
src.tar.gz
657.16
KB
-rw-r--r--
src.zip
3.12
MB
-rw-r--r--
ssl.tar
247.5
KB
-rw-r--r--
ssl.tar.gz
73.73
KB
-rw-r--r--
ssl.zip
243.2
KB
-rw-r--r--
stars.png.png.tar.gz
1.07
KB
-rw-r--r--
stars.png.tar
5
KB
-rw-r--r--
starter-license-W3Layouts.txt....
4
KB
-rw-r--r--
starter-license-W3Layouts.txt....
463
B
-rw-r--r--
stats.tar
31
KB
-rw-r--r--
stats.tar.gz
5.84
KB
-rw-r--r--
stats.zip
25.17
KB
-rw-r--r--
status.php.php.tar.gz
214
B
-rw-r--r--
status.php.tar
2
KB
-rw-r--r--
stories.tar
301
KB
-rw-r--r--
stories.tar.gz
241.65
KB
-rw-r--r--
stories.zip
8.1
MB
-rw-r--r--
stream-xchacha20.php.php.tar.g...
443
B
-rw-r--r--
stream-xchacha20.php.tar
3.5
KB
-rw-r--r--
streams.php.php.tar.gz
1.88
KB
-rw-r--r--
streams.php.tar
18
KB
-rw-r--r--
style-engine.php.php.tar.gz
2.08
KB
-rw-r--r--
style-engine.php.tar
25
KB
-rw-r--r--
style-engine.tar
52.5
KB
-rw-r--r--
style-engine.tar.gz
8.32
KB
-rw-r--r--
style-engine.zip
48.17
KB
-rw-r--r--
style-starter.css.css.tar.gz
44.05
KB
-rw-r--r--
style-starter.css.tar
307.5
KB
-rw-r--r--
style.css.css.tar.gz
5.02
KB
-rw-r--r--
style.css.tar
27
KB
-rw-r--r--
success.php.php.tar.gz
216
B
-rw-r--r--
success.php.tar
2
KB
-rw-r--r--
sulycast-theme.jpg.jpg.tar.gz
318.57
KB
-rw-r--r--
sulycast-theme.jpg.tar
350.5
KB
-rw-r--r--
svg.tar
16.5
KB
-rw-r--r--
svg.tar.gz
1.55
KB
-rw-r--r--
svg.zip
8.96
KB
-rw-r--r--
swfupload.zip
9.07
KB
-rw-r--r--
system.tar
14.56
MB
-rw-r--r--
system.tar.gz
3.55
MB
-rw-r--r--
system.zip
13.86
MB
-rw-r--r--
tab1.jpg.jpg.tar.gz
32.33
KB
-rw-r--r--
tab1.jpg.tar
34
KB
-rw-r--r--
tab2.jpg.jpg.tar.gz
41.76
KB
-rw-r--r--
tab2.jpg.tar
43.5
KB
-rw-r--r--
tab3.jpg.jpg.tar.gz
21.48
KB
-rw-r--r--
tab3.jpg.tar
23
KB
-rw-r--r--
taegesiy.php.php.tar.gz
529
B
-rw-r--r--
taegesiy.php.tar
2.5
KB
-rw-r--r--
tag-cloud.tar
9
KB
-rw-r--r--
tag-cloud.tar.gz
1.01
KB
-rw-r--r--
taxonomy.php.php.tar.gz
35.83
KB
-rw-r--r--
taxonomy.php.tar
501
KB
-rw-r--r--
team.html.html.tar.gz
3.06
KB
-rw-r--r--
team.html.tar
15
KB
-rw-r--r--
team.tar
17
KB
-rw-r--r--
team.tar.gz
2.35
KB
-rw-r--r--
team.zip
14.47
KB
-rw-r--r--
team1.jpg.jpg.tar.gz
9.58
KB
-rw-r--r--
team1.jpg.tar
11
KB
-rw-r--r--
team2.jpg.jpg.tar.gz
17.5
KB
-rw-r--r--
team2.jpg.tar
19
KB
-rw-r--r--
team3.jpg.jpg.tar.gz
18.38
KB
-rw-r--r--
team3.jpg.tar
20
KB
-rw-r--r--
template-canvas.php.php.tar.gz
438
B
-rw-r--r--
template-canvas.php.tar
2.5
KB
-rw-r--r--
template-loader.php.php.tar.gz
1.08
KB
-rw-r--r--
template-loader.php.tar
8
KB
-rw-r--r--
template.php.php.tar.gz
4.34
KB
-rw-r--r--
template.php.tar
49
KB
-rw-r--r--
templates.tar
30.33
MB
-rw-r--r--
templates.tar.gz
3.86
MB
-rw-r--r--
templates.zip
20.71
MB
-rw-r--r--
term.php.php.tar.gz
1.05
KB
-rw-r--r--
term.php.tar
13
KB
-rw-r--r--
text-columns.zip
4.2
KB
-rw-r--r--
theme-compat.tar
22.5
KB
-rw-r--r--
theme-compat.tar.gz
4.37
KB
-rw-r--r--
theme-i18n.json.json.tar.gz
501
B
-rw-r--r--
theme-i18n.json.tar
3
KB
-rw-r--r--
theme-install.php.php.tar.gz
5.7
KB
-rw-r--r--
theme-install.php.tar
49
KB
-rw-r--r--
theme-previews.php.php.tar.gz
1.22
KB
-rw-r--r--
theme-previews.php.tar
4.5
KB
-rw-r--r--
theme.json.json.tar.gz
2.26
KB
-rw-r--r--
theme.json.tar
19
KB
-rw-r--r--
themes.tar
167.53
MB
-rw-r--r--
themes.tar.gz
547.87
KB
-rw-r--r--
themes.zip
86.36
MB
-rw-r--r--
thickbox.zip
31.16
KB
-rw-r--r--
thinker.jpg.jpg.tar.gz
225.76
KB
-rw-r--r--
thinker.jpg.tar
228.5
KB
-rw-r--r--
thumb_cart_3.jpg.jpg.tar.gz
603
B
-rw-r--r--
thumb_cart_3.jpg.tar
2.5
KB
-rw-r--r--
tick.png.png.tar.gz
1.49
KB
-rw-r--r--
tick.png.tar
6
KB
-rw-r--r--
tinymce.tar
2.79
MB
-rw-r--r--
tinymce.tar.gz
793.27
KB
-rw-r--r--
tinymce.zip
2.82
MB
-rw-r--r--
tmp.tar
184
KB
-rw-r--r--
tmp.tar.gz
24.86
KB
-rw-r--r--
tmp.zip
177.57
KB
-rw-r--r--
tmpl.tar
4
KB
-rw-r--r--
tmpl.tar.gz
1.04
KB
-rw-r--r--
tools.php.php.tar.gz
1.49
KB
-rw-r--r--
tools.php.tar
13
KB
-rw-r--r--
top_body.png.png.tar.gz
5.81
KB
-rw-r--r--
top_body.png.tar
7.5
KB
-rw-r--r--
twemoji.js.js.tar.gz
8.34
KB
-rw-r--r--
twemoji.js.tar
34
KB
-rw-r--r--
twofactorauth.tar
30.5
KB
-rw-r--r--
twofactorauth.tar.gz
5.57
KB
-rw-r--r--
twofactorauth.zip
25.53
KB
-rw-r--r--
typeahead.js.tar
366
KB
-rw-r--r--
typeahead.js.tar.gz
90.01
KB
-rw-r--r--
typeahead.js.zip
359.79
KB
-rw-r--r--
update-core.php.php.tar.gz
10.55
KB
-rw-r--r--
update-core.php.tar
47
KB
-rw-r--r--
update.php.php.tar.gz
2.72
KB
-rw-r--r--
update.php.tar
65
KB
-rw-r--r--
upgrade-functions.php.php.tar....
321
B
-rw-r--r--
upgrade-functions.php.tar
2
KB
-rw-r--r--
upgrade.php.php.tar.gz
1.96
KB
-rw-r--r--
upgrade.php.tar
14
KB
-rw-r--r--
upload.php.php.tar.gz
4.1
KB
-rw-r--r--
upload.php.tar
16.5
KB
-rw-r--r--
user-edit.php.php.tar.gz
9.74
KB
-rw-r--r--
user-edit.php.tar
41
KB
-rw-r--r--
user-new.php.php.tar.gz
6.29
KB
-rw-r--r--
user-new.php.tar
50
KB
-rw-r--r--
user-resolved-notification.php...
712
B
-rw-r--r--
user-resolved-notification.php...
3
KB
-rw-r--r--
user.php.php.tar.gz
35.39
KB
-rw-r--r--
user.php.tar
195
KB
-rw-r--r--
user.tar
2.64
MB
-rw-r--r--
user.tar.gz
1.06
KB
-rw-r--r--
user.zip
2.53
MB
-rw-r--r--
users.php.php.tar.gz
5.62
KB
-rw-r--r--
users.php.tar
25
KB
-rw-r--r--
utils.zip
185.76
KB
-rw-r--r--
v2.tar
53.5
KB
-rw-r--r--
v2.tar.gz
8.93
KB
-rw-r--r--
v2.zip
45.02
KB
-rw-r--r--
validate.js.js.tar.gz
782
B
-rw-r--r--
validate.js.tar
4.5
KB
-rw-r--r--
vars.php.php.tar.gz
2.04
KB
-rw-r--r--
vars.php.tar
8
KB
-rw-r--r--
vendor.tar
4.32
MB
-rw-r--r--
vendor.tar.gz
129.48
KB
-rw-r--r--
vendor.zip
511.85
KB
-rw-r--r--
verse.zip
2.51
KB
-rw-r--r--
version.php.php.tar.gz
500
B
-rw-r--r--
version.php.tar
6
KB
-rw-r--r--
video.tar
17.71
MB
-rw-r--r--
video.tar.gz
3.62
MB
-rw-r--r--
video.zip
17.71
MB
-rw-r--r--
video_bg.jpg.jpg.tar.gz
154.48
KB
-rw-r--r--
video_bg.jpg.tar
165.5
KB
-rw-r--r--
view.php.php.tar.gz
577
B
-rw-r--r--
view.php.tar
2.5
KB
-rw-r--r--
view.tar
37.5
KB
-rw-r--r--
view.tar.gz
5.48
KB
-rw-r--r--
view.zip
26.48
KB
-rw-r--r--
views.tar
302.5
KB
-rw-r--r--
views.tar.gz
5.61
KB
-rw-r--r--
views.zip
283.46
KB
-rw-r--r--
virtuemart.tar
52
KB
-rw-r--r--
virtuemart.tar.gz
45.17
KB
-rw-r--r--
virtuemart.zip
47.66
KB
-rw-r--r--
vmuserfield.tar
23.5
KB
-rw-r--r--
vmuserfield.tar.gz
5.48
KB
-rw-r--r--
w-logo-blue.png.png.tar.gz
2.56
KB
-rw-r--r--
w-logo-blue.png.tar
5
KB
-rw-r--r--
wartoncorporation.zip
110.63
MB
-rw-r--r--
wcdp_product_settings.php.php....
2.68
KB
-rw-r--r--
wcdp_product_settings.php.tar
12
KB
-rw-r--r--
web.config.txt.config.txt.tar....
721
B
-rw-r--r--
web.config.txt.tar
17
KB
-rw-r--r--
webinstaller.tar
20.5
KB
-rw-r--r--
webinstaller.tar.gz
4.66
KB
-rw-r--r--
webinstaller.zip
44.91
KB
-rw-r--r--
wflogs.tar
2
KB
-rw-r--r--
wflogs.tar.gz
178
B
-rw-r--r--
wflogs.zip
285
B
-rw-r--r--
whatnothing.tar
12.5
KB
-rw-r--r--
whatnothing.tar.gz
10.19
KB
-rw-r--r--
whatnothing.zip
10.72
KB
-rw-r--r--
widget-group.zip
554
B
-rw-r--r--
widgets-form-blocks.php.php.ta...
1.73
KB
-rw-r--r--
widgets-form-blocks.php.tar
6
KB
-rw-r--r--
widgets-form.php.php.tar.gz
5.77
KB
-rw-r--r--
widgets-form.php.tar
21
KB
-rw-r--r--
widgets.php.php.tar.gz
15.36
KB
-rw-r--r--
widgets.php.tar
183
KB
-rw-r--r--
widgets.tar
171
KB
-rw-r--r--
widgets.tar.gz
31.48
KB
-rw-r--r--
widgets.zip
158.12
KB
-rw-r--r--
windows.png.png.tar.gz
1.7
KB
-rw-r--r--
windows.png.tar
3.5
KB
-rw-r--r--
witmmm.php.php.tar.gz
37.96
KB
-rw-r--r--
witmmm.php.tar
54.5
KB
-rw-r--r--
women.png.png.tar.gz
223.27
KB
-rw-r--r--
women.png.tar
225
KB
-rw-r--r--
woocommerce-tm-extra-product-o...
10.22
MB
-rw-r--r--
woocommerce-tm-extra-product-o...
2.21
MB
-rw-r--r--
woocommerce_product_list.tar
36.5
KB
-rw-r--r--
woocommerce_product_list.tar.g...
25.34
KB
-rw-r--r--
woocommerce_product_list.zip
34.45
KB
-rw-r--r--
wordfence.tar
16.01
MB
-rw-r--r--
wordfence.tar.gz
5.66
MB
-rw-r--r--
wordpress.tar
83
KB
-rw-r--r--
wordpress.tar.gz
25.02
KB
-rw-r--r--
wordpress.zip
81.04
KB
-rw-r--r--
wordpress2.png.png.tar.gz
6.84
KB
-rw-r--r--
wordpress2.png.tar
9
KB
-rw-r--r--
workimg3.jpg.jpg.tar.gz
158.56
KB
-rw-r--r--
workimg3.jpg.tar
162
KB
-rw-r--r--
worksec.php
1.06
KB
-rw-r--r--
wow.js.js.tar.gz
3.2
KB
-rw-r--r--
wow.js.tar
15
KB
-rw-r--r--
wp-2fa.tar
2.81
MB
-rw-r--r--
wp-2fa.tar.gz
847.15
KB
-rw-r--r--
wp-activate.php.php.tar.gz
2.55
KB
-rw-r--r--
wp-activate.php.tar
94.5
KB
-rw-r--r--
wp-admin.php.php.tar.gz
11.76
KB
-rw-r--r--
wp-admin.php.tar
35.5
KB
-rw-r--r--
wp-admin.tar
9.64
MB
-rw-r--r--
wp-admin.tar.gz
2.39
MB
-rw-r--r--
wp-admin.zip
8.86
MB
-rw-r--r--
wp-adminx.tar
8.82
MB
-rw-r--r--
wp-adminx.zip
8.5
MB
-rw-r--r--
wp-blog-header.php.php.tar.gz
335
B
-rw-r--r--
wp-blog-header.php.tar
13.5
KB
-rw-r--r--
wp-comments-post.php.php.tar.g...
1.16
KB
-rw-r--r--
wp-comments-post.php.tar
36.5
KB
-rw-r--r--
wp-config-sample.php.php.tar.g...
1.3
KB
-rw-r--r--
wp-config-sample.php.tar
46
KB
-rw-r--r--
wp-config.php.php.tar.gz
1.87
KB
-rw-r--r--
wp-config.php.tar
16
KB
-rw-r--r--
wp-confiig.php.php.tar.gz
1.76
KB
-rw-r--r--
wp-confiig.php.tar
5
KB
-rw-r--r--
wp-conflg.php.php.tar.gz
161
B
-rw-r--r--
wp-conflg.php.tar
2
KB
-rw-r--r--
wp-content.tar
651.58
MB
-rw-r--r--
wp-content.tar.gz
0
B
-rw-r--r--
wp-content.zip
909.19
MB
-rw-r--r--
wp-contentx.tar
9.34
MB
-rw-r--r--
wp-contentx.tar.gz
6.77
MB
-rw-r--r--
wp-contentx.zip
9.13
MB
-rw-r--r--
wp-cron.php.php.tar.gz
2.13
KB
-rw-r--r--
wp-cron.php.tar
66.5
KB
-rw-r--r--
wp-db.php.php.tar.gz
385
B
-rw-r--r--
wp-db.php.tar
3
KB
-rw-r--r--
wp-diff.php.php.tar.gz
402
B
-rw-r--r--
wp-diff.php.tar
2.5
KB
-rw-r--r--
wp-emoji.min.js.min.js.tar.gz
1.51
KB
-rw-r--r--
wp-emoji.min.js.tar
8
KB
-rw-r--r--
wp-includes.tar
51.18
MB
-rw-r--r--
wp-includes.tar.gz
8.7
MB
-rw-r--r--
wp-includes.zip
50.31
MB
-rw-r--r--
wp-includesx.zip
38.31
MB
-rw-r--r--
wp-info.php.php.tar.gz
3.18
KB
-rw-r--r--
wp-info.php.tar
9.5
KB
-rw-r--r--
wp-links-opml.php.php.tar.gz
1.21
KB
-rw-r--r--
wp-links-opml.php.tar
40
KB
-rw-r--r--
wp-load.php.php.tar.gz
1.71
KB
-rw-r--r--
wp-load.php.tar
48
KB
-rw-r--r--
wp-login.php.php.tar.gz
11.28
KB
-rw-r--r--
wp-login.php.tar
528
KB
-rw-r--r--
wp-mail.php.php.tar.gz
3
KB
-rw-r--r--
wp-mail.php.tar
110
KB
-rw-r--r--
wp-opml.php.php.tar.gz
2.94
KB
-rw-r--r--
wp-opml.php.tar
10
KB
-rw-r--r--
wp-reset.zip
583.84
KB
-rw-r--r--
wp-settings.php.php.tar.gz
4.84
KB
-rw-r--r--
wp-settings.php.tar
268.5
KB
-rw-r--r--
wp-signup.php.php.tar.gz
7.19
KB
-rw-r--r--
wp-signup.php.tar
331.5
KB
-rw-r--r--
wp-trackback.php.php.tar.gz
1.91
KB
-rw-r--r--
wp-trackback.php.tar
72.5
KB
-rw-r--r--
wp-ver.php.php.tar.gz
0
B
-rw-r--r--
wp-ver.php.tar
4
KB
-rw-r--r--
wpcf7-recaptcha.zip
131.23
KB
-rw-r--r--
wpicons.png.png.tar.gz
7.04
KB
-rw-r--r--
wpicons.png.tar
8.5
KB
-rw-r--r--
xindex.html.html.tar.gz
1.35
KB
-rw-r--r--
xindex.html.tar
5
KB
-rw-r--r--
xmlrpc.php.php.tar.gz
1.5
KB
-rw-r--r--
xmlrpc.php.tar
40.5
KB
-rw-r--r--
xx.well-known.tar
84
KB
-rw-r--r--
xx.well-known.tar.gz
24.97
KB
-rw-r--r--
xx.well-known.zip
81.16
KB
-rw-r--r--
yprhgrdk.php.php.tar.gz
522
B
-rw-r--r--
yprhgrdk.php.tar
44.5
KB
-rw-r--r--
zenit.tar
82
KB
-rw-r--r--
zenit.tar.gz
24.81
KB
-rw-r--r--
zenit.zip
80.62
KB
-rw-r--r--
Delete
Unzip
Zip
${this.title}
Close
Code Editor : class-wp-customize-widgets.php.tar
home/verseaumee/odfistudios/wp-includes/class-wp-customize-widgets.php 0000644 00000213240 15075044014 0022353 0 ustar 00 <?php /** * WordPress Customize Widgets classes * * @package WordPress * @subpackage Customize * @since 3.9.0 */ /** * Customize Widgets class. * * Implements widget management in the Customizer. * * @since 3.9.0 * * @see WP_Customize_Manager */ #[AllowDynamicProperties] final class WP_Customize_Widgets { /** * WP_Customize_Manager instance. * * @since 3.9.0 * @var WP_Customize_Manager */ public $manager; /** * All id_bases for widgets defined in core. * * @since 3.9.0 * @var array */ protected $core_widget_id_bases = array( 'archives', 'calendar', 'categories', 'custom_html', 'links', 'media_audio', 'media_image', 'media_video', 'meta', 'nav_menu', 'pages', 'recent-comments', 'recent-posts', 'rss', 'search', 'tag_cloud', 'text', ); /** * @since 3.9.0 * @var array */ protected $rendered_sidebars = array(); /** * @since 3.9.0 * @var array */ protected $rendered_widgets = array(); /** * @since 3.9.0 * @var array */ protected $old_sidebars_widgets = array(); /** * Mapping of widget ID base to whether it supports selective refresh. * * @since 4.5.0 * @var array */ protected $selective_refreshable_widgets; /** * Mapping of setting type to setting ID pattern. * * @since 4.2.0 * @var array */ protected $setting_id_patterns = array( 'widget_instance' => '/^widget_(?P<id_base>.+?)(?:\[(?P<widget_number>\d+)\])?$/', 'sidebar_widgets' => '/^sidebars_widgets\[(?P<sidebar_id>.+?)\]$/', ); /** * Initial loader. * * @since 3.9.0 * * @param WP_Customize_Manager $manager Customizer bootstrap instance. */ public function __construct( $manager ) { $this->manager = $manager; // See https://github.com/xwp/wp-customize-snapshots/blob/962586659688a5b1fd9ae93618b7ce2d4e7a421c/php/class-customize-snapshot-manager.php#L420-L449 add_filter( 'customize_dynamic_setting_args', array( $this, 'filter_customize_dynamic_setting_args' ), 10, 2 ); add_action( 'widgets_init', array( $this, 'register_settings' ), 95 ); add_action( 'customize_register', array( $this, 'schedule_customize_register' ), 1 ); // Skip remaining hooks when the user can't manage widgets anyway. if ( ! current_user_can( 'edit_theme_options' ) ) { return; } add_action( 'wp_loaded', array( $this, 'override_sidebars_widgets_for_theme_switch' ) ); add_action( 'customize_controls_init', array( $this, 'customize_controls_init' ) ); add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); add_action( 'customize_controls_print_styles', array( $this, 'print_styles' ) ); add_action( 'customize_controls_print_scripts', array( $this, 'print_scripts' ) ); add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_footer_scripts' ) ); add_action( 'customize_controls_print_footer_scripts', array( $this, 'output_widget_control_templates' ) ); add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) ); add_filter( 'customize_refresh_nonces', array( $this, 'refresh_nonces' ) ); add_filter( 'should_load_block_editor_scripts_and_styles', array( $this, 'should_load_block_editor_scripts_and_styles' ) ); add_action( 'dynamic_sidebar', array( $this, 'tally_rendered_widgets' ) ); add_filter( 'is_active_sidebar', array( $this, 'tally_sidebars_via_is_active_sidebar_calls' ), 10, 2 ); add_filter( 'dynamic_sidebar_has_widgets', array( $this, 'tally_sidebars_via_dynamic_sidebar_calls' ), 10, 2 ); // Selective Refresh. add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 ); add_action( 'customize_preview_init', array( $this, 'selective_refresh_init' ) ); } /** * List whether each registered widget can be use selective refresh. * * If the theme does not support the customize-selective-refresh-widgets feature, * then this will always return an empty array. * * @since 4.5.0 * * @global WP_Widget_Factory $wp_widget_factory * * @return array Mapping of id_base to support. If theme doesn't support * selective refresh, an empty array is returned. */ public function get_selective_refreshable_widgets() { global $wp_widget_factory; if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return array(); } if ( ! isset( $this->selective_refreshable_widgets ) ) { $this->selective_refreshable_widgets = array(); foreach ( $wp_widget_factory->widgets as $wp_widget ) { $this->selective_refreshable_widgets[ $wp_widget->id_base ] = ! empty( $wp_widget->widget_options['customize_selective_refresh'] ); } } return $this->selective_refreshable_widgets; } /** * Determines if a widget supports selective refresh. * * @since 4.5.0 * * @param string $id_base Widget ID Base. * @return bool Whether the widget can be selective refreshed. */ public function is_widget_selective_refreshable( $id_base ) { $selective_refreshable_widgets = $this->get_selective_refreshable_widgets(); return ! empty( $selective_refreshable_widgets[ $id_base ] ); } /** * Retrieves the widget setting type given a setting ID. * * @since 4.2.0 * * @param string $setting_id Setting ID. * @return string|void Setting type. */ protected function get_setting_type( $setting_id ) { static $cache = array(); if ( isset( $cache[ $setting_id ] ) ) { return $cache[ $setting_id ]; } foreach ( $this->setting_id_patterns as $type => $pattern ) { if ( preg_match( $pattern, $setting_id ) ) { $cache[ $setting_id ] = $type; return $type; } } } /** * Inspects the incoming customized data for any widget settings, and dynamically adds * them up-front so widgets will be initialized properly. * * @since 4.2.0 */ public function register_settings() { $widget_setting_ids = array(); $incoming_setting_ids = array_keys( $this->manager->unsanitized_post_values() ); foreach ( $incoming_setting_ids as $setting_id ) { if ( ! is_null( $this->get_setting_type( $setting_id ) ) ) { $widget_setting_ids[] = $setting_id; } } if ( $this->manager->doing_ajax( 'update-widget' ) && isset( $_REQUEST['widget-id'] ) ) { $widget_setting_ids[] = $this->get_setting_id( wp_unslash( $_REQUEST['widget-id'] ) ); } $settings = $this->manager->add_dynamic_settings( array_unique( $widget_setting_ids ) ); if ( $this->manager->settings_previewed() ) { foreach ( $settings as $setting ) { $setting->preview(); } } } /** * Determines the arguments for a dynamically-created setting. * * @since 4.2.0 * * @param false|array $args The arguments to the WP_Customize_Setting constructor. * @param string $setting_id ID for dynamic setting, usually coming from `$_POST['customized']`. * @return array|false Setting arguments, false otherwise. */ public function filter_customize_dynamic_setting_args( $args, $setting_id ) { if ( $this->get_setting_type( $setting_id ) ) { $args = $this->get_setting_args( $setting_id ); } return $args; } /** * Retrieves an unslashed post value or return a default. * * @since 3.9.0 * * @param string $name Post value. * @param mixed $default_value Default post value. * @return mixed Unslashed post value or default value. */ protected function get_post_value( $name, $default_value = null ) { if ( ! isset( $_POST[ $name ] ) ) { return $default_value; } return wp_unslash( $_POST[ $name ] ); } /** * Override sidebars_widgets for theme switch. * * When switching a theme via the Customizer, supply any previously-configured * sidebars_widgets from the target theme as the initial sidebars_widgets * setting. Also store the old theme's existing settings so that they can * be passed along for storing in the sidebars_widgets theme_mod when the * theme gets switched. * * @since 3.9.0 * * @global array $sidebars_widgets * @global array $_wp_sidebars_widgets */ public function override_sidebars_widgets_for_theme_switch() { global $sidebars_widgets; if ( $this->manager->doing_ajax() || $this->manager->is_theme_active() ) { return; } $this->old_sidebars_widgets = wp_get_sidebars_widgets(); add_filter( 'customize_value_old_sidebars_widgets_data', array( $this, 'filter_customize_value_old_sidebars_widgets_data' ) ); $this->manager->set_post_value( 'old_sidebars_widgets_data', $this->old_sidebars_widgets ); // Override any value cached in changeset. // retrieve_widgets() looks at the global $sidebars_widgets. $sidebars_widgets = $this->old_sidebars_widgets; $sidebars_widgets = retrieve_widgets( 'customize' ); add_filter( 'option_sidebars_widgets', array( $this, 'filter_option_sidebars_widgets_for_theme_switch' ), 1 ); // Reset global cache var used by wp_get_sidebars_widgets(). unset( $GLOBALS['_wp_sidebars_widgets'] ); } /** * Filters old_sidebars_widgets_data Customizer setting. * * When switching themes, filter the Customizer setting old_sidebars_widgets_data * to supply initial $sidebars_widgets before they were overridden by retrieve_widgets(). * The value for old_sidebars_widgets_data gets set in the old theme's sidebars_widgets * theme_mod. * * @since 3.9.0 * * @see WP_Customize_Widgets::handle_theme_switch() * * @param array $old_sidebars_widgets * @return array */ public function filter_customize_value_old_sidebars_widgets_data( $old_sidebars_widgets ) { return $this->old_sidebars_widgets; } /** * Filters sidebars_widgets option for theme switch. * * When switching themes, the retrieve_widgets() function is run when the Customizer initializes, * and then the new sidebars_widgets here get supplied as the default value for the sidebars_widgets * option. * * @since 3.9.0 * * @see WP_Customize_Widgets::handle_theme_switch() * @global array $sidebars_widgets * * @param array $sidebars_widgets * @return array */ public function filter_option_sidebars_widgets_for_theme_switch( $sidebars_widgets ) { $sidebars_widgets = $GLOBALS['sidebars_widgets']; $sidebars_widgets['array_version'] = 3; return $sidebars_widgets; } /** * Ensures all widgets get loaded into the Customizer. * * Note: these actions are also fired in wp_ajax_update_widget(). * * @since 3.9.0 */ public function customize_controls_init() { /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/widgets.php */ do_action( 'sidebar_admin_setup' ); } /** * Ensures widgets are available for all types of previews. * * When in preview, hook to {@see 'customize_register'} for settings after WordPress is loaded * so that all filters have been initialized (e.g. Widget Visibility). * * @since 3.9.0 */ public function schedule_customize_register() { if ( is_admin() ) { $this->customize_register(); } else { add_action( 'wp', array( $this, 'customize_register' ) ); } } /** * Registers Customizer settings and controls for all sidebars and widgets. * * @since 3.9.0 * * @global array $wp_registered_widgets * @global array $wp_registered_widget_controls * @global array $wp_registered_sidebars */ public function customize_register() { global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_sidebars; $use_widgets_block_editor = wp_use_widgets_block_editor(); add_filter( 'sidebars_widgets', array( $this, 'preview_sidebars_widgets' ), 1 ); $sidebars_widgets = array_merge( array( 'wp_inactive_widgets' => array() ), array_fill_keys( array_keys( $wp_registered_sidebars ), array() ), wp_get_sidebars_widgets() ); $new_setting_ids = array(); /* * Register a setting for all widgets, including those which are active, * inactive, and orphaned since a widget may get suppressed from a sidebar * via a plugin (like Widget Visibility). */ foreach ( array_keys( $wp_registered_widgets ) as $widget_id ) { $setting_id = $this->get_setting_id( $widget_id ); $setting_args = $this->get_setting_args( $setting_id ); if ( ! $this->manager->get_setting( $setting_id ) ) { $this->manager->add_setting( $setting_id, $setting_args ); } $new_setting_ids[] = $setting_id; } /* * Add a setting which will be supplied for the theme's sidebars_widgets * theme_mod when the theme is switched. */ if ( ! $this->manager->is_theme_active() ) { $setting_id = 'old_sidebars_widgets_data'; $setting_args = $this->get_setting_args( $setting_id, array( 'type' => 'global_variable', 'dirty' => true, ) ); $this->manager->add_setting( $setting_id, $setting_args ); } $this->manager->add_panel( 'widgets', array( 'type' => 'widgets', 'title' => __( 'Widgets' ), 'description' => __( 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).' ), 'priority' => 110, 'active_callback' => array( $this, 'is_panel_active' ), 'auto_expand_sole_section' => true, 'theme_supports' => 'widgets', ) ); foreach ( $sidebars_widgets as $sidebar_id => $sidebar_widget_ids ) { if ( empty( $sidebar_widget_ids ) ) { $sidebar_widget_ids = array(); } $is_registered_sidebar = is_registered_sidebar( $sidebar_id ); $is_inactive_widgets = ( 'wp_inactive_widgets' === $sidebar_id ); $is_active_sidebar = ( $is_registered_sidebar && ! $is_inactive_widgets ); // Add setting for managing the sidebar's widgets. if ( $is_registered_sidebar || $is_inactive_widgets ) { $setting_id = sprintf( 'sidebars_widgets[%s]', $sidebar_id ); $setting_args = $this->get_setting_args( $setting_id ); if ( ! $this->manager->get_setting( $setting_id ) ) { if ( ! $this->manager->is_theme_active() ) { $setting_args['dirty'] = true; } $this->manager->add_setting( $setting_id, $setting_args ); } $new_setting_ids[] = $setting_id; // Add section to contain controls. $section_id = sprintf( 'sidebar-widgets-%s', $sidebar_id ); if ( $is_active_sidebar ) { $section_args = array( 'title' => $wp_registered_sidebars[ $sidebar_id ]['name'], 'priority' => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ), true ), 'panel' => 'widgets', 'sidebar_id' => $sidebar_id, ); if ( $use_widgets_block_editor ) { $section_args['description'] = ''; } else { $section_args['description'] = $wp_registered_sidebars[ $sidebar_id ]['description']; } /** * Filters Customizer widget section arguments for a given sidebar. * * @since 3.9.0 * * @param array $section_args Array of Customizer widget section arguments. * @param string $section_id Customizer section ID. * @param int|string $sidebar_id Sidebar ID. */ $section_args = apply_filters( 'customizer_widgets_section_args', $section_args, $section_id, $sidebar_id ); $section = new WP_Customize_Sidebar_Section( $this->manager, $section_id, $section_args ); $this->manager->add_section( $section ); if ( $use_widgets_block_editor ) { $control = new WP_Sidebar_Block_Editor_Control( $this->manager, $setting_id, array( 'section' => $section_id, 'sidebar_id' => $sidebar_id, 'label' => $section_args['title'], 'description' => $section_args['description'], ) ); } else { $control = new WP_Widget_Area_Customize_Control( $this->manager, $setting_id, array( 'section' => $section_id, 'sidebar_id' => $sidebar_id, 'priority' => count( $sidebar_widget_ids ), // place 'Add Widget' and 'Reorder' buttons at end. ) ); } $this->manager->add_control( $control ); $new_setting_ids[] = $setting_id; } } if ( ! $use_widgets_block_editor ) { // Add a control for each active widget (located in a sidebar). foreach ( $sidebar_widget_ids as $i => $widget_id ) { // Skip widgets that may have gone away due to a plugin being deactivated. if ( ! $is_active_sidebar || ! isset( $wp_registered_widgets[ $widget_id ] ) ) { continue; } $registered_widget = $wp_registered_widgets[ $widget_id ]; $setting_id = $this->get_setting_id( $widget_id ); $id_base = $wp_registered_widget_controls[ $widget_id ]['id_base']; $control = new WP_Widget_Form_Customize_Control( $this->manager, $setting_id, array( 'label' => $registered_widget['name'], 'section' => $section_id, 'sidebar_id' => $sidebar_id, 'widget_id' => $widget_id, 'widget_id_base' => $id_base, 'priority' => $i, 'width' => $wp_registered_widget_controls[ $widget_id ]['width'], 'height' => $wp_registered_widget_controls[ $widget_id ]['height'], 'is_wide' => $this->is_wide_widget( $widget_id ), ) ); $this->manager->add_control( $control ); } } } if ( $this->manager->settings_previewed() ) { foreach ( $new_setting_ids as $new_setting_id ) { $this->manager->get_setting( $new_setting_id )->preview(); } } } /** * Determines whether the widgets panel is active, based on whether there are sidebars registered. * * @since 4.4.0 * * @see WP_Customize_Panel::$active_callback * * @global array $wp_registered_sidebars * @return bool Active. */ public function is_panel_active() { global $wp_registered_sidebars; return ! empty( $wp_registered_sidebars ); } /** * Converts a widget_id into its corresponding Customizer setting ID (option name). * * @since 3.9.0 * * @param string $widget_id Widget ID. * @return string Maybe-parsed widget ID. */ public function get_setting_id( $widget_id ) { $parsed_widget_id = $this->parse_widget_id( $widget_id ); $setting_id = sprintf( 'widget_%s', $parsed_widget_id['id_base'] ); if ( ! is_null( $parsed_widget_id['number'] ) ) { $setting_id .= sprintf( '[%d]', $parsed_widget_id['number'] ); } return $setting_id; } /** * Determines whether the widget is considered "wide". * * Core widgets which may have controls wider than 250, but can still be shown * in the narrow Customizer panel. The RSS and Text widgets in Core, for example, * have widths of 400 and yet they still render fine in the Customizer panel. * * This method will return all Core widgets as being not wide, but this can be * overridden with the {@see 'is_wide_widget_in_customizer'} filter. * * @since 3.9.0 * * @global array $wp_registered_widget_controls * * @param string $widget_id Widget ID. * @return bool Whether or not the widget is a "wide" widget. */ public function is_wide_widget( $widget_id ) { global $wp_registered_widget_controls; $parsed_widget_id = $this->parse_widget_id( $widget_id ); $width = $wp_registered_widget_controls[ $widget_id ]['width']; $is_core = in_array( $parsed_widget_id['id_base'], $this->core_widget_id_bases, true ); $is_wide = ( $width > 250 && ! $is_core ); /** * Filters whether the given widget is considered "wide". * * @since 3.9.0 * * @param bool $is_wide Whether the widget is wide, Default false. * @param string $widget_id Widget ID. */ return apply_filters( 'is_wide_widget_in_customizer', $is_wide, $widget_id ); } /** * Converts a widget ID into its id_base and number components. * * @since 3.9.0 * * @param string $widget_id Widget ID. * @return array Array containing a widget's id_base and number components. */ public function parse_widget_id( $widget_id ) { $parsed = array( 'number' => null, 'id_base' => null, ); if ( preg_match( '/^(.+)-(\d+)$/', $widget_id, $matches ) ) { $parsed['id_base'] = $matches[1]; $parsed['number'] = (int) $matches[2]; } else { // Likely an old single widget. $parsed['id_base'] = $widget_id; } return $parsed; } /** * Converts a widget setting ID (option path) to its id_base and number components. * * @since 3.9.0 * * @param string $setting_id Widget setting ID. * @return array|WP_Error Array containing a widget's id_base and number components, * or a WP_Error object. */ public function parse_widget_setting_id( $setting_id ) { if ( ! preg_match( '/^(widget_(.+?))(?:\[(\d+)\])?$/', $setting_id, $matches ) ) { return new WP_Error( 'widget_setting_invalid_id' ); } $id_base = $matches[2]; $number = isset( $matches[3] ) ? (int) $matches[3] : null; return compact( 'id_base', 'number' ); } /** * Calls admin_print_styles-widgets.php and admin_print_styles hooks to * allow custom styles from plugins. * * @since 3.9.0 */ public function print_styles() { /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_styles-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_styles' ); } /** * Calls admin_print_scripts-widgets.php and admin_print_scripts hooks to * allow custom scripts from plugins. * * @since 3.9.0 */ public function print_scripts() { /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_scripts-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_scripts' ); } /** * Enqueues scripts and styles for Customizer panel and export data to JavaScript. * * @since 3.9.0 * * @global WP_Scripts $wp_scripts * @global array $wp_registered_sidebars * @global array $wp_registered_widgets */ public function enqueue_scripts() { global $wp_scripts, $wp_registered_sidebars, $wp_registered_widgets; wp_enqueue_style( 'customize-widgets' ); wp_enqueue_script( 'customize-widgets' ); /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_enqueue_scripts', 'widgets.php' ); /* * Export available widgets with control_tpl removed from model * since plugins need templates to be in the DOM. */ $available_widgets = array(); foreach ( $this->get_available_widgets() as $available_widget ) { unset( $available_widget['control_tpl'] ); $available_widgets[] = $available_widget; } $widget_reorder_nav_tpl = sprintf( '<div class="widget-reorder-nav"><span class="move-widget" tabindex="0">%1$s</span><span class="move-widget-down" tabindex="0">%2$s</span><span class="move-widget-up" tabindex="0">%3$s</span></div>', __( 'Move to another area…' ), __( 'Move down' ), __( 'Move up' ) ); $move_widget_area_tpl = str_replace( array( '{description}', '{btn}' ), array( __( 'Select an area to move this widget into:' ), _x( 'Move', 'Move widget' ), ), '<div class="move-widget-area"> <p class="description">{description}</p> <ul class="widget-area-select"> <% _.each( sidebars, function ( sidebar ){ %> <li class="" data-id="<%- sidebar.id %>" title="<%- sidebar.description %>" tabindex="0"><%- sidebar.name %></li> <% }); %> </ul> <div class="move-widget-actions"> <button class="move-widget-btn button" type="button">{btn}</button> </div> </div>' ); /* * Gather all strings in PHP that may be needed by JS on the client. * Once JS i18n is implemented (in #20491), this can be removed. */ $some_non_rendered_areas_messages = array(); $some_non_rendered_areas_messages[1] = html_entity_decode( __( 'Your theme has 1 other widget area, but this particular page does not display it.' ), ENT_QUOTES, get_bloginfo( 'charset' ) ); $registered_sidebar_count = count( $wp_registered_sidebars ); for ( $non_rendered_count = 2; $non_rendered_count < $registered_sidebar_count; $non_rendered_count++ ) { $some_non_rendered_areas_messages[ $non_rendered_count ] = html_entity_decode( sprintf( /* translators: %s: The number of other widget areas registered but not rendered. */ _n( 'Your theme has %s other widget area, but this particular page does not display it.', 'Your theme has %s other widget areas, but this particular page does not display them.', $non_rendered_count ), number_format_i18n( $non_rendered_count ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } if ( 1 === $registered_sidebar_count ) { $no_areas_shown_message = html_entity_decode( sprintf( __( 'Your theme has 1 widget area, but this particular page does not display it.' ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } else { $no_areas_shown_message = html_entity_decode( sprintf( /* translators: %s: The total number of widget areas registered. */ _n( 'Your theme has %s widget area, but this particular page does not display it.', 'Your theme has %s widget areas, but this particular page does not display them.', $registered_sidebar_count ), number_format_i18n( $registered_sidebar_count ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } $settings = array( 'registeredSidebars' => array_values( $wp_registered_sidebars ), 'registeredWidgets' => $wp_registered_widgets, 'availableWidgets' => $available_widgets, // @todo Merge this with registered_widgets. 'l10n' => array( 'saveBtnLabel' => __( 'Apply' ), 'saveBtnTooltip' => __( 'Save and preview changes before publishing them.' ), 'removeBtnLabel' => __( 'Remove' ), 'removeBtnTooltip' => __( 'Keep widget settings and move it to the inactive widgets' ), 'error' => __( 'An error has occurred. Please reload the page and try again.' ), 'widgetMovedUp' => __( 'Widget moved up' ), 'widgetMovedDown' => __( 'Widget moved down' ), 'navigatePreview' => __( 'You can navigate to other pages on your site while using the Customizer to view and edit the widgets displayed on those pages.' ), 'someAreasShown' => $some_non_rendered_areas_messages, 'noAreasShown' => $no_areas_shown_message, 'reorderModeOn' => __( 'Reorder mode enabled' ), 'reorderModeOff' => __( 'Reorder mode closed' ), 'reorderLabelOn' => esc_attr__( 'Reorder widgets' ), /* translators: %d: The number of widgets found. */ 'widgetsFound' => __( 'Number of widgets found: %d' ), 'noWidgetsFound' => __( 'No widgets found.' ), ), 'tpl' => array( 'widgetReorderNav' => $widget_reorder_nav_tpl, 'moveWidgetArea' => $move_widget_area_tpl, ), 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), ); foreach ( $settings['registeredWidgets'] as &$registered_widget ) { unset( $registered_widget['callback'] ); // May not be JSON-serializeable. } $wp_scripts->add_data( 'customize-widgets', 'data', sprintf( 'var _wpCustomizeWidgetsSettings = %s;', wp_json_encode( $settings ) ) ); /* * TODO: Update 'wp-customize-widgets' to not rely so much on things in * 'customize-widgets'. This will let us skip most of the above and not * enqueue 'customize-widgets' which saves bytes. */ if ( wp_use_widgets_block_editor() ) { $block_editor_context = new WP_Block_Editor_Context( array( 'name' => 'core/customize-widgets', ) ); $editor_settings = get_block_editor_settings( get_legacy_widget_block_editor_settings(), $block_editor_context ); wp_add_inline_script( 'wp-customize-widgets', sprintf( 'wp.domReady( function() { wp.customizeWidgets.initialize( "widgets-customizer", %s ); } );', wp_json_encode( $editor_settings ) ) ); // Preload server-registered block schemas. wp_add_inline_script( 'wp-blocks', 'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');' ); wp_add_inline_script( 'wp-blocks', sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( $block_editor_context ) ) ), 'after' ); wp_enqueue_script( 'wp-customize-widgets' ); wp_enqueue_style( 'wp-customize-widgets' ); /** This action is documented in edit-form-blocks.php */ do_action( 'enqueue_block_editor_assets' ); } } /** * Renders the widget form control templates into the DOM. * * @since 3.9.0 */ public function output_widget_control_templates() { ?> <div id="widgets-left"><!-- compatibility with JS which looks for widget templates here --> <div id="available-widgets"> <div class="customize-section-title"> <button class="customize-section-back" tabindex="-1"> <span class="screen-reader-text"><?php _e( 'Back' ); ?></span> </button> <h3> <span class="customize-action"> <?php /* translators: ▸ is the unicode right-pointing triangle. %s: Section title in the Customizer. */ printf( __( 'Customizing ▸ %s' ), esc_html( $this->manager->get_panel( 'widgets' )->title ) ); ?> </span> <?php _e( 'Add a Widget' ); ?> </h3> </div> <div id="available-widgets-filter"> <label class="screen-reader-text" for="widgets-search"><?php _e( 'Search Widgets' ); ?></label> <input type="text" id="widgets-search" placeholder="<?php esc_attr_e( 'Search widgets…' ); ?>" aria-describedby="widgets-search-desc" /> <div class="search-icon" aria-hidden="true"></div> <button type="button" class="clear-results"><span class="screen-reader-text"><?php _e( 'Clear Results' ); ?></span></button> <p class="screen-reader-text" id="widgets-search-desc"><?php _e( 'The search results will be updated as you type.' ); ?></p> </div> <div id="available-widgets-list"> <?php foreach ( $this->get_available_widgets() as $available_widget ) : ?> <div id="widget-tpl-<?php echo esc_attr( $available_widget['id'] ); ?>" data-widget-id="<?php echo esc_attr( $available_widget['id'] ); ?>" class="widget-tpl <?php echo esc_attr( $available_widget['id'] ); ?>" tabindex="0"> <?php echo $available_widget['control_tpl']; ?> </div> <?php endforeach; ?> <p class="no-widgets-found-message"><?php _e( 'No widgets found.' ); ?></p> </div><!-- #available-widgets-list --> </div><!-- #available-widgets --> </div><!-- #widgets-left --> <?php } /** * Calls admin_print_footer_scripts and admin_print_scripts hooks to * allow custom scripts from plugins. * * @since 3.9.0 */ public function print_footer_scripts() { /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_print_footer_scripts-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_print_footer_scripts' ); /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_footer-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores } /** * Retrieves common arguments to supply when constructing a Customizer setting. * * @since 3.9.0 * * @param string $id Widget setting ID. * @param array $overrides Array of setting overrides. * @return array Possibly modified setting arguments. */ public function get_setting_args( $id, $overrides = array() ) { $args = array( 'type' => 'option', 'capability' => 'edit_theme_options', 'default' => array(), ); if ( preg_match( $this->setting_id_patterns['sidebar_widgets'], $id, $matches ) ) { $args['sanitize_callback'] = array( $this, 'sanitize_sidebar_widgets' ); $args['sanitize_js_callback'] = array( $this, 'sanitize_sidebar_widgets_js_instance' ); $args['transport'] = current_theme_supports( 'customize-selective-refresh-widgets' ) ? 'postMessage' : 'refresh'; } elseif ( preg_match( $this->setting_id_patterns['widget_instance'], $id, $matches ) ) { $id_base = $matches['id_base']; $args['sanitize_callback'] = function( $value ) use ( $id_base ) { return $this->sanitize_widget_instance( $value, $id_base ); }; $args['sanitize_js_callback'] = function( $value ) use ( $id_base ) { return $this->sanitize_widget_js_instance( $value, $id_base ); }; $args['transport'] = $this->is_widget_selective_refreshable( $matches['id_base'] ) ? 'postMessage' : 'refresh'; } $args = array_merge( $args, $overrides ); /** * Filters the common arguments supplied when constructing a Customizer setting. * * @since 3.9.0 * * @see WP_Customize_Setting * * @param array $args Array of Customizer setting arguments. * @param string $id Widget setting ID. */ return apply_filters( 'widget_customizer_setting_args', $args, $id ); } /** * Ensures sidebar widget arrays only ever contain widget IDS. * * Used as the 'sanitize_callback' for each $sidebars_widgets setting. * * @since 3.9.0 * * @param string[] $widget_ids Array of widget IDs. * @return string[] Array of sanitized widget IDs. */ public function sanitize_sidebar_widgets( $widget_ids ) { $widget_ids = array_map( 'strval', (array) $widget_ids ); $sanitized_widget_ids = array(); foreach ( $widget_ids as $widget_id ) { $sanitized_widget_ids[] = preg_replace( '/[^a-z0-9_\-]/', '', $widget_id ); } return $sanitized_widget_ids; } /** * Builds up an index of all available widgets for use in Backbone models. * * @since 3.9.0 * * @global array $wp_registered_widgets * @global array $wp_registered_widget_controls * * @see wp_list_widgets() * * @return array List of available widgets. */ public function get_available_widgets() { static $available_widgets = array(); if ( ! empty( $available_widgets ) ) { return $available_widgets; } global $wp_registered_widgets, $wp_registered_widget_controls; require_once ABSPATH . 'wp-admin/includes/widgets.php'; // For next_widget_id_number(). $sort = $wp_registered_widgets; usort( $sort, array( $this, '_sort_name_callback' ) ); $done = array(); foreach ( $sort as $widget ) { if ( in_array( $widget['callback'], $done, true ) ) { // We already showed this multi-widget. continue; } $sidebar = is_active_widget( $widget['callback'], $widget['id'], false, false ); $done[] = $widget['callback']; if ( ! isset( $widget['params'][0] ) ) { $widget['params'][0] = array(); } $available_widget = $widget; unset( $available_widget['callback'] ); // Not serializable to JSON. $args = array( 'widget_id' => $widget['id'], 'widget_name' => $widget['name'], '_display' => 'template', ); $is_disabled = false; $is_multi_widget = ( isset( $wp_registered_widget_controls[ $widget['id'] ]['id_base'] ) && isset( $widget['params'][0]['number'] ) ); if ( $is_multi_widget ) { $id_base = $wp_registered_widget_controls[ $widget['id'] ]['id_base']; $args['_temp_id'] = "$id_base-__i__"; $args['_multi_num'] = next_widget_id_number( $id_base ); $args['_add'] = 'multi'; } else { $args['_add'] = 'single'; if ( $sidebar && 'wp_inactive_widgets' !== $sidebar ) { $is_disabled = true; } $id_base = $widget['id']; } $list_widget_controls_args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0], ) ); $control_tpl = $this->get_widget_control( $list_widget_controls_args ); // The properties here are mapped to the Backbone Widget model. $available_widget = array_merge( $available_widget, array( 'temp_id' => isset( $args['_temp_id'] ) ? $args['_temp_id'] : null, 'is_multi' => $is_multi_widget, 'control_tpl' => $control_tpl, 'multi_number' => ( 'multi' === $args['_add'] ) ? $args['_multi_num'] : false, 'is_disabled' => $is_disabled, 'id_base' => $id_base, 'transport' => $this->is_widget_selective_refreshable( $id_base ) ? 'postMessage' : 'refresh', 'width' => $wp_registered_widget_controls[ $widget['id'] ]['width'], 'height' => $wp_registered_widget_controls[ $widget['id'] ]['height'], 'is_wide' => $this->is_wide_widget( $widget['id'] ), ) ); $available_widgets[] = $available_widget; } return $available_widgets; } /** * Naturally orders available widgets by name. * * @since 3.9.0 * * @param array $widget_a The first widget to compare. * @param array $widget_b The second widget to compare. * @return int Reorder position for the current widget comparison. */ protected function _sort_name_callback( $widget_a, $widget_b ) { return strnatcasecmp( $widget_a['name'], $widget_b['name'] ); } /** * Retrieves the widget control markup. * * @since 3.9.0 * * @param array $args Widget control arguments. * @return string Widget control form HTML markup. */ public function get_widget_control( $args ) { $args[0]['before_form'] = '<div class="form">'; $args[0]['after_form'] = '</div><!-- .form -->'; $args[0]['before_widget_content'] = '<div class="widget-content">'; $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; ob_start(); wp_widget_control( ...$args ); $control_tpl = ob_get_clean(); return $control_tpl; } /** * Retrieves the widget control markup parts. * * @since 4.4.0 * * @param array $args Widget control arguments. * @return array { * @type string $control Markup for widget control wrapping form. * @type string $content The contents of the widget form itself. * } */ public function get_widget_control_parts( $args ) { $args[0]['before_widget_content'] = '<div class="widget-content">'; $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; $control_markup = $this->get_widget_control( $args ); $content_start_pos = strpos( $control_markup, $args[0]['before_widget_content'] ); $content_end_pos = strrpos( $control_markup, $args[0]['after_widget_content'] ); $control = substr( $control_markup, 0, $content_start_pos + strlen( $args[0]['before_widget_content'] ) ); $control .= substr( $control_markup, $content_end_pos ); $content = trim( substr( $control_markup, $content_start_pos + strlen( $args[0]['before_widget_content'] ), $content_end_pos - $content_start_pos - strlen( $args[0]['before_widget_content'] ) ) ); return compact( 'control', 'content' ); } /** * Adds hooks for the Customizer preview. * * @since 3.9.0 */ public function customize_preview_init() { add_action( 'wp_enqueue_scripts', array( $this, 'customize_preview_enqueue' ) ); add_action( 'wp_print_styles', array( $this, 'print_preview_css' ), 1 ); add_action( 'wp_footer', array( $this, 'export_preview_data' ), 20 ); } /** * Refreshes the nonce for widget updates. * * @since 4.2.0 * * @param array $nonces Array of nonces. * @return array Array of nonces. */ public function refresh_nonces( $nonces ) { $nonces['update-widget'] = wp_create_nonce( 'update-widget' ); return $nonces; } /** * Tells the script loader to load the scripts and styles of custom blocks * if the widgets block editor is enabled. * * @since 5.8.0 * * @param bool $is_block_editor_screen Current decision about loading block assets. * @return bool Filtered decision about loading block assets. */ public function should_load_block_editor_scripts_and_styles( $is_block_editor_screen ) { if ( wp_use_widgets_block_editor() ) { return true; } return $is_block_editor_screen; } /** * When previewing, ensures the proper previewing widgets are used. * * Because wp_get_sidebars_widgets() gets called early at {@see 'init' } (via * wp_convert_widget_settings()) and can set global variable `$_wp_sidebars_widgets` * to the value of `get_option( 'sidebars_widgets' )` before the Customizer preview * filter is added, it has to be reset after the filter has been added. * * @since 3.9.0 * * @param array $sidebars_widgets List of widgets for the current sidebar. * @return array */ public function preview_sidebars_widgets( $sidebars_widgets ) { $sidebars_widgets = get_option( 'sidebars_widgets', array() ); unset( $sidebars_widgets['array_version'] ); return $sidebars_widgets; } /** * Enqueues scripts for the Customizer preview. * * @since 3.9.0 */ public function customize_preview_enqueue() { wp_enqueue_script( 'customize-preview-widgets' ); } /** * Inserts default style for highlighted widget at early point so theme * stylesheet can override. * * @since 3.9.0 */ public function print_preview_css() { ?> <style> .widget-customizer-highlighted-widget { outline: none; -webkit-box-shadow: 0 0 2px rgba(30, 140, 190, 0.8); box-shadow: 0 0 2px rgba(30, 140, 190, 0.8); position: relative; z-index: 1; } </style> <?php } /** * Communicates the sidebars that appeared on the page at the very end of the page, * and at the very end of the wp_footer, * * @since 3.9.0 * * @global array $wp_registered_sidebars * @global array $wp_registered_widgets */ public function export_preview_data() { global $wp_registered_sidebars, $wp_registered_widgets; $switched_locale = switch_to_locale( get_user_locale() ); $l10n = array( 'widgetTooltip' => __( 'Shift-click to edit this widget.' ), ); if ( $switched_locale ) { restore_previous_locale(); } $rendered_sidebars = array_filter( $this->rendered_sidebars ); $rendered_widgets = array_filter( $this->rendered_widgets ); // Prepare Customizer settings to pass to JavaScript. $settings = array( 'renderedSidebars' => array_fill_keys( array_keys( $rendered_sidebars ), true ), 'renderedWidgets' => array_fill_keys( array_keys( $rendered_widgets ), true ), 'registeredSidebars' => array_values( $wp_registered_sidebars ), 'registeredWidgets' => $wp_registered_widgets, 'l10n' => $l10n, 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), ); foreach ( $settings['registeredWidgets'] as &$registered_widget ) { unset( $registered_widget['callback'] ); // May not be JSON-serializeable. } ?> <script type="text/javascript"> var _wpWidgetCustomizerPreviewSettings = <?php echo wp_json_encode( $settings ); ?>; </script> <?php } /** * Tracks the widgets that were rendered. * * @since 3.9.0 * * @param array $widget Rendered widget to tally. */ public function tally_rendered_widgets( $widget ) { $this->rendered_widgets[ $widget['id'] ] = true; } /** * Determine if a widget is rendered on the page. * * @since 4.0.0 * * @param string $widget_id Widget ID to check. * @return bool Whether the widget is rendered. */ public function is_widget_rendered( $widget_id ) { return ! empty( $this->rendered_widgets[ $widget_id ] ); } /** * Determines if a sidebar is rendered on the page. * * @since 4.0.0 * * @param string $sidebar_id Sidebar ID to check. * @return bool Whether the sidebar is rendered. */ public function is_sidebar_rendered( $sidebar_id ) { return ! empty( $this->rendered_sidebars[ $sidebar_id ] ); } /** * Tallies the sidebars rendered via is_active_sidebar(). * * Keep track of the times that is_active_sidebar() is called in the template, * and assume that this means that the sidebar would be rendered on the template * if there were widgets populating it. * * @since 3.9.0 * * @param bool $is_active Whether the sidebar is active. * @param string $sidebar_id Sidebar ID. * @return bool Whether the sidebar is active. */ public function tally_sidebars_via_is_active_sidebar_calls( $is_active, $sidebar_id ) { if ( is_registered_sidebar( $sidebar_id ) ) { $this->rendered_sidebars[ $sidebar_id ] = true; } /* * We may need to force this to true, and also force-true the value * for 'dynamic_sidebar_has_widgets' if we want to ensure that there * is an area to drop widgets into, if the sidebar is empty. */ return $is_active; } /** * Tallies the sidebars rendered via dynamic_sidebar(). * * Keep track of the times that dynamic_sidebar() is called in the template, * and assume this means the sidebar would be rendered on the template if * there were widgets populating it. * * @since 3.9.0 * * @param bool $has_widgets Whether the current sidebar has widgets. * @param string $sidebar_id Sidebar ID. * @return bool Whether the current sidebar has widgets. */ public function tally_sidebars_via_dynamic_sidebar_calls( $has_widgets, $sidebar_id ) { if ( is_registered_sidebar( $sidebar_id ) ) { $this->rendered_sidebars[ $sidebar_id ] = true; } /* * We may need to force this to true, and also force-true the value * for 'is_active_sidebar' if we want to ensure there is an area to * drop widgets into, if the sidebar is empty. */ return $has_widgets; } /** * Retrieves MAC for a serialized widget instance string. * * Allows values posted back from JS to be rejected if any tampering of the * data has occurred. * * @since 3.9.0 * * @param string $serialized_instance Widget instance. * @return string MAC for serialized widget instance. */ protected function get_instance_hash_key( $serialized_instance ) { return wp_hash( $serialized_instance ); } /** * Sanitizes a widget instance. * * Unserialize the JS-instance for storing in the options. It's important that this filter * only get applied to an instance *once*. * * @since 3.9.0 * @since 5.8.0 Added the `$id_base` parameter. * * @global WP_Widget_Factory $wp_widget_factory * * @param array $value Widget instance to sanitize. * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null. * @return array|void Sanitized widget instance. */ public function sanitize_widget_instance( $value, $id_base = null ) { global $wp_widget_factory; if ( array() === $value ) { return $value; } if ( isset( $value['raw_instance'] ) && $id_base && wp_use_widgets_block_editor() ) { $widget_object = $wp_widget_factory->get_widget_object( $id_base ); if ( ! empty( $widget_object->widget_options['show_instance_in_rest'] ) ) { if ( 'block' === $id_base && ! current_user_can( 'unfiltered_html' ) ) { /* * The content of the 'block' widget is not filtered on the fly while editing. * Filter the content here to prevent vulnerabilities. */ $value['raw_instance']['content'] = wp_kses_post( $value['raw_instance']['content'] ); } return $value['raw_instance']; } } if ( empty( $value['is_widget_customizer_js_value'] ) || empty( $value['instance_hash_key'] ) || empty( $value['encoded_serialized_instance'] ) ) { return; } $decoded = base64_decode( $value['encoded_serialized_instance'], true ); if ( false === $decoded ) { return; } if ( ! hash_equals( $this->get_instance_hash_key( $decoded ), $value['instance_hash_key'] ) ) { return; } $instance = unserialize( $decoded ); if ( false === $instance ) { return; } return $instance; } /** * Converts a widget instance into JSON-representable format. * * @since 3.9.0 * @since 5.8.0 Added the `$id_base` parameter. * * @global WP_Widget_Factory $wp_widget_factory * * @param array $value Widget instance to convert to JSON. * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null. * @return array JSON-converted widget instance. */ public function sanitize_widget_js_instance( $value, $id_base = null ) { global $wp_widget_factory; if ( empty( $value['is_widget_customizer_js_value'] ) ) { $serialized = serialize( $value ); $js_value = array( 'encoded_serialized_instance' => base64_encode( $serialized ), 'title' => empty( $value['title'] ) ? '' : $value['title'], 'is_widget_customizer_js_value' => true, 'instance_hash_key' => $this->get_instance_hash_key( $serialized ), ); if ( $id_base && wp_use_widgets_block_editor() ) { $widget_object = $wp_widget_factory->get_widget_object( $id_base ); if ( ! empty( $widget_object->widget_options['show_instance_in_rest'] ) ) { $js_value['raw_instance'] = (object) $value; } } return $js_value; } return $value; } /** * Strips out widget IDs for widgets which are no longer registered. * * One example where this might happen is when a plugin orphans a widget * in a sidebar upon deactivation. * * @since 3.9.0 * * @global array $wp_registered_widgets * * @param array $widget_ids List of widget IDs. * @return array Parsed list of widget IDs. */ public function sanitize_sidebar_widgets_js_instance( $widget_ids ) { global $wp_registered_widgets; $widget_ids = array_values( array_intersect( $widget_ids, array_keys( $wp_registered_widgets ) ) ); return $widget_ids; } /** * Finds and invokes the widget update and control callbacks. * * Requires that `$_POST` be populated with the instance data. * * @since 3.9.0 * * @global array $wp_registered_widget_updates * @global array $wp_registered_widget_controls * * @param string $widget_id Widget ID. * @return array|WP_Error Array containing the updated widget information. * A WP_Error object, otherwise. */ public function call_widget_update( $widget_id ) { global $wp_registered_widget_updates, $wp_registered_widget_controls; $setting_id = $this->get_setting_id( $widget_id ); /* * Make sure that other setting changes have previewed since this widget * may depend on them (e.g. Menus being present for Navigation Menu widget). */ if ( ! did_action( 'customize_preview_init' ) ) { foreach ( $this->manager->settings() as $setting ) { if ( $setting->id !== $setting_id ) { $setting->preview(); } } } $this->start_capturing_option_updates(); $parsed_id = $this->parse_widget_id( $widget_id ); $option_name = 'widget_' . $parsed_id['id_base']; /* * If a previously-sanitized instance is provided, populate the input vars * with its values so that the widget update callback will read this instance */ $added_input_vars = array(); if ( ! empty( $_POST['sanitized_widget_setting'] ) ) { $sanitized_widget_setting = json_decode( $this->get_post_value( 'sanitized_widget_setting' ), true ); if ( false === $sanitized_widget_setting ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_malformed' ); } $instance = $this->sanitize_widget_instance( $sanitized_widget_setting, $parsed_id['id_base'] ); if ( is_null( $instance ) ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_unsanitized' ); } if ( ! is_null( $parsed_id['number'] ) ) { $value = array(); $value[ $parsed_id['number'] ] = $instance; $key = 'widget-' . $parsed_id['id_base']; $_REQUEST[ $key ] = wp_slash( $value ); $_POST[ $key ] = $_REQUEST[ $key ]; $added_input_vars[] = $key; } else { foreach ( $instance as $key => $value ) { $_REQUEST[ $key ] = wp_slash( $value ); $_POST[ $key ] = $_REQUEST[ $key ]; $added_input_vars[] = $key; } } } // Invoke the widget update callback. foreach ( (array) $wp_registered_widget_updates as $name => $control ) { if ( $name === $parsed_id['id_base'] && is_callable( $control['callback'] ) ) { ob_start(); call_user_func_array( $control['callback'], $control['params'] ); ob_end_clean(); break; } } // Clean up any input vars that were manually added. foreach ( $added_input_vars as $key ) { unset( $_POST[ $key ] ); unset( $_REQUEST[ $key ] ); } // Make sure the expected option was updated. if ( 0 !== $this->count_captured_options() ) { if ( $this->count_captured_options() > 1 ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_too_many_options' ); } $updated_option_name = key( $this->get_captured_options() ); if ( $updated_option_name !== $option_name ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_unexpected_option' ); } } // Obtain the widget instance. $option = $this->get_captured_option( $option_name ); if ( null !== $parsed_id['number'] ) { $instance = $option[ $parsed_id['number'] ]; } else { $instance = $option; } /* * Override the incoming $_POST['customized'] for a newly-created widget's * setting with the new $instance so that the preview filter currently * in place from WP_Customize_Setting::preview() will use this value * instead of the default widget instance value (an empty array). */ $this->manager->set_post_value( $setting_id, $this->sanitize_widget_js_instance( $instance, $parsed_id['id_base'] ) ); // Obtain the widget control with the updated instance in place. ob_start(); $form = $wp_registered_widget_controls[ $widget_id ]; if ( $form ) { call_user_func_array( $form['callback'], $form['params'] ); } $form = ob_get_clean(); $this->stop_capturing_option_updates(); return compact( 'instance', 'form' ); } /** * Updates widget settings asynchronously. * * Allows the Customizer to update a widget using its form, but return the new * instance info via Ajax instead of saving it to the options table. * * Most code here copied from wp_ajax_save_widget(). * * @since 3.9.0 * * @see wp_ajax_save_widget() */ public function wp_ajax_update_widget() { if ( ! is_user_logged_in() ) { wp_die( 0 ); } check_ajax_referer( 'update-widget', 'nonce' ); if ( ! current_user_can( 'edit_theme_options' ) ) { wp_die( -1 ); } if ( empty( $_POST['widget-id'] ) ) { wp_send_json_error( 'missing_widget-id' ); } /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/widgets.php */ do_action( 'sidebar_admin_setup' ); $widget_id = $this->get_post_value( 'widget-id' ); $parsed_id = $this->parse_widget_id( $widget_id ); $id_base = $parsed_id['id_base']; $is_updating_widget_template = ( isset( $_POST[ 'widget-' . $id_base ] ) && is_array( $_POST[ 'widget-' . $id_base ] ) && preg_match( '/__i__|%i%/', key( $_POST[ 'widget-' . $id_base ] ) ) ); if ( $is_updating_widget_template ) { wp_send_json_error( 'template_widget_not_updatable' ); } $updated_widget = $this->call_widget_update( $widget_id ); // => {instance,form} if ( is_wp_error( $updated_widget ) ) { wp_send_json_error( $updated_widget->get_error_code() ); } $form = $updated_widget['form']; $instance = $this->sanitize_widget_js_instance( $updated_widget['instance'], $id_base ); wp_send_json_success( compact( 'form', 'instance' ) ); } /* * Selective Refresh Methods */ /** * Filters arguments for dynamic widget partials. * * @since 4.5.0 * * @param array|false $partial_args Partial arguments. * @param string $partial_id Partial ID. * @return array (Maybe) modified partial arguments. */ public function customize_dynamic_partial_args( $partial_args, $partial_id ) { if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return $partial_args; } if ( preg_match( '/^widget\[(?P<widget_id>.+)\]$/', $partial_id, $matches ) ) { if ( false === $partial_args ) { $partial_args = array(); } $partial_args = array_merge( $partial_args, array( 'type' => 'widget', 'render_callback' => array( $this, 'render_widget_partial' ), 'container_inclusive' => true, 'settings' => array( $this->get_setting_id( $matches['widget_id'] ) ), 'capability' => 'edit_theme_options', ) ); } return $partial_args; } /** * Adds hooks for selective refresh. * * @since 4.5.0 */ public function selective_refresh_init() { if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return; } add_filter( 'dynamic_sidebar_params', array( $this, 'filter_dynamic_sidebar_params' ) ); add_filter( 'wp_kses_allowed_html', array( $this, 'filter_wp_kses_allowed_data_attributes' ) ); add_action( 'dynamic_sidebar_before', array( $this, 'start_dynamic_sidebar' ) ); add_action( 'dynamic_sidebar_after', array( $this, 'end_dynamic_sidebar' ) ); } /** * Inject selective refresh data attributes into widget container elements. * * @since 4.5.0 * * @param array $params { * Dynamic sidebar params. * * @type array $args Sidebar args. * @type array $widget_args Widget args. * } * @see WP_Customize_Nav_Menus::filter_wp_nav_menu_args() * * @return array Params. */ public function filter_dynamic_sidebar_params( $params ) { $sidebar_args = array_merge( array( 'before_widget' => '', 'after_widget' => '', ), $params[0] ); // Skip widgets not in a registered sidebar or ones which lack a proper wrapper element to attach the data-* attributes to. $matches = array(); $is_valid = ( isset( $sidebar_args['id'] ) && is_registered_sidebar( $sidebar_args['id'] ) && ( isset( $this->current_dynamic_sidebar_id_stack[0] ) && $this->current_dynamic_sidebar_id_stack[0] === $sidebar_args['id'] ) && preg_match( '#^<(?P<tag_name>\w+)#', $sidebar_args['before_widget'], $matches ) ); if ( ! $is_valid ) { return $params; } $this->before_widget_tags_seen[ $matches['tag_name'] ] = true; $context = array( 'sidebar_id' => $sidebar_args['id'], ); if ( isset( $this->context_sidebar_instance_number ) ) { $context['sidebar_instance_number'] = $this->context_sidebar_instance_number; } elseif ( isset( $sidebar_args['id'] ) && isset( $this->sidebar_instance_count[ $sidebar_args['id'] ] ) ) { $context['sidebar_instance_number'] = $this->sidebar_instance_count[ $sidebar_args['id'] ]; } $attributes = sprintf( ' data-customize-partial-id="%s"', esc_attr( 'widget[' . $sidebar_args['widget_id'] . ']' ) ); $attributes .= ' data-customize-partial-type="widget"'; $attributes .= sprintf( ' data-customize-partial-placement-context="%s"', esc_attr( wp_json_encode( $context ) ) ); $attributes .= sprintf( ' data-customize-widget-id="%s"', esc_attr( $sidebar_args['widget_id'] ) ); $sidebar_args['before_widget'] = preg_replace( '#^(<\w+)#', '$1 ' . $attributes, $sidebar_args['before_widget'] ); $params[0] = $sidebar_args; return $params; } /** * List of the tag names seen for before_widget strings. * * This is used in the {@see 'filter_wp_kses_allowed_html'} filter to ensure that the * data-* attributes can be allowed. * * @since 4.5.0 * @var array */ protected $before_widget_tags_seen = array(); /** * Ensures the HTML data-* attributes for selective refresh are allowed by kses. * * This is needed in case the `$before_widget` is run through wp_kses() when printed. * * @since 4.5.0 * * @param array $allowed_html Allowed HTML. * @return array (Maybe) modified allowed HTML. */ public function filter_wp_kses_allowed_data_attributes( $allowed_html ) { foreach ( array_keys( $this->before_widget_tags_seen ) as $tag_name ) { if ( ! isset( $allowed_html[ $tag_name ] ) ) { $allowed_html[ $tag_name ] = array(); } $allowed_html[ $tag_name ] = array_merge( $allowed_html[ $tag_name ], array_fill_keys( array( 'data-customize-partial-id', 'data-customize-partial-type', 'data-customize-partial-placement-context', 'data-customize-partial-widget-id', 'data-customize-partial-options', ), true ) ); } return $allowed_html; } /** * Keep track of the number of times that dynamic_sidebar() was called for a given sidebar index. * * This helps facilitate the uncommon scenario where a single sidebar is rendered multiple times on a template. * * @since 4.5.0 * @var array */ protected $sidebar_instance_count = array(); /** * The current request's sidebar_instance_number context. * * @since 4.5.0 * @var int|null */ protected $context_sidebar_instance_number; /** * Current sidebar ID being rendered. * * @since 4.5.0 * @var array */ protected $current_dynamic_sidebar_id_stack = array(); /** * Begins keeping track of the current sidebar being rendered. * * Insert marker before widgets are rendered in a dynamic sidebar. * * @since 4.5.0 * * @param int|string $index Index, name, or ID of the dynamic sidebar. */ public function start_dynamic_sidebar( $index ) { array_unshift( $this->current_dynamic_sidebar_id_stack, $index ); if ( ! isset( $this->sidebar_instance_count[ $index ] ) ) { $this->sidebar_instance_count[ $index ] = 0; } $this->sidebar_instance_count[ $index ] += 1; if ( ! $this->manager->selective_refresh->is_render_partials_request() ) { printf( "\n<!--dynamic_sidebar_before:%s:%d-->\n", esc_html( $index ), (int) $this->sidebar_instance_count[ $index ] ); } } /** * Finishes keeping track of the current sidebar being rendered. * * Inserts a marker after widgets are rendered in a dynamic sidebar. * * @since 4.5.0 * * @param int|string $index Index, name, or ID of the dynamic sidebar. */ public function end_dynamic_sidebar( $index ) { array_shift( $this->current_dynamic_sidebar_id_stack ); if ( ! $this->manager->selective_refresh->is_render_partials_request() ) { printf( "\n<!--dynamic_sidebar_after:%s:%d-->\n", esc_html( $index ), (int) $this->sidebar_instance_count[ $index ] ); } } /** * Current sidebar being rendered. * * @since 4.5.0 * @var string|null */ protected $rendering_widget_id; /** * Current widget being rendered. * * @since 4.5.0 * @var string|null */ protected $rendering_sidebar_id; /** * Filters sidebars_widgets to ensure the currently-rendered widget is the only widget in the current sidebar. * * @since 4.5.0 * * @param array $sidebars_widgets Sidebars widgets. * @return array Filtered sidebars widgets. */ public function filter_sidebars_widgets_for_rendering_widget( $sidebars_widgets ) { $sidebars_widgets[ $this->rendering_sidebar_id ] = array( $this->rendering_widget_id ); return $sidebars_widgets; } /** * Renders a specific widget using the supplied sidebar arguments. * * @since 4.5.0 * * @see dynamic_sidebar() * * @param WP_Customize_Partial $partial Partial. * @param array $context { * Sidebar args supplied as container context. * * @type string $sidebar_id ID for sidebar for widget to render into. * @type int $sidebar_instance_number Disambiguating instance number. * } * @return string|false */ public function render_widget_partial( $partial, $context ) { $id_data = $partial->id_data(); $widget_id = array_shift( $id_data['keys'] ); if ( ! is_array( $context ) || empty( $context['sidebar_id'] ) || ! is_registered_sidebar( $context['sidebar_id'] ) ) { return false; } $this->rendering_sidebar_id = $context['sidebar_id']; if ( isset( $context['sidebar_instance_number'] ) ) { $this->context_sidebar_instance_number = (int) $context['sidebar_instance_number']; } // Filter sidebars_widgets so that only the queried widget is in the sidebar. $this->rendering_widget_id = $widget_id; $filter_callback = array( $this, 'filter_sidebars_widgets_for_rendering_widget' ); add_filter( 'sidebars_widgets', $filter_callback, 1000 ); // Render the widget. ob_start(); $this->rendering_sidebar_id = $context['sidebar_id']; dynamic_sidebar( $this->rendering_sidebar_id ); $container = ob_get_clean(); // Reset variables for next partial render. remove_filter( 'sidebars_widgets', $filter_callback, 1000 ); $this->context_sidebar_instance_number = null; $this->rendering_sidebar_id = null; $this->rendering_widget_id = null; return $container; } // // Option Update Capturing. // /** * List of captured widget option updates. * * @since 3.9.0 * @var array $_captured_options Values updated while option capture is happening. */ protected $_captured_options = array(); /** * Whether option capture is currently happening. * * @since 3.9.0 * @var bool $_is_current Whether option capture is currently happening or not. */ protected $_is_capturing_option_updates = false; /** * Determines whether the captured option update should be ignored. * * @since 3.9.0 * * @param string $option_name Option name. * @return bool Whether the option capture is ignored. */ protected function is_option_capture_ignored( $option_name ) { return ( 0 === strpos( $option_name, '_transient_' ) ); } /** * Retrieves captured widget option updates. * * @since 3.9.0 * * @return array Array of captured options. */ protected function get_captured_options() { return $this->_captured_options; } /** * Retrieves the option that was captured from being saved. * * @since 4.2.0 * * @param string $option_name Option name. * @param mixed $default_value Optional. Default value to return if the option does not exist. Default false. * @return mixed Value set for the option. */ protected function get_captured_option( $option_name, $default_value = false ) { if ( array_key_exists( $option_name, $this->_captured_options ) ) { $value = $this->_captured_options[ $option_name ]; } else { $value = $default_value; } return $value; } /** * Retrieves the number of captured widget option updates. * * @since 3.9.0 * * @return int Number of updated options. */ protected function count_captured_options() { return count( $this->_captured_options ); } /** * Begins keeping track of changes to widget options, caching new values. * * @since 3.9.0 */ protected function start_capturing_option_updates() { if ( $this->_is_capturing_option_updates ) { return; } $this->_is_capturing_option_updates = true; add_filter( 'pre_update_option', array( $this, 'capture_filter_pre_update_option' ), 10, 3 ); } /** * Pre-filters captured option values before updating. * * @since 3.9.0 * * @param mixed $new_value The new option value. * @param string $option_name Name of the option. * @param mixed $old_value The old option value. * @return mixed Filtered option value. */ public function capture_filter_pre_update_option( $new_value, $option_name, $old_value ) { if ( $this->is_option_capture_ignored( $option_name ) ) { return $new_value; } if ( ! isset( $this->_captured_options[ $option_name ] ) ) { add_filter( "pre_option_{$option_name}", array( $this, 'capture_filter_pre_get_option' ) ); } $this->_captured_options[ $option_name ] = $new_value; return $old_value; } /** * Pre-filters captured option values before retrieving. * * @since 3.9.0 * * @param mixed $value Value to return instead of the option value. * @return mixed Filtered option value. */ public function capture_filter_pre_get_option( $value ) { $option_name = preg_replace( '/^pre_option_/', '', current_filter() ); if ( isset( $this->_captured_options[ $option_name ] ) ) { $value = $this->_captured_options[ $option_name ]; /** This filter is documented in wp-includes/option.php */ $value = apply_filters( 'option_' . $option_name, $value, $option_name ); } return $value; } /** * Undoes any changes to the options since options capture began. * * @since 3.9.0 */ protected function stop_capturing_option_updates() { if ( ! $this->_is_capturing_option_updates ) { return; } remove_filter( 'pre_update_option', array( $this, 'capture_filter_pre_update_option' ), 10 ); foreach ( array_keys( $this->_captured_options ) as $option_name ) { remove_filter( "pre_option_{$option_name}", array( $this, 'capture_filter_pre_get_option' ) ); } $this->_captured_options = array(); $this->_is_capturing_option_updates = false; } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function setup_widget_addition_previews() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function prepreview_added_sidebars_widgets() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function prepreview_added_widget_instance() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function remove_prepreview_filters() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } } home/verseaumee/aisatoshi_webx/wp-includes/class-wp-customize-widgets.php 0000644 00000213716 15075057241 0023046 0 ustar 00 <?php /** * WordPress Customize Widgets classes * * @package WordPress * @subpackage Customize * @since 3.9.0 */ /** * Customize Widgets class. * * Implements widget management in the Customizer. * * @since 3.9.0 * * @see WP_Customize_Manager */ #[AllowDynamicProperties] final class WP_Customize_Widgets { /** * WP_Customize_Manager instance. * * @since 3.9.0 * @var WP_Customize_Manager */ public $manager; /** * All id_bases for widgets defined in core. * * @since 3.9.0 * @var array */ protected $core_widget_id_bases = array( 'archives', 'calendar', 'categories', 'custom_html', 'links', 'media_audio', 'media_image', 'media_video', 'meta', 'nav_menu', 'pages', 'recent-comments', 'recent-posts', 'rss', 'search', 'tag_cloud', 'text', ); /** * @since 3.9.0 * @var array */ protected $rendered_sidebars = array(); /** * @since 3.9.0 * @var array */ protected $rendered_widgets = array(); /** * @since 3.9.0 * @var array */ protected $old_sidebars_widgets = array(); /** * Mapping of widget ID base to whether it supports selective refresh. * * @since 4.5.0 * @var array */ protected $selective_refreshable_widgets; /** * Mapping of setting type to setting ID pattern. * * @since 4.2.0 * @var array */ protected $setting_id_patterns = array( 'widget_instance' => '/^widget_(?P<id_base>.+?)(?:\[(?P<widget_number>\d+)\])?$/', 'sidebar_widgets' => '/^sidebars_widgets\[(?P<sidebar_id>.+?)\]$/', ); /** * Initial loader. * * @since 3.9.0 * * @param WP_Customize_Manager $manager Customizer bootstrap instance. */ public function __construct( $manager ) { $this->manager = $manager; // See https://github.com/xwp/wp-customize-snapshots/blob/962586659688a5b1fd9ae93618b7ce2d4e7a421c/php/class-customize-snapshot-manager.php#L420-L449 add_filter( 'customize_dynamic_setting_args', array( $this, 'filter_customize_dynamic_setting_args' ), 10, 2 ); add_action( 'widgets_init', array( $this, 'register_settings' ), 95 ); add_action( 'customize_register', array( $this, 'schedule_customize_register' ), 1 ); // Skip remaining hooks when the user can't manage widgets anyway. if ( ! current_user_can( 'edit_theme_options' ) ) { return; } add_action( 'wp_loaded', array( $this, 'override_sidebars_widgets_for_theme_switch' ) ); add_action( 'customize_controls_init', array( $this, 'customize_controls_init' ) ); add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); add_action( 'customize_controls_print_styles', array( $this, 'print_styles' ) ); add_action( 'customize_controls_print_scripts', array( $this, 'print_scripts' ) ); add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_footer_scripts' ) ); add_action( 'customize_controls_print_footer_scripts', array( $this, 'output_widget_control_templates' ) ); add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) ); add_filter( 'customize_refresh_nonces', array( $this, 'refresh_nonces' ) ); add_filter( 'should_load_block_editor_scripts_and_styles', array( $this, 'should_load_block_editor_scripts_and_styles' ) ); add_action( 'dynamic_sidebar', array( $this, 'tally_rendered_widgets' ) ); add_filter( 'is_active_sidebar', array( $this, 'tally_sidebars_via_is_active_sidebar_calls' ), 10, 2 ); add_filter( 'dynamic_sidebar_has_widgets', array( $this, 'tally_sidebars_via_dynamic_sidebar_calls' ), 10, 2 ); // Selective Refresh. add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 ); add_action( 'customize_preview_init', array( $this, 'selective_refresh_init' ) ); } /** * List whether each registered widget can be use selective refresh. * * If the theme does not support the customize-selective-refresh-widgets feature, * then this will always return an empty array. * * @since 4.5.0 * * @global WP_Widget_Factory $wp_widget_factory * * @return array Mapping of id_base to support. If theme doesn't support * selective refresh, an empty array is returned. */ public function get_selective_refreshable_widgets() { global $wp_widget_factory; if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return array(); } if ( ! isset( $this->selective_refreshable_widgets ) ) { $this->selective_refreshable_widgets = array(); foreach ( $wp_widget_factory->widgets as $wp_widget ) { $this->selective_refreshable_widgets[ $wp_widget->id_base ] = ! empty( $wp_widget->widget_options['customize_selective_refresh'] ); } } return $this->selective_refreshable_widgets; } /** * Determines if a widget supports selective refresh. * * @since 4.5.0 * * @param string $id_base Widget ID Base. * @return bool Whether the widget can be selective refreshed. */ public function is_widget_selective_refreshable( $id_base ) { $selective_refreshable_widgets = $this->get_selective_refreshable_widgets(); return ! empty( $selective_refreshable_widgets[ $id_base ] ); } /** * Retrieves the widget setting type given a setting ID. * * @since 4.2.0 * * @param string $setting_id Setting ID. * @return string|void Setting type. */ protected function get_setting_type( $setting_id ) { static $cache = array(); if ( isset( $cache[ $setting_id ] ) ) { return $cache[ $setting_id ]; } foreach ( $this->setting_id_patterns as $type => $pattern ) { if ( preg_match( $pattern, $setting_id ) ) { $cache[ $setting_id ] = $type; return $type; } } } /** * Inspects the incoming customized data for any widget settings, and dynamically adds * them up-front so widgets will be initialized properly. * * @since 4.2.0 */ public function register_settings() { $widget_setting_ids = array(); $incoming_setting_ids = array_keys( $this->manager->unsanitized_post_values() ); foreach ( $incoming_setting_ids as $setting_id ) { if ( ! is_null( $this->get_setting_type( $setting_id ) ) ) { $widget_setting_ids[] = $setting_id; } } if ( $this->manager->doing_ajax( 'update-widget' ) && isset( $_REQUEST['widget-id'] ) ) { $widget_setting_ids[] = $this->get_setting_id( wp_unslash( $_REQUEST['widget-id'] ) ); } $settings = $this->manager->add_dynamic_settings( array_unique( $widget_setting_ids ) ); if ( $this->manager->settings_previewed() ) { foreach ( $settings as $setting ) { $setting->preview(); } } } /** * Determines the arguments for a dynamically-created setting. * * @since 4.2.0 * * @param false|array $args The arguments to the WP_Customize_Setting constructor. * @param string $setting_id ID for dynamic setting, usually coming from `$_POST['customized']`. * @return array|false Setting arguments, false otherwise. */ public function filter_customize_dynamic_setting_args( $args, $setting_id ) { if ( $this->get_setting_type( $setting_id ) ) { $args = $this->get_setting_args( $setting_id ); } return $args; } /** * Retrieves an unslashed post value or return a default. * * @since 3.9.0 * * @param string $name Post value. * @param mixed $default_value Default post value. * @return mixed Unslashed post value or default value. */ protected function get_post_value( $name, $default_value = null ) { if ( ! isset( $_POST[ $name ] ) ) { return $default_value; } return wp_unslash( $_POST[ $name ] ); } /** * Override sidebars_widgets for theme switch. * * When switching a theme via the Customizer, supply any previously-configured * sidebars_widgets from the target theme as the initial sidebars_widgets * setting. Also store the old theme's existing settings so that they can * be passed along for storing in the sidebars_widgets theme_mod when the * theme gets switched. * * @since 3.9.0 * * @global array $sidebars_widgets * @global array $_wp_sidebars_widgets */ public function override_sidebars_widgets_for_theme_switch() { global $sidebars_widgets; if ( $this->manager->doing_ajax() || $this->manager->is_theme_active() ) { return; } $this->old_sidebars_widgets = wp_get_sidebars_widgets(); add_filter( 'customize_value_old_sidebars_widgets_data', array( $this, 'filter_customize_value_old_sidebars_widgets_data' ) ); $this->manager->set_post_value( 'old_sidebars_widgets_data', $this->old_sidebars_widgets ); // Override any value cached in changeset. // retrieve_widgets() looks at the global $sidebars_widgets. $sidebars_widgets = $this->old_sidebars_widgets; $sidebars_widgets = retrieve_widgets( 'customize' ); add_filter( 'option_sidebars_widgets', array( $this, 'filter_option_sidebars_widgets_for_theme_switch' ), 1 ); // Reset global cache var used by wp_get_sidebars_widgets(). unset( $GLOBALS['_wp_sidebars_widgets'] ); } /** * Filters old_sidebars_widgets_data Customizer setting. * * When switching themes, filter the Customizer setting old_sidebars_widgets_data * to supply initial $sidebars_widgets before they were overridden by retrieve_widgets(). * The value for old_sidebars_widgets_data gets set in the old theme's sidebars_widgets * theme_mod. * * @since 3.9.0 * * @see WP_Customize_Widgets::handle_theme_switch() * * @param array $old_sidebars_widgets * @return array */ public function filter_customize_value_old_sidebars_widgets_data( $old_sidebars_widgets ) { return $this->old_sidebars_widgets; } /** * Filters sidebars_widgets option for theme switch. * * When switching themes, the retrieve_widgets() function is run when the Customizer initializes, * and then the new sidebars_widgets here get supplied as the default value for the sidebars_widgets * option. * * @since 3.9.0 * * @see WP_Customize_Widgets::handle_theme_switch() * @global array $sidebars_widgets * * @param array $sidebars_widgets * @return array */ public function filter_option_sidebars_widgets_for_theme_switch( $sidebars_widgets ) { $sidebars_widgets = $GLOBALS['sidebars_widgets']; $sidebars_widgets['array_version'] = 3; return $sidebars_widgets; } /** * Ensures all widgets get loaded into the Customizer. * * Note: these actions are also fired in wp_ajax_update_widget(). * * @since 3.9.0 */ public function customize_controls_init() { /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/widgets.php */ do_action( 'sidebar_admin_setup' ); } /** * Ensures widgets are available for all types of previews. * * When in preview, hook to {@see 'customize_register'} for settings after WordPress is loaded * so that all filters have been initialized (e.g. Widget Visibility). * * @since 3.9.0 */ public function schedule_customize_register() { if ( is_admin() ) { $this->customize_register(); } else { add_action( 'wp', array( $this, 'customize_register' ) ); } } /** * Registers Customizer settings and controls for all sidebars and widgets. * * @since 3.9.0 * * @global array $wp_registered_widgets * @global array $wp_registered_widget_controls * @global array $wp_registered_sidebars */ public function customize_register() { global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_sidebars; $use_widgets_block_editor = wp_use_widgets_block_editor(); add_filter( 'sidebars_widgets', array( $this, 'preview_sidebars_widgets' ), 1 ); $sidebars_widgets = array_merge( array( 'wp_inactive_widgets' => array() ), array_fill_keys( array_keys( $wp_registered_sidebars ), array() ), wp_get_sidebars_widgets() ); $new_setting_ids = array(); /* * Register a setting for all widgets, including those which are active, * inactive, and orphaned since a widget may get suppressed from a sidebar * via a plugin (like Widget Visibility). */ foreach ( array_keys( $wp_registered_widgets ) as $widget_id ) { $setting_id = $this->get_setting_id( $widget_id ); $setting_args = $this->get_setting_args( $setting_id ); if ( ! $this->manager->get_setting( $setting_id ) ) { $this->manager->add_setting( $setting_id, $setting_args ); } $new_setting_ids[] = $setting_id; } /* * Add a setting which will be supplied for the theme's sidebars_widgets * theme_mod when the theme is switched. */ if ( ! $this->manager->is_theme_active() ) { $setting_id = 'old_sidebars_widgets_data'; $setting_args = $this->get_setting_args( $setting_id, array( 'type' => 'global_variable', 'dirty' => true, ) ); $this->manager->add_setting( $setting_id, $setting_args ); } $this->manager->add_panel( 'widgets', array( 'type' => 'widgets', 'title' => __( 'Widgets' ), 'description' => __( 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).' ), 'priority' => 110, 'active_callback' => array( $this, 'is_panel_active' ), 'auto_expand_sole_section' => true, 'theme_supports' => 'widgets', ) ); foreach ( $sidebars_widgets as $sidebar_id => $sidebar_widget_ids ) { if ( empty( $sidebar_widget_ids ) ) { $sidebar_widget_ids = array(); } $is_registered_sidebar = is_registered_sidebar( $sidebar_id ); $is_inactive_widgets = ( 'wp_inactive_widgets' === $sidebar_id ); $is_active_sidebar = ( $is_registered_sidebar && ! $is_inactive_widgets ); // Add setting for managing the sidebar's widgets. if ( $is_registered_sidebar || $is_inactive_widgets ) { $setting_id = sprintf( 'sidebars_widgets[%s]', $sidebar_id ); $setting_args = $this->get_setting_args( $setting_id ); if ( ! $this->manager->get_setting( $setting_id ) ) { if ( ! $this->manager->is_theme_active() ) { $setting_args['dirty'] = true; } $this->manager->add_setting( $setting_id, $setting_args ); } $new_setting_ids[] = $setting_id; // Add section to contain controls. $section_id = sprintf( 'sidebar-widgets-%s', $sidebar_id ); if ( $is_active_sidebar ) { $section_args = array( 'title' => $wp_registered_sidebars[ $sidebar_id ]['name'], 'priority' => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ), true ), 'panel' => 'widgets', 'sidebar_id' => $sidebar_id, ); if ( $use_widgets_block_editor ) { $section_args['description'] = ''; } else { $section_args['description'] = $wp_registered_sidebars[ $sidebar_id ]['description']; } /** * Filters Customizer widget section arguments for a given sidebar. * * @since 3.9.0 * * @param array $section_args Array of Customizer widget section arguments. * @param string $section_id Customizer section ID. * @param int|string $sidebar_id Sidebar ID. */ $section_args = apply_filters( 'customizer_widgets_section_args', $section_args, $section_id, $sidebar_id ); $section = new WP_Customize_Sidebar_Section( $this->manager, $section_id, $section_args ); $this->manager->add_section( $section ); if ( $use_widgets_block_editor ) { $control = new WP_Sidebar_Block_Editor_Control( $this->manager, $setting_id, array( 'section' => $section_id, 'sidebar_id' => $sidebar_id, 'label' => $section_args['title'], 'description' => $section_args['description'], ) ); } else { $control = new WP_Widget_Area_Customize_Control( $this->manager, $setting_id, array( 'section' => $section_id, 'sidebar_id' => $sidebar_id, 'priority' => count( $sidebar_widget_ids ), // place 'Add Widget' and 'Reorder' buttons at end. ) ); } $this->manager->add_control( $control ); $new_setting_ids[] = $setting_id; } } if ( ! $use_widgets_block_editor ) { // Add a control for each active widget (located in a sidebar). foreach ( $sidebar_widget_ids as $i => $widget_id ) { // Skip widgets that may have gone away due to a plugin being deactivated. if ( ! $is_active_sidebar || ! isset( $wp_registered_widgets[ $widget_id ] ) ) { continue; } $registered_widget = $wp_registered_widgets[ $widget_id ]; $setting_id = $this->get_setting_id( $widget_id ); $id_base = $wp_registered_widget_controls[ $widget_id ]['id_base']; $control = new WP_Widget_Form_Customize_Control( $this->manager, $setting_id, array( 'label' => $registered_widget['name'], 'section' => $section_id, 'sidebar_id' => $sidebar_id, 'widget_id' => $widget_id, 'widget_id_base' => $id_base, 'priority' => $i, 'width' => $wp_registered_widget_controls[ $widget_id ]['width'], 'height' => $wp_registered_widget_controls[ $widget_id ]['height'], 'is_wide' => $this->is_wide_widget( $widget_id ), ) ); $this->manager->add_control( $control ); } } } if ( $this->manager->settings_previewed() ) { foreach ( $new_setting_ids as $new_setting_id ) { $this->manager->get_setting( $new_setting_id )->preview(); } } } /** * Determines whether the widgets panel is active, based on whether there are sidebars registered. * * @since 4.4.0 * * @see WP_Customize_Panel::$active_callback * * @global array $wp_registered_sidebars * @return bool Active. */ public function is_panel_active() { global $wp_registered_sidebars; return ! empty( $wp_registered_sidebars ); } /** * Converts a widget_id into its corresponding Customizer setting ID (option name). * * @since 3.9.0 * * @param string $widget_id Widget ID. * @return string Maybe-parsed widget ID. */ public function get_setting_id( $widget_id ) { $parsed_widget_id = $this->parse_widget_id( $widget_id ); $setting_id = sprintf( 'widget_%s', $parsed_widget_id['id_base'] ); if ( ! is_null( $parsed_widget_id['number'] ) ) { $setting_id .= sprintf( '[%d]', $parsed_widget_id['number'] ); } return $setting_id; } /** * Determines whether the widget is considered "wide". * * Core widgets which may have controls wider than 250, but can still be shown * in the narrow Customizer panel. The RSS and Text widgets in Core, for example, * have widths of 400 and yet they still render fine in the Customizer panel. * * This method will return all Core widgets as being not wide, but this can be * overridden with the {@see 'is_wide_widget_in_customizer'} filter. * * @since 3.9.0 * * @global array $wp_registered_widget_controls * * @param string $widget_id Widget ID. * @return bool Whether or not the widget is a "wide" widget. */ public function is_wide_widget( $widget_id ) { global $wp_registered_widget_controls; $parsed_widget_id = $this->parse_widget_id( $widget_id ); $width = $wp_registered_widget_controls[ $widget_id ]['width']; $is_core = in_array( $parsed_widget_id['id_base'], $this->core_widget_id_bases, true ); $is_wide = ( $width > 250 && ! $is_core ); /** * Filters whether the given widget is considered "wide". * * @since 3.9.0 * * @param bool $is_wide Whether the widget is wide, Default false. * @param string $widget_id Widget ID. */ return apply_filters( 'is_wide_widget_in_customizer', $is_wide, $widget_id ); } /** * Converts a widget ID into its id_base and number components. * * @since 3.9.0 * * @param string $widget_id Widget ID. * @return array Array containing a widget's id_base and number components. */ public function parse_widget_id( $widget_id ) { $parsed = array( 'number' => null, 'id_base' => null, ); if ( preg_match( '/^(.+)-(\d+)$/', $widget_id, $matches ) ) { $parsed['id_base'] = $matches[1]; $parsed['number'] = (int) $matches[2]; } else { // Likely an old single widget. $parsed['id_base'] = $widget_id; } return $parsed; } /** * Converts a widget setting ID (option path) to its id_base and number components. * * @since 3.9.0 * * @param string $setting_id Widget setting ID. * @return array|WP_Error Array containing a widget's id_base and number components, * or a WP_Error object. */ public function parse_widget_setting_id( $setting_id ) { if ( ! preg_match( '/^(widget_(.+?))(?:\[(\d+)\])?$/', $setting_id, $matches ) ) { return new WP_Error( 'widget_setting_invalid_id' ); } $id_base = $matches[2]; $number = isset( $matches[3] ) ? (int) $matches[3] : null; return compact( 'id_base', 'number' ); } /** * Calls admin_print_styles-widgets.php and admin_print_styles hooks to * allow custom styles from plugins. * * @since 3.9.0 */ public function print_styles() { /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_styles-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_styles' ); } /** * Calls admin_print_scripts-widgets.php and admin_print_scripts hooks to * allow custom scripts from plugins. * * @since 3.9.0 */ public function print_scripts() { /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_scripts-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_scripts' ); } /** * Enqueues scripts and styles for Customizer panel and export data to JavaScript. * * @since 3.9.0 * * @global WP_Scripts $wp_scripts * @global array $wp_registered_sidebars * @global array $wp_registered_widgets */ public function enqueue_scripts() { global $wp_scripts, $wp_registered_sidebars, $wp_registered_widgets; wp_enqueue_style( 'customize-widgets' ); wp_enqueue_script( 'customize-widgets' ); /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_enqueue_scripts', 'widgets.php' ); /* * Export available widgets with control_tpl removed from model * since plugins need templates to be in the DOM. */ $available_widgets = array(); foreach ( $this->get_available_widgets() as $available_widget ) { unset( $available_widget['control_tpl'] ); $available_widgets[] = $available_widget; } $widget_reorder_nav_tpl = sprintf( '<div class="widget-reorder-nav"><span class="move-widget" tabindex="0">%1$s</span><span class="move-widget-down" tabindex="0">%2$s</span><span class="move-widget-up" tabindex="0">%3$s</span></div>', __( 'Move to another area…' ), __( 'Move down' ), __( 'Move up' ) ); $move_widget_area_tpl = str_replace( array( '{description}', '{btn}' ), array( __( 'Select an area to move this widget into:' ), _x( 'Move', 'Move widget' ), ), '<div class="move-widget-area"> <p class="description">{description}</p> <ul class="widget-area-select"> <% _.each( sidebars, function ( sidebar ){ %> <li class="" data-id="<%- sidebar.id %>" title="<%- sidebar.description %>" tabindex="0"><%- sidebar.name %></li> <% }); %> </ul> <div class="move-widget-actions"> <button class="move-widget-btn button" type="button">{btn}</button> </div> </div>' ); /* * Gather all strings in PHP that may be needed by JS on the client. * Once JS i18n is implemented (in #20491), this can be removed. */ $some_non_rendered_areas_messages = array(); $some_non_rendered_areas_messages[1] = html_entity_decode( __( 'Your theme has 1 other widget area, but this particular page does not display it.' ), ENT_QUOTES, get_bloginfo( 'charset' ) ); $registered_sidebar_count = count( $wp_registered_sidebars ); for ( $non_rendered_count = 2; $non_rendered_count < $registered_sidebar_count; $non_rendered_count++ ) { $some_non_rendered_areas_messages[ $non_rendered_count ] = html_entity_decode( sprintf( /* translators: %s: The number of other widget areas registered but not rendered. */ _n( 'Your theme has %s other widget area, but this particular page does not display it.', 'Your theme has %s other widget areas, but this particular page does not display them.', $non_rendered_count ), number_format_i18n( $non_rendered_count ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } if ( 1 === $registered_sidebar_count ) { $no_areas_shown_message = html_entity_decode( sprintf( __( 'Your theme has 1 widget area, but this particular page does not display it.' ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } else { $no_areas_shown_message = html_entity_decode( sprintf( /* translators: %s: The total number of widget areas registered. */ _n( 'Your theme has %s widget area, but this particular page does not display it.', 'Your theme has %s widget areas, but this particular page does not display them.', $registered_sidebar_count ), number_format_i18n( $registered_sidebar_count ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } $settings = array( 'registeredSidebars' => array_values( $wp_registered_sidebars ), 'registeredWidgets' => $wp_registered_widgets, 'availableWidgets' => $available_widgets, // @todo Merge this with registered_widgets. 'l10n' => array( 'saveBtnLabel' => __( 'Apply' ), 'saveBtnTooltip' => __( 'Save and preview changes before publishing them.' ), 'removeBtnLabel' => __( 'Remove' ), 'removeBtnTooltip' => __( 'Keep widget settings and move it to the inactive widgets' ), 'error' => __( 'An error has occurred. Please reload the page and try again.' ), 'widgetMovedUp' => __( 'Widget moved up' ), 'widgetMovedDown' => __( 'Widget moved down' ), 'navigatePreview' => __( 'You can navigate to other pages on your site while using the Customizer to view and edit the widgets displayed on those pages.' ), 'someAreasShown' => $some_non_rendered_areas_messages, 'noAreasShown' => $no_areas_shown_message, 'reorderModeOn' => __( 'Reorder mode enabled' ), 'reorderModeOff' => __( 'Reorder mode closed' ), 'reorderLabelOn' => esc_attr__( 'Reorder widgets' ), /* translators: %d: The number of widgets found. */ 'widgetsFound' => __( 'Number of widgets found: %d' ), 'noWidgetsFound' => __( 'No widgets found.' ), ), 'tpl' => array( 'widgetReorderNav' => $widget_reorder_nav_tpl, 'moveWidgetArea' => $move_widget_area_tpl, ), 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), ); foreach ( $settings['registeredWidgets'] as &$registered_widget ) { unset( $registered_widget['callback'] ); // May not be JSON-serializeable. } $wp_scripts->add_data( 'customize-widgets', 'data', sprintf( 'var _wpCustomizeWidgetsSettings = %s;', wp_json_encode( $settings ) ) ); /* * TODO: Update 'wp-customize-widgets' to not rely so much on things in * 'customize-widgets'. This will let us skip most of the above and not * enqueue 'customize-widgets' which saves bytes. */ if ( wp_use_widgets_block_editor() ) { $block_editor_context = new WP_Block_Editor_Context( array( 'name' => 'core/customize-widgets', ) ); $editor_settings = get_block_editor_settings( get_legacy_widget_block_editor_settings(), $block_editor_context ); wp_add_inline_script( 'wp-customize-widgets', sprintf( 'wp.domReady( function() { wp.customizeWidgets.initialize( "widgets-customizer", %s ); } );', wp_json_encode( $editor_settings ) ) ); // Preload server-registered block schemas. wp_add_inline_script( 'wp-blocks', 'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');' ); wp_add_inline_script( 'wp-blocks', sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( $block_editor_context ) ) ), 'after' ); wp_enqueue_script( 'wp-customize-widgets' ); wp_enqueue_style( 'wp-customize-widgets' ); /** This action is documented in edit-form-blocks.php */ do_action( 'enqueue_block_editor_assets' ); } } /** * Renders the widget form control templates into the DOM. * * @since 3.9.0 */ public function output_widget_control_templates() { ?> <div id="widgets-left"><!-- compatibility with JS which looks for widget templates here --> <div id="available-widgets"> <div class="customize-section-title"> <button class="customize-section-back" tabindex="-1"> <span class="screen-reader-text"> <?php /* translators: Hidden accessibility text. */ _e( 'Back' ); ?> </span> </button> <h3> <span class="customize-action"> <?php /* translators: ▸ is the unicode right-pointing triangle. %s: Section title in the Customizer. */ printf( __( 'Customizing ▸ %s' ), esc_html( $this->manager->get_panel( 'widgets' )->title ) ); ?> </span> <?php _e( 'Add a Widget' ); ?> </h3> </div> <div id="available-widgets-filter"> <label class="screen-reader-text" for="widgets-search"> <?php /* translators: Hidden accessibility text. */ _e( 'Search Widgets' ); ?> </label> <input type="text" id="widgets-search" placeholder="<?php esc_attr_e( 'Search widgets…' ); ?>" aria-describedby="widgets-search-desc" /> <div class="search-icon" aria-hidden="true"></div> <button type="button" class="clear-results"><span class="screen-reader-text"> <?php /* translators: Hidden accessibility text. */ _e( 'Clear Results' ); ?> </span></button> <p class="screen-reader-text" id="widgets-search-desc"> <?php /* translators: Hidden accessibility text. */ _e( 'The search results will be updated as you type.' ); ?> </p> </div> <div id="available-widgets-list"> <?php foreach ( $this->get_available_widgets() as $available_widget ) : ?> <div id="widget-tpl-<?php echo esc_attr( $available_widget['id'] ); ?>" data-widget-id="<?php echo esc_attr( $available_widget['id'] ); ?>" class="widget-tpl <?php echo esc_attr( $available_widget['id'] ); ?>" tabindex="0"> <?php echo $available_widget['control_tpl']; ?> </div> <?php endforeach; ?> <p class="no-widgets-found-message"><?php _e( 'No widgets found.' ); ?></p> </div><!-- #available-widgets-list --> </div><!-- #available-widgets --> </div><!-- #widgets-left --> <?php } /** * Calls admin_print_footer_scripts and admin_print_scripts hooks to * allow custom scripts from plugins. * * @since 3.9.0 */ public function print_footer_scripts() { /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_print_footer_scripts-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_print_footer_scripts' ); /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_footer-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores } /** * Retrieves common arguments to supply when constructing a Customizer setting. * * @since 3.9.0 * * @param string $id Widget setting ID. * @param array $overrides Array of setting overrides. * @return array Possibly modified setting arguments. */ public function get_setting_args( $id, $overrides = array() ) { $args = array( 'type' => 'option', 'capability' => 'edit_theme_options', 'default' => array(), ); if ( preg_match( $this->setting_id_patterns['sidebar_widgets'], $id, $matches ) ) { $args['sanitize_callback'] = array( $this, 'sanitize_sidebar_widgets' ); $args['sanitize_js_callback'] = array( $this, 'sanitize_sidebar_widgets_js_instance' ); $args['transport'] = current_theme_supports( 'customize-selective-refresh-widgets' ) ? 'postMessage' : 'refresh'; } elseif ( preg_match( $this->setting_id_patterns['widget_instance'], $id, $matches ) ) { $id_base = $matches['id_base']; $args['sanitize_callback'] = function( $value ) use ( $id_base ) { return $this->sanitize_widget_instance( $value, $id_base ); }; $args['sanitize_js_callback'] = function( $value ) use ( $id_base ) { return $this->sanitize_widget_js_instance( $value, $id_base ); }; $args['transport'] = $this->is_widget_selective_refreshable( $matches['id_base'] ) ? 'postMessage' : 'refresh'; } $args = array_merge( $args, $overrides ); /** * Filters the common arguments supplied when constructing a Customizer setting. * * @since 3.9.0 * * @see WP_Customize_Setting * * @param array $args Array of Customizer setting arguments. * @param string $id Widget setting ID. */ return apply_filters( 'widget_customizer_setting_args', $args, $id ); } /** * Ensures sidebar widget arrays only ever contain widget IDS. * * Used as the 'sanitize_callback' for each $sidebars_widgets setting. * * @since 3.9.0 * * @param string[] $widget_ids Array of widget IDs. * @return string[] Array of sanitized widget IDs. */ public function sanitize_sidebar_widgets( $widget_ids ) { $widget_ids = array_map( 'strval', (array) $widget_ids ); $sanitized_widget_ids = array(); foreach ( $widget_ids as $widget_id ) { $sanitized_widget_ids[] = preg_replace( '/[^a-z0-9_\-]/', '', $widget_id ); } return $sanitized_widget_ids; } /** * Builds up an index of all available widgets for use in Backbone models. * * @since 3.9.0 * * @global array $wp_registered_widgets * @global array $wp_registered_widget_controls * * @see wp_list_widgets() * * @return array List of available widgets. */ public function get_available_widgets() { static $available_widgets = array(); if ( ! empty( $available_widgets ) ) { return $available_widgets; } global $wp_registered_widgets, $wp_registered_widget_controls; require_once ABSPATH . 'wp-admin/includes/widgets.php'; // For next_widget_id_number(). $sort = $wp_registered_widgets; usort( $sort, array( $this, '_sort_name_callback' ) ); $done = array(); foreach ( $sort as $widget ) { if ( in_array( $widget['callback'], $done, true ) ) { // We already showed this multi-widget. continue; } $sidebar = is_active_widget( $widget['callback'], $widget['id'], false, false ); $done[] = $widget['callback']; if ( ! isset( $widget['params'][0] ) ) { $widget['params'][0] = array(); } $available_widget = $widget; unset( $available_widget['callback'] ); // Not serializable to JSON. $args = array( 'widget_id' => $widget['id'], 'widget_name' => $widget['name'], '_display' => 'template', ); $is_disabled = false; $is_multi_widget = ( isset( $wp_registered_widget_controls[ $widget['id'] ]['id_base'] ) && isset( $widget['params'][0]['number'] ) ); if ( $is_multi_widget ) { $id_base = $wp_registered_widget_controls[ $widget['id'] ]['id_base']; $args['_temp_id'] = "$id_base-__i__"; $args['_multi_num'] = next_widget_id_number( $id_base ); $args['_add'] = 'multi'; } else { $args['_add'] = 'single'; if ( $sidebar && 'wp_inactive_widgets' !== $sidebar ) { $is_disabled = true; } $id_base = $widget['id']; } $list_widget_controls_args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0], ) ); $control_tpl = $this->get_widget_control( $list_widget_controls_args ); // The properties here are mapped to the Backbone Widget model. $available_widget = array_merge( $available_widget, array( 'temp_id' => isset( $args['_temp_id'] ) ? $args['_temp_id'] : null, 'is_multi' => $is_multi_widget, 'control_tpl' => $control_tpl, 'multi_number' => ( 'multi' === $args['_add'] ) ? $args['_multi_num'] : false, 'is_disabled' => $is_disabled, 'id_base' => $id_base, 'transport' => $this->is_widget_selective_refreshable( $id_base ) ? 'postMessage' : 'refresh', 'width' => $wp_registered_widget_controls[ $widget['id'] ]['width'], 'height' => $wp_registered_widget_controls[ $widget['id'] ]['height'], 'is_wide' => $this->is_wide_widget( $widget['id'] ), ) ); $available_widgets[] = $available_widget; } return $available_widgets; } /** * Naturally orders available widgets by name. * * @since 3.9.0 * * @param array $widget_a The first widget to compare. * @param array $widget_b The second widget to compare. * @return int Reorder position for the current widget comparison. */ protected function _sort_name_callback( $widget_a, $widget_b ) { return strnatcasecmp( $widget_a['name'], $widget_b['name'] ); } /** * Retrieves the widget control markup. * * @since 3.9.0 * * @param array $args Widget control arguments. * @return string Widget control form HTML markup. */ public function get_widget_control( $args ) { $args[0]['before_form'] = '<div class="form">'; $args[0]['after_form'] = '</div><!-- .form -->'; $args[0]['before_widget_content'] = '<div class="widget-content">'; $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; ob_start(); wp_widget_control( ...$args ); $control_tpl = ob_get_clean(); return $control_tpl; } /** * Retrieves the widget control markup parts. * * @since 4.4.0 * * @param array $args Widget control arguments. * @return array { * @type string $control Markup for widget control wrapping form. * @type string $content The contents of the widget form itself. * } */ public function get_widget_control_parts( $args ) { $args[0]['before_widget_content'] = '<div class="widget-content">'; $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; $control_markup = $this->get_widget_control( $args ); $content_start_pos = strpos( $control_markup, $args[0]['before_widget_content'] ); $content_end_pos = strrpos( $control_markup, $args[0]['after_widget_content'] ); $control = substr( $control_markup, 0, $content_start_pos + strlen( $args[0]['before_widget_content'] ) ); $control .= substr( $control_markup, $content_end_pos ); $content = trim( substr( $control_markup, $content_start_pos + strlen( $args[0]['before_widget_content'] ), $content_end_pos - $content_start_pos - strlen( $args[0]['before_widget_content'] ) ) ); return compact( 'control', 'content' ); } /** * Adds hooks for the Customizer preview. * * @since 3.9.0 */ public function customize_preview_init() { add_action( 'wp_enqueue_scripts', array( $this, 'customize_preview_enqueue' ) ); add_action( 'wp_print_styles', array( $this, 'print_preview_css' ), 1 ); add_action( 'wp_footer', array( $this, 'export_preview_data' ), 20 ); } /** * Refreshes the nonce for widget updates. * * @since 4.2.0 * * @param array $nonces Array of nonces. * @return array Array of nonces. */ public function refresh_nonces( $nonces ) { $nonces['update-widget'] = wp_create_nonce( 'update-widget' ); return $nonces; } /** * Tells the script loader to load the scripts and styles of custom blocks * if the widgets block editor is enabled. * * @since 5.8.0 * * @param bool $is_block_editor_screen Current decision about loading block assets. * @return bool Filtered decision about loading block assets. */ public function should_load_block_editor_scripts_and_styles( $is_block_editor_screen ) { if ( wp_use_widgets_block_editor() ) { return true; } return $is_block_editor_screen; } /** * When previewing, ensures the proper previewing widgets are used. * * Because wp_get_sidebars_widgets() gets called early at {@see 'init' } (via * wp_convert_widget_settings()) and can set global variable `$_wp_sidebars_widgets` * to the value of `get_option( 'sidebars_widgets' )` before the Customizer preview * filter is added, it has to be reset after the filter has been added. * * @since 3.9.0 * * @param array $sidebars_widgets List of widgets for the current sidebar. * @return array */ public function preview_sidebars_widgets( $sidebars_widgets ) { $sidebars_widgets = get_option( 'sidebars_widgets', array() ); unset( $sidebars_widgets['array_version'] ); return $sidebars_widgets; } /** * Enqueues scripts for the Customizer preview. * * @since 3.9.0 */ public function customize_preview_enqueue() { wp_enqueue_script( 'customize-preview-widgets' ); } /** * Inserts default style for highlighted widget at early point so theme * stylesheet can override. * * @since 3.9.0 */ public function print_preview_css() { ?> <style> .widget-customizer-highlighted-widget { outline: none; -webkit-box-shadow: 0 0 2px rgba(30, 140, 190, 0.8); box-shadow: 0 0 2px rgba(30, 140, 190, 0.8); position: relative; z-index: 1; } </style> <?php } /** * Communicates the sidebars that appeared on the page at the very end of the page, * and at the very end of the wp_footer, * * @since 3.9.0 * * @global array $wp_registered_sidebars * @global array $wp_registered_widgets */ public function export_preview_data() { global $wp_registered_sidebars, $wp_registered_widgets; $switched_locale = switch_to_user_locale( get_current_user_id() ); $l10n = array( 'widgetTooltip' => __( 'Shift-click to edit this widget.' ), ); if ( $switched_locale ) { restore_previous_locale(); } $rendered_sidebars = array_filter( $this->rendered_sidebars ); $rendered_widgets = array_filter( $this->rendered_widgets ); // Prepare Customizer settings to pass to JavaScript. $settings = array( 'renderedSidebars' => array_fill_keys( array_keys( $rendered_sidebars ), true ), 'renderedWidgets' => array_fill_keys( array_keys( $rendered_widgets ), true ), 'registeredSidebars' => array_values( $wp_registered_sidebars ), 'registeredWidgets' => $wp_registered_widgets, 'l10n' => $l10n, 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), ); foreach ( $settings['registeredWidgets'] as &$registered_widget ) { unset( $registered_widget['callback'] ); // May not be JSON-serializeable. } ?> <script type="text/javascript"> var _wpWidgetCustomizerPreviewSettings = <?php echo wp_json_encode( $settings ); ?>; </script> <?php } /** * Tracks the widgets that were rendered. * * @since 3.9.0 * * @param array $widget Rendered widget to tally. */ public function tally_rendered_widgets( $widget ) { $this->rendered_widgets[ $widget['id'] ] = true; } /** * Determine if a widget is rendered on the page. * * @since 4.0.0 * * @param string $widget_id Widget ID to check. * @return bool Whether the widget is rendered. */ public function is_widget_rendered( $widget_id ) { return ! empty( $this->rendered_widgets[ $widget_id ] ); } /** * Determines if a sidebar is rendered on the page. * * @since 4.0.0 * * @param string $sidebar_id Sidebar ID to check. * @return bool Whether the sidebar is rendered. */ public function is_sidebar_rendered( $sidebar_id ) { return ! empty( $this->rendered_sidebars[ $sidebar_id ] ); } /** * Tallies the sidebars rendered via is_active_sidebar(). * * Keep track of the times that is_active_sidebar() is called in the template, * and assume that this means that the sidebar would be rendered on the template * if there were widgets populating it. * * @since 3.9.0 * * @param bool $is_active Whether the sidebar is active. * @param string $sidebar_id Sidebar ID. * @return bool Whether the sidebar is active. */ public function tally_sidebars_via_is_active_sidebar_calls( $is_active, $sidebar_id ) { if ( is_registered_sidebar( $sidebar_id ) ) { $this->rendered_sidebars[ $sidebar_id ] = true; } /* * We may need to force this to true, and also force-true the value * for 'dynamic_sidebar_has_widgets' if we want to ensure that there * is an area to drop widgets into, if the sidebar is empty. */ return $is_active; } /** * Tallies the sidebars rendered via dynamic_sidebar(). * * Keep track of the times that dynamic_sidebar() is called in the template, * and assume this means the sidebar would be rendered on the template if * there were widgets populating it. * * @since 3.9.0 * * @param bool $has_widgets Whether the current sidebar has widgets. * @param string $sidebar_id Sidebar ID. * @return bool Whether the current sidebar has widgets. */ public function tally_sidebars_via_dynamic_sidebar_calls( $has_widgets, $sidebar_id ) { if ( is_registered_sidebar( $sidebar_id ) ) { $this->rendered_sidebars[ $sidebar_id ] = true; } /* * We may need to force this to true, and also force-true the value * for 'is_active_sidebar' if we want to ensure there is an area to * drop widgets into, if the sidebar is empty. */ return $has_widgets; } /** * Retrieves MAC for a serialized widget instance string. * * Allows values posted back from JS to be rejected if any tampering of the * data has occurred. * * @since 3.9.0 * * @param string $serialized_instance Widget instance. * @return string MAC for serialized widget instance. */ protected function get_instance_hash_key( $serialized_instance ) { return wp_hash( $serialized_instance ); } /** * Sanitizes a widget instance. * * Unserialize the JS-instance for storing in the options. It's important that this filter * only get applied to an instance *once*. * * @since 3.9.0 * @since 5.8.0 Added the `$id_base` parameter. * * @global WP_Widget_Factory $wp_widget_factory * * @param array $value Widget instance to sanitize. * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null. * @return array|void Sanitized widget instance. */ public function sanitize_widget_instance( $value, $id_base = null ) { global $wp_widget_factory; if ( array() === $value ) { return $value; } if ( isset( $value['raw_instance'] ) && $id_base && wp_use_widgets_block_editor() ) { $widget_object = $wp_widget_factory->get_widget_object( $id_base ); if ( ! empty( $widget_object->widget_options['show_instance_in_rest'] ) ) { if ( 'block' === $id_base && ! current_user_can( 'unfiltered_html' ) ) { /* * The content of the 'block' widget is not filtered on the fly while editing. * Filter the content here to prevent vulnerabilities. */ $value['raw_instance']['content'] = wp_kses_post( $value['raw_instance']['content'] ); } return $value['raw_instance']; } } if ( empty( $value['is_widget_customizer_js_value'] ) || empty( $value['instance_hash_key'] ) || empty( $value['encoded_serialized_instance'] ) ) { return; } $decoded = base64_decode( $value['encoded_serialized_instance'], true ); if ( false === $decoded ) { return; } if ( ! hash_equals( $this->get_instance_hash_key( $decoded ), $value['instance_hash_key'] ) ) { return; } $instance = unserialize( $decoded ); if ( false === $instance ) { return; } return $instance; } /** * Converts a widget instance into JSON-representable format. * * @since 3.9.0 * @since 5.8.0 Added the `$id_base` parameter. * * @global WP_Widget_Factory $wp_widget_factory * * @param array $value Widget instance to convert to JSON. * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null. * @return array JSON-converted widget instance. */ public function sanitize_widget_js_instance( $value, $id_base = null ) { global $wp_widget_factory; if ( empty( $value['is_widget_customizer_js_value'] ) ) { $serialized = serialize( $value ); $js_value = array( 'encoded_serialized_instance' => base64_encode( $serialized ), 'title' => empty( $value['title'] ) ? '' : $value['title'], 'is_widget_customizer_js_value' => true, 'instance_hash_key' => $this->get_instance_hash_key( $serialized ), ); if ( $id_base && wp_use_widgets_block_editor() ) { $widget_object = $wp_widget_factory->get_widget_object( $id_base ); if ( ! empty( $widget_object->widget_options['show_instance_in_rest'] ) ) { $js_value['raw_instance'] = (object) $value; } } return $js_value; } return $value; } /** * Strips out widget IDs for widgets which are no longer registered. * * One example where this might happen is when a plugin orphans a widget * in a sidebar upon deactivation. * * @since 3.9.0 * * @global array $wp_registered_widgets * * @param array $widget_ids List of widget IDs. * @return array Parsed list of widget IDs. */ public function sanitize_sidebar_widgets_js_instance( $widget_ids ) { global $wp_registered_widgets; $widget_ids = array_values( array_intersect( $widget_ids, array_keys( $wp_registered_widgets ) ) ); return $widget_ids; } /** * Finds and invokes the widget update and control callbacks. * * Requires that `$_POST` be populated with the instance data. * * @since 3.9.0 * * @global array $wp_registered_widget_updates * @global array $wp_registered_widget_controls * * @param string $widget_id Widget ID. * @return array|WP_Error Array containing the updated widget information. * A WP_Error object, otherwise. */ public function call_widget_update( $widget_id ) { global $wp_registered_widget_updates, $wp_registered_widget_controls; $setting_id = $this->get_setting_id( $widget_id ); /* * Make sure that other setting changes have previewed since this widget * may depend on them (e.g. Menus being present for Navigation Menu widget). */ if ( ! did_action( 'customize_preview_init' ) ) { foreach ( $this->manager->settings() as $setting ) { if ( $setting->id !== $setting_id ) { $setting->preview(); } } } $this->start_capturing_option_updates(); $parsed_id = $this->parse_widget_id( $widget_id ); $option_name = 'widget_' . $parsed_id['id_base']; /* * If a previously-sanitized instance is provided, populate the input vars * with its values so that the widget update callback will read this instance */ $added_input_vars = array(); if ( ! empty( $_POST['sanitized_widget_setting'] ) ) { $sanitized_widget_setting = json_decode( $this->get_post_value( 'sanitized_widget_setting' ), true ); if ( false === $sanitized_widget_setting ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_malformed' ); } $instance = $this->sanitize_widget_instance( $sanitized_widget_setting, $parsed_id['id_base'] ); if ( is_null( $instance ) ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_unsanitized' ); } if ( ! is_null( $parsed_id['number'] ) ) { $value = array(); $value[ $parsed_id['number'] ] = $instance; $key = 'widget-' . $parsed_id['id_base']; $_REQUEST[ $key ] = wp_slash( $value ); $_POST[ $key ] = $_REQUEST[ $key ]; $added_input_vars[] = $key; } else { foreach ( $instance as $key => $value ) { $_REQUEST[ $key ] = wp_slash( $value ); $_POST[ $key ] = $_REQUEST[ $key ]; $added_input_vars[] = $key; } } } // Invoke the widget update callback. foreach ( (array) $wp_registered_widget_updates as $name => $control ) { if ( $name === $parsed_id['id_base'] && is_callable( $control['callback'] ) ) { ob_start(); call_user_func_array( $control['callback'], $control['params'] ); ob_end_clean(); break; } } // Clean up any input vars that were manually added. foreach ( $added_input_vars as $key ) { unset( $_POST[ $key ] ); unset( $_REQUEST[ $key ] ); } // Make sure the expected option was updated. if ( 0 !== $this->count_captured_options() ) { if ( $this->count_captured_options() > 1 ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_too_many_options' ); } $updated_option_name = key( $this->get_captured_options() ); if ( $updated_option_name !== $option_name ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_unexpected_option' ); } } // Obtain the widget instance. $option = $this->get_captured_option( $option_name ); if ( null !== $parsed_id['number'] ) { $instance = $option[ $parsed_id['number'] ]; } else { $instance = $option; } /* * Override the incoming $_POST['customized'] for a newly-created widget's * setting with the new $instance so that the preview filter currently * in place from WP_Customize_Setting::preview() will use this value * instead of the default widget instance value (an empty array). */ $this->manager->set_post_value( $setting_id, $this->sanitize_widget_js_instance( $instance, $parsed_id['id_base'] ) ); // Obtain the widget control with the updated instance in place. ob_start(); $form = $wp_registered_widget_controls[ $widget_id ]; if ( $form ) { call_user_func_array( $form['callback'], $form['params'] ); } $form = ob_get_clean(); $this->stop_capturing_option_updates(); return compact( 'instance', 'form' ); } /** * Updates widget settings asynchronously. * * Allows the Customizer to update a widget using its form, but return the new * instance info via Ajax instead of saving it to the options table. * * Most code here copied from wp_ajax_save_widget(). * * @since 3.9.0 * * @see wp_ajax_save_widget() */ public function wp_ajax_update_widget() { if ( ! is_user_logged_in() ) { wp_die( 0 ); } check_ajax_referer( 'update-widget', 'nonce' ); if ( ! current_user_can( 'edit_theme_options' ) ) { wp_die( -1 ); } if ( empty( $_POST['widget-id'] ) ) { wp_send_json_error( 'missing_widget-id' ); } /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/widgets.php */ do_action( 'sidebar_admin_setup' ); $widget_id = $this->get_post_value( 'widget-id' ); $parsed_id = $this->parse_widget_id( $widget_id ); $id_base = $parsed_id['id_base']; $is_updating_widget_template = ( isset( $_POST[ 'widget-' . $id_base ] ) && is_array( $_POST[ 'widget-' . $id_base ] ) && preg_match( '/__i__|%i%/', key( $_POST[ 'widget-' . $id_base ] ) ) ); if ( $is_updating_widget_template ) { wp_send_json_error( 'template_widget_not_updatable' ); } $updated_widget = $this->call_widget_update( $widget_id ); // => {instance,form} if ( is_wp_error( $updated_widget ) ) { wp_send_json_error( $updated_widget->get_error_code() ); } $form = $updated_widget['form']; $instance = $this->sanitize_widget_js_instance( $updated_widget['instance'], $id_base ); wp_send_json_success( compact( 'form', 'instance' ) ); } /* * Selective Refresh Methods */ /** * Filters arguments for dynamic widget partials. * * @since 4.5.0 * * @param array|false $partial_args Partial arguments. * @param string $partial_id Partial ID. * @return array (Maybe) modified partial arguments. */ public function customize_dynamic_partial_args( $partial_args, $partial_id ) { if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return $partial_args; } if ( preg_match( '/^widget\[(?P<widget_id>.+)\]$/', $partial_id, $matches ) ) { if ( false === $partial_args ) { $partial_args = array(); } $partial_args = array_merge( $partial_args, array( 'type' => 'widget', 'render_callback' => array( $this, 'render_widget_partial' ), 'container_inclusive' => true, 'settings' => array( $this->get_setting_id( $matches['widget_id'] ) ), 'capability' => 'edit_theme_options', ) ); } return $partial_args; } /** * Adds hooks for selective refresh. * * @since 4.5.0 */ public function selective_refresh_init() { if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return; } add_filter( 'dynamic_sidebar_params', array( $this, 'filter_dynamic_sidebar_params' ) ); add_filter( 'wp_kses_allowed_html', array( $this, 'filter_wp_kses_allowed_data_attributes' ) ); add_action( 'dynamic_sidebar_before', array( $this, 'start_dynamic_sidebar' ) ); add_action( 'dynamic_sidebar_after', array( $this, 'end_dynamic_sidebar' ) ); } /** * Inject selective refresh data attributes into widget container elements. * * @since 4.5.0 * * @param array $params { * Dynamic sidebar params. * * @type array $args Sidebar args. * @type array $widget_args Widget args. * } * @see WP_Customize_Nav_Menus::filter_wp_nav_menu_args() * * @return array Params. */ public function filter_dynamic_sidebar_params( $params ) { $sidebar_args = array_merge( array( 'before_widget' => '', 'after_widget' => '', ), $params[0] ); // Skip widgets not in a registered sidebar or ones which lack a proper wrapper element to attach the data-* attributes to. $matches = array(); $is_valid = ( isset( $sidebar_args['id'] ) && is_registered_sidebar( $sidebar_args['id'] ) && ( isset( $this->current_dynamic_sidebar_id_stack[0] ) && $this->current_dynamic_sidebar_id_stack[0] === $sidebar_args['id'] ) && preg_match( '#^<(?P<tag_name>\w+)#', $sidebar_args['before_widget'], $matches ) ); if ( ! $is_valid ) { return $params; } $this->before_widget_tags_seen[ $matches['tag_name'] ] = true; $context = array( 'sidebar_id' => $sidebar_args['id'], ); if ( isset( $this->context_sidebar_instance_number ) ) { $context['sidebar_instance_number'] = $this->context_sidebar_instance_number; } elseif ( isset( $sidebar_args['id'] ) && isset( $this->sidebar_instance_count[ $sidebar_args['id'] ] ) ) { $context['sidebar_instance_number'] = $this->sidebar_instance_count[ $sidebar_args['id'] ]; } $attributes = sprintf( ' data-customize-partial-id="%s"', esc_attr( 'widget[' . $sidebar_args['widget_id'] . ']' ) ); $attributes .= ' data-customize-partial-type="widget"'; $attributes .= sprintf( ' data-customize-partial-placement-context="%s"', esc_attr( wp_json_encode( $context ) ) ); $attributes .= sprintf( ' data-customize-widget-id="%s"', esc_attr( $sidebar_args['widget_id'] ) ); $sidebar_args['before_widget'] = preg_replace( '#^(<\w+)#', '$1 ' . $attributes, $sidebar_args['before_widget'] ); $params[0] = $sidebar_args; return $params; } /** * List of the tag names seen for before_widget strings. * * This is used in the {@see 'filter_wp_kses_allowed_html'} filter to ensure that the * data-* attributes can be allowed. * * @since 4.5.0 * @var array */ protected $before_widget_tags_seen = array(); /** * Ensures the HTML data-* attributes for selective refresh are allowed by kses. * * This is needed in case the `$before_widget` is run through wp_kses() when printed. * * @since 4.5.0 * * @param array $allowed_html Allowed HTML. * @return array (Maybe) modified allowed HTML. */ public function filter_wp_kses_allowed_data_attributes( $allowed_html ) { foreach ( array_keys( $this->before_widget_tags_seen ) as $tag_name ) { if ( ! isset( $allowed_html[ $tag_name ] ) ) { $allowed_html[ $tag_name ] = array(); } $allowed_html[ $tag_name ] = array_merge( $allowed_html[ $tag_name ], array_fill_keys( array( 'data-customize-partial-id', 'data-customize-partial-type', 'data-customize-partial-placement-context', 'data-customize-partial-widget-id', 'data-customize-partial-options', ), true ) ); } return $allowed_html; } /** * Keep track of the number of times that dynamic_sidebar() was called for a given sidebar index. * * This helps facilitate the uncommon scenario where a single sidebar is rendered multiple times on a template. * * @since 4.5.0 * @var array */ protected $sidebar_instance_count = array(); /** * The current request's sidebar_instance_number context. * * @since 4.5.0 * @var int|null */ protected $context_sidebar_instance_number; /** * Current sidebar ID being rendered. * * @since 4.5.0 * @var array */ protected $current_dynamic_sidebar_id_stack = array(); /** * Begins keeping track of the current sidebar being rendered. * * Insert marker before widgets are rendered in a dynamic sidebar. * * @since 4.5.0 * * @param int|string $index Index, name, or ID of the dynamic sidebar. */ public function start_dynamic_sidebar( $index ) { array_unshift( $this->current_dynamic_sidebar_id_stack, $index ); if ( ! isset( $this->sidebar_instance_count[ $index ] ) ) { $this->sidebar_instance_count[ $index ] = 0; } $this->sidebar_instance_count[ $index ] += 1; if ( ! $this->manager->selective_refresh->is_render_partials_request() ) { printf( "\n<!--dynamic_sidebar_before:%s:%d-->\n", esc_html( $index ), (int) $this->sidebar_instance_count[ $index ] ); } } /** * Finishes keeping track of the current sidebar being rendered. * * Inserts a marker after widgets are rendered in a dynamic sidebar. * * @since 4.5.0 * * @param int|string $index Index, name, or ID of the dynamic sidebar. */ public function end_dynamic_sidebar( $index ) { array_shift( $this->current_dynamic_sidebar_id_stack ); if ( ! $this->manager->selective_refresh->is_render_partials_request() ) { printf( "\n<!--dynamic_sidebar_after:%s:%d-->\n", esc_html( $index ), (int) $this->sidebar_instance_count[ $index ] ); } } /** * Current sidebar being rendered. * * @since 4.5.0 * @var string|null */ protected $rendering_widget_id; /** * Current widget being rendered. * * @since 4.5.0 * @var string|null */ protected $rendering_sidebar_id; /** * Filters sidebars_widgets to ensure the currently-rendered widget is the only widget in the current sidebar. * * @since 4.5.0 * * @param array $sidebars_widgets Sidebars widgets. * @return array Filtered sidebars widgets. */ public function filter_sidebars_widgets_for_rendering_widget( $sidebars_widgets ) { $sidebars_widgets[ $this->rendering_sidebar_id ] = array( $this->rendering_widget_id ); return $sidebars_widgets; } /** * Renders a specific widget using the supplied sidebar arguments. * * @since 4.5.0 * * @see dynamic_sidebar() * * @param WP_Customize_Partial $partial Partial. * @param array $context { * Sidebar args supplied as container context. * * @type string $sidebar_id ID for sidebar for widget to render into. * @type int $sidebar_instance_number Disambiguating instance number. * } * @return string|false */ public function render_widget_partial( $partial, $context ) { $id_data = $partial->id_data(); $widget_id = array_shift( $id_data['keys'] ); if ( ! is_array( $context ) || empty( $context['sidebar_id'] ) || ! is_registered_sidebar( $context['sidebar_id'] ) ) { return false; } $this->rendering_sidebar_id = $context['sidebar_id']; if ( isset( $context['sidebar_instance_number'] ) ) { $this->context_sidebar_instance_number = (int) $context['sidebar_instance_number']; } // Filter sidebars_widgets so that only the queried widget is in the sidebar. $this->rendering_widget_id = $widget_id; $filter_callback = array( $this, 'filter_sidebars_widgets_for_rendering_widget' ); add_filter( 'sidebars_widgets', $filter_callback, 1000 ); // Render the widget. ob_start(); $this->rendering_sidebar_id = $context['sidebar_id']; dynamic_sidebar( $this->rendering_sidebar_id ); $container = ob_get_clean(); // Reset variables for next partial render. remove_filter( 'sidebars_widgets', $filter_callback, 1000 ); $this->context_sidebar_instance_number = null; $this->rendering_sidebar_id = null; $this->rendering_widget_id = null; return $container; } // // Option Update Capturing. // /** * List of captured widget option updates. * * @since 3.9.0 * @var array $_captured_options Values updated while option capture is happening. */ protected $_captured_options = array(); /** * Whether option capture is currently happening. * * @since 3.9.0 * @var bool $_is_current Whether option capture is currently happening or not. */ protected $_is_capturing_option_updates = false; /** * Determines whether the captured option update should be ignored. * * @since 3.9.0 * * @param string $option_name Option name. * @return bool Whether the option capture is ignored. */ protected function is_option_capture_ignored( $option_name ) { return ( 0 === strpos( $option_name, '_transient_' ) ); } /** * Retrieves captured widget option updates. * * @since 3.9.0 * * @return array Array of captured options. */ protected function get_captured_options() { return $this->_captured_options; } /** * Retrieves the option that was captured from being saved. * * @since 4.2.0 * * @param string $option_name Option name. * @param mixed $default_value Optional. Default value to return if the option does not exist. Default false. * @return mixed Value set for the option. */ protected function get_captured_option( $option_name, $default_value = false ) { if ( array_key_exists( $option_name, $this->_captured_options ) ) { $value = $this->_captured_options[ $option_name ]; } else { $value = $default_value; } return $value; } /** * Retrieves the number of captured widget option updates. * * @since 3.9.0 * * @return int Number of updated options. */ protected function count_captured_options() { return count( $this->_captured_options ); } /** * Begins keeping track of changes to widget options, caching new values. * * @since 3.9.0 */ protected function start_capturing_option_updates() { if ( $this->_is_capturing_option_updates ) { return; } $this->_is_capturing_option_updates = true; add_filter( 'pre_update_option', array( $this, 'capture_filter_pre_update_option' ), 10, 3 ); } /** * Pre-filters captured option values before updating. * * @since 3.9.0 * * @param mixed $new_value The new option value. * @param string $option_name Name of the option. * @param mixed $old_value The old option value. * @return mixed Filtered option value. */ public function capture_filter_pre_update_option( $new_value, $option_name, $old_value ) { if ( $this->is_option_capture_ignored( $option_name ) ) { return $new_value; } if ( ! isset( $this->_captured_options[ $option_name ] ) ) { add_filter( "pre_option_{$option_name}", array( $this, 'capture_filter_pre_get_option' ) ); } $this->_captured_options[ $option_name ] = $new_value; return $old_value; } /** * Pre-filters captured option values before retrieving. * * @since 3.9.0 * * @param mixed $value Value to return instead of the option value. * @return mixed Filtered option value. */ public function capture_filter_pre_get_option( $value ) { $option_name = preg_replace( '/^pre_option_/', '', current_filter() ); if ( isset( $this->_captured_options[ $option_name ] ) ) { $value = $this->_captured_options[ $option_name ]; /** This filter is documented in wp-includes/option.php */ $value = apply_filters( 'option_' . $option_name, $value, $option_name ); } return $value; } /** * Undoes any changes to the options since options capture began. * * @since 3.9.0 */ protected function stop_capturing_option_updates() { if ( ! $this->_is_capturing_option_updates ) { return; } remove_filter( 'pre_update_option', array( $this, 'capture_filter_pre_update_option' ), 10 ); foreach ( array_keys( $this->_captured_options ) as $option_name ) { remove_filter( "pre_option_{$option_name}", array( $this, 'capture_filter_pre_get_option' ) ); } $this->_captured_options = array(); $this->_is_capturing_option_updates = false; } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function setup_widget_addition_previews() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function prepreview_added_sidebars_widgets() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function prepreview_added_widget_instance() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function remove_prepreview_filters() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } } home/verseaumee/mymusicpromo/wp-includes/class-wp-customize-widgets.php 0000644 00000200330 15075057575 0022576 0 ustar 00 <?php /** * WordPress Customize Widgets classes * * @package WordPress * @subpackage Customize * @since 3.9.0 */ /** * Customize Widgets class. * * Implements widget management in the Customizer. * * @since 3.9.0 * * @see WP_Customize_Manager */ final class WP_Customize_Widgets { /** * WP_Customize_Manager instance. * * @since 3.9.0 * @var WP_Customize_Manager */ public $manager; /** * All id_bases for widgets defined in core. * * @since 3.9.0 * @var array */ protected $core_widget_id_bases = array( 'archives', 'calendar', 'categories', 'custom_html', 'links', 'media_audio', 'media_image', 'media_video', 'meta', 'nav_menu', 'pages', 'recent-comments', 'recent-posts', 'rss', 'search', 'tag_cloud', 'text', ); /** * @since 3.9.0 * @var array */ protected $rendered_sidebars = array(); /** * @since 3.9.0 * @var array */ protected $rendered_widgets = array(); /** * @since 3.9.0 * @var array */ protected $old_sidebars_widgets = array(); /** * Mapping of widget ID base to whether it supports selective refresh. * * @since 4.5.0 * @var array */ protected $selective_refreshable_widgets; /** * Mapping of setting type to setting ID pattern. * * @since 4.2.0 * @var array */ protected $setting_id_patterns = array( 'widget_instance' => '/^widget_(?P<id_base>.+?)(?:\[(?P<widget_number>\d+)\])?$/', 'sidebar_widgets' => '/^sidebars_widgets\[(?P<sidebar_id>.+?)\]$/', ); /** * Initial loader. * * @since 3.9.0 * * @param WP_Customize_Manager $manager Customize manager bootstrap instance. */ public function __construct( $manager ) { $this->manager = $manager; // See https://github.com/xwp/wp-customize-snapshots/blob/962586659688a5b1fd9ae93618b7ce2d4e7a421c/php/class-customize-snapshot-manager.php#L420-L449 add_filter( 'customize_dynamic_setting_args', array( $this, 'filter_customize_dynamic_setting_args' ), 10, 2 ); add_action( 'widgets_init', array( $this, 'register_settings' ), 95 ); add_action( 'customize_register', array( $this, 'schedule_customize_register' ), 1 ); // Skip remaining hooks when the user can't manage widgets anyway. if ( ! current_user_can( 'edit_theme_options' ) ) { return; } add_action( 'wp_loaded', array( $this, 'override_sidebars_widgets_for_theme_switch' ) ); add_action( 'customize_controls_init', array( $this, 'customize_controls_init' ) ); add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); add_action( 'customize_controls_print_styles', array( $this, 'print_styles' ) ); add_action( 'customize_controls_print_scripts', array( $this, 'print_scripts' ) ); add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_footer_scripts' ) ); add_action( 'customize_controls_print_footer_scripts', array( $this, 'output_widget_control_templates' ) ); add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) ); add_filter( 'customize_refresh_nonces', array( $this, 'refresh_nonces' ) ); add_action( 'dynamic_sidebar', array( $this, 'tally_rendered_widgets' ) ); add_filter( 'is_active_sidebar', array( $this, 'tally_sidebars_via_is_active_sidebar_calls' ), 10, 2 ); add_filter( 'dynamic_sidebar_has_widgets', array( $this, 'tally_sidebars_via_dynamic_sidebar_calls' ), 10, 2 ); // Selective Refresh. add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 ); add_action( 'customize_preview_init', array( $this, 'selective_refresh_init' ) ); } /** * List whether each registered widget can be use selective refresh. * * If the theme does not support the customize-selective-refresh-widgets feature, * then this will always return an empty array. * * @since 4.5.0 * * @global WP_Widget_Factory $wp_widget_factory * * @return array Mapping of id_base to support. If theme doesn't support * selective refresh, an empty array is returned. */ public function get_selective_refreshable_widgets() { global $wp_widget_factory; if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return array(); } if ( ! isset( $this->selective_refreshable_widgets ) ) { $this->selective_refreshable_widgets = array(); foreach ( $wp_widget_factory->widgets as $wp_widget ) { $this->selective_refreshable_widgets[ $wp_widget->id_base ] = ! empty( $wp_widget->widget_options['customize_selective_refresh'] ); } } return $this->selective_refreshable_widgets; } /** * Determines if a widget supports selective refresh. * * @since 4.5.0 * * @param string $id_base Widget ID Base. * @return bool Whether the widget can be selective refreshed. */ public function is_widget_selective_refreshable( $id_base ) { $selective_refreshable_widgets = $this->get_selective_refreshable_widgets(); return ! empty( $selective_refreshable_widgets[ $id_base ] ); } /** * Retrieves the widget setting type given a setting ID. * * @since 4.2.0 * * @staticvar array $cache * * @param string $setting_id Setting ID. * @return string|void Setting type. */ protected function get_setting_type( $setting_id ) { static $cache = array(); if ( isset( $cache[ $setting_id ] ) ) { return $cache[ $setting_id ]; } foreach ( $this->setting_id_patterns as $type => $pattern ) { if ( preg_match( $pattern, $setting_id ) ) { $cache[ $setting_id ] = $type; return $type; } } } /** * Inspects the incoming customized data for any widget settings, and dynamically adds * them up-front so widgets will be initialized properly. * * @since 4.2.0 */ public function register_settings() { $widget_setting_ids = array(); $incoming_setting_ids = array_keys( $this->manager->unsanitized_post_values() ); foreach ( $incoming_setting_ids as $setting_id ) { if ( ! is_null( $this->get_setting_type( $setting_id ) ) ) { $widget_setting_ids[] = $setting_id; } } if ( $this->manager->doing_ajax( 'update-widget' ) && isset( $_REQUEST['widget-id'] ) ) { $widget_setting_ids[] = $this->get_setting_id( wp_unslash( $_REQUEST['widget-id'] ) ); } $settings = $this->manager->add_dynamic_settings( array_unique( $widget_setting_ids ) ); if ( $this->manager->settings_previewed() ) { foreach ( $settings as $setting ) { $setting->preview(); } } } /** * Determines the arguments for a dynamically-created setting. * * @since 4.2.0 * * @param false|array $args The arguments to the WP_Customize_Setting constructor. * @param string $setting_id ID for dynamic setting, usually coming from `$_POST['customized']`. * @return false|array Setting arguments, false otherwise. */ public function filter_customize_dynamic_setting_args( $args, $setting_id ) { if ( $this->get_setting_type( $setting_id ) ) { $args = $this->get_setting_args( $setting_id ); } return $args; } /** * Retrieves an unslashed post value or return a default. * * @since 3.9.0 * * @param string $name Post value. * @param mixed $default Default post value. * @return mixed Unslashed post value or default value. */ protected function get_post_value( $name, $default = null ) { if ( ! isset( $_POST[ $name ] ) ) { return $default; } return wp_unslash( $_POST[ $name ] ); } /** * Override sidebars_widgets for theme switch. * * When switching a theme via the Customizer, supply any previously-configured * sidebars_widgets from the target theme as the initial sidebars_widgets * setting. Also store the old theme's existing settings so that they can * be passed along for storing in the sidebars_widgets theme_mod when the * theme gets switched. * * @since 3.9.0 * * @global array $sidebars_widgets * @global array $_wp_sidebars_widgets */ public function override_sidebars_widgets_for_theme_switch() { global $sidebars_widgets; if ( $this->manager->doing_ajax() || $this->manager->is_theme_active() ) { return; } $this->old_sidebars_widgets = wp_get_sidebars_widgets(); add_filter( 'customize_value_old_sidebars_widgets_data', array( $this, 'filter_customize_value_old_sidebars_widgets_data' ) ); $this->manager->set_post_value( 'old_sidebars_widgets_data', $this->old_sidebars_widgets ); // Override any value cached in changeset. // retrieve_widgets() looks at the global $sidebars_widgets $sidebars_widgets = $this->old_sidebars_widgets; $sidebars_widgets = retrieve_widgets( 'customize' ); add_filter( 'option_sidebars_widgets', array( $this, 'filter_option_sidebars_widgets_for_theme_switch' ), 1 ); // reset global cache var used by wp_get_sidebars_widgets() unset( $GLOBALS['_wp_sidebars_widgets'] ); } /** * Filters old_sidebars_widgets_data Customizer setting. * * When switching themes, filter the Customizer setting old_sidebars_widgets_data * to supply initial $sidebars_widgets before they were overridden by retrieve_widgets(). * The value for old_sidebars_widgets_data gets set in the old theme's sidebars_widgets * theme_mod. * * @since 3.9.0 * * @see WP_Customize_Widgets::handle_theme_switch() * * @param array $old_sidebars_widgets * @return array */ public function filter_customize_value_old_sidebars_widgets_data( $old_sidebars_widgets ) { return $this->old_sidebars_widgets; } /** * Filters sidebars_widgets option for theme switch. * * When switching themes, the retrieve_widgets() function is run when the Customizer initializes, * and then the new sidebars_widgets here get supplied as the default value for the sidebars_widgets * option. * * @since 3.9.0 * * @see WP_Customize_Widgets::handle_theme_switch() * @global array $sidebars_widgets * * @param array $sidebars_widgets * @return array */ public function filter_option_sidebars_widgets_for_theme_switch( $sidebars_widgets ) { $sidebars_widgets = $GLOBALS['sidebars_widgets']; $sidebars_widgets['array_version'] = 3; return $sidebars_widgets; } /** * Ensures all widgets get loaded into the Customizer. * * Note: these actions are also fired in wp_ajax_update_widget(). * * @since 3.9.0 */ public function customize_controls_init() { /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'load-widgets.php' ); /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'widgets.php' ); /** This action is documented in wp-admin/widgets.php */ do_action( 'sidebar_admin_setup' ); } /** * Ensures widgets are available for all types of previews. * * When in preview, hook to {@see 'customize_register'} for settings after WordPress is loaded * so that all filters have been initialized (e.g. Widget Visibility). * * @since 3.9.0 */ public function schedule_customize_register() { if ( is_admin() ) { $this->customize_register(); } else { add_action( 'wp', array( $this, 'customize_register' ) ); } } /** * Registers Customizer settings and controls for all sidebars and widgets. * * @since 3.9.0 * * @global array $wp_registered_widgets * @global array $wp_registered_widget_controls * @global array $wp_registered_sidebars */ public function customize_register() { global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_sidebars; add_filter( 'sidebars_widgets', array( $this, 'preview_sidebars_widgets' ), 1 ); $sidebars_widgets = array_merge( array( 'wp_inactive_widgets' => array() ), array_fill_keys( array_keys( $wp_registered_sidebars ), array() ), wp_get_sidebars_widgets() ); $new_setting_ids = array(); /* * Register a setting for all widgets, including those which are active, * inactive, and orphaned since a widget may get suppressed from a sidebar * via a plugin (like Widget Visibility). */ foreach ( array_keys( $wp_registered_widgets ) as $widget_id ) { $setting_id = $this->get_setting_id( $widget_id ); $setting_args = $this->get_setting_args( $setting_id ); if ( ! $this->manager->get_setting( $setting_id ) ) { $this->manager->add_setting( $setting_id, $setting_args ); } $new_setting_ids[] = $setting_id; } /* * Add a setting which will be supplied for the theme's sidebars_widgets * theme_mod when the theme is switched. */ if ( ! $this->manager->is_theme_active() ) { $setting_id = 'old_sidebars_widgets_data'; $setting_args = $this->get_setting_args( $setting_id, array( 'type' => 'global_variable', 'dirty' => true, ) ); $this->manager->add_setting( $setting_id, $setting_args ); } $this->manager->add_panel( 'widgets', array( 'type' => 'widgets', 'title' => __( 'Widgets' ), 'description' => __( 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).' ), 'priority' => 110, 'active_callback' => array( $this, 'is_panel_active' ), 'auto_expand_sole_section' => true, ) ); foreach ( $sidebars_widgets as $sidebar_id => $sidebar_widget_ids ) { if ( empty( $sidebar_widget_ids ) ) { $sidebar_widget_ids = array(); } $is_registered_sidebar = is_registered_sidebar( $sidebar_id ); $is_inactive_widgets = ( 'wp_inactive_widgets' === $sidebar_id ); $is_active_sidebar = ( $is_registered_sidebar && ! $is_inactive_widgets ); // Add setting for managing the sidebar's widgets. if ( $is_registered_sidebar || $is_inactive_widgets ) { $setting_id = sprintf( 'sidebars_widgets[%s]', $sidebar_id ); $setting_args = $this->get_setting_args( $setting_id ); if ( ! $this->manager->get_setting( $setting_id ) ) { if ( ! $this->manager->is_theme_active() ) { $setting_args['dirty'] = true; } $this->manager->add_setting( $setting_id, $setting_args ); } $new_setting_ids[] = $setting_id; // Add section to contain controls. $section_id = sprintf( 'sidebar-widgets-%s', $sidebar_id ); if ( $is_active_sidebar ) { $section_args = array( 'title' => $wp_registered_sidebars[ $sidebar_id ]['name'], 'description' => $wp_registered_sidebars[ $sidebar_id ]['description'], 'priority' => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ) ), 'panel' => 'widgets', 'sidebar_id' => $sidebar_id, ); /** * Filters Customizer widget section arguments for a given sidebar. * * @since 3.9.0 * * @param array $section_args Array of Customizer widget section arguments. * @param string $section_id Customizer section ID. * @param int|string $sidebar_id Sidebar ID. */ $section_args = apply_filters( 'customizer_widgets_section_args', $section_args, $section_id, $sidebar_id ); $section = new WP_Customize_Sidebar_Section( $this->manager, $section_id, $section_args ); $this->manager->add_section( $section ); $control = new WP_Widget_Area_Customize_Control( $this->manager, $setting_id, array( 'section' => $section_id, 'sidebar_id' => $sidebar_id, 'priority' => count( $sidebar_widget_ids ), // place 'Add Widget' and 'Reorder' buttons at end. ) ); $new_setting_ids[] = $setting_id; $this->manager->add_control( $control ); } } // Add a control for each active widget (located in a sidebar). foreach ( $sidebar_widget_ids as $i => $widget_id ) { // Skip widgets that may have gone away due to a plugin being deactivated. if ( ! $is_active_sidebar || ! isset( $wp_registered_widgets[$widget_id] ) ) { continue; } $registered_widget = $wp_registered_widgets[$widget_id]; $setting_id = $this->get_setting_id( $widget_id ); $id_base = $wp_registered_widget_controls[$widget_id]['id_base']; $control = new WP_Widget_Form_Customize_Control( $this->manager, $setting_id, array( 'label' => $registered_widget['name'], 'section' => $section_id, 'sidebar_id' => $sidebar_id, 'widget_id' => $widget_id, 'widget_id_base' => $id_base, 'priority' => $i, 'width' => $wp_registered_widget_controls[$widget_id]['width'], 'height' => $wp_registered_widget_controls[$widget_id]['height'], 'is_wide' => $this->is_wide_widget( $widget_id ), ) ); $this->manager->add_control( $control ); } } if ( $this->manager->settings_previewed() ) { foreach ( $new_setting_ids as $new_setting_id ) { $this->manager->get_setting( $new_setting_id )->preview(); } } } /** * Determines whether the widgets panel is active, based on whether there are sidebars registered. * * @since 4.4.0 * * @see WP_Customize_Panel::$active_callback * * @global array $wp_registered_sidebars * @return bool Active. */ public function is_panel_active() { global $wp_registered_sidebars; return ! empty( $wp_registered_sidebars ); } /** * Converts a widget_id into its corresponding Customizer setting ID (option name). * * @since 3.9.0 * * @param string $widget_id Widget ID. * @return string Maybe-parsed widget ID. */ public function get_setting_id( $widget_id ) { $parsed_widget_id = $this->parse_widget_id( $widget_id ); $setting_id = sprintf( 'widget_%s', $parsed_widget_id['id_base'] ); if ( ! is_null( $parsed_widget_id['number'] ) ) { $setting_id .= sprintf( '[%d]', $parsed_widget_id['number'] ); } return $setting_id; } /** * Determines whether the widget is considered "wide". * * Core widgets which may have controls wider than 250, but can still be shown * in the narrow Customizer panel. The RSS and Text widgets in Core, for example, * have widths of 400 and yet they still render fine in the Customizer panel. * * This method will return all Core widgets as being not wide, but this can be * overridden with the {@see 'is_wide_widget_in_customizer'} filter. * * @since 3.9.0 * * @global $wp_registered_widget_controls * * @param string $widget_id Widget ID. * @return bool Whether or not the widget is a "wide" widget. */ public function is_wide_widget( $widget_id ) { global $wp_registered_widget_controls; $parsed_widget_id = $this->parse_widget_id( $widget_id ); $width = $wp_registered_widget_controls[$widget_id]['width']; $is_core = in_array( $parsed_widget_id['id_base'], $this->core_widget_id_bases ); $is_wide = ( $width > 250 && ! $is_core ); /** * Filters whether the given widget is considered "wide". * * @since 3.9.0 * * @param bool $is_wide Whether the widget is wide, Default false. * @param string $widget_id Widget ID. */ return apply_filters( 'is_wide_widget_in_customizer', $is_wide, $widget_id ); } /** * Converts a widget ID into its id_base and number components. * * @since 3.9.0 * * @param string $widget_id Widget ID. * @return array Array containing a widget's id_base and number components. */ public function parse_widget_id( $widget_id ) { $parsed = array( 'number' => null, 'id_base' => null, ); if ( preg_match( '/^(.+)-(\d+)$/', $widget_id, $matches ) ) { $parsed['id_base'] = $matches[1]; $parsed['number'] = intval( $matches[2] ); } else { // likely an old single widget $parsed['id_base'] = $widget_id; } return $parsed; } /** * Converts a widget setting ID (option path) to its id_base and number components. * * @since 3.9.0 * * @param string $setting_id Widget setting ID. * @return WP_Error|array Array containing a widget's id_base and number components, * or a WP_Error object. */ public function parse_widget_setting_id( $setting_id ) { if ( ! preg_match( '/^(widget_(.+?))(?:\[(\d+)\])?$/', $setting_id, $matches ) ) { return new WP_Error( 'widget_setting_invalid_id' ); } $id_base = $matches[2]; $number = isset( $matches[3] ) ? intval( $matches[3] ) : null; return compact( 'id_base', 'number' ); } /** * Calls admin_print_styles-widgets.php and admin_print_styles hooks to * allow custom styles from plugins. * * @since 3.9.0 */ public function print_styles() { /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_styles-widgets.php' ); /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_styles' ); } /** * Calls admin_print_scripts-widgets.php and admin_print_scripts hooks to * allow custom scripts from plugins. * * @since 3.9.0 */ public function print_scripts() { /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_scripts-widgets.php' ); /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_scripts' ); } /** * Enqueues scripts and styles for Customizer panel and export data to JavaScript. * * @since 3.9.0 * * @global WP_Scripts $wp_scripts * @global array $wp_registered_sidebars * @global array $wp_registered_widgets */ public function enqueue_scripts() { global $wp_scripts, $wp_registered_sidebars, $wp_registered_widgets; wp_enqueue_style( 'customize-widgets' ); wp_enqueue_script( 'customize-widgets' ); /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_enqueue_scripts', 'widgets.php' ); /* * Export available widgets with control_tpl removed from model * since plugins need templates to be in the DOM. */ $available_widgets = array(); foreach ( $this->get_available_widgets() as $available_widget ) { unset( $available_widget['control_tpl'] ); $available_widgets[] = $available_widget; } $widget_reorder_nav_tpl = sprintf( '<div class="widget-reorder-nav"><span class="move-widget" tabindex="0">%1$s</span><span class="move-widget-down" tabindex="0">%2$s</span><span class="move-widget-up" tabindex="0">%3$s</span></div>', __( 'Move to another area…' ), __( 'Move down' ), __( 'Move up' ) ); $move_widget_area_tpl = str_replace( array( '{description}', '{btn}' ), array( __( 'Select an area to move this widget into:' ), _x( 'Move', 'Move widget' ), ), '<div class="move-widget-area"> <p class="description">{description}</p> <ul class="widget-area-select"> <% _.each( sidebars, function ( sidebar ){ %> <li class="" data-id="<%- sidebar.id %>" title="<%- sidebar.description %>" tabindex="0"><%- sidebar.name %></li> <% }); %> </ul> <div class="move-widget-actions"> <button class="move-widget-btn button" type="button">{btn}</button> </div> </div>' ); /* * Gather all strings in PHP that may be needed by JS on the client. * Once JS i18n is implemented (in #20491), this can be removed. */ $some_non_rendered_areas_messages = array(); $some_non_rendered_areas_messages[1] = html_entity_decode( __( 'Your theme has 1 other widget area, but this particular page doesn’t display it.' ), ENT_QUOTES, get_bloginfo( 'charset' ) ); $registered_sidebar_count = count( $wp_registered_sidebars ); for ( $non_rendered_count = 2; $non_rendered_count < $registered_sidebar_count; $non_rendered_count++ ) { $some_non_rendered_areas_messages[ $non_rendered_count ] = html_entity_decode( sprintf( /* translators: %s: the number of other widget areas registered but not rendered */ _n( 'Your theme has %s other widget area, but this particular page doesn’t display it.', 'Your theme has %s other widget areas, but this particular page doesn’t display them.', $non_rendered_count ), number_format_i18n( $non_rendered_count ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } if ( 1 === $registered_sidebar_count ) { $no_areas_shown_message = html_entity_decode( sprintf( __( 'Your theme has 1 widget area, but this particular page doesn’t display it.' ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } else { $no_areas_shown_message = html_entity_decode( sprintf( /* translators: %s: the total number of widget areas registered */ _n( 'Your theme has %s widget area, but this particular page doesn’t display it.', 'Your theme has %s widget areas, but this particular page doesn’t display them.', $registered_sidebar_count ), number_format_i18n( $registered_sidebar_count ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } $settings = array( 'registeredSidebars' => array_values( $wp_registered_sidebars ), 'registeredWidgets' => $wp_registered_widgets, 'availableWidgets' => $available_widgets, // @todo Merge this with registered_widgets 'l10n' => array( 'saveBtnLabel' => __( 'Apply' ), 'saveBtnTooltip' => __( 'Save and preview changes before publishing them.' ), 'removeBtnLabel' => __( 'Remove' ), 'removeBtnTooltip' => __( 'Trash widget by moving it to the inactive widgets sidebar.' ), 'error' => __( 'An error has occurred. Please reload the page and try again.' ), 'widgetMovedUp' => __( 'Widget moved up' ), 'widgetMovedDown' => __( 'Widget moved down' ), 'navigatePreview' => __( 'You can navigate to other pages on your site while using the Customizer to view and edit the widgets displayed on those pages.' ), 'someAreasShown' => $some_non_rendered_areas_messages, 'noAreasShown' => $no_areas_shown_message, 'reorderModeOn' => __( 'Reorder mode enabled' ), 'reorderModeOff' => __( 'Reorder mode closed' ), 'reorderLabelOn' => esc_attr__( 'Reorder widgets' ), /* translators: %d: the number of widgets found */ 'widgetsFound' => __( 'Number of widgets found: %d' ), 'noWidgetsFound' => __( 'No widgets found.' ), ), 'tpl' => array( 'widgetReorderNav' => $widget_reorder_nav_tpl, 'moveWidgetArea' => $move_widget_area_tpl, ), 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), ); foreach ( $settings['registeredWidgets'] as &$registered_widget ) { unset( $registered_widget['callback'] ); // may not be JSON-serializeable } $wp_scripts->add_data( 'customize-widgets', 'data', sprintf( 'var _wpCustomizeWidgetsSettings = %s;', wp_json_encode( $settings ) ) ); } /** * Renders the widget form control templates into the DOM. * * @since 3.9.0 */ public function output_widget_control_templates() { ?> <div id="widgets-left"><!-- compatibility with JS which looks for widget templates here --> <div id="available-widgets"> <div class="customize-section-title"> <button class="customize-section-back" tabindex="-1"> <span class="screen-reader-text"><?php _e( 'Back' ); ?></span> </button> <h3> <span class="customize-action"><?php /* translators: ▸ is the unicode right-pointing triangle, and %s is the section title in the Customizer */ echo sprintf( __( 'Customizing ▸ %s' ), esc_html( $this->manager->get_panel( 'widgets' )->title ) ); ?></span> <?php _e( 'Add a Widget' ); ?> </h3> </div> <div id="available-widgets-filter"> <label class="screen-reader-text" for="widgets-search"><?php _e( 'Search Widgets' ); ?></label> <input type="text" id="widgets-search" placeholder="<?php esc_attr_e( 'Search widgets…' ) ?>" aria-describedby="widgets-search-desc" /> <div class="search-icon" aria-hidden="true"></div> <button type="button" class="clear-results"><span class="screen-reader-text"><?php _e( 'Clear Results' ); ?></span></button> <p class="screen-reader-text" id="widgets-search-desc"><?php _e( 'The search results will be updated as you type.' ); ?></p> </div> <div id="available-widgets-list"> <?php foreach ( $this->get_available_widgets() as $available_widget ): ?> <div id="widget-tpl-<?php echo esc_attr( $available_widget['id'] ) ?>" data-widget-id="<?php echo esc_attr( $available_widget['id'] ) ?>" class="widget-tpl <?php echo esc_attr( $available_widget['id'] ) ?>" tabindex="0"> <?php echo $available_widget['control_tpl']; ?> </div> <?php endforeach; ?> <p class="no-widgets-found-message"><?php _e( 'No widgets found.' ); ?></p> </div><!-- #available-widgets-list --> </div><!-- #available-widgets --> </div><!-- #widgets-left --> <?php } /** * Calls admin_print_footer_scripts and admin_print_scripts hooks to * allow custom scripts from plugins. * * @since 3.9.0 */ public function print_footer_scripts() { /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_print_footer_scripts-widgets.php' ); /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_print_footer_scripts' ); /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_footer-widgets.php' ); } /** * Retrieves common arguments to supply when constructing a Customizer setting. * * @since 3.9.0 * * @param string $id Widget setting ID. * @param array $overrides Array of setting overrides. * @return array Possibly modified setting arguments. */ public function get_setting_args( $id, $overrides = array() ) { $args = array( 'type' => 'option', 'capability' => 'edit_theme_options', 'default' => array(), ); if ( preg_match( $this->setting_id_patterns['sidebar_widgets'], $id, $matches ) ) { $args['sanitize_callback'] = array( $this, 'sanitize_sidebar_widgets' ); $args['sanitize_js_callback'] = array( $this, 'sanitize_sidebar_widgets_js_instance' ); $args['transport'] = current_theme_supports( 'customize-selective-refresh-widgets' ) ? 'postMessage' : 'refresh'; } elseif ( preg_match( $this->setting_id_patterns['widget_instance'], $id, $matches ) ) { $args['sanitize_callback'] = array( $this, 'sanitize_widget_instance' ); $args['sanitize_js_callback'] = array( $this, 'sanitize_widget_js_instance' ); $args['transport'] = $this->is_widget_selective_refreshable( $matches['id_base'] ) ? 'postMessage' : 'refresh'; } $args = array_merge( $args, $overrides ); /** * Filters the common arguments supplied when constructing a Customizer setting. * * @since 3.9.0 * * @see WP_Customize_Setting * * @param array $args Array of Customizer setting arguments. * @param string $id Widget setting ID. */ return apply_filters( 'widget_customizer_setting_args', $args, $id ); } /** * Ensures sidebar widget arrays only ever contain widget IDS. * * Used as the 'sanitize_callback' for each $sidebars_widgets setting. * * @since 3.9.0 * * @param array $widget_ids Array of widget IDs. * @return array Array of sanitized widget IDs. */ public function sanitize_sidebar_widgets( $widget_ids ) { $widget_ids = array_map( 'strval', (array) $widget_ids ); $sanitized_widget_ids = array(); foreach ( $widget_ids as $widget_id ) { $sanitized_widget_ids[] = preg_replace( '/[^a-z0-9_\-]/', '', $widget_id ); } return $sanitized_widget_ids; } /** * Builds up an index of all available widgets for use in Backbone models. * * @since 3.9.0 * * @global array $wp_registered_widgets * @global array $wp_registered_widget_controls * @staticvar array $available_widgets * * @see wp_list_widgets() * * @return array List of available widgets. */ public function get_available_widgets() { static $available_widgets = array(); if ( ! empty( $available_widgets ) ) { return $available_widgets; } global $wp_registered_widgets, $wp_registered_widget_controls; require_once ABSPATH . '/wp-admin/includes/widgets.php'; // for next_widget_id_number() $sort = $wp_registered_widgets; usort( $sort, array( $this, '_sort_name_callback' ) ); $done = array(); foreach ( $sort as $widget ) { if ( in_array( $widget['callback'], $done, true ) ) { // We already showed this multi-widget continue; } $sidebar = is_active_widget( $widget['callback'], $widget['id'], false, false ); $done[] = $widget['callback']; if ( ! isset( $widget['params'][0] ) ) { $widget['params'][0] = array(); } $available_widget = $widget; unset( $available_widget['callback'] ); // not serializable to JSON $args = array( 'widget_id' => $widget['id'], 'widget_name' => $widget['name'], '_display' => 'template', ); $is_disabled = false; $is_multi_widget = ( isset( $wp_registered_widget_controls[$widget['id']]['id_base'] ) && isset( $widget['params'][0]['number'] ) ); if ( $is_multi_widget ) { $id_base = $wp_registered_widget_controls[$widget['id']]['id_base']; $args['_temp_id'] = "$id_base-__i__"; $args['_multi_num'] = next_widget_id_number( $id_base ); $args['_add'] = 'multi'; } else { $args['_add'] = 'single'; if ( $sidebar && 'wp_inactive_widgets' !== $sidebar ) { $is_disabled = true; } $id_base = $widget['id']; } $list_widget_controls_args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0] ) ); $control_tpl = $this->get_widget_control( $list_widget_controls_args ); // The properties here are mapped to the Backbone Widget model. $available_widget = array_merge( $available_widget, array( 'temp_id' => isset( $args['_temp_id'] ) ? $args['_temp_id'] : null, 'is_multi' => $is_multi_widget, 'control_tpl' => $control_tpl, 'multi_number' => ( $args['_add'] === 'multi' ) ? $args['_multi_num'] : false, 'is_disabled' => $is_disabled, 'id_base' => $id_base, 'transport' => $this->is_widget_selective_refreshable( $id_base ) ? 'postMessage' : 'refresh', 'width' => $wp_registered_widget_controls[$widget['id']]['width'], 'height' => $wp_registered_widget_controls[$widget['id']]['height'], 'is_wide' => $this->is_wide_widget( $widget['id'] ), ) ); $available_widgets[] = $available_widget; } return $available_widgets; } /** * Naturally orders available widgets by name. * * @since 3.9.0 * * @param array $widget_a The first widget to compare. * @param array $widget_b The second widget to compare. * @return int Reorder position for the current widget comparison. */ protected function _sort_name_callback( $widget_a, $widget_b ) { return strnatcasecmp( $widget_a['name'], $widget_b['name'] ); } /** * Retrieves the widget control markup. * * @since 3.9.0 * * @param array $args Widget control arguments. * @return string Widget control form HTML markup. */ public function get_widget_control( $args ) { $args[0]['before_form'] = '<div class="form">'; $args[0]['after_form'] = '</div><!-- .form -->'; $args[0]['before_widget_content'] = '<div class="widget-content">'; $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; ob_start(); call_user_func_array( 'wp_widget_control', $args ); $control_tpl = ob_get_clean(); return $control_tpl; } /** * Retrieves the widget control markup parts. * * @since 4.4.0 * * @param array $args Widget control arguments. * @return array { * @type string $control Markup for widget control wrapping form. * @type string $content The contents of the widget form itself. * } */ public function get_widget_control_parts( $args ) { $args[0]['before_widget_content'] = '<div class="widget-content">'; $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; $control_markup = $this->get_widget_control( $args ); $content_start_pos = strpos( $control_markup, $args[0]['before_widget_content'] ); $content_end_pos = strrpos( $control_markup, $args[0]['after_widget_content'] ); $control = substr( $control_markup, 0, $content_start_pos + strlen( $args[0]['before_widget_content'] ) ); $control .= substr( $control_markup, $content_end_pos ); $content = trim( substr( $control_markup, $content_start_pos + strlen( $args[0]['before_widget_content'] ), $content_end_pos - $content_start_pos - strlen( $args[0]['before_widget_content'] ) ) ); return compact( 'control', 'content' ); } /** * Adds hooks for the Customizer preview. * * @since 3.9.0 */ public function customize_preview_init() { add_action( 'wp_enqueue_scripts', array( $this, 'customize_preview_enqueue' ) ); add_action( 'wp_print_styles', array( $this, 'print_preview_css' ), 1 ); add_action( 'wp_footer', array( $this, 'export_preview_data' ), 20 ); } /** * Refreshes the nonce for widget updates. * * @since 4.2.0 * * @param array $nonces Array of nonces. * @return array $nonces Array of nonces. */ public function refresh_nonces( $nonces ) { $nonces['update-widget'] = wp_create_nonce( 'update-widget' ); return $nonces; } /** * When previewing, ensures the proper previewing widgets are used. * * Because wp_get_sidebars_widgets() gets called early at {@see 'init' } (via * wp_convert_widget_settings()) and can set global variable `$_wp_sidebars_widgets` * to the value of `get_option( 'sidebars_widgets' )` before the Customizer preview * filter is added, it has to be reset after the filter has been added. * * @since 3.9.0 * * @param array $sidebars_widgets List of widgets for the current sidebar. * @return array */ public function preview_sidebars_widgets( $sidebars_widgets ) { $sidebars_widgets = get_option( 'sidebars_widgets', array() ); unset( $sidebars_widgets['array_version'] ); return $sidebars_widgets; } /** * Enqueues scripts for the Customizer preview. * * @since 3.9.0 */ public function customize_preview_enqueue() { wp_enqueue_script( 'customize-preview-widgets' ); } /** * Inserts default style for highlighted widget at early point so theme * stylesheet can override. * * @since 3.9.0 */ public function print_preview_css() { ?> <style> .widget-customizer-highlighted-widget { outline: none; -webkit-box-shadow: 0 0 2px rgba(30,140,190,0.8); box-shadow: 0 0 2px rgba(30,140,190,0.8); position: relative; z-index: 1; } </style> <?php } /** * Communicates the sidebars that appeared on the page at the very end of the page, * and at the very end of the wp_footer, * * @since 3.9.0 * * @global array $wp_registered_sidebars * @global array $wp_registered_widgets */ public function export_preview_data() { global $wp_registered_sidebars, $wp_registered_widgets; $switched_locale = switch_to_locale( get_user_locale() ); $l10n = array( 'widgetTooltip' => __( 'Shift-click to edit this widget.' ), ); if ( $switched_locale ) { restore_previous_locale(); } // Prepare Customizer settings to pass to JavaScript. $settings = array( 'renderedSidebars' => array_fill_keys( array_unique( $this->rendered_sidebars ), true ), 'renderedWidgets' => array_fill_keys( array_keys( $this->rendered_widgets ), true ), 'registeredSidebars' => array_values( $wp_registered_sidebars ), 'registeredWidgets' => $wp_registered_widgets, 'l10n' => $l10n, 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), ); foreach ( $settings['registeredWidgets'] as &$registered_widget ) { unset( $registered_widget['callback'] ); // may not be JSON-serializeable } ?> <script type="text/javascript"> var _wpWidgetCustomizerPreviewSettings = <?php echo wp_json_encode( $settings ); ?>; </script> <?php } /** * Tracks the widgets that were rendered. * * @since 3.9.0 * * @param array $widget Rendered widget to tally. */ public function tally_rendered_widgets( $widget ) { $this->rendered_widgets[ $widget['id'] ] = true; } /** * Determine if a widget is rendered on the page. * * @since 4.0.0 * * @param string $widget_id Widget ID to check. * @return bool Whether the widget is rendered. */ public function is_widget_rendered( $widget_id ) { return in_array( $widget_id, $this->rendered_widgets ); } /** * Determines if a sidebar is rendered on the page. * * @since 4.0.0 * * @param string $sidebar_id Sidebar ID to check. * @return bool Whether the sidebar is rendered. */ public function is_sidebar_rendered( $sidebar_id ) { return in_array( $sidebar_id, $this->rendered_sidebars ); } /** * Tallies the sidebars rendered via is_active_sidebar(). * * Keep track of the times that is_active_sidebar() is called in the template, * and assume that this means that the sidebar would be rendered on the template * if there were widgets populating it. * * @since 3.9.0 * * @param bool $is_active Whether the sidebar is active. * @param string $sidebar_id Sidebar ID. * @return bool Whether the sidebar is active. */ public function tally_sidebars_via_is_active_sidebar_calls( $is_active, $sidebar_id ) { if ( is_registered_sidebar( $sidebar_id ) ) { $this->rendered_sidebars[] = $sidebar_id; } /* * We may need to force this to true, and also force-true the value * for 'dynamic_sidebar_has_widgets' if we want to ensure that there * is an area to drop widgets into, if the sidebar is empty. */ return $is_active; } /** * Tallies the sidebars rendered via dynamic_sidebar(). * * Keep track of the times that dynamic_sidebar() is called in the template, * and assume this means the sidebar would be rendered on the template if * there were widgets populating it. * * @since 3.9.0 * * @param bool $has_widgets Whether the current sidebar has widgets. * @param string $sidebar_id Sidebar ID. * @return bool Whether the current sidebar has widgets. */ public function tally_sidebars_via_dynamic_sidebar_calls( $has_widgets, $sidebar_id ) { if ( is_registered_sidebar( $sidebar_id ) ) { $this->rendered_sidebars[] = $sidebar_id; } /* * We may need to force this to true, and also force-true the value * for 'is_active_sidebar' if we want to ensure there is an area to * drop widgets into, if the sidebar is empty. */ return $has_widgets; } /** * Retrieves MAC for a serialized widget instance string. * * Allows values posted back from JS to be rejected if any tampering of the * data has occurred. * * @since 3.9.0 * * @param string $serialized_instance Widget instance. * @return string MAC for serialized widget instance. */ protected function get_instance_hash_key( $serialized_instance ) { return wp_hash( $serialized_instance ); } /** * Sanitizes a widget instance. * * Unserialize the JS-instance for storing in the options. It's important that this filter * only get applied to an instance *once*. * * @since 3.9.0 * * @param array $value Widget instance to sanitize. * @return array|void Sanitized widget instance. */ public function sanitize_widget_instance( $value ) { if ( $value === array() ) { return $value; } if ( empty( $value['is_widget_customizer_js_value'] ) || empty( $value['instance_hash_key'] ) || empty( $value['encoded_serialized_instance'] ) ) { return; } $decoded = base64_decode( $value['encoded_serialized_instance'], true ); if ( false === $decoded ) { return; } if ( ! hash_equals( $this->get_instance_hash_key( $decoded ), $value['instance_hash_key'] ) ) { return; } $instance = unserialize( $decoded ); if ( false === $instance ) { return; } return $instance; } /** * Converts a widget instance into JSON-representable format. * * @since 3.9.0 * * @param array $value Widget instance to convert to JSON. * @return array JSON-converted widget instance. */ public function sanitize_widget_js_instance( $value ) { if ( empty( $value['is_widget_customizer_js_value'] ) ) { $serialized = serialize( $value ); $value = array( 'encoded_serialized_instance' => base64_encode( $serialized ), 'title' => empty( $value['title'] ) ? '' : $value['title'], 'is_widget_customizer_js_value' => true, 'instance_hash_key' => $this->get_instance_hash_key( $serialized ), ); } return $value; } /** * Strips out widget IDs for widgets which are no longer registered. * * One example where this might happen is when a plugin orphans a widget * in a sidebar upon deactivation. * * @since 3.9.0 * * @global array $wp_registered_widgets * * @param array $widget_ids List of widget IDs. * @return array Parsed list of widget IDs. */ public function sanitize_sidebar_widgets_js_instance( $widget_ids ) { global $wp_registered_widgets; $widget_ids = array_values( array_intersect( $widget_ids, array_keys( $wp_registered_widgets ) ) ); return $widget_ids; } /** * Finds and invokes the widget update and control callbacks. * * Requires that `$_POST` be populated with the instance data. * * @since 3.9.0 * * @global array $wp_registered_widget_updates * @global array $wp_registered_widget_controls * * @param string $widget_id Widget ID. * @return WP_Error|array Array containing the updated widget information. * A WP_Error object, otherwise. */ public function call_widget_update( $widget_id ) { global $wp_registered_widget_updates, $wp_registered_widget_controls; $setting_id = $this->get_setting_id( $widget_id ); /* * Make sure that other setting changes have previewed since this widget * may depend on them (e.g. Menus being present for Navigation Menu widget). */ if ( ! did_action( 'customize_preview_init' ) ) { foreach ( $this->manager->settings() as $setting ) { if ( $setting->id !== $setting_id ) { $setting->preview(); } } } $this->start_capturing_option_updates(); $parsed_id = $this->parse_widget_id( $widget_id ); $option_name = 'widget_' . $parsed_id['id_base']; /* * If a previously-sanitized instance is provided, populate the input vars * with its values so that the widget update callback will read this instance */ $added_input_vars = array(); if ( ! empty( $_POST['sanitized_widget_setting'] ) ) { $sanitized_widget_setting = json_decode( $this->get_post_value( 'sanitized_widget_setting' ), true ); if ( false === $sanitized_widget_setting ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_malformed' ); } $instance = $this->sanitize_widget_instance( $sanitized_widget_setting ); if ( is_null( $instance ) ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_unsanitized' ); } if ( ! is_null( $parsed_id['number'] ) ) { $value = array(); $value[$parsed_id['number']] = $instance; $key = 'widget-' . $parsed_id['id_base']; $_REQUEST[$key] = $_POST[$key] = wp_slash( $value ); $added_input_vars[] = $key; } else { foreach ( $instance as $key => $value ) { $_REQUEST[$key] = $_POST[$key] = wp_slash( $value ); $added_input_vars[] = $key; } } } // Invoke the widget update callback. foreach ( (array) $wp_registered_widget_updates as $name => $control ) { if ( $name === $parsed_id['id_base'] && is_callable( $control['callback'] ) ) { ob_start(); call_user_func_array( $control['callback'], $control['params'] ); ob_end_clean(); break; } } // Clean up any input vars that were manually added foreach ( $added_input_vars as $key ) { unset( $_POST[ $key ] ); unset( $_REQUEST[ $key ] ); } // Make sure the expected option was updated. if ( 0 !== $this->count_captured_options() ) { if ( $this->count_captured_options() > 1 ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_too_many_options' ); } $updated_option_name = key( $this->get_captured_options() ); if ( $updated_option_name !== $option_name ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_unexpected_option' ); } } // Obtain the widget instance. $option = $this->get_captured_option( $option_name ); if ( null !== $parsed_id['number'] ) { $instance = $option[ $parsed_id['number'] ]; } else { $instance = $option; } /* * Override the incoming $_POST['customized'] for a newly-created widget's * setting with the new $instance so that the preview filter currently * in place from WP_Customize_Setting::preview() will use this value * instead of the default widget instance value (an empty array). */ $this->manager->set_post_value( $setting_id, $this->sanitize_widget_js_instance( $instance ) ); // Obtain the widget control with the updated instance in place. ob_start(); $form = $wp_registered_widget_controls[ $widget_id ]; if ( $form ) { call_user_func_array( $form['callback'], $form['params'] ); } $form = ob_get_clean(); $this->stop_capturing_option_updates(); return compact( 'instance', 'form' ); } /** * Updates widget settings asynchronously. * * Allows the Customizer to update a widget using its form, but return the new * instance info via Ajax instead of saving it to the options table. * * Most code here copied from wp_ajax_save_widget(). * * @since 3.9.0 * * @see wp_ajax_save_widget() */ public function wp_ajax_update_widget() { if ( ! is_user_logged_in() ) { wp_die( 0 ); } check_ajax_referer( 'update-widget', 'nonce' ); if ( ! current_user_can( 'edit_theme_options' ) ) { wp_die( -1 ); } if ( empty( $_POST['widget-id'] ) ) { wp_send_json_error( 'missing_widget-id' ); } /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'load-widgets.php' ); /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'widgets.php' ); /** This action is documented in wp-admin/widgets.php */ do_action( 'sidebar_admin_setup' ); $widget_id = $this->get_post_value( 'widget-id' ); $parsed_id = $this->parse_widget_id( $widget_id ); $id_base = $parsed_id['id_base']; $is_updating_widget_template = ( isset( $_POST[ 'widget-' . $id_base ] ) && is_array( $_POST[ 'widget-' . $id_base ] ) && preg_match( '/__i__|%i%/', key( $_POST[ 'widget-' . $id_base ] ) ) ); if ( $is_updating_widget_template ) { wp_send_json_error( 'template_widget_not_updatable' ); } $updated_widget = $this->call_widget_update( $widget_id ); // => {instance,form} if ( is_wp_error( $updated_widget ) ) { wp_send_json_error( $updated_widget->get_error_code() ); } $form = $updated_widget['form']; $instance = $this->sanitize_widget_js_instance( $updated_widget['instance'] ); wp_send_json_success( compact( 'form', 'instance' ) ); } /* * Selective Refresh Methods */ /** * Filters arguments for dynamic widget partials. * * @since 4.5.0 * * @param array|false $partial_args Partial arguments. * @param string $partial_id Partial ID. * @return array (Maybe) modified partial arguments. */ public function customize_dynamic_partial_args( $partial_args, $partial_id ) { if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return $partial_args; } if ( preg_match( '/^widget\[(?P<widget_id>.+)\]$/', $partial_id, $matches ) ) { if ( false === $partial_args ) { $partial_args = array(); } $partial_args = array_merge( $partial_args, array( 'type' => 'widget', 'render_callback' => array( $this, 'render_widget_partial' ), 'container_inclusive' => true, 'settings' => array( $this->get_setting_id( $matches['widget_id'] ) ), 'capability' => 'edit_theme_options', ) ); } return $partial_args; } /** * Adds hooks for selective refresh. * * @since 4.5.0 */ public function selective_refresh_init() { if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return; } add_filter( 'dynamic_sidebar_params', array( $this, 'filter_dynamic_sidebar_params' ) ); add_filter( 'wp_kses_allowed_html', array( $this, 'filter_wp_kses_allowed_data_attributes' ) ); add_action( 'dynamic_sidebar_before', array( $this, 'start_dynamic_sidebar' ) ); add_action( 'dynamic_sidebar_after', array( $this, 'end_dynamic_sidebar' ) ); } /** * Inject selective refresh data attributes into widget container elements. * * @param array $params { * Dynamic sidebar params. * * @type array $args Sidebar args. * @type array $widget_args Widget args. * } * @see WP_Customize_Nav_Menus_Partial_Refresh::filter_wp_nav_menu_args() * * @return array Params. */ public function filter_dynamic_sidebar_params( $params ) { $sidebar_args = array_merge( array( 'before_widget' => '', 'after_widget' => '', ), $params[0] ); // Skip widgets not in a registered sidebar or ones which lack a proper wrapper element to attach the data-* attributes to. $matches = array(); $is_valid = ( isset( $sidebar_args['id'] ) && is_registered_sidebar( $sidebar_args['id'] ) && ( isset( $this->current_dynamic_sidebar_id_stack[0] ) && $this->current_dynamic_sidebar_id_stack[0] === $sidebar_args['id'] ) && preg_match( '#^<(?P<tag_name>\w+)#', $sidebar_args['before_widget'], $matches ) ); if ( ! $is_valid ) { return $params; } $this->before_widget_tags_seen[ $matches['tag_name'] ] = true; $context = array( 'sidebar_id' => $sidebar_args['id'], ); if ( isset( $this->context_sidebar_instance_number ) ) { $context['sidebar_instance_number'] = $this->context_sidebar_instance_number; } else if ( isset( $sidebar_args['id'] ) && isset( $this->sidebar_instance_count[ $sidebar_args['id'] ] ) ) { $context['sidebar_instance_number'] = $this->sidebar_instance_count[ $sidebar_args['id'] ]; } $attributes = sprintf( ' data-customize-partial-id="%s"', esc_attr( 'widget[' . $sidebar_args['widget_id'] . ']' ) ); $attributes .= ' data-customize-partial-type="widget"'; $attributes .= sprintf( ' data-customize-partial-placement-context="%s"', esc_attr( wp_json_encode( $context ) ) ); $attributes .= sprintf( ' data-customize-widget-id="%s"', esc_attr( $sidebar_args['widget_id'] ) ); $sidebar_args['before_widget'] = preg_replace( '#^(<\w+)#', '$1 ' . $attributes, $sidebar_args['before_widget'] ); $params[0] = $sidebar_args; return $params; } /** * List of the tag names seen for before_widget strings. * * This is used in the {@see 'filter_wp_kses_allowed_html'} filter to ensure that the * data-* attributes can be whitelisted. * * @since 4.5.0 * @var array */ protected $before_widget_tags_seen = array(); /** * Ensures the HTML data-* attributes for selective refresh are allowed by kses. * * This is needed in case the `$before_widget` is run through wp_kses() when printed. * * @since 4.5.0 * * @param array $allowed_html Allowed HTML. * @return array (Maybe) modified allowed HTML. */ public function filter_wp_kses_allowed_data_attributes( $allowed_html ) { foreach ( array_keys( $this->before_widget_tags_seen ) as $tag_name ) { if ( ! isset( $allowed_html[ $tag_name ] ) ) { $allowed_html[ $tag_name ] = array(); } $allowed_html[ $tag_name ] = array_merge( $allowed_html[ $tag_name ], array_fill_keys( array( 'data-customize-partial-id', 'data-customize-partial-type', 'data-customize-partial-placement-context', 'data-customize-partial-widget-id', 'data-customize-partial-options', ), true ) ); } return $allowed_html; } /** * Keep track of the number of times that dynamic_sidebar() was called for a given sidebar index. * * This helps facilitate the uncommon scenario where a single sidebar is rendered multiple times on a template. * * @since 4.5.0 * @var array */ protected $sidebar_instance_count = array(); /** * The current request's sidebar_instance_number context. * * @since 4.5.0 * @var int */ protected $context_sidebar_instance_number; /** * Current sidebar ID being rendered. * * @since 4.5.0 * @var array */ protected $current_dynamic_sidebar_id_stack = array(); /** * Begins keeping track of the current sidebar being rendered. * * Insert marker before widgets are rendered in a dynamic sidebar. * * @since 4.5.0 * * @param int|string $index Index, name, or ID of the dynamic sidebar. */ public function start_dynamic_sidebar( $index ) { array_unshift( $this->current_dynamic_sidebar_id_stack, $index ); if ( ! isset( $this->sidebar_instance_count[ $index ] ) ) { $this->sidebar_instance_count[ $index ] = 0; } $this->sidebar_instance_count[ $index ] += 1; if ( ! $this->manager->selective_refresh->is_render_partials_request() ) { printf( "\n<!--dynamic_sidebar_before:%s:%d-->\n", esc_html( $index ), intval( $this->sidebar_instance_count[ $index ] ) ); } } /** * Finishes keeping track of the current sidebar being rendered. * * Inserts a marker after widgets are rendered in a dynamic sidebar. * * @since 4.5.0 * * @param int|string $index Index, name, or ID of the dynamic sidebar. */ public function end_dynamic_sidebar( $index ) { array_shift( $this->current_dynamic_sidebar_id_stack ); if ( ! $this->manager->selective_refresh->is_render_partials_request() ) { printf( "\n<!--dynamic_sidebar_after:%s:%d-->\n", esc_html( $index ), intval( $this->sidebar_instance_count[ $index ] ) ); } } /** * Current sidebar being rendered. * * @since 4.5.0 * @var string */ protected $rendering_widget_id; /** * Current widget being rendered. * * @since 4.5.0 * @var string */ protected $rendering_sidebar_id; /** * Filters sidebars_widgets to ensure the currently-rendered widget is the only widget in the current sidebar. * * @since 4.5.0 * * @param array $sidebars_widgets Sidebars widgets. * @return array Filtered sidebars widgets. */ public function filter_sidebars_widgets_for_rendering_widget( $sidebars_widgets ) { $sidebars_widgets[ $this->rendering_sidebar_id ] = array( $this->rendering_widget_id ); return $sidebars_widgets; } /** * Renders a specific widget using the supplied sidebar arguments. * * @since 4.5.0 * * @see dynamic_sidebar() * * @param WP_Customize_Partial $partial Partial. * @param array $context { * Sidebar args supplied as container context. * * @type string $sidebar_id ID for sidebar for widget to render into. * @type int $sidebar_instance_number Disambiguating instance number. * } * @return string|false */ public function render_widget_partial( $partial, $context ) { $id_data = $partial->id_data(); $widget_id = array_shift( $id_data['keys'] ); if ( ! is_array( $context ) || empty( $context['sidebar_id'] ) || ! is_registered_sidebar( $context['sidebar_id'] ) ) { return false; } $this->rendering_sidebar_id = $context['sidebar_id']; if ( isset( $context['sidebar_instance_number'] ) ) { $this->context_sidebar_instance_number = intval( $context['sidebar_instance_number'] ); } // Filter sidebars_widgets so that only the queried widget is in the sidebar. $this->rendering_widget_id = $widget_id; $filter_callback = array( $this, 'filter_sidebars_widgets_for_rendering_widget' ); add_filter( 'sidebars_widgets', $filter_callback, 1000 ); // Render the widget. ob_start(); dynamic_sidebar( $this->rendering_sidebar_id = $context['sidebar_id'] ); $container = ob_get_clean(); // Reset variables for next partial render. remove_filter( 'sidebars_widgets', $filter_callback, 1000 ); $this->context_sidebar_instance_number = null; $this->rendering_sidebar_id = null; $this->rendering_widget_id = null; return $container; } // // Option Update Capturing // /** * List of captured widget option updates. * * @since 3.9.0 * @var array $_captured_options Values updated while option capture is happening. */ protected $_captured_options = array(); /** * Whether option capture is currently happening. * * @since 3.9.0 * @var bool $_is_current Whether option capture is currently happening or not. */ protected $_is_capturing_option_updates = false; /** * Determines whether the captured option update should be ignored. * * @since 3.9.0 * * @param string $option_name Option name. * @return bool Whether the option capture is ignored. */ protected function is_option_capture_ignored( $option_name ) { return ( 0 === strpos( $option_name, '_transient_' ) ); } /** * Retrieves captured widget option updates. * * @since 3.9.0 * * @return array Array of captured options. */ protected function get_captured_options() { return $this->_captured_options; } /** * Retrieves the option that was captured from being saved. * * @since 4.2.0 * * @param string $option_name Option name. * @param mixed $default Optional. Default value to return if the option does not exist. Default false. * @return mixed Value set for the option. */ protected function get_captured_option( $option_name, $default = false ) { if ( array_key_exists( $option_name, $this->_captured_options ) ) { $value = $this->_captured_options[ $option_name ]; } else { $value = $default; } return $value; } /** * Retrieves the number of captured widget option updates. * * @since 3.9.0 * * @return int Number of updated options. */ protected function count_captured_options() { return count( $this->_captured_options ); } /** * Begins keeping track of changes to widget options, caching new values. * * @since 3.9.0 */ protected function start_capturing_option_updates() { if ( $this->_is_capturing_option_updates ) { return; } $this->_is_capturing_option_updates = true; add_filter( 'pre_update_option', array( $this, 'capture_filter_pre_update_option' ), 10, 3 ); } /** * Pre-filters captured option values before updating. * * @since 3.9.0 * * @param mixed $new_value The new option value. * @param string $option_name Name of the option. * @param mixed $old_value The old option value. * @return mixed Filtered option value. */ public function capture_filter_pre_update_option( $new_value, $option_name, $old_value ) { if ( $this->is_option_capture_ignored( $option_name ) ) { return; } if ( ! isset( $this->_captured_options[ $option_name ] ) ) { add_filter( "pre_option_{$option_name}", array( $this, 'capture_filter_pre_get_option' ) ); } $this->_captured_options[ $option_name ] = $new_value; return $old_value; } /** * Pre-filters captured option values before retrieving. * * @since 3.9.0 * * @param mixed $value Value to return instead of the option value. * @return mixed Filtered option value. */ public function capture_filter_pre_get_option( $value ) { $option_name = preg_replace( '/^pre_option_/', '', current_filter() ); if ( isset( $this->_captured_options[ $option_name ] ) ) { $value = $this->_captured_options[ $option_name ]; /** This filter is documented in wp-includes/option.php */ $value = apply_filters( 'option_' . $option_name, $value, $option_name ); } return $value; } /** * Undoes any changes to the options since options capture began. * * @since 3.9.0 */ protected function stop_capturing_option_updates() { if ( ! $this->_is_capturing_option_updates ) { return; } remove_filter( 'pre_update_option', array( $this, 'capture_filter_pre_update_option' ), 10 ); foreach ( array_keys( $this->_captured_options ) as $option_name ) { remove_filter( "pre_option_{$option_name}", array( $this, 'capture_filter_pre_get_option' ) ); } $this->_captured_options = array(); $this->_is_capturing_option_updates = false; } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function setup_widget_addition_previews() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function prepreview_added_sidebars_widgets() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function prepreview_added_widget_instance() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function remove_prepreview_filters() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } } home/verseaumee/empowernetorg/wp-includes/class-wp-customize-widgets.php 0000604 00000213540 15075304334 0022717 0 ustar 00 <?php /** * WordPress Customize Widgets classes * * @package WordPress * @subpackage Customize * @since 3.9.0 */ /** * Customize Widgets class. * * Implements widget management in the Customizer. * * @since 3.9.0 * * @see WP_Customize_Manager */ #[AllowDynamicProperties] final class WP_Customize_Widgets { /** * WP_Customize_Manager instance. * * @since 3.9.0 * @var WP_Customize_Manager */ public $manager; /** * All id_bases for widgets defined in core. * * @since 3.9.0 * @var array */ protected $core_widget_id_bases = array( 'archives', 'calendar', 'categories', 'custom_html', 'links', 'media_audio', 'media_image', 'media_video', 'meta', 'nav_menu', 'pages', 'recent-comments', 'recent-posts', 'rss', 'search', 'tag_cloud', 'text', ); /** * @since 3.9.0 * @var array */ protected $rendered_sidebars = array(); /** * @since 3.9.0 * @var array */ protected $rendered_widgets = array(); /** * @since 3.9.0 * @var array */ protected $old_sidebars_widgets = array(); /** * Mapping of widget ID base to whether it supports selective refresh. * * @since 4.5.0 * @var array */ protected $selective_refreshable_widgets; /** * Mapping of setting type to setting ID pattern. * * @since 4.2.0 * @var array */ protected $setting_id_patterns = array( 'widget_instance' => '/^widget_(?P<id_base>.+?)(?:\[(?P<widget_number>\d+)\])?$/', 'sidebar_widgets' => '/^sidebars_widgets\[(?P<sidebar_id>.+?)\]$/', ); /** * Initial loader. * * @since 3.9.0 * * @param WP_Customize_Manager $manager Customizer bootstrap instance. */ public function __construct( $manager ) { $this->manager = $manager; // See https://github.com/xwp/wp-customize-snapshots/blob/962586659688a5b1fd9ae93618b7ce2d4e7a421c/php/class-customize-snapshot-manager.php#L420-L449 add_filter( 'customize_dynamic_setting_args', array( $this, 'filter_customize_dynamic_setting_args' ), 10, 2 ); add_action( 'widgets_init', array( $this, 'register_settings' ), 95 ); add_action( 'customize_register', array( $this, 'schedule_customize_register' ), 1 ); // Skip remaining hooks when the user can't manage widgets anyway. if ( ! current_user_can( 'edit_theme_options' ) ) { return; } add_action( 'wp_loaded', array( $this, 'override_sidebars_widgets_for_theme_switch' ) ); add_action( 'customize_controls_init', array( $this, 'customize_controls_init' ) ); add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); add_action( 'customize_controls_print_styles', array( $this, 'print_styles' ) ); add_action( 'customize_controls_print_scripts', array( $this, 'print_scripts' ) ); add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_footer_scripts' ) ); add_action( 'customize_controls_print_footer_scripts', array( $this, 'output_widget_control_templates' ) ); add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) ); add_filter( 'customize_refresh_nonces', array( $this, 'refresh_nonces' ) ); add_filter( 'should_load_block_editor_scripts_and_styles', array( $this, 'should_load_block_editor_scripts_and_styles' ) ); add_action( 'dynamic_sidebar', array( $this, 'tally_rendered_widgets' ) ); add_filter( 'is_active_sidebar', array( $this, 'tally_sidebars_via_is_active_sidebar_calls' ), 10, 2 ); add_filter( 'dynamic_sidebar_has_widgets', array( $this, 'tally_sidebars_via_dynamic_sidebar_calls' ), 10, 2 ); // Selective Refresh. add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 ); add_action( 'customize_preview_init', array( $this, 'selective_refresh_init' ) ); } /** * List whether each registered widget can be use selective refresh. * * If the theme does not support the customize-selective-refresh-widgets feature, * then this will always return an empty array. * * @since 4.5.0 * * @global WP_Widget_Factory $wp_widget_factory * * @return array Mapping of id_base to support. If theme doesn't support * selective refresh, an empty array is returned. */ public function get_selective_refreshable_widgets() { global $wp_widget_factory; if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return array(); } if ( ! isset( $this->selective_refreshable_widgets ) ) { $this->selective_refreshable_widgets = array(); foreach ( $wp_widget_factory->widgets as $wp_widget ) { $this->selective_refreshable_widgets[ $wp_widget->id_base ] = ! empty( $wp_widget->widget_options['customize_selective_refresh'] ); } } return $this->selective_refreshable_widgets; } /** * Determines if a widget supports selective refresh. * * @since 4.5.0 * * @param string $id_base Widget ID Base. * @return bool Whether the widget can be selective refreshed. */ public function is_widget_selective_refreshable( $id_base ) { $selective_refreshable_widgets = $this->get_selective_refreshable_widgets(); return ! empty( $selective_refreshable_widgets[ $id_base ] ); } /** * Retrieves the widget setting type given a setting ID. * * @since 4.2.0 * * @param string $setting_id Setting ID. * @return string|void Setting type. */ protected function get_setting_type( $setting_id ) { static $cache = array(); if ( isset( $cache[ $setting_id ] ) ) { return $cache[ $setting_id ]; } foreach ( $this->setting_id_patterns as $type => $pattern ) { if ( preg_match( $pattern, $setting_id ) ) { $cache[ $setting_id ] = $type; return $type; } } } /** * Inspects the incoming customized data for any widget settings, and dynamically adds * them up-front so widgets will be initialized properly. * * @since 4.2.0 */ public function register_settings() { $widget_setting_ids = array(); $incoming_setting_ids = array_keys( $this->manager->unsanitized_post_values() ); foreach ( $incoming_setting_ids as $setting_id ) { if ( ! is_null( $this->get_setting_type( $setting_id ) ) ) { $widget_setting_ids[] = $setting_id; } } if ( $this->manager->doing_ajax( 'update-widget' ) && isset( $_REQUEST['widget-id'] ) ) { $widget_setting_ids[] = $this->get_setting_id( wp_unslash( $_REQUEST['widget-id'] ) ); } $settings = $this->manager->add_dynamic_settings( array_unique( $widget_setting_ids ) ); if ( $this->manager->settings_previewed() ) { foreach ( $settings as $setting ) { $setting->preview(); } } } /** * Determines the arguments for a dynamically-created setting. * * @since 4.2.0 * * @param false|array $args The arguments to the WP_Customize_Setting constructor. * @param string $setting_id ID for dynamic setting, usually coming from `$_POST['customized']`. * @return array|false Setting arguments, false otherwise. */ public function filter_customize_dynamic_setting_args( $args, $setting_id ) { if ( $this->get_setting_type( $setting_id ) ) { $args = $this->get_setting_args( $setting_id ); } return $args; } /** * Retrieves an unslashed post value or return a default. * * @since 3.9.0 * * @param string $name Post value. * @param mixed $default_value Default post value. * @return mixed Unslashed post value or default value. */ protected function get_post_value( $name, $default_value = null ) { if ( ! isset( $_POST[ $name ] ) ) { return $default_value; } return wp_unslash( $_POST[ $name ] ); } /** * Override sidebars_widgets for theme switch. * * When switching a theme via the Customizer, supply any previously-configured * sidebars_widgets from the target theme as the initial sidebars_widgets * setting. Also store the old theme's existing settings so that they can * be passed along for storing in the sidebars_widgets theme_mod when the * theme gets switched. * * @since 3.9.0 * * @global array $sidebars_widgets * @global array $_wp_sidebars_widgets */ public function override_sidebars_widgets_for_theme_switch() { global $sidebars_widgets; if ( $this->manager->doing_ajax() || $this->manager->is_theme_active() ) { return; } $this->old_sidebars_widgets = wp_get_sidebars_widgets(); add_filter( 'customize_value_old_sidebars_widgets_data', array( $this, 'filter_customize_value_old_sidebars_widgets_data' ) ); $this->manager->set_post_value( 'old_sidebars_widgets_data', $this->old_sidebars_widgets ); // Override any value cached in changeset. // retrieve_widgets() looks at the global $sidebars_widgets. $sidebars_widgets = $this->old_sidebars_widgets; $sidebars_widgets = retrieve_widgets( 'customize' ); add_filter( 'option_sidebars_widgets', array( $this, 'filter_option_sidebars_widgets_for_theme_switch' ), 1 ); // Reset global cache var used by wp_get_sidebars_widgets(). unset( $GLOBALS['_wp_sidebars_widgets'] ); } /** * Filters old_sidebars_widgets_data Customizer setting. * * When switching themes, filter the Customizer setting old_sidebars_widgets_data * to supply initial $sidebars_widgets before they were overridden by retrieve_widgets(). * The value for old_sidebars_widgets_data gets set in the old theme's sidebars_widgets * theme_mod. * * @since 3.9.0 * * @see WP_Customize_Widgets::handle_theme_switch() * * @param array $old_sidebars_widgets * @return array */ public function filter_customize_value_old_sidebars_widgets_data( $old_sidebars_widgets ) { return $this->old_sidebars_widgets; } /** * Filters sidebars_widgets option for theme switch. * * When switching themes, the retrieve_widgets() function is run when the Customizer initializes, * and then the new sidebars_widgets here get supplied as the default value for the sidebars_widgets * option. * * @since 3.9.0 * * @see WP_Customize_Widgets::handle_theme_switch() * @global array $sidebars_widgets * * @param array $sidebars_widgets * @return array */ public function filter_option_sidebars_widgets_for_theme_switch( $sidebars_widgets ) { $sidebars_widgets = $GLOBALS['sidebars_widgets']; $sidebars_widgets['array_version'] = 3; return $sidebars_widgets; } /** * Ensures all widgets get loaded into the Customizer. * * Note: these actions are also fired in wp_ajax_update_widget(). * * @since 3.9.0 */ public function customize_controls_init() { /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/widgets.php */ do_action( 'sidebar_admin_setup' ); } /** * Ensures widgets are available for all types of previews. * * When in preview, hook to {@see 'customize_register'} for settings after WordPress is loaded * so that all filters have been initialized (e.g. Widget Visibility). * * @since 3.9.0 */ public function schedule_customize_register() { if ( is_admin() ) { $this->customize_register(); } else { add_action( 'wp', array( $this, 'customize_register' ) ); } } /** * Registers Customizer settings and controls for all sidebars and widgets. * * @since 3.9.0 * * @global array $wp_registered_widgets * @global array $wp_registered_widget_controls * @global array $wp_registered_sidebars */ public function customize_register() { global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_sidebars; $use_widgets_block_editor = wp_use_widgets_block_editor(); add_filter( 'sidebars_widgets', array( $this, 'preview_sidebars_widgets' ), 1 ); $sidebars_widgets = array_merge( array( 'wp_inactive_widgets' => array() ), array_fill_keys( array_keys( $wp_registered_sidebars ), array() ), wp_get_sidebars_widgets() ); $new_setting_ids = array(); /* * Register a setting for all widgets, including those which are active, * inactive, and orphaned since a widget may get suppressed from a sidebar * via a plugin (like Widget Visibility). */ foreach ( array_keys( $wp_registered_widgets ) as $widget_id ) { $setting_id = $this->get_setting_id( $widget_id ); $setting_args = $this->get_setting_args( $setting_id ); if ( ! $this->manager->get_setting( $setting_id ) ) { $this->manager->add_setting( $setting_id, $setting_args ); } $new_setting_ids[] = $setting_id; } /* * Add a setting which will be supplied for the theme's sidebars_widgets * theme_mod when the theme is switched. */ if ( ! $this->manager->is_theme_active() ) { $setting_id = 'old_sidebars_widgets_data'; $setting_args = $this->get_setting_args( $setting_id, array( 'type' => 'global_variable', 'dirty' => true, ) ); $this->manager->add_setting( $setting_id, $setting_args ); } $this->manager->add_panel( 'widgets', array( 'type' => 'widgets', 'title' => __( 'Widgets' ), 'description' => __( 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).' ), 'priority' => 110, 'active_callback' => array( $this, 'is_panel_active' ), 'auto_expand_sole_section' => true, 'theme_supports' => 'widgets', ) ); foreach ( $sidebars_widgets as $sidebar_id => $sidebar_widget_ids ) { if ( empty( $sidebar_widget_ids ) ) { $sidebar_widget_ids = array(); } $is_registered_sidebar = is_registered_sidebar( $sidebar_id ); $is_inactive_widgets = ( 'wp_inactive_widgets' === $sidebar_id ); $is_active_sidebar = ( $is_registered_sidebar && ! $is_inactive_widgets ); // Add setting for managing the sidebar's widgets. if ( $is_registered_sidebar || $is_inactive_widgets ) { $setting_id = sprintf( 'sidebars_widgets[%s]', $sidebar_id ); $setting_args = $this->get_setting_args( $setting_id ); if ( ! $this->manager->get_setting( $setting_id ) ) { if ( ! $this->manager->is_theme_active() ) { $setting_args['dirty'] = true; } $this->manager->add_setting( $setting_id, $setting_args ); } $new_setting_ids[] = $setting_id; // Add section to contain controls. $section_id = sprintf( 'sidebar-widgets-%s', $sidebar_id ); if ( $is_active_sidebar ) { $section_args = array( 'title' => $wp_registered_sidebars[ $sidebar_id ]['name'], 'priority' => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ), true ), 'panel' => 'widgets', 'sidebar_id' => $sidebar_id, ); if ( $use_widgets_block_editor ) { $section_args['description'] = ''; } else { $section_args['description'] = $wp_registered_sidebars[ $sidebar_id ]['description']; } /** * Filters Customizer widget section arguments for a given sidebar. * * @since 3.9.0 * * @param array $section_args Array of Customizer widget section arguments. * @param string $section_id Customizer section ID. * @param int|string $sidebar_id Sidebar ID. */ $section_args = apply_filters( 'customizer_widgets_section_args', $section_args, $section_id, $sidebar_id ); $section = new WP_Customize_Sidebar_Section( $this->manager, $section_id, $section_args ); $this->manager->add_section( $section ); if ( $use_widgets_block_editor ) { $control = new WP_Sidebar_Block_Editor_Control( $this->manager, $setting_id, array( 'section' => $section_id, 'sidebar_id' => $sidebar_id, 'label' => $section_args['title'], 'description' => $section_args['description'], ) ); } else { $control = new WP_Widget_Area_Customize_Control( $this->manager, $setting_id, array( 'section' => $section_id, 'sidebar_id' => $sidebar_id, 'priority' => count( $sidebar_widget_ids ), // place 'Add Widget' and 'Reorder' buttons at end. ) ); } $this->manager->add_control( $control ); $new_setting_ids[] = $setting_id; } } if ( ! $use_widgets_block_editor ) { // Add a control for each active widget (located in a sidebar). foreach ( $sidebar_widget_ids as $i => $widget_id ) { // Skip widgets that may have gone away due to a plugin being deactivated. if ( ! $is_active_sidebar || ! isset( $wp_registered_widgets[ $widget_id ] ) ) { continue; } $registered_widget = $wp_registered_widgets[ $widget_id ]; $setting_id = $this->get_setting_id( $widget_id ); $id_base = $wp_registered_widget_controls[ $widget_id ]['id_base']; $control = new WP_Widget_Form_Customize_Control( $this->manager, $setting_id, array( 'label' => $registered_widget['name'], 'section' => $section_id, 'sidebar_id' => $sidebar_id, 'widget_id' => $widget_id, 'widget_id_base' => $id_base, 'priority' => $i, 'width' => $wp_registered_widget_controls[ $widget_id ]['width'], 'height' => $wp_registered_widget_controls[ $widget_id ]['height'], 'is_wide' => $this->is_wide_widget( $widget_id ), ) ); $this->manager->add_control( $control ); } } } if ( $this->manager->settings_previewed() ) { foreach ( $new_setting_ids as $new_setting_id ) { $this->manager->get_setting( $new_setting_id )->preview(); } } } /** * Determines whether the widgets panel is active, based on whether there are sidebars registered. * * @since 4.4.0 * * @see WP_Customize_Panel::$active_callback * * @global array $wp_registered_sidebars * @return bool Active. */ public function is_panel_active() { global $wp_registered_sidebars; return ! empty( $wp_registered_sidebars ); } /** * Converts a widget_id into its corresponding Customizer setting ID (option name). * * @since 3.9.0 * * @param string $widget_id Widget ID. * @return string Maybe-parsed widget ID. */ public function get_setting_id( $widget_id ) { $parsed_widget_id = $this->parse_widget_id( $widget_id ); $setting_id = sprintf( 'widget_%s', $parsed_widget_id['id_base'] ); if ( ! is_null( $parsed_widget_id['number'] ) ) { $setting_id .= sprintf( '[%d]', $parsed_widget_id['number'] ); } return $setting_id; } /** * Determines whether the widget is considered "wide". * * Core widgets which may have controls wider than 250, but can still be shown * in the narrow Customizer panel. The RSS and Text widgets in Core, for example, * have widths of 400 and yet they still render fine in the Customizer panel. * * This method will return all Core widgets as being not wide, but this can be * overridden with the {@see 'is_wide_widget_in_customizer'} filter. * * @since 3.9.0 * * @global array $wp_registered_widget_controls * * @param string $widget_id Widget ID. * @return bool Whether or not the widget is a "wide" widget. */ public function is_wide_widget( $widget_id ) { global $wp_registered_widget_controls; $parsed_widget_id = $this->parse_widget_id( $widget_id ); $width = $wp_registered_widget_controls[ $widget_id ]['width']; $is_core = in_array( $parsed_widget_id['id_base'], $this->core_widget_id_bases, true ); $is_wide = ( $width > 250 && ! $is_core ); /** * Filters whether the given widget is considered "wide". * * @since 3.9.0 * * @param bool $is_wide Whether the widget is wide, Default false. * @param string $widget_id Widget ID. */ return apply_filters( 'is_wide_widget_in_customizer', $is_wide, $widget_id ); } /** * Converts a widget ID into its id_base and number components. * * @since 3.9.0 * * @param string $widget_id Widget ID. * @return array Array containing a widget's id_base and number components. */ public function parse_widget_id( $widget_id ) { $parsed = array( 'number' => null, 'id_base' => null, ); if ( preg_match( '/^(.+)-(\d+)$/', $widget_id, $matches ) ) { $parsed['id_base'] = $matches[1]; $parsed['number'] = (int) $matches[2]; } else { // Likely an old single widget. $parsed['id_base'] = $widget_id; } return $parsed; } /** * Converts a widget setting ID (option path) to its id_base and number components. * * @since 3.9.0 * * @param string $setting_id Widget setting ID. * @return array|WP_Error Array containing a widget's id_base and number components, * or a WP_Error object. */ public function parse_widget_setting_id( $setting_id ) { if ( ! preg_match( '/^(widget_(.+?))(?:\[(\d+)\])?$/', $setting_id, $matches ) ) { return new WP_Error( 'widget_setting_invalid_id' ); } $id_base = $matches[2]; $number = isset( $matches[3] ) ? (int) $matches[3] : null; return compact( 'id_base', 'number' ); } /** * Calls admin_print_styles-widgets.php and admin_print_styles hooks to * allow custom styles from plugins. * * @since 3.9.0 */ public function print_styles() { /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_styles-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_styles' ); } /** * Calls admin_print_scripts-widgets.php and admin_print_scripts hooks to * allow custom scripts from plugins. * * @since 3.9.0 */ public function print_scripts() { /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_scripts-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_print_scripts' ); } /** * Enqueues scripts and styles for Customizer panel and export data to JavaScript. * * @since 3.9.0 * * @global WP_Scripts $wp_scripts * @global array $wp_registered_sidebars * @global array $wp_registered_widgets */ public function enqueue_scripts() { global $wp_scripts, $wp_registered_sidebars, $wp_registered_widgets; wp_enqueue_style( 'customize-widgets' ); wp_enqueue_script( 'customize-widgets' ); /** This action is documented in wp-admin/admin-header.php */ do_action( 'admin_enqueue_scripts', 'widgets.php' ); /* * Export available widgets with control_tpl removed from model * since plugins need templates to be in the DOM. */ $available_widgets = array(); foreach ( $this->get_available_widgets() as $available_widget ) { unset( $available_widget['control_tpl'] ); $available_widgets[] = $available_widget; } $widget_reorder_nav_tpl = sprintf( '<div class="widget-reorder-nav"><span class="move-widget" tabindex="0">%1$s</span><span class="move-widget-down" tabindex="0">%2$s</span><span class="move-widget-up" tabindex="0">%3$s</span></div>', __( 'Move to another area…' ), __( 'Move down' ), __( 'Move up' ) ); $move_widget_area_tpl = str_replace( array( '{description}', '{btn}' ), array( __( 'Select an area to move this widget into:' ), _x( 'Move', 'Move widget' ), ), '<div class="move-widget-area"> <p class="description">{description}</p> <ul class="widget-area-select"> <% _.each( sidebars, function ( sidebar ){ %> <li class="" data-id="<%- sidebar.id %>" title="<%- sidebar.description %>" tabindex="0"><%- sidebar.name %></li> <% }); %> </ul> <div class="move-widget-actions"> <button class="move-widget-btn button" type="button">{btn}</button> </div> </div>' ); /* * Gather all strings in PHP that may be needed by JS on the client. * Once JS i18n is implemented (in #20491), this can be removed. */ $some_non_rendered_areas_messages = array(); $some_non_rendered_areas_messages[1] = html_entity_decode( __( 'Your theme has 1 other widget area, but this particular page does not display it.' ), ENT_QUOTES, get_bloginfo( 'charset' ) ); $registered_sidebar_count = count( $wp_registered_sidebars ); for ( $non_rendered_count = 2; $non_rendered_count < $registered_sidebar_count; $non_rendered_count++ ) { $some_non_rendered_areas_messages[ $non_rendered_count ] = html_entity_decode( sprintf( /* translators: %s: The number of other widget areas registered but not rendered. */ _n( 'Your theme has %s other widget area, but this particular page does not display it.', 'Your theme has %s other widget areas, but this particular page does not display them.', $non_rendered_count ), number_format_i18n( $non_rendered_count ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } if ( 1 === $registered_sidebar_count ) { $no_areas_shown_message = html_entity_decode( sprintf( __( 'Your theme has 1 widget area, but this particular page does not display it.' ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } else { $no_areas_shown_message = html_entity_decode( sprintf( /* translators: %s: The total number of widget areas registered. */ _n( 'Your theme has %s widget area, but this particular page does not display it.', 'Your theme has %s widget areas, but this particular page does not display them.', $registered_sidebar_count ), number_format_i18n( $registered_sidebar_count ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); } $settings = array( 'registeredSidebars' => array_values( $wp_registered_sidebars ), 'registeredWidgets' => $wp_registered_widgets, 'availableWidgets' => $available_widgets, // @todo Merge this with registered_widgets. 'l10n' => array( 'saveBtnLabel' => __( 'Apply' ), 'saveBtnTooltip' => __( 'Save and preview changes before publishing them.' ), 'removeBtnLabel' => __( 'Remove' ), 'removeBtnTooltip' => __( 'Keep widget settings and move it to the inactive widgets' ), 'error' => __( 'An error has occurred. Please reload the page and try again.' ), 'widgetMovedUp' => __( 'Widget moved up' ), 'widgetMovedDown' => __( 'Widget moved down' ), 'navigatePreview' => __( 'You can navigate to other pages on your site while using the Customizer to view and edit the widgets displayed on those pages.' ), 'someAreasShown' => $some_non_rendered_areas_messages, 'noAreasShown' => $no_areas_shown_message, 'reorderModeOn' => __( 'Reorder mode enabled' ), 'reorderModeOff' => __( 'Reorder mode closed' ), 'reorderLabelOn' => esc_attr__( 'Reorder widgets' ), /* translators: %d: The number of widgets found. */ 'widgetsFound' => __( 'Number of widgets found: %d' ), 'noWidgetsFound' => __( 'No widgets found.' ), ), 'tpl' => array( 'widgetReorderNav' => $widget_reorder_nav_tpl, 'moveWidgetArea' => $move_widget_area_tpl, ), 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), ); foreach ( $settings['registeredWidgets'] as &$registered_widget ) { unset( $registered_widget['callback'] ); // May not be JSON-serializable. } $wp_scripts->add_data( 'customize-widgets', 'data', sprintf( 'var _wpCustomizeWidgetsSettings = %s;', wp_json_encode( $settings ) ) ); /* * TODO: Update 'wp-customize-widgets' to not rely so much on things in * 'customize-widgets'. This will let us skip most of the above and not * enqueue 'customize-widgets' which saves bytes. */ if ( wp_use_widgets_block_editor() ) { $block_editor_context = new WP_Block_Editor_Context( array( 'name' => 'core/customize-widgets', ) ); $editor_settings = get_block_editor_settings( get_legacy_widget_block_editor_settings(), $block_editor_context ); wp_add_inline_script( 'wp-customize-widgets', sprintf( 'wp.domReady( function() { wp.customizeWidgets.initialize( "widgets-customizer", %s ); } );', wp_json_encode( $editor_settings ) ) ); // Preload server-registered block schemas. wp_add_inline_script( 'wp-blocks', 'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');' ); wp_add_inline_script( 'wp-blocks', sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( $block_editor_context ) ) ), 'after' ); wp_enqueue_script( 'wp-customize-widgets' ); wp_enqueue_style( 'wp-customize-widgets' ); /** This action is documented in edit-form-blocks.php */ do_action( 'enqueue_block_editor_assets' ); } } /** * Renders the widget form control templates into the DOM. * * @since 3.9.0 */ public function output_widget_control_templates() { ?> <div id="widgets-left"><!-- compatibility with JS which looks for widget templates here --> <div id="available-widgets"> <div class="customize-section-title"> <button class="customize-section-back" tabindex="-1"> <span class="screen-reader-text"> <?php /* translators: Hidden accessibility text. */ _e( 'Back' ); ?> </span> </button> <h3> <span class="customize-action"> <?php /* translators: ▸ is the unicode right-pointing triangle. %s: Section title in the Customizer. */ printf( __( 'Customizing ▸ %s' ), esc_html( $this->manager->get_panel( 'widgets' )->title ) ); ?> </span> <?php _e( 'Add a Widget' ); ?> </h3> </div> <div id="available-widgets-filter"> <label for="widgets-search"> <?php /* translators: Hidden accessibility text. */ _e( 'Search Widgets' ); ?> </label> <input type="text" id="widgets-search" aria-describedby="widgets-search-desc" /> <div class="search-icon" aria-hidden="true"></div> <button type="button" class="clear-results"><span class="screen-reader-text"> <?php /* translators: Hidden accessibility text. */ _e( 'Clear Results' ); ?> </span></button> <p class="screen-reader-text" id="widgets-search-desc"> <?php /* translators: Hidden accessibility text. */ _e( 'The search results will be updated as you type.' ); ?> </p> </div> <div id="available-widgets-list"> <?php foreach ( $this->get_available_widgets() as $available_widget ) : ?> <div id="widget-tpl-<?php echo esc_attr( $available_widget['id'] ); ?>" data-widget-id="<?php echo esc_attr( $available_widget['id'] ); ?>" class="widget-tpl <?php echo esc_attr( $available_widget['id'] ); ?>" tabindex="0"> <?php echo $available_widget['control_tpl']; ?> </div> <?php endforeach; ?> <p class="no-widgets-found-message"><?php _e( 'No widgets found.' ); ?></p> </div><!-- #available-widgets-list --> </div><!-- #available-widgets --> </div><!-- #widgets-left --> <?php } /** * Calls admin_print_footer_scripts and admin_print_scripts hooks to * allow custom scripts from plugins. * * @since 3.9.0 */ public function print_footer_scripts() { /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_print_footer_scripts-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_print_footer_scripts' ); /** This action is documented in wp-admin/admin-footer.php */ do_action( 'admin_footer-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores } /** * Retrieves common arguments to supply when constructing a Customizer setting. * * @since 3.9.0 * * @param string $id Widget setting ID. * @param array $overrides Array of setting overrides. * @return array Possibly modified setting arguments. */ public function get_setting_args( $id, $overrides = array() ) { $args = array( 'type' => 'option', 'capability' => 'edit_theme_options', 'default' => array(), ); if ( preg_match( $this->setting_id_patterns['sidebar_widgets'], $id, $matches ) ) { $args['sanitize_callback'] = array( $this, 'sanitize_sidebar_widgets' ); $args['sanitize_js_callback'] = array( $this, 'sanitize_sidebar_widgets_js_instance' ); $args['transport'] = current_theme_supports( 'customize-selective-refresh-widgets' ) ? 'postMessage' : 'refresh'; } elseif ( preg_match( $this->setting_id_patterns['widget_instance'], $id, $matches ) ) { $id_base = $matches['id_base']; $args['sanitize_callback'] = function ( $value ) use ( $id_base ) { return $this->sanitize_widget_instance( $value, $id_base ); }; $args['sanitize_js_callback'] = function ( $value ) use ( $id_base ) { return $this->sanitize_widget_js_instance( $value, $id_base ); }; $args['transport'] = $this->is_widget_selective_refreshable( $matches['id_base'] ) ? 'postMessage' : 'refresh'; } $args = array_merge( $args, $overrides ); /** * Filters the common arguments supplied when constructing a Customizer setting. * * @since 3.9.0 * * @see WP_Customize_Setting * * @param array $args Array of Customizer setting arguments. * @param string $id Widget setting ID. */ return apply_filters( 'widget_customizer_setting_args', $args, $id ); } /** * Ensures sidebar widget arrays only ever contain widget IDS. * * Used as the 'sanitize_callback' for each $sidebars_widgets setting. * * @since 3.9.0 * * @param string[] $widget_ids Array of widget IDs. * @return string[] Array of sanitized widget IDs. */ public function sanitize_sidebar_widgets( $widget_ids ) { $widget_ids = array_map( 'strval', (array) $widget_ids ); $sanitized_widget_ids = array(); foreach ( $widget_ids as $widget_id ) { $sanitized_widget_ids[] = preg_replace( '/[^a-z0-9_\-]/', '', $widget_id ); } return $sanitized_widget_ids; } /** * Builds up an index of all available widgets for use in Backbone models. * * @since 3.9.0 * * @global array $wp_registered_widgets * @global array $wp_registered_widget_controls * * @see wp_list_widgets() * * @return array List of available widgets. */ public function get_available_widgets() { static $available_widgets = array(); if ( ! empty( $available_widgets ) ) { return $available_widgets; } global $wp_registered_widgets, $wp_registered_widget_controls; require_once ABSPATH . 'wp-admin/includes/widgets.php'; // For next_widget_id_number(). $sort = $wp_registered_widgets; usort( $sort, array( $this, '_sort_name_callback' ) ); $done = array(); foreach ( $sort as $widget ) { if ( in_array( $widget['callback'], $done, true ) ) { // We already showed this multi-widget. continue; } $sidebar = is_active_widget( $widget['callback'], $widget['id'], false, false ); $done[] = $widget['callback']; if ( ! isset( $widget['params'][0] ) ) { $widget['params'][0] = array(); } $available_widget = $widget; unset( $available_widget['callback'] ); // Not serializable to JSON. $args = array( 'widget_id' => $widget['id'], 'widget_name' => $widget['name'], '_display' => 'template', ); $is_disabled = false; $is_multi_widget = ( isset( $wp_registered_widget_controls[ $widget['id'] ]['id_base'] ) && isset( $widget['params'][0]['number'] ) ); if ( $is_multi_widget ) { $id_base = $wp_registered_widget_controls[ $widget['id'] ]['id_base']; $args['_temp_id'] = "$id_base-__i__"; $args['_multi_num'] = next_widget_id_number( $id_base ); $args['_add'] = 'multi'; } else { $args['_add'] = 'single'; if ( $sidebar && 'wp_inactive_widgets' !== $sidebar ) { $is_disabled = true; } $id_base = $widget['id']; } $list_widget_controls_args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0], ) ); $control_tpl = $this->get_widget_control( $list_widget_controls_args ); // The properties here are mapped to the Backbone Widget model. $available_widget = array_merge( $available_widget, array( 'temp_id' => isset( $args['_temp_id'] ) ? $args['_temp_id'] : null, 'is_multi' => $is_multi_widget, 'control_tpl' => $control_tpl, 'multi_number' => ( 'multi' === $args['_add'] ) ? $args['_multi_num'] : false, 'is_disabled' => $is_disabled, 'id_base' => $id_base, 'transport' => $this->is_widget_selective_refreshable( $id_base ) ? 'postMessage' : 'refresh', 'width' => $wp_registered_widget_controls[ $widget['id'] ]['width'], 'height' => $wp_registered_widget_controls[ $widget['id'] ]['height'], 'is_wide' => $this->is_wide_widget( $widget['id'] ), ) ); $available_widgets[] = $available_widget; } return $available_widgets; } /** * Naturally orders available widgets by name. * * @since 3.9.0 * * @param array $widget_a The first widget to compare. * @param array $widget_b The second widget to compare. * @return int Reorder position for the current widget comparison. */ protected function _sort_name_callback( $widget_a, $widget_b ) { return strnatcasecmp( $widget_a['name'], $widget_b['name'] ); } /** * Retrieves the widget control markup. * * @since 3.9.0 * * @param array $args Widget control arguments. * @return string Widget control form HTML markup. */ public function get_widget_control( $args ) { $args[0]['before_form'] = '<div class="form">'; $args[0]['after_form'] = '</div><!-- .form -->'; $args[0]['before_widget_content'] = '<div class="widget-content">'; $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; ob_start(); wp_widget_control( ...$args ); $control_tpl = ob_get_clean(); return $control_tpl; } /** * Retrieves the widget control markup parts. * * @since 4.4.0 * * @param array $args Widget control arguments. * @return array { * @type string $control Markup for widget control wrapping form. * @type string $content The contents of the widget form itself. * } */ public function get_widget_control_parts( $args ) { $args[0]['before_widget_content'] = '<div class="widget-content">'; $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; $control_markup = $this->get_widget_control( $args ); $content_start_pos = strpos( $control_markup, $args[0]['before_widget_content'] ); $content_end_pos = strrpos( $control_markup, $args[0]['after_widget_content'] ); $control = substr( $control_markup, 0, $content_start_pos + strlen( $args[0]['before_widget_content'] ) ); $control .= substr( $control_markup, $content_end_pos ); $content = trim( substr( $control_markup, $content_start_pos + strlen( $args[0]['before_widget_content'] ), $content_end_pos - $content_start_pos - strlen( $args[0]['before_widget_content'] ) ) ); return compact( 'control', 'content' ); } /** * Adds hooks for the Customizer preview. * * @since 3.9.0 */ public function customize_preview_init() { add_action( 'wp_enqueue_scripts', array( $this, 'customize_preview_enqueue' ) ); add_action( 'wp_print_styles', array( $this, 'print_preview_css' ), 1 ); add_action( 'wp_footer', array( $this, 'export_preview_data' ), 20 ); } /** * Refreshes the nonce for widget updates. * * @since 4.2.0 * * @param array $nonces Array of nonces. * @return array Array of nonces. */ public function refresh_nonces( $nonces ) { $nonces['update-widget'] = wp_create_nonce( 'update-widget' ); return $nonces; } /** * Tells the script loader to load the scripts and styles of custom blocks * if the widgets block editor is enabled. * * @since 5.8.0 * * @param bool $is_block_editor_screen Current decision about loading block assets. * @return bool Filtered decision about loading block assets. */ public function should_load_block_editor_scripts_and_styles( $is_block_editor_screen ) { if ( wp_use_widgets_block_editor() ) { return true; } return $is_block_editor_screen; } /** * When previewing, ensures the proper previewing widgets are used. * * Because wp_get_sidebars_widgets() gets called early at {@see 'init' } (via * wp_convert_widget_settings()) and can set global variable `$_wp_sidebars_widgets` * to the value of `get_option( 'sidebars_widgets' )` before the Customizer preview * filter is added, it has to be reset after the filter has been added. * * @since 3.9.0 * * @param array $sidebars_widgets List of widgets for the current sidebar. * @return array */ public function preview_sidebars_widgets( $sidebars_widgets ) { $sidebars_widgets = get_option( 'sidebars_widgets', array() ); unset( $sidebars_widgets['array_version'] ); return $sidebars_widgets; } /** * Enqueues scripts for the Customizer preview. * * @since 3.9.0 */ public function customize_preview_enqueue() { wp_enqueue_script( 'customize-preview-widgets' ); } /** * Inserts default style for highlighted widget at early point so theme * stylesheet can override. * * @since 3.9.0 */ public function print_preview_css() { ?> <style> .widget-customizer-highlighted-widget { outline: none; -webkit-box-shadow: 0 0 2px rgba(30, 140, 190, 0.8); box-shadow: 0 0 2px rgba(30, 140, 190, 0.8); position: relative; z-index: 1; } </style> <?php } /** * Communicates the sidebars that appeared on the page at the very end of the page, * and at the very end of the wp_footer, * * @since 3.9.0 * * @global array $wp_registered_sidebars * @global array $wp_registered_widgets */ public function export_preview_data() { global $wp_registered_sidebars, $wp_registered_widgets; $switched_locale = switch_to_user_locale( get_current_user_id() ); $l10n = array( 'widgetTooltip' => __( 'Shift-click to edit this widget.' ), ); if ( $switched_locale ) { restore_previous_locale(); } $rendered_sidebars = array_filter( $this->rendered_sidebars ); $rendered_widgets = array_filter( $this->rendered_widgets ); // Prepare Customizer settings to pass to JavaScript. $settings = array( 'renderedSidebars' => array_fill_keys( array_keys( $rendered_sidebars ), true ), 'renderedWidgets' => array_fill_keys( array_keys( $rendered_widgets ), true ), 'registeredSidebars' => array_values( $wp_registered_sidebars ), 'registeredWidgets' => $wp_registered_widgets, 'l10n' => $l10n, 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), ); foreach ( $settings['registeredWidgets'] as &$registered_widget ) { unset( $registered_widget['callback'] ); // May not be JSON-serializable. } wp_print_inline_script_tag( sprintf( 'var _wpWidgetCustomizerPreviewSettings = %s;', wp_json_encode( $settings ) ) ); } /** * Tracks the widgets that were rendered. * * @since 3.9.0 * * @param array $widget Rendered widget to tally. */ public function tally_rendered_widgets( $widget ) { $this->rendered_widgets[ $widget['id'] ] = true; } /** * Determine if a widget is rendered on the page. * * @since 4.0.0 * * @param string $widget_id Widget ID to check. * @return bool Whether the widget is rendered. */ public function is_widget_rendered( $widget_id ) { return ! empty( $this->rendered_widgets[ $widget_id ] ); } /** * Determines if a sidebar is rendered on the page. * * @since 4.0.0 * * @param string $sidebar_id Sidebar ID to check. * @return bool Whether the sidebar is rendered. */ public function is_sidebar_rendered( $sidebar_id ) { return ! empty( $this->rendered_sidebars[ $sidebar_id ] ); } /** * Tallies the sidebars rendered via is_active_sidebar(). * * Keep track of the times that is_active_sidebar() is called in the template, * and assume that this means that the sidebar would be rendered on the template * if there were widgets populating it. * * @since 3.9.0 * * @param bool $is_active Whether the sidebar is active. * @param string $sidebar_id Sidebar ID. * @return bool Whether the sidebar is active. */ public function tally_sidebars_via_is_active_sidebar_calls( $is_active, $sidebar_id ) { if ( is_registered_sidebar( $sidebar_id ) ) { $this->rendered_sidebars[ $sidebar_id ] = true; } /* * We may need to force this to true, and also force-true the value * for 'dynamic_sidebar_has_widgets' if we want to ensure that there * is an area to drop widgets into, if the sidebar is empty. */ return $is_active; } /** * Tallies the sidebars rendered via dynamic_sidebar(). * * Keep track of the times that dynamic_sidebar() is called in the template, * and assume this means the sidebar would be rendered on the template if * there were widgets populating it. * * @since 3.9.0 * * @param bool $has_widgets Whether the current sidebar has widgets. * @param string $sidebar_id Sidebar ID. * @return bool Whether the current sidebar has widgets. */ public function tally_sidebars_via_dynamic_sidebar_calls( $has_widgets, $sidebar_id ) { if ( is_registered_sidebar( $sidebar_id ) ) { $this->rendered_sidebars[ $sidebar_id ] = true; } /* * We may need to force this to true, and also force-true the value * for 'is_active_sidebar' if we want to ensure there is an area to * drop widgets into, if the sidebar is empty. */ return $has_widgets; } /** * Retrieves MAC for a serialized widget instance string. * * Allows values posted back from JS to be rejected if any tampering of the * data has occurred. * * @since 3.9.0 * * @param string $serialized_instance Widget instance. * @return string MAC for serialized widget instance. */ protected function get_instance_hash_key( $serialized_instance ) { return wp_hash( $serialized_instance ); } /** * Sanitizes a widget instance. * * Unserialize the JS-instance for storing in the options. It's important that this filter * only get applied to an instance *once*. * * @since 3.9.0 * @since 5.8.0 Added the `$id_base` parameter. * * @global WP_Widget_Factory $wp_widget_factory * * @param array $value Widget instance to sanitize. * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null. * @return array|void Sanitized widget instance. */ public function sanitize_widget_instance( $value, $id_base = null ) { global $wp_widget_factory; if ( array() === $value ) { return $value; } if ( isset( $value['raw_instance'] ) && $id_base && wp_use_widgets_block_editor() ) { $widget_object = $wp_widget_factory->get_widget_object( $id_base ); if ( ! empty( $widget_object->widget_options['show_instance_in_rest'] ) ) { if ( 'block' === $id_base && ! current_user_can( 'unfiltered_html' ) ) { /* * The content of the 'block' widget is not filtered on the fly while editing. * Filter the content here to prevent vulnerabilities. */ $value['raw_instance']['content'] = wp_kses_post( $value['raw_instance']['content'] ); } return $value['raw_instance']; } } if ( empty( $value['is_widget_customizer_js_value'] ) || empty( $value['instance_hash_key'] ) || empty( $value['encoded_serialized_instance'] ) ) { return; } $decoded = base64_decode( $value['encoded_serialized_instance'], true ); if ( false === $decoded ) { return; } if ( ! hash_equals( $this->get_instance_hash_key( $decoded ), $value['instance_hash_key'] ) ) { return; } $instance = unserialize( $decoded ); if ( false === $instance ) { return; } return $instance; } /** * Converts a widget instance into JSON-representable format. * * @since 3.9.0 * @since 5.8.0 Added the `$id_base` parameter. * * @global WP_Widget_Factory $wp_widget_factory * * @param array $value Widget instance to convert to JSON. * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null. * @return array JSON-converted widget instance. */ public function sanitize_widget_js_instance( $value, $id_base = null ) { global $wp_widget_factory; if ( empty( $value['is_widget_customizer_js_value'] ) ) { $serialized = serialize( $value ); $js_value = array( 'encoded_serialized_instance' => base64_encode( $serialized ), 'title' => empty( $value['title'] ) ? '' : $value['title'], 'is_widget_customizer_js_value' => true, 'instance_hash_key' => $this->get_instance_hash_key( $serialized ), ); if ( $id_base && wp_use_widgets_block_editor() ) { $widget_object = $wp_widget_factory->get_widget_object( $id_base ); if ( ! empty( $widget_object->widget_options['show_instance_in_rest'] ) ) { $js_value['raw_instance'] = (object) $value; } } return $js_value; } return $value; } /** * Strips out widget IDs for widgets which are no longer registered. * * One example where this might happen is when a plugin orphans a widget * in a sidebar upon deactivation. * * @since 3.9.0 * * @global array $wp_registered_widgets * * @param array $widget_ids List of widget IDs. * @return array Parsed list of widget IDs. */ public function sanitize_sidebar_widgets_js_instance( $widget_ids ) { global $wp_registered_widgets; $widget_ids = array_values( array_intersect( $widget_ids, array_keys( $wp_registered_widgets ) ) ); return $widget_ids; } /** * Finds and invokes the widget update and control callbacks. * * Requires that `$_POST` be populated with the instance data. * * @since 3.9.0 * * @global array $wp_registered_widget_updates * @global array $wp_registered_widget_controls * * @param string $widget_id Widget ID. * @return array|WP_Error Array containing the updated widget information. * A WP_Error object, otherwise. */ public function call_widget_update( $widget_id ) { global $wp_registered_widget_updates, $wp_registered_widget_controls; $setting_id = $this->get_setting_id( $widget_id ); /* * Make sure that other setting changes have previewed since this widget * may depend on them (e.g. Menus being present for Navigation Menu widget). */ if ( ! did_action( 'customize_preview_init' ) ) { foreach ( $this->manager->settings() as $setting ) { if ( $setting->id !== $setting_id ) { $setting->preview(); } } } $this->start_capturing_option_updates(); $parsed_id = $this->parse_widget_id( $widget_id ); $option_name = 'widget_' . $parsed_id['id_base']; /* * If a previously-sanitized instance is provided, populate the input vars * with its values so that the widget update callback will read this instance */ $added_input_vars = array(); if ( ! empty( $_POST['sanitized_widget_setting'] ) ) { $sanitized_widget_setting = json_decode( $this->get_post_value( 'sanitized_widget_setting' ), true ); if ( false === $sanitized_widget_setting ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_malformed' ); } $instance = $this->sanitize_widget_instance( $sanitized_widget_setting, $parsed_id['id_base'] ); if ( is_null( $instance ) ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_unsanitized' ); } if ( ! is_null( $parsed_id['number'] ) ) { $value = array(); $value[ $parsed_id['number'] ] = $instance; $key = 'widget-' . $parsed_id['id_base']; $_REQUEST[ $key ] = wp_slash( $value ); $_POST[ $key ] = $_REQUEST[ $key ]; $added_input_vars[] = $key; } else { foreach ( $instance as $key => $value ) { $_REQUEST[ $key ] = wp_slash( $value ); $_POST[ $key ] = $_REQUEST[ $key ]; $added_input_vars[] = $key; } } } // Invoke the widget update callback. foreach ( (array) $wp_registered_widget_updates as $name => $control ) { if ( $name === $parsed_id['id_base'] && is_callable( $control['callback'] ) ) { ob_start(); call_user_func_array( $control['callback'], $control['params'] ); ob_end_clean(); break; } } // Clean up any input vars that were manually added. foreach ( $added_input_vars as $key ) { unset( $_POST[ $key ] ); unset( $_REQUEST[ $key ] ); } // Make sure the expected option was updated. if ( 0 !== $this->count_captured_options() ) { if ( $this->count_captured_options() > 1 ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_too_many_options' ); } $updated_option_name = key( $this->get_captured_options() ); if ( $updated_option_name !== $option_name ) { $this->stop_capturing_option_updates(); return new WP_Error( 'widget_setting_unexpected_option' ); } } // Obtain the widget instance. $option = $this->get_captured_option( $option_name ); if ( null !== $parsed_id['number'] ) { $instance = $option[ $parsed_id['number'] ]; } else { $instance = $option; } /* * Override the incoming $_POST['customized'] for a newly-created widget's * setting with the new $instance so that the preview filter currently * in place from WP_Customize_Setting::preview() will use this value * instead of the default widget instance value (an empty array). */ $this->manager->set_post_value( $setting_id, $this->sanitize_widget_js_instance( $instance, $parsed_id['id_base'] ) ); // Obtain the widget control with the updated instance in place. ob_start(); $form = $wp_registered_widget_controls[ $widget_id ]; if ( $form ) { call_user_func_array( $form['callback'], $form['params'] ); } $form = ob_get_clean(); $this->stop_capturing_option_updates(); return compact( 'instance', 'form' ); } /** * Updates widget settings asynchronously. * * Allows the Customizer to update a widget using its form, but return the new * instance info via Ajax instead of saving it to the options table. * * Most code here copied from wp_ajax_save_widget(). * * @since 3.9.0 * * @see wp_ajax_save_widget() */ public function wp_ajax_update_widget() { if ( ! is_user_logged_in() ) { wp_die( 0 ); } check_ajax_referer( 'update-widget', 'nonce' ); if ( ! current_user_can( 'edit_theme_options' ) ) { wp_die( -1 ); } if ( empty( $_POST['widget-id'] ) ) { wp_send_json_error( 'missing_widget-id' ); } /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/includes/ajax-actions.php */ do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/widgets.php */ do_action( 'sidebar_admin_setup' ); $widget_id = $this->get_post_value( 'widget-id' ); $parsed_id = $this->parse_widget_id( $widget_id ); $id_base = $parsed_id['id_base']; $is_updating_widget_template = ( isset( $_POST[ 'widget-' . $id_base ] ) && is_array( $_POST[ 'widget-' . $id_base ] ) && preg_match( '/__i__|%i%/', key( $_POST[ 'widget-' . $id_base ] ) ) ); if ( $is_updating_widget_template ) { wp_send_json_error( 'template_widget_not_updatable' ); } $updated_widget = $this->call_widget_update( $widget_id ); // => {instance,form} if ( is_wp_error( $updated_widget ) ) { wp_send_json_error( $updated_widget->get_error_code() ); } $form = $updated_widget['form']; $instance = $this->sanitize_widget_js_instance( $updated_widget['instance'], $id_base ); wp_send_json_success( compact( 'form', 'instance' ) ); } /* * Selective Refresh Methods */ /** * Filters arguments for dynamic widget partials. * * @since 4.5.0 * * @param array|false $partial_args Partial arguments. * @param string $partial_id Partial ID. * @return array (Maybe) modified partial arguments. */ public function customize_dynamic_partial_args( $partial_args, $partial_id ) { if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return $partial_args; } if ( preg_match( '/^widget\[(?P<widget_id>.+)\]$/', $partial_id, $matches ) ) { if ( false === $partial_args ) { $partial_args = array(); } $partial_args = array_merge( $partial_args, array( 'type' => 'widget', 'render_callback' => array( $this, 'render_widget_partial' ), 'container_inclusive' => true, 'settings' => array( $this->get_setting_id( $matches['widget_id'] ) ), 'capability' => 'edit_theme_options', ) ); } return $partial_args; } /** * Adds hooks for selective refresh. * * @since 4.5.0 */ public function selective_refresh_init() { if ( ! current_theme_supports( 'customize-selective-refresh-widgets' ) ) { return; } add_filter( 'dynamic_sidebar_params', array( $this, 'filter_dynamic_sidebar_params' ) ); add_filter( 'wp_kses_allowed_html', array( $this, 'filter_wp_kses_allowed_data_attributes' ) ); add_action( 'dynamic_sidebar_before', array( $this, 'start_dynamic_sidebar' ) ); add_action( 'dynamic_sidebar_after', array( $this, 'end_dynamic_sidebar' ) ); } /** * Inject selective refresh data attributes into widget container elements. * * @since 4.5.0 * * @param array $params { * Dynamic sidebar params. * * @type array $args Sidebar args. * @type array $widget_args Widget args. * } * @see WP_Customize_Nav_Menus::filter_wp_nav_menu_args() * * @return array Params. */ public function filter_dynamic_sidebar_params( $params ) { $sidebar_args = array_merge( array( 'before_widget' => '', 'after_widget' => '', ), $params[0] ); // Skip widgets not in a registered sidebar or ones which lack a proper wrapper element to attach the data-* attributes to. $matches = array(); $is_valid = ( isset( $sidebar_args['id'] ) && is_registered_sidebar( $sidebar_args['id'] ) && ( isset( $this->current_dynamic_sidebar_id_stack[0] ) && $this->current_dynamic_sidebar_id_stack[0] === $sidebar_args['id'] ) && preg_match( '#^<(?P<tag_name>\w+)#', $sidebar_args['before_widget'], $matches ) ); if ( ! $is_valid ) { return $params; } $this->before_widget_tags_seen[ $matches['tag_name'] ] = true; $context = array( 'sidebar_id' => $sidebar_args['id'], ); if ( isset( $this->context_sidebar_instance_number ) ) { $context['sidebar_instance_number'] = $this->context_sidebar_instance_number; } elseif ( isset( $sidebar_args['id'] ) && isset( $this->sidebar_instance_count[ $sidebar_args['id'] ] ) ) { $context['sidebar_instance_number'] = $this->sidebar_instance_count[ $sidebar_args['id'] ]; } $attributes = sprintf( ' data-customize-partial-id="%s"', esc_attr( 'widget[' . $sidebar_args['widget_id'] . ']' ) ); $attributes .= ' data-customize-partial-type="widget"'; $attributes .= sprintf( ' data-customize-partial-placement-context="%s"', esc_attr( wp_json_encode( $context ) ) ); $attributes .= sprintf( ' data-customize-widget-id="%s"', esc_attr( $sidebar_args['widget_id'] ) ); $sidebar_args['before_widget'] = preg_replace( '#^(<\w+)#', '$1 ' . $attributes, $sidebar_args['before_widget'] ); $params[0] = $sidebar_args; return $params; } /** * List of the tag names seen for before_widget strings. * * This is used in the {@see 'filter_wp_kses_allowed_html'} filter to ensure that the * data-* attributes can be allowed. * * @since 4.5.0 * @var array */ protected $before_widget_tags_seen = array(); /** * Ensures the HTML data-* attributes for selective refresh are allowed by kses. * * This is needed in case the `$before_widget` is run through wp_kses() when printed. * * @since 4.5.0 * * @param array $allowed_html Allowed HTML. * @return array (Maybe) modified allowed HTML. */ public function filter_wp_kses_allowed_data_attributes( $allowed_html ) { foreach ( array_keys( $this->before_widget_tags_seen ) as $tag_name ) { if ( ! isset( $allowed_html[ $tag_name ] ) ) { $allowed_html[ $tag_name ] = array(); } $allowed_html[ $tag_name ] = array_merge( $allowed_html[ $tag_name ], array_fill_keys( array( 'data-customize-partial-id', 'data-customize-partial-type', 'data-customize-partial-placement-context', 'data-customize-partial-widget-id', 'data-customize-partial-options', ), true ) ); } return $allowed_html; } /** * Keep track of the number of times that dynamic_sidebar() was called for a given sidebar index. * * This helps facilitate the uncommon scenario where a single sidebar is rendered multiple times on a template. * * @since 4.5.0 * @var array */ protected $sidebar_instance_count = array(); /** * The current request's sidebar_instance_number context. * * @since 4.5.0 * @var int|null */ protected $context_sidebar_instance_number; /** * Current sidebar ID being rendered. * * @since 4.5.0 * @var array */ protected $current_dynamic_sidebar_id_stack = array(); /** * Begins keeping track of the current sidebar being rendered. * * Insert marker before widgets are rendered in a dynamic sidebar. * * @since 4.5.0 * * @param int|string $index Index, name, or ID of the dynamic sidebar. */ public function start_dynamic_sidebar( $index ) { array_unshift( $this->current_dynamic_sidebar_id_stack, $index ); if ( ! isset( $this->sidebar_instance_count[ $index ] ) ) { $this->sidebar_instance_count[ $index ] = 0; } $this->sidebar_instance_count[ $index ] += 1; if ( ! $this->manager->selective_refresh->is_render_partials_request() ) { printf( "\n<!--dynamic_sidebar_before:%s:%d-->\n", esc_html( $index ), (int) $this->sidebar_instance_count[ $index ] ); } } /** * Finishes keeping track of the current sidebar being rendered. * * Inserts a marker after widgets are rendered in a dynamic sidebar. * * @since 4.5.0 * * @param int|string $index Index, name, or ID of the dynamic sidebar. */ public function end_dynamic_sidebar( $index ) { array_shift( $this->current_dynamic_sidebar_id_stack ); if ( ! $this->manager->selective_refresh->is_render_partials_request() ) { printf( "\n<!--dynamic_sidebar_after:%s:%d-->\n", esc_html( $index ), (int) $this->sidebar_instance_count[ $index ] ); } } /** * Current sidebar being rendered. * * @since 4.5.0 * @var string|null */ protected $rendering_widget_id; /** * Current widget being rendered. * * @since 4.5.0 * @var string|null */ protected $rendering_sidebar_id; /** * Filters sidebars_widgets to ensure the currently-rendered widget is the only widget in the current sidebar. * * @since 4.5.0 * * @param array $sidebars_widgets Sidebars widgets. * @return array Filtered sidebars widgets. */ public function filter_sidebars_widgets_for_rendering_widget( $sidebars_widgets ) { $sidebars_widgets[ $this->rendering_sidebar_id ] = array( $this->rendering_widget_id ); return $sidebars_widgets; } /** * Renders a specific widget using the supplied sidebar arguments. * * @since 4.5.0 * * @see dynamic_sidebar() * * @param WP_Customize_Partial $partial Partial. * @param array $context { * Sidebar args supplied as container context. * * @type string $sidebar_id ID for sidebar for widget to render into. * @type int $sidebar_instance_number Disambiguating instance number. * } * @return string|false */ public function render_widget_partial( $partial, $context ) { $id_data = $partial->id_data(); $widget_id = array_shift( $id_data['keys'] ); if ( ! is_array( $context ) || empty( $context['sidebar_id'] ) || ! is_registered_sidebar( $context['sidebar_id'] ) ) { return false; } $this->rendering_sidebar_id = $context['sidebar_id']; if ( isset( $context['sidebar_instance_number'] ) ) { $this->context_sidebar_instance_number = (int) $context['sidebar_instance_number']; } // Filter sidebars_widgets so that only the queried widget is in the sidebar. $this->rendering_widget_id = $widget_id; $filter_callback = array( $this, 'filter_sidebars_widgets_for_rendering_widget' ); add_filter( 'sidebars_widgets', $filter_callback, 1000 ); // Render the widget. ob_start(); $this->rendering_sidebar_id = $context['sidebar_id']; dynamic_sidebar( $this->rendering_sidebar_id ); $container = ob_get_clean(); // Reset variables for next partial render. remove_filter( 'sidebars_widgets', $filter_callback, 1000 ); $this->context_sidebar_instance_number = null; $this->rendering_sidebar_id = null; $this->rendering_widget_id = null; return $container; } // // Option Update Capturing. // /** * List of captured widget option updates. * * @since 3.9.0 * @var array $_captured_options Values updated while option capture is happening. */ protected $_captured_options = array(); /** * Whether option capture is currently happening. * * @since 3.9.0 * @var bool $_is_current Whether option capture is currently happening or not. */ protected $_is_capturing_option_updates = false; /** * Determines whether the captured option update should be ignored. * * @since 3.9.0 * * @param string $option_name Option name. * @return bool Whether the option capture is ignored. */ protected function is_option_capture_ignored( $option_name ) { return ( str_starts_with( $option_name, '_transient_' ) ); } /** * Retrieves captured widget option updates. * * @since 3.9.0 * * @return array Array of captured options. */ protected function get_captured_options() { return $this->_captured_options; } /** * Retrieves the option that was captured from being saved. * * @since 4.2.0 * * @param string $option_name Option name. * @param mixed $default_value Optional. Default value to return if the option does not exist. Default false. * @return mixed Value set for the option. */ protected function get_captured_option( $option_name, $default_value = false ) { if ( array_key_exists( $option_name, $this->_captured_options ) ) { $value = $this->_captured_options[ $option_name ]; } else { $value = $default_value; } return $value; } /** * Retrieves the number of captured widget option updates. * * @since 3.9.0 * * @return int Number of updated options. */ protected function count_captured_options() { return count( $this->_captured_options ); } /** * Begins keeping track of changes to widget options, caching new values. * * @since 3.9.0 */ protected function start_capturing_option_updates() { if ( $this->_is_capturing_option_updates ) { return; } $this->_is_capturing_option_updates = true; add_filter( 'pre_update_option', array( $this, 'capture_filter_pre_update_option' ), 10, 3 ); } /** * Pre-filters captured option values before updating. * * @since 3.9.0 * * @param mixed $new_value The new option value. * @param string $option_name Name of the option. * @param mixed $old_value The old option value. * @return mixed Filtered option value. */ public function capture_filter_pre_update_option( $new_value, $option_name, $old_value ) { if ( $this->is_option_capture_ignored( $option_name ) ) { return $new_value; } if ( ! isset( $this->_captured_options[ $option_name ] ) ) { add_filter( "pre_option_{$option_name}", array( $this, 'capture_filter_pre_get_option' ) ); } $this->_captured_options[ $option_name ] = $new_value; return $old_value; } /** * Pre-filters captured option values before retrieving. * * @since 3.9.0 * * @param mixed $value Value to return instead of the option value. * @return mixed Filtered option value. */ public function capture_filter_pre_get_option( $value ) { $option_name = preg_replace( '/^pre_option_/', '', current_filter() ); if ( isset( $this->_captured_options[ $option_name ] ) ) { $value = $this->_captured_options[ $option_name ]; /** This filter is documented in wp-includes/option.php */ $value = apply_filters( 'option_' . $option_name, $value, $option_name ); } return $value; } /** * Undoes any changes to the options since options capture began. * * @since 3.9.0 */ protected function stop_capturing_option_updates() { if ( ! $this->_is_capturing_option_updates ) { return; } remove_filter( 'pre_update_option', array( $this, 'capture_filter_pre_update_option' ), 10 ); foreach ( array_keys( $this->_captured_options ) as $option_name ) { remove_filter( "pre_option_{$option_name}", array( $this, 'capture_filter_pre_get_option' ) ); } $this->_captured_options = array(); $this->_is_capturing_option_updates = false; } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function setup_widget_addition_previews() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function prepreview_added_sidebars_widgets() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function prepreview_added_widget_instance() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } /** * {@internal Missing Summary} * * See the {@see 'customize_dynamic_setting_args'} filter. * * @since 3.9.0 * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. */ public function remove_prepreview_filters() { _deprecated_function( __METHOD__, '4.2.0', 'customize_dynamic_setting_args' ); } }
Close