class-fl-builder-fonts.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. <?php
  2. /**
  3. * Helper class for font settings.
  4. *
  5. * @class FLBuilderFonts
  6. * @since 1.6.3
  7. */
  8. final class FLBuilderFonts {
  9. /**
  10. * An array of fonts / weights.
  11. * @var array
  12. */
  13. static private $fonts = array();
  14. /**
  15. * @since 1.9.5
  16. * @return void
  17. */
  18. static public function init() {
  19. add_action( 'wp_enqueue_scripts', __CLASS__ . '::combine_google_fonts', 10000 );
  20. add_action( 'wp_enqueue_scripts', __CLASS__ . '::enqueue_google_fonts', 9999 );
  21. }
  22. /**
  23. * Renders the JavasCript variable for font settings dropdowns.
  24. *
  25. * @since 1.6.3
  26. * @return void
  27. */
  28. static public function js() {
  29. $default = json_encode( apply_filters( 'fl_builder_font_families_default', FLBuilderFontFamilies::$default ) );
  30. $system = json_encode( apply_filters( 'fl_builder_font_families_system', FLBuilderFontFamilies::$system ) );
  31. $google = json_encode( apply_filters( 'fl_builder_font_families_google', FLBuilderFontFamilies::google() ) );
  32. echo 'var FLBuilderFontFamilies = { default: ' . $default . ', system: ' . $system . ', google: ' . $google . ' };';
  33. }
  34. /**
  35. * Renders a list of all available fonts.
  36. *
  37. * @since 1.6.3
  38. * @param string $font The current selected font.
  39. * @return void
  40. */
  41. static public function display_select_font( $font ) {
  42. $system_fonts = apply_filters( 'fl_builder_font_families_system', FLBuilderFontFamilies::$system );
  43. $google_fonts = apply_filters( 'fl_builder_font_families_google', FLBuilderFontFamilies::google() );
  44. echo '<option value="Default" ' . selected( 'Default', $font, false ) . '>' . __( 'Default', 'fl-builder' ) . '</option>';
  45. echo '<optgroup label="System">';
  46. foreach ( $system_fonts as $name => $variants ) {
  47. echo '<option value="' . $name . '" ' . selected( $name, $font, false ) . '>' . $name . '</option>';
  48. }
  49. echo '<optgroup label="Google">';
  50. foreach ( $google_fonts as $name => $variants ) {
  51. echo '<option value="' . $name . '" ' . selected( $name, $font, false ) . '>' . $name . '</option>';
  52. }
  53. }
  54. /**
  55. * Renders a list of all available weights for a selected font.
  56. *
  57. * @since 1.6.3
  58. * @param string $font The current selected font.
  59. * @param string $weight The current selected weight.
  60. * @return void
  61. */
  62. static public function display_select_weight( $font, $weight ) {
  63. if ( 'Default' == $font ) {
  64. echo '<option value="default" selected="selected">' . __( 'Default', 'fl-builder' ) . '</option>';
  65. } else {
  66. $system_fonts = apply_filters( 'fl_builder_font_families_system', FLBuilderFontFamilies::$system );
  67. $google_fonts = apply_filters( 'fl_builder_font_families_google', FLBuilderFontFamilies::google() );
  68. if ( array_key_exists( $font, $system_fonts ) ) {
  69. foreach ( $system_fonts[ $font ]['weights'] as $variant ) {
  70. echo '<option value="' . $variant . '" ' . selected( $variant, $weight, false ) . '>' . FLBuilderFonts::get_weight_string( $variant ) . '</option>';
  71. }
  72. } else {
  73. foreach ( $google_fonts[ $font ] as $variant ) {
  74. echo '<option value="' . $variant . '" ' . selected( $variant, $weight, false ) . '>' . FLBuilderFonts::get_weight_string( $variant ) . '</option>';
  75. }
  76. }
  77. }
  78. }
  79. /**
  80. * Returns a font weight name for a respective weight.
  81. *
  82. * @since 1.6.3
  83. * @param string $weight The selected weight.
  84. * @return string The weight name.
  85. */
  86. static public function get_weight_string( $weight ) {
  87. $weight_string = apply_filters( 'fl_builder_font_weight_strings', array(
  88. 'default' => __( 'Default', 'fl-builder' ),
  89. 'regular' => __( 'Regular', 'fl-builder' ),
  90. '100' => 'Thin 100',
  91. '200' => 'Extra-Light 200',
  92. '300' => 'Light 300',
  93. '400' => 'Normal 400',
  94. '500' => 'Medium 500',
  95. '600' => 'Semi-Bold 600',
  96. '700' => 'Bold 700',
  97. '800' => 'Extra-Bold 800',
  98. '900' => 'Ultra-Bold 900',
  99. ) );
  100. return $weight_string[ $weight ];
  101. }
  102. /**
  103. * Helper function to render css styles for a selected font.
  104. *
  105. * @since 1.6.3
  106. * @param array $font An array with font-family and weight.
  107. * @return void
  108. */
  109. static public function font_css( $font ) {
  110. $system_fonts = apply_filters( 'fl_builder_font_families_system', FLBuilderFontFamilies::$system );
  111. $css = '';
  112. if ( array_key_exists( $font['family'], $system_fonts ) ) {
  113. $css .= 'font-family: "' . $font['family'] . '",' . $system_fonts[ $font['family'] ]['fallback'] . ';';
  114. } else {
  115. $css .= 'font-family: "' . $font['family'] . '", sans-serif;';
  116. }
  117. if ( 'regular' == $font['weight'] ) {
  118. $css .= 'font-weight: normal;';
  119. } else {
  120. if ( 'i' == substr( $font['weight'], -1 ) ) {
  121. $css .= 'font-weight: ' . substr( $font['weight'], 0, -1 ) . ';';
  122. $css .= 'font-style: italic;';
  123. } else {
  124. $css .= 'font-weight: ' . $font['weight'] . ';';
  125. }
  126. }
  127. echo $css;
  128. }
  129. /**
  130. * Add fonts to the $font array for a module.
  131. *
  132. * @since 1.6.3
  133. * @param object $module The respective module.
  134. * @return void
  135. */
  136. static public function add_fonts_for_module( $module ) {
  137. $fields = FLBuilderModel::get_settings_form_fields( $module->form );
  138. foreach ( $fields as $name => $field ) {
  139. if ( 'font' == $field['type'] && isset( $module->settings->$name ) ) {
  140. self::add_font( $module->settings->$name );
  141. } elseif ( isset( $field['form'] ) ) {
  142. $form = FLBuilderModel::$settings_forms[ $field['form'] ];
  143. self::add_fonts_for_nested_module_form( $module, $form['tabs'], $name );
  144. }
  145. }
  146. }
  147. /**
  148. * Add fonts to the $font array for a nested module form.
  149. *
  150. * @since 1.8.6
  151. * @access private
  152. * @param object $module The module to add for.
  153. * @param array $form The nested form.
  154. * @param string $setting The nested form setting key.
  155. * @return void
  156. */
  157. static private function add_fonts_for_nested_module_form( $module, $form, $setting ) {
  158. $fields = FLBuilderModel::get_settings_form_fields( $form );
  159. foreach ( $fields as $name => $field ) {
  160. if ( 'font' == $field['type'] && isset( $module->settings->$setting ) ) {
  161. foreach ( $module->settings->$setting as $key => $val ) {
  162. if ( isset( $val->$name ) ) {
  163. self::add_font( (array) $val->$name );
  164. } elseif ( $name == $key && ! empty( $val ) ) {
  165. self::add_font( (array) $val );
  166. }
  167. }
  168. }
  169. }
  170. }
  171. /**
  172. * Enqueue the stylesheet for fonts.
  173. *
  174. * @since 1.6.3
  175. * @return void
  176. */
  177. static public function enqueue_styles() {
  178. return false;
  179. }
  180. /**
  181. * @since 2.1.3
  182. */
  183. static public function enqueue_google_fonts() {
  184. $google_fonts_domain = apply_filters( 'fl_builder_google_fonts_domain', '//fonts.googleapis.com/' );
  185. $google_url = $google_fonts_domain . 'css?family=';
  186. if ( count( self::$fonts ) > 0 ) {
  187. foreach ( self::$fonts as $family => $weights ) {
  188. $google_url .= $family . ':' . implode( ',', $weights ) . '|';
  189. }
  190. $google_url = substr( $google_url, 0, -1 );
  191. wp_enqueue_style( 'fl-builder-google-fonts-' . md5( $google_url ), $google_url, array() );
  192. self::$fonts = array();
  193. }
  194. }
  195. /**
  196. * Adds data to the $fonts array for a font to be rendered.
  197. *
  198. * @since 1.6.3
  199. * @param array $font an array with the font family and weight to add.
  200. * @return void
  201. */
  202. static public function add_font( $font ) {
  203. if ( is_array( $font ) && 'Default' != $font['family'] ) {
  204. $system_fonts = apply_filters( 'fl_builder_font_families_system', FLBuilderFontFamilies::$system );
  205. // check if is a Google Font
  206. if ( ! array_key_exists( $font['family'], $system_fonts ) ) {
  207. // check if font family is already added
  208. if ( array_key_exists( $font['family'], self::$fonts ) ) {
  209. // check if the weight is already added
  210. if ( ! in_array( $font['weight'], self::$fonts[ $font['family'] ] ) ) {
  211. self::$fonts[ $font['family'] ][] = $font['weight'];
  212. }
  213. } else {
  214. // adds a new font and weight
  215. self::$fonts[ $font['family'] ] = array( $font['weight'] );
  216. }
  217. }
  218. }
  219. }
  220. /**
  221. * Combines all enqueued google font HTTP calls into one URL.
  222. *
  223. * @since 1.9.5
  224. * @return void
  225. */
  226. static public function combine_google_fonts() {
  227. global $wp_styles;
  228. // Check for any enqueued `fonts.googleapis.com` from BB theme or plugin
  229. if ( isset( $wp_styles->queue ) ) {
  230. $google_fonts_domain = 'https://fonts.googleapis.com/css';
  231. $enqueued_google_fonts = array();
  232. $families = array();
  233. $subsets = array();
  234. $font_args = array();
  235. // Collect all enqueued google fonts
  236. foreach ( $wp_styles->queue as $key => $handle ) {
  237. if ( ! isset( $wp_styles->registered[ $handle ] ) || strpos( $handle, 'fl-builder-google-fonts-' ) === false ) {
  238. continue;
  239. }
  240. $style_src = $wp_styles->registered[ $handle ]->src;
  241. if ( strpos( $style_src, 'fonts.googleapis.com/css' ) !== false ) {
  242. $url = wp_parse_url( $style_src );
  243. if ( is_string( $url['query'] ) ) {
  244. parse_str( $url['query'], $parsed_url );
  245. if ( isset( $parsed_url['family'] ) ) {
  246. // Collect all subsets
  247. if ( isset( $parsed_url['subset'] ) ) {
  248. $subsets[] = urlencode( trim( $parsed_url['subset'] ) );
  249. }
  250. $font_families = explode( '|', $parsed_url['family'] );
  251. foreach ( $font_families as $parsed_font ) {
  252. $get_font = explode( ':', $parsed_font );
  253. // Extract the font data
  254. if ( isset( $get_font[0] ) && ! empty( $get_font[0] ) ) {
  255. $family = $get_font[0];
  256. $weights = isset( $get_font[1] ) && ! empty( $get_font[1] ) ? explode( ',', $get_font[1] ) : array();
  257. // Combine weights if family has been enqueued
  258. if ( isset( $enqueued_google_fonts[ $family ] ) && $weights != $enqueued_google_fonts[ $family ]['weights'] ) {
  259. $combined_weights = array_merge( $weights, $enqueued_google_fonts[ $family ]['weights'] );
  260. $enqueued_google_fonts[ $family ]['weights'] = array_unique( $combined_weights );
  261. } else {
  262. $enqueued_google_fonts[ $family ] = array(
  263. 'handle' => $handle,
  264. 'family' => $family,
  265. 'weights' => $weights,
  266. );
  267. }
  268. // Remove enqueued google font style, so we would only have one HTTP request.
  269. wp_dequeue_style( $handle );
  270. }
  271. }
  272. }
  273. }
  274. }
  275. }
  276. // Start combining all enqueued google fonts
  277. if ( count( $enqueued_google_fonts ) > 0 ) {
  278. foreach ( $enqueued_google_fonts as $family => $data ) {
  279. // Collect all family and weights
  280. if ( ! empty( $data['weights'] ) ) {
  281. $families[] = $family . ':' . implode( ',', $data['weights'] );
  282. } else {
  283. $families[] = $family;
  284. }
  285. }
  286. if ( ! empty( $families ) ) {
  287. $font_args['family'] = implode( '|', $families );
  288. if ( ! empty( $subsets ) ) {
  289. $font_args['subset'] = implode( ',', $subsets );
  290. }
  291. $src = add_query_arg( $font_args, $google_fonts_domain );
  292. // Enqueue google fonts into one URL request
  293. wp_enqueue_style(
  294. 'fl-builder-google-fonts-' . md5( $src ),
  295. $src,
  296. array()
  297. );
  298. // Clears data
  299. $enqueued_google_fonts = array();
  300. }
  301. }
  302. }
  303. }
  304. }
  305. FLBuilderFonts::init();
  306. /**
  307. * Font info class for system and Google fonts.
  308. *
  309. * @class FLFontFamilies
  310. * @since 1.6.3
  311. */
  312. final class FLBuilderFontFamilies {
  313. /**
  314. * Parse fonts.json to get all possible Google fonts.
  315. * @since 1.10.7
  316. * @return array
  317. */
  318. static function google() {
  319. $fonts = array();
  320. $json = (array) json_decode( file_get_contents( FL_BUILDER_DIR . 'json/fonts.json' ), true );
  321. foreach ( $json as $k => $font ) {
  322. $name = key( $font );
  323. foreach ( $font[ $name ] as $key => $variant ) {
  324. if ( stristr( $variant, 'italic' ) ) {
  325. unset( $font[ $name ][ $key ] );
  326. }
  327. if ( 'regular' == $variant ) {
  328. $font[ $name ][ $key ] = '400';
  329. }
  330. }
  331. $fonts[ $name ] = $font[ $name ];
  332. }
  333. return $fonts;
  334. }
  335. static public $default = array(
  336. 'Default' => array(
  337. 'default'
  338. ),
  339. );
  340. /**
  341. * Array with a list of system fonts.
  342. * @var array
  343. */
  344. static public $system = array(
  345. 'Helvetica' => array(
  346. 'fallback' => 'Verdana, Arial, sans-serif',
  347. 'weights' => array(
  348. '300',
  349. '400',
  350. '700',
  351. ),
  352. ),
  353. 'Verdana' => array(
  354. 'fallback' => 'Helvetica, Arial, sans-serif',
  355. 'weights' => array(
  356. '300',
  357. '400',
  358. '700',
  359. ),
  360. ),
  361. 'Arial' => array(
  362. 'fallback' => 'Helvetica, Verdana, sans-serif',
  363. 'weights' => array(
  364. '300',
  365. '400',
  366. '700',
  367. ),
  368. ),
  369. 'Times' => array(
  370. 'fallback' => 'Georgia, serif',
  371. 'weights' => array(
  372. '300',
  373. '400',
  374. '700',
  375. ),
  376. ),
  377. 'Georgia' => array(
  378. 'fallback' => 'Times, serif',
  379. 'weights' => array(
  380. '300',
  381. '400',
  382. '700',
  383. ),
  384. ),
  385. 'Courier' => array(
  386. 'fallback' => 'monospace',
  387. 'weights' => array(
  388. '300',
  389. '400',
  390. '700',
  391. ),
  392. ),
  393. );
  394. }