File "fonts.php"

Full Path: /home/pumpbmko/public_html/wp-content/plugins/gutenberg/lib/compat/wordpress-6.5/fonts/fonts.php
File size: 16.42 KB
MIME-type: text/x-php
Charset: utf-8

<?php
/**
 * Font Library initialization.
 *
 * This file contains Font Library init calls.
 *
 * @package    WordPress
 * @subpackage Font Library
 * @since      6.5.0
 */

/**
 * Registers the routes for the objects of the controller.
 *
 * This function will not be merged into Core. However, the
 * code in the function will be. @core-merge annotation
 * provides instructions on where the could needs to go
 * in Core.
 *
 * @since 6.5.0
 */
function gutenberg_create_initial_post_types() {
	// @core-merge: This code will go into Core's `create_initial_post_types()`.
	$args = array(
		'labels'                         => array(
			'name'          => __( 'Font Families', 'gutenberg' ),
			'singular_name' => __( 'Font Family', 'gutenberg' ),
		),
		'public'                         => false,
		'_builtin'                       => true, /* internal use only. don't use this when registering your own post type. */
		'hierarchical'                   => false,
		'capabilities'                   => array(
			'read'                   => 'edit_theme_options',
			'read_private_posts'     => 'edit_theme_options',
			'create_posts'           => 'edit_theme_options',
			'publish_posts'          => 'edit_theme_options',
			'edit_posts'             => 'edit_theme_options',
			'edit_others_posts'      => 'edit_theme_options',
			'edit_published_posts'   => 'edit_theme_options',
			'delete_posts'           => 'edit_theme_options',
			'delete_others_posts'    => 'edit_theme_options',
			'delete_published_posts' => 'edit_theme_options',
		),
		'map_meta_cap'                   => true,
		'query_var'                      => false,
		'show_in_rest'                   => true,
		'rest_base'                      => 'font-families',
		'rest_controller_class'          => 'WP_REST_Font_Families_Controller',
		// Disable autosave endpoints for font families.
		'autosave_rest_controller_class' => 'stdClass',
	);
	register_post_type( 'wp_font_family', $args );

	register_post_type(
		'wp_font_face',
		array(
			'labels'                         => array(
				'name'          => __( 'Font Faces', 'gutenberg' ),
				'singular_name' => __( 'Font Face', 'gutenberg' ),
			),
			'public'                         => false,
			'_builtin'                       => true, /* internal use only. don't use this when registering your own post type. */
			'hierarchical'                   => false,
			'capabilities'                   => array(
				'read'                   => 'edit_theme_options',
				'read_private_posts'     => 'edit_theme_options',
				'create_posts'           => 'edit_theme_options',
				'publish_posts'          => 'edit_theme_options',
				'edit_posts'             => 'edit_theme_options',
				'edit_others_posts'      => 'edit_theme_options',
				'edit_published_posts'   => 'edit_theme_options',
				'delete_posts'           => 'edit_theme_options',
				'delete_others_posts'    => 'edit_theme_options',
				'delete_published_posts' => 'edit_theme_options',
			),
			'map_meta_cap'                   => true,
			'query_var'                      => false,
			'show_in_rest'                   => true,
			'rest_base'                      => 'font-families/(?P<font_family_id>[\d]+)/font-faces',
			'rest_controller_class'          => 'WP_REST_Font_Faces_Controller',
			// Disable autosave endpoints for font faces.
			'autosave_rest_controller_class' => 'stdClass',
		)
	);
}

/**
 * Initializes REST routes.
 *
 * @global string $wp_version The WordPress version string.
 */
function gutenberg_create_initial_rest_routes() {
	global $wp_version;

	// Runs only if the Font Library is not available in core ( i.e. in core < 6.5-alpha ).
	if ( version_compare( $wp_version, '6.5-alpha', '<' ) ) {
		$font_collections_controller = new WP_REST_Font_Collections_Controller();
		$font_collections_controller->register_routes();
	}
}

add_action( 'rest_api_init', 'gutenberg_create_initial_rest_routes' );

/**
 * Initializes REST routes and post types.
 *
 * @global string $wp_version The WordPress version string.
 */
function gutenberg_init_font_library() {
	global $wp_version;

	// Runs only if the Font Library is not available in core ( i.e. in core < 6.5-alpha ).
	if ( version_compare( $wp_version, '6.5-alpha', '<' ) ) {
		gutenberg_create_initial_post_types();
	}
}

