/var/www/html_us/wp-content/plugins/woocommerce/src/Internal/Font/FontFace.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
<?php
/**
 * FontFace class file
 */

namespace Automattic\WooCommerce\Internal\Font;

// IMPORTANT: We have to switch to the WordPress API to create the FontFace post type when they will be implemented: https://github.com/WordPress/gutenberg/issues/58670!

/**
 * Helper class for font face related functionality.
 *
 * @internal Just for internal use.
 */
class FontFace {

    const 
POST_TYPE 'wp_font_face';

    
/**
     * Gets the installed font face by slug.
     *
     * @param string $slug The font face slug.
     * @return \WP_Post|null The font face post or null if not found.
     */
    
public static function get_installed_font_faces_by_slug$slug ) {
        
$query = new \WP_Query(
            array(
                
'post_type'              => self::POST_TYPE,
                
'update_post_meta_cache' => false,
                
'update_post_term_cache' => false,
                
'name'                   => $slug,
            )
        );

        if ( ! empty( 
$query->get_posts() ) ) {
            return 
$query->get_posts()[0];
        }
        return 
null;
    }

    
/**
     * Sanitizes a single src value for a font face.
     *
     * Copied from Gutenberg: https://github.com/WordPress/gutenberg/blob/8d94c3bd7af977d998466b56bd773f9b19de8d03/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-faces-controller.php/#L837-L840
     *
     * @param string $value Font face src that is a URL or the key for a $_FILES array item.
     *
     * @return string Sanitized value.
     */
    
private static function sanitize_src$value ) {
        
$value ltrim$value );
        return 
false === wp_http_validate_url$value ) ? (string) $value esc_url_raw$value );
    }

    
/**
     * Handles file upload error.
     *
     * Copied from Gutenberg: https://github.com/WordPress/gutenberg/blob/b283c47dba96d74dd7589a823d8ab84c9e5a4765/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-faces-controller.php/#L859-L883
     *
     * @param array  $file    File upload data.
     * @param string $message Error message from wp_handle_upload().
     * @return WP_Error WP_Error object.
     */
    
private static function handle_font_file_upload_error$file$message ) {
        
$status 500;
        
$code   'rest_font_upload_unknown_error';

        if ( 
__'Sorry, you are not allowed to upload this file type.''woocommerce' ) === $message ) {
            
$status 400;
            
$code   'rest_font_upload_invalid_file_type';
        }

        return new 
\WP_Error$code$message, array( 'status' => $status ) );
    }

    
/**
     * Handles the upload of a font file using wp_handle_upload().
     *
     * Copied from Gutenberg: https://github.com/WordPress/gutenberg/blob/f4889bf58ddeb8470c8d2a765f1b57229c515eda/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-faces-controller.php/#L859-L896
     *
     * @param array $file Single file item from $_FILES.
     * @return array Array containing uploaded file attributes on success, or error on failure.
     */
    
private static function handle_font_file_upload$file ) {
        
add_filter'upload_mimes', array( 'WP_Font_Utils''get_allowed_font_mime_types' ) );

        
/*
         * Set the upload directory to the fonts directory.
         *
         * wp_get_font_dir() contains the 'font_dir' hook, whose callbacks are
         * likely to call wp_get_upload_dir().
         *
         * To avoid an infinite loop, don't hook wp_get_font_dir() to 'upload_dir'.
         * Instead, just pass its return value to the 'upload_dir' callback.
         */
        
$font_dir       wp_get_font_dir();
        
$set_upload_dir = function () use ( $font_dir ) {
            return 
$font_dir;
        };
        
add_filter'upload_dir'$set_upload_dir );

        
$overrides = array(
            
'upload_error_handler' => array( self::class, 'handle_font_file_upload_error' ),
            
// Arbitrary string to avoid the is_uploaded_file() check applied
            // when using 'wp_handle_upload'.
            
'action'               => 'wp_handle_font_upload',
            
// Not testing a form submission.
            
'test_form'            => false,
            
// Seems mime type for files that are not images cannot be tested.
            // See wp_check_filetype_and_ext().
            
'test_type'            => true,
            
// Only allow uploading font files for this request.
            
'mimes'                => \WP_Font_Utils::get_allowed_font_mime_types(),
        );

        
$uploaded_file wp_handle_upload$file$overrides );
        
remove_filter'upload_dir'$set_upload_dir );
        
