PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.0.13
Kirki – Freeform Page Builder, Website Builder & Customizer v6.0.13
6.1.1 6.1.0 6.0.14 6.0.13 6.0.12 6.0.11 6.0.10 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.19 4.0.20 4.0.21 4.0.22 4.0.23 4.0.24 4.1 4.2.0 5.0.0 5.1.0 5.1.1 5.2.0 5.2.1 5.2.2 5.2.3 6.0.0 trunk 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.1.0 3.1.1 3.1.2
kirki / app / Services / FontService.php
kirki / app / Services Last commit date
AppsService.php 2 weeks ago CollaborationCommentService.php 2 weeks ago CollaborationService.php 2 weeks ago CollectionItemService.php 2 weeks ago CollectionService.php 2 weeks ago EditorService.php 2 weeks ago FontService.php 2 weeks ago MediaService.php 2 weeks ago PageService.php 2 weeks ago PageSettingsService.php 2 weeks ago UtilityPageService.php 2 weeks ago
FontService.php
172 lines
1 <?php
2
3 namespace Kirki\App\Services;
4
5 use Exception;
6 use Kirki\App\DTO\GoogleFontDTO;
7 use Kirki\App\Supports\Facades\GlobalData;
8 use Kirki\Framework\Http\Response;
9 use Kirki\Framework\Supports\Facades\File;
10 use Kirki\Framework\Supports\Facades\Http;
11
12 use function Kirki\App\get_upload_directory;
13 use function Kirki\App\get_upload_directory_url;
14
15 defined('ABSPATH') || exit;
16
17 class FontService
18 {
19 public static function create()
20 {
21 return new static();
22 }
23
24 public function download_google_font(GoogleFontDTO $payload)
25 {
26 // Extra security: keep only a-z, 0-9, and hyphens
27 $font_family_slug = preg_replace('/[^a-z0-9\-]/i', '', sanitize_title_with_dashes($payload->family));
28
29 if (empty($font_family_slug) || strpos($font_family_slug, '..') !== false) {
30 throw new Exception(esc_html__('Not valid font family.', 'kirki'), Response::FORBIDDEN);
31 }
32
33 $has_write_permission = File::is_writable(get_upload_directory());
34
35 if (!$has_write_permission) {
36 throw new Exception(esc_html__('Upload directory is not writable.', 'kirki'), Response::FORBIDDEN);
37 }
38
39 $font_dir = get_upload_directory() . "/kirki-fonts/{$font_family_slug}";
40 $css_file_path = $font_dir . "/{$font_family_slug}.css";
41
42 if (File::exists($css_file_path)) {
43 throw new Exception(esc_html__('Font already downloaded.', 'kirki'), Response::FORBIDDEN);
44 }
45
46 if (stripos($payload->fontUrl, 'fonts.googleapis.com') === false) {
47 throw new Exception(esc_html__('Only Google Fonts is supported.', 'kirki'), Response::FORBIDDEN);
48 }
49
50 try {
51 if (!File::is_directory($font_dir)) {
52 File::make_dir($font_dir);
53 }
54
55 $css = Http::get($payload->fontUrl);
56
57 if ($css->failed()) {
58 throw new Exception(esc_html__('Failed to fetch Google Fonts CSS.', 'kirki'));
59 }
60
61 if (isset($payload->files['regular'])) {
62 $payload->files['400'] = $payload->files['regular'];
63 unset($payload->files['regular']);
64 }
65
66 $formats = [
67 'woff2' => 'woff2',
68 'woff' => 'woff',
69 'ttf' => 'truetype',
70 'otf' => 'opentype',
71 ];
72 $local_css = '';
73
74 foreach ($payload->files as $weight => $url) {
75 $allowed_ext = array_keys($formats);
76 $extension = strtolower(pathinfo($url, PATHINFO_EXTENSION));
77
78 if (!in_array($extension, $allowed_ext, true)) {
79 /* translators: %s: file extension */
80 throw new Exception(esc_html(sprintf(__('Invalid or unsafe file extension: %s.', 'kirki'), $extension)));
81 }
82
83 $file_name = "{$weight}.{$extension}";
84 $file_path = $font_dir . '/' . $file_name;
85
86 $font_data = Http::get($url);
87
88 if ($font_data->failed()) {
89 throw new Exception(esc_html__('Failed to fetch font file.', 'kirki'));
90 }
91
92 File::put($file_path, $font_data->__toString());
93
94 $format = $formats[$extension] ?? 'truetype';
95 $local_css .= "@font-face {
96 font-family: '{$payload->family}';
97 font-style: normal;
98 font-weight: {$weight};
99 font-display: swap;
100 src: url('{$file_name}') format('{$format}');
101 }\n";
102 }
103
104 if (empty($local_css)) {
105 throw new Exception(esc_html__('No usable font files were downloaded.', 'kirki'));
106 }
107
108 File::put($css_file_path, $local_css);
109 $payload->localUrl = get_upload_directory_url() . "/kirki-fonts/{$font_family_slug}/{$font_family_slug}.css";
110
111 $this->save_google_font_into_global_custom_fonts($payload);
112
113 return $payload;
114
115 } catch (Exception $exception) {
116 if (File::is_directory($font_dir)) {
117 File::delete($font_dir);
118 }
119
120 throw $exception;
121 }
122 }
123
124 public function remove_google_font(GoogleFontDTO $payload) {
125 $font_family_slug = sanitize_title_with_dashes( basename( $payload->family ) );
126 $font_dir = get_upload_directory() . "/kirki-fonts/{$font_family_slug}";
127
128 if (File::is_directory($font_dir)) {
129 File::delete($font_dir);
130 }
131
132 $payload->exclude(['localUrl']);
133
134 $this->save_google_font_into_global_custom_fonts($payload);
135
136 return true;
137 }
138
139 protected function save_google_font_into_global_custom_fonts(GoogleFontDTO $font) {
140 // first get the font data
141 $custom_fonts = GlobalData::get_global_custom_fonts();
142
143 if (empty($custom_fonts)) {
144 $custom_fonts = [];
145 }
146
147 if (!empty($font->family)) {
148 $custom_fonts[$font->family] = $font->to_array();
149
150 GlobalData::update_global_custom_fonts($custom_fonts);
151 }
152 }
153
154 public function remove_custom_fonts_permanently(array $fonts)
155 {
156 foreach ($fonts as $font) {
157 $upload_dir = get_upload_directory() . '/kirki-fonts/' . $font['family'];
158
159 if (File::is_directory($upload_dir)) {
160 File::delete($upload_dir);
161 }
162
163 // Remove font from local.
164 $font_family_slug = sanitize_title_with_dashes($font['family']);
165 $font_local_dir = get_upload_directory() . "/kirki-fonts/{$font_family_slug}";
166
167 if (File::is_directory($font_local_dir)) {
168 File::delete($font_local_dir);
169 }
170 }
171 }
172 }