add_action( 'init', 'gutenberg_init_font_library' );


if ( ! function_exists( 'wp_register_font_collection' ) ) {
	/**
	 * Registers a new font collection in the font library.
	 *
	 * See {@link https://schemas.wp.org/trunk/font-collection.json} for the schema
	 * the font collection data must adhere to.
	 *
	 * @since 6.5.0
	 *
	 * @param string $slug Font collection slug. May only contain alphanumeric characters, dashes,
	 *                     and underscores. See sanitize_title().
	 * @param array  $args {
	 *     Font collection data.
	 *
	 *     @type string       $name          Required. Name of the font collection shown in the Font Library.
	 *     @type string       $description   Optional. A short descriptive summary of the font collection. Default empty.
	 *     @type array|string $font_families Required. Array of font family definitions that are in the collection,
	 *                                       or a string containing the path or URL to a JSON file containing the font collection.
	 *     @type array        $categories    Optional. Array of categories, each with a name and slug, that are used by the
	 *                                       fonts in the collection. Default empty.
	 * }
	 * @return WP_Font_Collection|WP_Error A font collection if it was registered
	 *                                     successfully, or WP_Error object on failure.
	 */
	function wp_register_font_collection( string $slug, array $args ) {
		return WP_Font_Library::get_instance()->register_font_collection( $slug, $args );
	}
}

if ( ! function_exists( 'wp_unregister_font_collection' ) ) {
	/**
	 * Unregisters a font collection from the Font Library.
	 *
	 * @since 6.5.0
	 *
	 * @param string $slug Font collection slug.
	 * @return bool True if the font collection was unregistered successfully, else false.
	 */
	function wp_unregister_font_collection( string $slug ) {
		return WP_Font_Library::get_instance()->unregister_font_collection( $slug );
	}
}

function gutenberg_register_font_collections() {
	if ( null !== WP_Font_Library::get_instance()->get_font_collection( 'google-fonts' ) ) {
		return;
	}
	wp_register_font_collection(
		'google-fonts',
		array(
			'name'          => _x( 'Google Fonts', 'font collection name', 'gutenberg' ),
			'description'   => __( 'Install from Google Fonts. Fonts are copied to and served from your site.', 'gutenberg' ),
			'font_families' => 'https://s.w.org/images/fonts/wp-6.5/collections/google-fonts-with-preview.json',
			'categories'    => array(
				array(
					'name' => _x( 'Sans Serif', 'font category', 'gutenberg' ),
					'slug' => 'sans-serif',
				),
				array(
					'name' => _x( 'Display', 'font category', 'gutenberg' ),
					'slug' => 'display',
				),
				array(
					'name' => _x( 'Serif', 'font category', 'gutenberg' ),
					'slug' => 'serif',
				),
				array(
					'name' => _x( 'Handwriting', 'font category', 'gutenberg' ),
					'slug' => 'handwriting',
				),
				array(
					'name' => _x( 'Monospace', 'font category', 'gutenberg' ),
					'slug' => 'monospace',
				),
			),
		)
	);
}
add_action( 'init', 'gutenberg_register_font_collections', 11 );

// @core-merge: This code should probably go into Core's src/wp-includes/fonts.php.
if ( ! function_exists( 'wp_get_font_dir' ) ) {
	/**
	 * Retrieves font uploads directory information.
	 *
	 * Same as wp_font_dir() but "light weight" as it doesn't attempt to create the font uploads directory.
	 * Intended for use in themes, when only 'basedir' and 'baseurl' are needed, generally in all cases
	 * when not uploading files.
	 *
	 * @since 6.5.0
	 *
	 * @see wp_font_dir()
	 *
	 * @return array See wp_font_dir() for description.
	 */
	function wp_get_font_dir() {
		return wp_font_dir( false );
	}
}