remove_filter'upload_mimes', array( 'WP_Font_Utils''get_allowed_font_mime_types' ) );

        return 
$uploaded_file;
    }

    
/**
     * Downloads a file from a URL.
     *
     * @param string $file_url The file URL.
     **/
    
private static function download_file$file_url ) {
        if ( ! 
function_exists'download_url' ) ) {
            require_once 
ABSPATH 'wp-admin/includes/file.php';
        }

        
$allowed_extensions = array( 'ttf''otf''woff''woff2''eot' );

        
$allowed_extensions array_map'preg_quote'$allowed_extensions );

        
// Set variables for storage, fix file filename for query strings.
        
preg_match'/[^\?]+\.(' implode'|'$allowed_extensions ) . ')\b/i'$file_url$matches );
        
$file_array         = array();
        
$file_array['name'] = wp_basename$matches[0] );

        
// Download file to temp location.
        
$file_array['tmp_name'] = download_url$file_url );
        return 
$file_array;
    }

    
/**
     * Inserts a font face.
     *
     * @param array $font_face The font face settings.
     * @param int   $parent_font_family_id The parent font family ID.
     * @return \WP_Error|\WP_Post The inserted font face post or an error if the font face already exists.
     */
    
public static function insert_font_face( array $font_faceint $parent_font_family_id ) {
        
$slug \WP_Font_Utils::get_font_face_slug$font_face );

        
// Check that the font face slug is unique.
        
$query = new \WP_Query(
            array(
                
'post_type'              => self::POST_TYPE,
                
'posts_per_page'         => 1,
                
'name'                   => $slug,
                
'update_post_meta_cache' => false,
                
'update_post_term_cache' => false,
            )
        );

        if ( ! empty( 
$query->get_posts() ) ) {
            return new 
\WP_Error(
                
'duplicate_font_face',
                
/* translators: %s: Font face slug. */
                
sprintf__'A font face with slug "%s" already exists.''woocommerce' ), $slug ),
            );
        }

        
// Validate the font face settings.

        
$validation_error self::validate_font_face$font_face );
        if ( 
is_wp_error$validation_error ) ) {
            return 
$validation_error;
        }

        
$parsed_font_face['fontFamily'] = addslashes\WP_Font_Utils::sanitize_font_family$font_face['fontFamily'] ) );
        
$parsed_font_face['fontStyle']  = sanitize_text_field$font_face['fontStyle'] );
        
$parsed_font_face['fontWeight'] = sanitize_text_field$font_face['fontWeight'] );
        
$file                           self::download_file$font_face['src'] );

        
$uploaded_file self::handle_font_file_upload$file );

        
$parsed_font_face['src']     = self::sanitize_src$uploaded_file['url'] );
        
$parsed_font_face['preview'] = esc_url_raw$font_face['preview'] );

        
// Insert the font face.
        
wp_insert_post(
            array(
                
'post_type'    => self::POST_TYPE,
                
'post_parent'  => $parent_font_family_id,
                
'post_title'   => $slug,
                
'post_name'    => sanitize_title$slug ),
                
'post_content' => wp_json_encode$parsed_font_face ),
                
'post_status'  => 'publish',
            )
        );
    }


    
/**
     * Validates a font face.
     *
     * @param array $font_face The font face settings.
     * @return \WP_Error|null The error if the font family is invalid, null otherwise.
     */
    
private static function validate_font_face$font_face ) {
        
// Validate the font face family name.
        
if ( empty( $font_face['fontFamily'] ) ) {
            return new 
\WP_Error(
                
'invalid_font_face_font_family',
                
__'The font face family name is required.''woocommerce' ),
            );
        }

        
// Validate the font face font style.
        
if ( empty( $font_face['fontStyle'] ) ) {
            return new 
\WP_Error(
                
'invalid_font_face_font_style',
                
__'The font face font style is required.''woocommerce' ),
            );
        }

        
// Validate the font face weight.
        
if ( empty( $font_face['fontWeight'] ) ) {
            return new 
\WP_Error(
                
'invalid_font_face_font_weight',
                
__'The font face weight is required.''woocommerce' ),
            );
        }

        
// Validate the font face src.
        
if ( empty( $font_face['src'] ) ) {
            return new 
\WP_Error(
                
'invalid_font_face_src',
                
__'The font face src is required.''woocommerce' ),
            );
        }
    }

}