// @core-merge: This code should probably go into Core's src/wp-includes/fonts.php.
if ( ! function_exists( 'wp_font_dir' ) ) {
	/**
	 * Returns an array containing the current fonts upload directory's path and URL.
	 *
	 * @since 6.5.0
	 *
	 * @param bool $create_dir Optional. Whether to check and create the font uploads directory. Default true.
	 * @return array {
	 *     Array of information about the font upload directory.
	 *
	 *     @type string       $path    Base directory and subdirectory or full path to the fonts upload directory.
	 *     @type string       $url     Base URL and subdirectory or absolute URL to the fonts upload directory.
	 *     @type string       $subdir  Subdirectory
	 *     @type string       $basedir Path without subdir.
	 *     @type string       $baseurl URL path without subdir.
	 *     @type string|false $error   False or error message.
	 * }
	 */
	function wp_font_dir( $create_dir = true ) {
		/*
		 * Allow extenders to manipulate the font directory consistently.
		 *
		 * Ensures the upload_dir filter is fired both when calling this function
		 * directly and when the upload directory is filtered in the Font Face
		 * REST API endpoint.
		 */
		add_filter( 'upload_dir', '_wp_filter_font_directory' );
		$font_dir = wp_upload_dir( null, $create_dir, false );
		remove_filter( 'upload_dir', '_wp_filter_font_directory' );
		return $font_dir;
	}
}

// @core-merge: This code should probably go into Core's src/wp-includes/fonts.php.
if ( ! function_exists( '_wp_filter_font_directory' ) ) {
	/**
	 * Returns the font directory for use by the font library.
	 *
	 * This function is a callback for the {@see 'upload_dir'} filter. It is not
	 * intended to be called directly. Use wp_get_font_dir() instead.
	 *
	 * The function can be used when extending the font library to modify the upload
	 * destination for font files via the upload_dir filter. The recommended way to
	 * do this is:
	 *
	 * ```php
	 * add_filter( 'upload_dir', '_wp_filter_font_directory' );
	 * // Your code to upload or sideload a font file.
	 * remove_filter( 'upload_dir', '_wp_filter_font_directory' );
	 * ```
	 *
	 * @since 6.5.0
	 * @access private
	 *
	 * @param string $font_dir The font directory.
	 * @return string The modified font directory.
	 */
	function _wp_filter_font_directory( $font_dir ) {
		if ( doing_filter( 'font_dir' ) ) {
			// Avoid an infinite loop.
			return $font_dir;
		}

		$font_dir = array(
			'path'    => untrailingslashit( $font_dir['basedir'] ) . '/fonts',
			'url'     => untrailingslashit( $font_dir['baseurl'] ) . '/fonts',
			'subdir'  => '',
			'basedir' => untrailingslashit( $font_dir['basedir'] ) . '/fonts',
			'baseurl' => untrailingslashit( $font_dir['baseurl'] ) . '/fonts',
			'error'   => false,
		);

		/**
		 * Filters the fonts directory data.
		 *
		 * This filter allows developers to modify the fonts directory data.
		 *
		 * @since 6.5.0
		 *
		 * @param array $font_dir {
		 *     Array of information about the font upload directory.
		 *
		 *     @type string       $path    Base directory and subdirectory or full path to the fonts upload directory.
		 *     @type string       $url     Base URL and subdirectory or absolute URL to the fonts upload directory.
		 *     @type string       $subdir  Subdirectory
		 *     @type string       $basedir Path without subdir.
		 *     @type string       $baseurl URL path without subdir.
		 *     @type string|false $error   False or error message.
		 * }
		 */
		return apply_filters( 'font_dir', $font_dir );
	}
}

// @core-merge: Filters should go in `src/wp-includes/default-filters.php`,
// functions in a general file for font library.
if ( ! function_exists( '_wp_after_delete_font_family' ) ) {
	/**
	 * Deletes child font faces when a font family is deleted.
	 *
	 * @access private
	 * @since 6.5.0
	 *
	 * @param int     $post_id Post ID.
	 * @param WP_Post $post    Post object.
	 */
	function _wp_after_delete_font_family( $post_id, $post ) {
		if ( 'wp_font_family' !== $post->post_type ) {
			return;
		}

		$font_faces = get_children(
			array(
				'post_parent' => $post_id,
				'post_type'   => 'wp_font_face',
			)
		);

		foreach ( $font_faces as $font_face ) {
			wp_delete_post( $font_face->ID, true );
		}
	}
	add_action( 'deleted_post', '_wp_after_delete_font_family', 10, 2 );
}

if ( ! function_exists( '_wp_before_delete_font_face' ) ) {
	/**
	 * Deletes associated font files when a font face is deleted.
	 *
	 * @access private
	 * @since 6.5.0
	 *
	 * @param int     $post_id Post ID.
	 * @param WP_Post $post    Post object.
	 */
	function _wp_before_delete_font_face( $post_id, $post ) {
		if ( 'wp_font_face' !== $post->post_type ) {
			return;
		}

		$font_files = get_post_meta( $post_id, '_wp_font_face_file', false );
		$font_dir   = untrailingslashit( wp_get_font_dir()['basedir'] );

		foreach ( $font_files as $font_file ) {
			wp_delete_file( $font_dir . '/' . $font_file );
		}
	}
	add_action( 'before_delete_post', '_wp_before_delete_font_face', 10, 2 );
}

// @core-merge: Do not merge this function, it is for deleting fonts from the wp-content/fonts directory only used in Gutenberg.
/**
 * Deletes associated font files from wp-content/fonts, when a font face is deleted.
 *
 * @param int     $post_id Post ID.
 * @param WP_Post $post    Post object.
 */
function gutenberg_before_delete_font_face( $post_id, $post ) {
	if ( 'wp_font_face' !== $post->post_type ) {
		return;
	}

	$font_files = get_post_meta( $post_id, '_wp_font_face_file', false );

	if ( empty( $font_files ) ) {
		return;
	}

	$site_path = '';
	if ( is_multisite() && ! ( is_main_network() && is_main_site() ) ) {
		$site_path = '/sites/' . get_current_blog_id();
	}

	$font_dir = path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path;

	foreach ( $font_files as $font_file ) {
		$font_path = $font_dir . '/' . $font_file;

		if ( file_exists( $font_path ) ) {
			wp_delete_file( $font_path );
		}
	}
}
add_action( 'before_delete_post', 'gutenberg_before_delete_font_face', 10, 2 );

// @core-merge: Do not merge this back compat function, it is for supporting a legacy font family format only in Gutenberg.
/**
 * Convert legacy font family posts to the new format.
 *
 * @return void
 */
function gutenberg_convert_legacy_font_family_format() {
	if ( get_option( 'gutenberg_font_family_format_converted' ) ) {
		return;
	}

	$font_families = new WP_Query(
		array(
			'post_type'              => 'wp_font_family',
			// Set a maximum, but in reality there will be far less than this.
			'posts_per_page'         => 999,
			'update_post_term_cache' => false,
		)
	);

	foreach ( $font_families->get_posts() as $font_family ) {
		$already_converted = get_post_meta( $font_family->ID, '_gutenberg_legacy_font_family', true );
		if ( $already_converted ) {
			continue;
		}

		// Stash the old font family content in a meta field just in case we need it.
		update_post_meta( $font_family->ID, '_gutenberg_legacy_font_family', $font_family->post_content );

		$font_family_json = json_decode( $font_family->post_content, true );
		if ( ! $font_family_json ) {
			continue;
		}

		$font_faces = isset( $font_family_json['fontFace'] ) ? $font_family_json['fontFace'] : array();
		unset( $font_family_json['fontFace'] );

		// Save wp_font_face posts within the family.
		foreach ( $font_faces as $font_face ) {
			$args                 = array();
			$args['post_type']    = 'wp_font_face';
			$args['post_title']   = WP_Font_Utils::get_font_face_slug( $font_face );
			$args['post_name']    = sanitize_title( $args['post_title'] );
			$args['post_status']  = 'publish';
			$args['post_parent']  = $font_family->ID;
			$args['post_content'] = wp_json_encode( $font_face );

			$font_face_id = wp_insert_post( wp_slash( $args ) );

			$file_urls = (array) ( isset( $font_face['src'] ) ? $font_face['src'] : array() );

			foreach ( $file_urls as $file_url ) {
				// continue if the file is not local.
				if ( false === strpos( $file_url, site_url() ) ) {
					continue;
				}

				$relative_path = basename( $file_url );
				update_post_meta( $font_face_id, '_wp_font_face_file', $relative_path );
			}
		}

		// Update the font family post to remove the font face data.
		$args               = array();
		$args['ID']         = $font_family->ID;
		$args['post_title'] = isset( $font_family_json['name'] ) ? $font_family_json['name'] : '';
		$args['post_name']  = sanitize_title( $font_family_json['slug'] );

		unset( $font_family_json['name'] );
		unset( $font_family_json['slug'] );

		$args['post_content'] = wp_json_encode( $font_family_json );

		wp_update_post( wp_slash( $args ) );
	}

	update_option( 'gutenberg_font_family_format_converted', true );
}
add_action( 'init', 'gutenberg_convert_legacy_font_family_format' );