Better_Font_Awesome_Library

The Advanced Custom Fields: Font Awesome Better Font Awesome Library class.

Defined (1)

The class is defined in the following location(s).

/better-font-awesome-library/better-font-awesome-library.php  
  1. class Better_Font_Awesome_Library { 
  2.  
  3. /** 
  4. * Better Font Awesome Library slug. 
  5. * @since 1.0.0 
  6. * @var string 
  7. */ 
  8. const SLUG = 'bfa'; 
  9.  
  10. /** 
  11. * Better Font Awesome Library version slug. 
  12. * @since 1.0.0 
  13. * @var string 
  14. */ 
  15. const VERSION = '1.0.0'; 
  16.  
  17. /** 
  18. * jsDelivr API URL for Font Awesome version info. 
  19. * @since 1.0.0 
  20. * @var string 
  21. */ 
  22. const JSDELIVR_API_URL = 'http://api.jsdelivr.com/v1/jsdelivr/libraries/fontawesome/?fields=versions, lastversion'; 
  23.  
  24. /** 
  25. * Initialization args. 
  26. * @since 1.0.0 
  27. * @var array 
  28. */ 
  29. private $args; 
  30.  
  31. /** 
  32. * Default args to use if any $arg isn't specified. 
  33. * @since 1.0.0 
  34. * @var array 
  35. */ 
  36. private $default_args = array( 
  37. 'version' => 'latest',  
  38. 'minified' => true,  
  39. 'remove_existing_fa' => false,  
  40. 'load_styles' => true,  
  41. 'load_admin_styles' => true,  
  42. 'load_shortcode' => true,  
  43. 'load_tinymce_plugin' => true,  
  44. ); 
  45.  
  46. /** 
  47. * Root URL of the library. 
  48. * @since 1.0.4 
  49. * @var string 
  50. */ 
  51. private $root_url; 
  52.  
  53. /** 
  54. * Args for wp_remote_get() calls. 
  55. * @since 1.0.0 
  56. * @var array 
  57. */ 
  58. private $wp_remote_get_args = array( 
  59. 'timeout' => 10,  
  60. 'sslverify' => false,  
  61. ); 
  62.  
  63. /** 
  64. * Array to hold the jsDelivr API data. 
  65. * @since 1.0.0 
  66. * @var string 
  67. */ 
  68. private $api_data = array(); 
  69.  
  70. /** 
  71. * Version of Font Awesome being used. 
  72. * @since 1.0.0 
  73. * @var string 
  74. */ 
  75. private $font_awesome_version; 
  76.  
  77. /** 
  78. * Font Awesome stylesheet URL. 
  79. * @since 1.0.0 
  80. * @var string 
  81. */ 
  82. private $stylesheet_url; 
  83.  
  84. /** 
  85. * Font Awesome CSS. 
  86. * @since 1.0.0 
  87. * @var string 
  88. */ 
  89. private $css; 
  90.  
  91. /** 
  92. * Data associated with the local fallback version of Font Awesome. 
  93. * @since 1.0.0 
  94. * @var string 
  95. */ 
  96. private $fallback_data = array( 
  97. 'directory' => 'lib/fallback-font-awesome/',  
  98. 'path' => '',  
  99. 'url' => '',  
  100. 'version' => '',  
  101. 'css' => '',  
  102. ); 
  103.  
  104. /** 
  105. * Array of available Font Awesome icon slugs. 
  106. * @since 1.0.0 
  107. * @var string 
  108. */ 
  109. private $icons = array(); 
  110.  
  111. /** 
  112. * Font Awesome prefix to be used ('icon' or 'fa'). 
  113. * @since 1.0.0 
  114. * @var string 
  115. */ 
  116. private $prefix; 
  117.  
  118. /** 
  119. * Array to track errors and wp_remote_get() failures. 
  120. * @since 1.0.0 
  121. * @var array 
  122. */ 
  123. private $errors = array(); 
  124.  
  125. /** 
  126. * Instance of this class. 
  127. * @since 1.0.0 
  128. * @var Better_Font_Awesome_Library 
  129. */ 
  130. private static $instance = null; 
  131.  
  132. /** 
  133. * Returns the instance of this class, and initializes 
  134. * the instance if it doesn't already exist. 
  135. * @since 1.0.0 
  136. * @return Better_Font_Awesome_Library The BFAL object. 
  137. */ 
  138. public static function get_instance( $args = array() ) { 
  139.  
  140. // If the single instance hasn't been set, set it now. 
  141. if ( null == self::$instance ) { 
  142. self::$instance = new self( $args ); 
  143.  
  144. return self::$instance; 
  145.  
  146.  
  147. /** 
  148. * Better Font Awesome Library constructor. 
  149. * @since 1.0.0 
  150. * @param array $args Initialization arguments. 
  151. */ 
  152. private function __construct( $args = array() ) { 
  153.  
  154. // Get initialization args. 
  155. $this->args = $args; 
  156.  
  157. // Load the library functionality. 
  158. $this->load(); 
  159.  
  160.  
  161. /** 
  162. * Set up all plugin library functionality. 
  163. * @since 1.0.0 
  164. */ 
  165. public function load() { 
  166.  
  167. // Initialize library properties and actions as needed. 
  168. $this->initialize( $this->args ); 
  169.  
  170. // Use the jsDelivr API to fetch info on the jsDelivr Font Awesome CDN. 
  171. $this->setup_api_data(); 
  172.  
  173. // Set the version of Font Awesome to be used. 
  174. $this->set_active_version(); 
  175.  
  176. // Set the URL for the Font Awesome stylesheet. 
  177. $this->set_stylesheet_url( $this->font_awesome_version ); 
  178.  
  179. // Get stylesheet and generate list of available icons in Font Awesome stylesheet. 
  180. $this->setup_stylesheet_data(); 
  181.  
  182. // Add Font Awesome and/or custom CSS to the editor. 
  183. $this->add_editor_styles(); 
  184.  
  185. // Output any necessary admin notices. 
  186. add_action( 'admin_notices', array( $this, 'do_admin_notice' ) ); 
  187.  
  188. /** 
  189. * Remove existing Font Awesome CSS and shortcodes if needed. 
  190. * Use priority 15 to ensure this is done after other plugin 
  191. * CSS/shortcodes are loaded. This must run before any other 
  192. * style/script/shortcode actions so it doesn't accidentally 
  193. * remove them. 
  194. */ 
  195. if ( $this->args['remove_existing_fa'] ) { 
  196.  
  197. add_action( 'wp_enqueue_scripts', array( $this, 'remove_font_awesome_css' ), 15 ); 
  198. add_action( 'init', array( $this, 'remove_icon_shortcode' ), 20 ); 
  199.  
  200.  
  201. /** 
  202. * Load front-end scripts and styles. 
  203. * Use priority 15 to make sure styles/scripts load after other plugins. 
  204. */ 
  205. if ( $this->args['load_styles'] || $this->args['remove_existing_fa'] ) { 
  206. add_action( 'wp_enqueue_scripts', array( $this, 'register_font_awesome_css' ), 15 ); 
  207.  
  208. /** 
  209. * Load admin scripts and styles. 
  210. * Use priority 15 to make sure styles/scripts load after other plugins. 
  211. */ 
  212. if ( $this->args['load_admin_styles'] || $this->args['load_tinymce_plugin'] ) { 
  213. add_action( 'admin_enqueue_scripts', array( $this, 'register_font_awesome_css' ), 15 ); 
  214.  
  215. /** 
  216. * Add [icon] shortcode. 
  217. * Use priority 15 to ensure this is done after removing existing Font 
  218. * Awesome CSS and shortcodes. 
  219. */ 
  220. if ( $this->args['load_shortcode'] || $this->args['load_tinymce_plugin'] ) { 
  221. add_action( 'init', array( $this, 'add_icon_shortcode' ), 20 ); 
  222.  
  223. // Load TinyMCE functionality. 
  224. if ( $this->args['load_tinymce_plugin'] ) { 
  225.  
  226. add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) ); 
  227.  
  228. // Add shortcode insertion button. 
  229. add_action( 'media_buttons', array( $this, 'add_insert_shortcode_button' ), 99 ); 
  230.  
  231.  
  232.  
  233. /** 
  234. * Do necessary initialization actions. 
  235. * @since 1.0.0 
  236. */ 
  237. private function initialize( $args ) { 
  238.  
  239. // Parse the initialization args with the defaults. 
  240. $this->parse_args( $args ); 
  241.  
  242. // Setup root URL, which differs for plugins vs. themes. 
  243. $this->setup_root_url(); 
  244.  
  245. // Set fallback stylesheet directory URL and path. 
  246. $this->setup_fallback_data(); 
  247.  
  248.  
  249. /** 
  250. * Parse the initialization args with the defaults and apply bfa_args filter. 
  251. * @since 1.0.0 
  252. * @param array $args Args used to initialize BFAL. 
  253. */ 
  254. private function parse_args( $args = array() ) { 
  255.  
  256. // Parse initialization args with defaults. 
  257. $this->args = wp_parse_args( $args, $this->default_args ); 
  258.  
  259. /** 
  260. * Filter the initialization args. 
  261. * @since 1.0.0 
  262. * @param array $this->args BFAL initialization args. 
  263. */ 
  264. $this->args = apply_filters( 'bfa_init_args', $this->args ); 
  265.  
  266. /** 
  267. * Filter the wp_remote_get args. 
  268. * @since 1.0.0 
  269. * @param array $this->wp_remote_get_args BFAL wp_remote_get_args args. 
  270. */ 
  271. $this->wp_remote_get_args = apply_filters( 'bfa_wp_remote_get_args', $this->wp_remote_get_args ); 
  272.  
  273.  
  274. /** 
  275. * Set up root URL for library, which differs for plugins vs. themes. 
  276. * @since 1.0.4 
  277. */ 
  278. function setup_root_url() { 
  279.  
  280. // Get BFA directory and theme root directory paths. 
  281. $bfa_directory = dirname(__FILE__); 
  282. $theme_directory = get_stylesheet_directory(); 
  283. $plugin_dir = plugin_dir_url( __FILE__ ); 
  284.  
  285. /** 
  286. * Check if we're inside a theme or plugin. 
  287. * If we're in a theme, than plugin_dir_url() will return a 
  288. * funky URL that includes the actual file path (e.g. 
  289. * /srv/www/site_name/wp-content/...) 
  290. */ 
  291. $is_theme = false; 
  292. if ( strpos( $plugin_dir, $bfa_directory ) !== false ) { 
  293. $is_theme = true; 
  294.  
  295. // First check if we're inside a theme. 
  296. if ( $is_theme ) { 
  297.  
  298. // Get relative BFA directory by removing theme root directory path. 
  299. $bfa_rel_path = str_replace( $theme_directory, '', $bfa_directory ); 
  300. $this->root_url = trailingslashit( get_stylesheet_directory_uri() . $bfa_rel_path ); 
  301.  
  302. } else { // Otherwise we're inside a plugin. 
  303.  
  304. $this->root_url = trailingslashit( plugin_dir_url( __FILE__ ) ); 
  305.  
  306.  
  307.  
  308. /** 
  309. * Set up data for the local fallback version of Font Awesome. 
  310. * @since 1.0.0 
  311. */ 
  312. private function setup_fallback_data() { 
  313.  
  314. // Set fallback directory path. 
  315. $directory_path = plugin_dir_path( __FILE__ ) . $this->fallback_data['directory']; 
  316.  
  317. /** 
  318. * Filter directory path. 
  319. * @since 1.0.0 
  320. * @param string $directory_path The path to the fallback Font Awesome directory. 
  321. */ 
  322. $directory_path = trailingslashit( apply_filters( 'bfa_fallback_directory_path', $directory_path ) ); 
  323.  
  324. // Set fallback path and URL. 
  325. $this->fallback_data['path'] = $directory_path . 'css/font-awesome' . $this->get_min_suffix() . '.css'; 
  326. $this->fallback_data['url'] = $this->root_url . $this->fallback_data['directory'] . 'css/font-awesome' . $this->get_min_suffix() . '.css'; 
  327.  
  328. // Get the fallback version based on package.json. 
  329. $fallback_json_file_path = $directory_path . 'package.json'; 
  330. $fallback_data = json_decode( $this->get_local_file_contents( $fallback_json_file_path ) ); 
  331. $this->fallback_data['version'] = $fallback_data->version; 
  332.  
  333. // Get the fallback CSS. 
  334. $this->fallback_data['css'] = $this->get_fallback_css(); 
  335.  
  336.  
  337. /** 
  338. * Set up data for all versions of Font Awesome available on the jsDelivr 
  339. * CDN. 
  340. * Uses the jsDelivr API. 
  341. * @since 1.0.0 
  342. */ 
  343. private function setup_api_data() { 
  344. $this->api_data = $this->fetch_api_data( self::JSDELIVR_API_URL ); 
  345.  
  346. /** 
  347. * Fetch the jsDelivr API data. 
  348. * First check to see if the api-versions transient is set, and if not use 
  349. * the jsDelivr API to retrieve all available versions of Font Awesome. 
  350. * @since 1.0.0 
  351. * @return array|WP_ERROR Available CDN Font Awesome versions, or a 
  352. * WP_ERROR if the fetch fails. 
  353. */ 
  354. private function fetch_api_data( $url ) { 
  355.  
  356. if ( false === ( $response = get_transient( self::SLUG . '-api-versions' ) ) ) { 
  357.  
  358. $response = wp_remote_get( $url, $this->wp_remote_get_args ); 
  359.  
  360. if ( 200 == wp_remote_retrieve_response_code( $response ) ) { 
  361.  
  362. // Decode the API data and grab the versions info. 
  363. $json_data = json_decode( wp_remote_retrieve_body( $response ) ); 
  364. $response = $json_data[0]; 
  365.  
  366. /** 
  367. * Filter the API transient expiration. 
  368. * @since 1.0.0 
  369. * @param int Expiration for API transient. 
  370. */ 
  371. $transient_expiration = apply_filters( 'bfa_api_transient_expiration', 12 * HOUR_IN_SECONDS ); 
  372.  
  373. // Set the API transient. 
  374. set_transient( self::SLUG . '-api-versions', $response, $transient_expiration ); 
  375.  
  376. } elseif ( is_wp_error( $response ) ) { // Check for faulty wp_remote_get() 
  377.  
  378. $this->set_error( 'api', $response->get_error_code(), $response->get_error_message() . " (URL: $url)" ); 
  379. $response = ''; 
  380.  
  381. } elseif ( isset( $response['response'] ) ) { // Check for 404 and other non-WP_ERROR codes 
  382.  
  383. $this->set_error( 'api', $response['response']['code'], $response['response']['message'] . " (URL: $url)" ); 
  384. $response = ''; 
  385.  
  386. } else { // Total failsafe 
  387.  
  388. $this->set_error( 'api', 'Unknown', __( 'The jsDelivr API servers appear to be temporarily unavailable.', 'better-font-awesome' ) . " (URL: $url)" ); 
  389. $response = ''; 
  390.  
  391.  
  392.  
  393. return $response; 
  394.  
  395.  
  396. /** 
  397. * Set the version of Font Awesome to use. 
  398. * @since 1.0.0 
  399. */ 
  400. private function set_active_version() { 
  401.  
  402. if ( 'latest' == $this->args['version'] ) { 
  403. $this->font_awesome_version = $this->get_latest_version(); 
  404. } else { 
  405. $this->font_awesome_version = $this->args['version']; 
  406.  
  407.  
  408. /** 
  409. * Get the latest available Font Awesome version. 
  410. * @since 1.0.0 
  411. * @return string Latest available Font Awesome version, either via the 
  412. * jsDelivr API data (if available), or a best guess based on transient and 
  413. * fallback version data. 
  414. */ 
  415. private function get_latest_version() { 
  416.  
  417. if ( $this->api_data_exists() ) { 
  418. return $this->get_api_value( 'lastversion' ); 
  419. } else { 
  420. return $this->guess_latest_version(); 
  421.  
  422.  
  423. /** 
  424. * Guess the latest Font Awesome version. 
  425. * Check both the transient Font Awesome CSS array and the locally-hosted 
  426. * version of Font Awesome to determine the latest listed version. 
  427. * @since 1.0.0 
  428. * @return string Latest transient or fallback version of Font Awesome CSS. 
  429. */ 
  430. private function guess_latest_version() { 
  431.  
  432. $css_transient_latest_version = $this->get_css_transient_latest_version(); 
  433.  
  434. if ( version_compare( $css_transient_latest_version, $this->fallback_data['version'], '>' ) ) { 
  435. return $css_transient_latest_version; 
  436. } else { 
  437. return $this->fallback_data['version']; 
  438.  
  439.  
  440. /** 
  441. * Get the latest version saved in the CSS transient. 
  442. * @since 1.0.0 
  443. * @return string Latest version key in the CSS transient array. 
  444. * Return '0' if the CSS transient isn't set. 
  445. */ 
  446. private function get_css_transient_latest_version() { 
  447.  
  448. $transient_css_array = get_transient( self::SLUG . '-css' ); 
  449.  
  450. if ( ! empty( $transient_css_array ) ) { 
  451. return max( array_keys( $transient_css_array ) ); 
  452. } else { 
  453. return '0'; 
  454.  
  455.  
  456. /** 
  457. * Determine the remote Font Awesome stylesheet URL based on the selected 
  458. * version. 
  459. * @since 1.0.0 
  460. * @param string $version Version of Font Awesome to use. 
  461. */ 
  462. private function set_stylesheet_url( $version ) { 
  463. $this->stylesheet_url = '//cdn.jsdelivr.net/fontawesome/' . $version . '/css/font-awesome' . $this->get_min_suffix() . '.css'; 
  464.  
  465. /** 
  466. * Get stylesheet CSS and populate icons array. 
  467. * @since 1.0.0 
  468. */ 
  469. private function setup_stylesheet_data() { 
  470.  
  471. // Get the Font Awesome CSS. 
  472. $this->css = $this->get_css( $this->stylesheet_url, $this->font_awesome_version ); 
  473.  
  474. // Get the list of available icons from the Font Awesome CSS. 
  475. $this->icons = $this->setup_icon_array( $this->css ); 
  476.  
  477. // Set up prefix based on version ('fa' or 'icon'). 
  478. $this->prefix = $this->setup_prefix( $this->font_awesome_version ); 
  479.  
  480.  
  481. /** 
  482. * Get the Font Awesome CSS. 
  483. * @since 1.0.0 
  484. * @param string $url URL of the remote stylesheet. 
  485. * @param string $version Version of Font Awesome to fetch. 
  486. * @return string $response Font Awesome CSS, from either: 
  487. * 1. transient,  
  488. * 2. wp_remote_get(), or 
  489. * 3. fallback CSS. 
  490. */ 
  491. private function get_css( $url, $version ) { 
  492.  
  493. // First try getting the transient CSS. 
  494. $response = $this->get_transient_css( $version ); 
  495.  
  496. // Next, try fetching the CSS from the remote jsDelivr CDN. 
  497. if ( ! $response ) { 
  498. $response = $this->get_remote_css( $url, $version ); 
  499.  
  500. /** 
  501. * Filter the force fallback flag. 
  502. * @since 1.0.4 
  503. * @param bool Whether or not to force the fallback CSS. 
  504. */ 
  505. $force_fallback = apply_filters( 'bfa_force_fallback', false ); 
  506.  
  507. /** 
  508. * Use the local fallback if both the transient and wp_remote_get() 
  509. * methods fail, or if fallback is forced with bfa_force_fallback filter. 
  510. */ 
  511. if ( is_wp_error( $response ) || $force_fallback ) { 
  512.  
  513. // Log the CSS fetch error. 
  514. if ( ! $force_fallback ) { 
  515. $this->set_error( 'css', $response->get_error_code(), $response->get_error_message() . " (URL: $url)" ); 
  516.  
  517. // Use the local fallback CSS. 
  518. $response = $this->fallback_data['css']; 
  519.  
  520. // Update the version string to match the fallback version. 
  521. $this->font_awesome_version = $this->fallback_data['version']; 
  522.  
  523. // Update the stylesheet URL to match the fallback version. 
  524. $this->stylesheet_url = $this->fallback_data['url']; 
  525.  
  526. return $response; 
  527.  
  528.  
  529. /** 
  530. * Get the transient copy of the CSS for the specified version. 
  531. * @since 1.0.0 
  532. * @param string $version Font Awesome version to check. 
  533. * @return string Transient CSS if it exists, otherwise null. 
  534. */ 
  535. private function get_transient_css( $version ) { 
  536.  
  537. $transient_css_array = get_transient( self::SLUG . '-css' ); 
  538. return isset( $transient_css_array[ $version ] ) ? $transient_css_array[ $version ] : ''; 
  539.  
  540.  
  541. /** 
  542. * Get the CSS from the remote jsDelivr CDN. 
  543. * @since 1.0.0 
  544. * @param string $url URL for the remote stylesheet. 
  545. * @param string $version Font Awesome version to fetch. 
  546. * @return string|WP_ERROR $response Remote CSS, or WP_ERROR if 
  547. * wp_remote_get() fails. 
  548. */ 
  549. private function get_remote_css( $url, $version ) { 
  550.  
  551. // Get the remote Font Awesome CSS. 
  552. $url = set_url_scheme( $url ); 
  553. $response = wp_remote_get( $url, $this->wp_remote_get_args ); 
  554.  
  555. /** 
  556. * If fetch was successful, return the remote CSS, and set the CSS 
  557. * transient for this version. Otherwise, return a WP_Error object. 
  558. */ 
  559. if ( 200 == wp_remote_retrieve_response_code( $response ) ) { 
  560.  
  561. $response = wp_remote_retrieve_body( $response ); 
  562. $this->set_css_transient( $version, $response ); 
  563.  
  564. } elseif ( is_wp_error( $response ) ) { // Check for faulty wp_remote_get() 
  565. $response = $response; 
  566. } elseif ( isset( $response['response'] ) ) { // Check for 404 and other non-WP_ERROR codes 
  567. $response = new WP_Error( $response['response']['code'], $response['response']['message'] . " (URL: $url)" ); 
  568. } else { // Total failsafe 
  569. $response = ''; 
  570.  
  571. return $response; 
  572.  
  573.  
  574. /** 
  575. * Set the CSS transient array. 
  576. * @since 1.0.0 
  577. * @param string $version Version of Font Awesome for which to set the 
  578. * transient. 
  579. * @param string $value CSS for corresponding version of Font Awesome. 
  580. */ 
  581. private function set_css_transient( $version, $value ) { 
  582.  
  583. /** 
  584. * Get the transient array, which contains data for multiple Font 
  585. * Awesome version. 
  586. */ 
  587. $transient_css_array = get_transient( self::SLUG . '-css' ); 
  588.  
  589. // Set the new value for the specified Font Awesome version. 
  590. $transient_css_array[ $version ] = $value; 
  591.  
  592. /** 
  593. * Filter the CSS transient expiration. 
  594. * @since 1.0.0 
  595. * @param int Expiration for the CSS transient. 
  596. */ 
  597. $transient_expiration = apply_filters( 'bfa_css_transient_expiration', 30 * DAY_IN_SECONDS ); 
  598.  
  599. // Set the new CSS array transient. 
  600. set_transient( self::SLUG . '-css', $transient_css_array, $transient_expiration ); 
  601.  
  602.  
  603. /** 
  604. * Get the CSS of the local fallback Font Awesome version. 
  605. * @since 1.0.0 
  606. * @return string Contents of the local fallback Font Awesome stylesheet. 
  607. */ 
  608. private function get_fallback_css() { 
  609. return $this->get_local_file_contents( $this->fallback_data['path'] ); 
  610.  
  611. /** 
  612. * Get array of icons from the Font Awesome CSS. 
  613. * @since 1.0.0 
  614. * @param string $css The Font Awesome CSS. 
  615. * @return array All available icon names (e.g. adjust, car, pencil). 
  616. */ 
  617. private function setup_icon_array( $css ) { 
  618.  
  619. $icons = array(); 
  620. $hex_codes = array(); 
  621.  
  622. /** 
  623. * Get all CSS selectors that have a "content:" pseudo-element rule,  
  624. * as well as all associated hex codes. 
  625. */ 
  626. preg_match_all( '/\.(icon-|fa-)([^, }]*)\s*:before\s*{\s*(content:)\s*"(\\\\[^"]+)"/s', $css, $matches ); 
  627. $icons = $matches[2]; 
  628. $hex_codes = $matches[4]; 
  629.  
  630. // Add hex codes as icon array index. 
  631. $icons = array_combine( $hex_codes, $icons ); 
  632.  
  633. // Alphabetize the icons array by icon name. 
  634. asort( $icons ); 
  635.  
  636. /** 
  637. * Filter the array of available icons. 
  638. * @since 1.0.0 
  639. * @param array $icons Array of all available icons. 
  640. */ 
  641. $icons = apply_filters( 'bfa_icon_list', $icons ); 
  642.  
  643. return $icons; 
  644.  
  645.  
  646. /** 
  647. * Get the Font Awesosome prefix ('fa' or 'icon'). 
  648. * @since 1.0.0 
  649. * @param string $version Font Awesome version being used. 
  650. * @return string $prefix 'fa' or 'icon', depending on the version. 
  651. */ 
  652. private function setup_prefix( $version ) { 
  653.  
  654. if ( 0 <= version_compare( $version, '4' ) ) { 
  655. $prefix = 'fa'; 
  656. } else { 
  657. $prefix = 'icon'; 
  658.  
  659. /** 
  660. * Filter the Font Awesome prefix. 
  661. * @since 1.0.0 
  662. * @param string $prefix Font Awesome prefix ('icon' or 'fa'). 
  663. */ 
  664. $prefix = apply_filters( 'bfa_prefix', $prefix ); 
  665.  
  666. return $prefix; 
  667.  
  668.  
  669. /** 
  670. * Remove styles that include 'fontawesome' or 'font-awesome' in their slug. 
  671. * @since 1.0.0 
  672. */ 
  673. public function remove_font_awesome_css() { 
  674.  
  675. global $wp_styles; 
  676.  
  677. // Loop through all registered styles and remove any that appear to be Font Awesome. 
  678. foreach ( $wp_styles->registered as $script => $details ) { 
  679.  
  680. if ( false !== strpos( $script, 'fontawesome' ) || false !== strpos( $script, 'font-awesome' ) ) { 
  681. wp_dequeue_style( $script ); 
  682.  
  683.  
  684.  
  685. /** 
  686. * Remove [icon] shortcode. 
  687. * @since 1.0.0 
  688. */ 
  689. public function remove_icon_shortcode() { 
  690. remove_shortcode( 'icon' ); 
  691.  
  692. /** 
  693. * Add [icon] shortcode. 
  694. * Usage: 
  695. * [icon name="flag" class="fw 2x spin" unprefixed_class="custom_class"] 
  696. * @since 1.0.0 
  697. */ 
  698. public function add_icon_shortcode() { 
  699. add_shortcode( 'icon', array( $this, 'render_shortcode' ) ); 
  700.  
  701. /** 
  702. * Render [icon] shortcode. 
  703. * Usage: 
  704. * [icon name="flag" class="fw 2x spin" unprefixed_class="custom_class"] 
  705. * @param array $atts Shortcode attributes. 
  706. * @return string $output Icon HTML (e.g. <i class="fa fa-car"></i>). 
  707. */ 
  708. public function render_shortcode( $atts ) { 
  709.  
  710. extract( shortcode_atts( array( 
  711. 'name' => '',  
  712. 'class' => '',  
  713. 'unprefixed_class' => '',  
  714. 'title' => '', /** For compatibility with other plugins */ 
  715. 'size' => '', /** For compatibility with other plugins */ 
  716. 'space' => '',  
  717. ), $atts ) 
  718. ); 
  719.  
  720. /** 
  721. * Include for backwards compatibility with Font Awesome More Icons plugin. 
  722. * @see https://wordpress.org/plugins/font-awesome-more-icons/ 
  723. */ 
  724. $title = $title ? 'title="' . $title . '" ' : ''; 
  725. $space = 'true' == $space ? ' ' : ''; 
  726. $size = $size ? ' '. $this->prefix . '-' . $size : ''; 
  727.  
  728. // Remove "icon-" and "fa-" from name 
  729. // This helps both: 
  730. // 1. Incorrect shortcodes (when user includes full class name including prefix) 
  731. // 2. Old shortcodes from other plugins that required prefixes 
  732.  
  733. /** 
  734. * Strip 'icon-' and 'fa-' from the BEGINNING of $name. 
  735. * This corrects for: 
  736. * 1. Incorrect shortcodes (when user includes full class name including prefix) 
  737. * 2. Old shortcodes from other plugins that required prefixes 
  738. */ 
  739. $prefixes = array( 'icon-', 'fa-' ); 
  740. foreach ( $prefixes as $prefix ) { 
  741.  
  742. if ( substr( $name, 0, strlen( $prefix ) ) == $prefix ) { 
  743. $name = substr( $name, strlen( $prefix ) ); 
  744.  
  745.  
  746. $name = str_replace( 'fa-', '', $name ); 
  747.  
  748. // Add the version-specific prefix back on to $name, if it exists. 
  749. $icon_name = $this->prefix ? $this->prefix . '-' . $name : $name; 
  750.  
  751. // Remove "icon-" and "fa-" from the icon class. 
  752. $class = str_replace( 'icon-', '', $class ); 
  753. $class = str_replace( 'fa-', '', $class ); 
  754.  
  755. // Remove extra spaces from the icon class. 
  756. $class = trim( $class ); 
  757. $class = preg_replace( '/\s{3, }/', ' ', $class ); 
  758.  
  759. // Add the version-specific prefix back on to each class. 
  760. $class_array = explode( ' ', $class ); 
  761. foreach ( $class_array as $index => $class ) { 
  762. $class_array[ $index ] = $this->prefix ? $this->prefix . '-' . $class : $class; 
  763. $class = implode( ' ', $class_array ); 
  764.  
  765. // Add unprefixed classes. 
  766. $class .= $unprefixed_class ? ' ' . $unprefixed_class : ''; 
  767.  
  768. /** 
  769. * Filter the icon class. 
  770. * @since 1.0.0 
  771. * @param string $class Classes attached to the icon. 
  772. */ 
  773. $class = apply_filters( 'bfa_icon_class', $class, $name ); 
  774.  
  775. // Generate the HTML <i> icon element output. 
  776. $output = sprintf( '<i class="%s %s %s %s" %s>%s</i>',  
  777. $this->prefix,  
  778. $icon_name,  
  779. $class,  
  780. $size,  
  781. $title,  
  782. $space 
  783. ); 
  784.  
  785. /** 
  786. * Filter the icon output. 
  787. * @since 1.0.0 
  788. * @param string $output Icon output. 
  789. */ 
  790. return apply_filters( 'bfa_icon', $output ); 
  791.  
  792.  
  793. /** 
  794. * Register and enqueue Font Awesome CSS. 
  795. */ 
  796. public function register_font_awesome_css() { 
  797.  
  798. wp_register_style( self::SLUG . '-font-awesome', $this->stylesheet_url, '', $this->font_awesome_version ); 
  799. wp_enqueue_style( self::SLUG . '-font-awesome' ); 
  800.  
  801.  
  802. /** 
  803. * Add Font Awesome CSS to TinyMCE. 
  804. * @since 1.0.0 
  805. */ 
  806. public function add_editor_styles() { 
  807. add_editor_style( $this->stylesheet_url ); 
  808.  
  809. /** 
  810. * Load admin CSS. 
  811. * @since 1.0.0 
  812. */ 
  813. public function enqueue_admin_scripts() { 
  814.  
  815. // Check whether to get minified or non-minified files. 
  816. $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min'; 
  817.  
  818. // Custom admin CSS. 
  819. wp_enqueue_style( self::SLUG . '-admin', $this->root_url . 'css/admin-styles.css' ); 
  820.  
  821. // Custom admin JS. 
  822. wp_enqueue_script( self::SLUG . '-admin', $this->root_url . 'js/admin.js' ); 
  823.  
  824. // Icon picker JS and CSS. 
  825. wp_enqueue_style( 'fontawesome-iconpicker', $this->root_url . 'lib/fontawesome-iconpicker/css/fontawesome-iconpicker' . $suffix . '.css' ); 
  826. wp_enqueue_script( 'fontawesome-iconpicker', $this->root_url . 'lib/fontawesome-iconpicker/js/fontawesome-iconpicker' . $suffix . '.js' ); 
  827.  
  828. // Output PHP variables to JS. 
  829. $bfa_vars = array( 
  830. 'fa_prefix' => $this->prefix,  
  831. 'fa_icons' => $this->get_icons(),  
  832. ); 
  833. wp_localize_script( self::SLUG . '-admin', 'bfa_vars', $bfa_vars ); 
  834.  
  835.  
  836. /** 
  837. * [add_insert_shortcode_button description] 
  838. * @since 1.3.0 
  839. */ 
  840. public function add_insert_shortcode_button() { 
  841.  
  842. ob_start(); 
  843. ?> 
  844. <span class="bfa-iconpicker fontawesome-iconpicker" data-selected="fa-flag"> 
  845. <a href="#" class="button button-secondary iconpicker-component"> 
  846. <span class="fa icon fa-flag icon-flag"></span>  
  847. <?php esc_html_e( 'Insert Icon', 'better-font-awesome' ); ?> 
  848. <i class="change-icon-placeholder"></i> 
  849. </a> 
  850. </span> 
  851. <?php 
  852. echo ob_get_clean(); 
  853.  
  854.  
  855. /** 
  856. * Generate admin notices. 
  857. * @since 1.0.0 
  858. */ 
  859. public function do_admin_notice() { 
  860.  
  861. if ( ! empty( $this->errors ) && apply_filters( 'bfa_show_errors', true ) ) : 
  862. ?> 
  863. <div class="error"> 
  864. <p> 
  865. <b><?php _e( 'Better Font Awesome', 'better-font-awesome' ); ?></b> 
  866. </p> 
  867.  
  868. <!-- API Error --> 
  869. <?php if ( is_wp_error ( $this->get_error('api') ) ) : ?> 
  870. <p> 
  871. <b><?php _e( 'API Error', 'better-font-awesome' ); ?></b><br /> 
  872. <?php 
  873. printf( __( 'The attempt to reach the jsDelivr API server failed with the following error: %s', 'better-font-awesome' ),  
  874. '<code>' . $this->get_error('api')->get_error_code() . ': ' . $this->get_error('api')->get_error_message() . '</code>' 
  875. ); 
  876. ?> 
  877. </p> 
  878. <?php endif; ?> 
  879.  
  880. <!-- CSS Error --> 
  881. <?php if ( is_wp_error ( $this->get_error('css') ) ) : ?> 
  882. <p> 
  883. <b><?php _e( 'Remote CSS Error', 'better-font-awesome' ); ?></b><br /> 
  884. <?php 
  885. printf( __( 'The attempt to fetch the remote Font Awesome stylesheet failed with the following error: %s %s The embedded fallback Font Awesome will be used instead (version: %s).', 'better-font-awesome' ),  
  886. '<code>' . $this->get_error('css')->get_error_code() . ': ' . $this->get_error('css')->get_error_message() . '</code>',  
  887. '<br />',  
  888. '<code>' . $this->font_awesome_version . '</code>' 
  889. ); 
  890. ?> 
  891. </p> 
  892. <?php endif; ?> 
  893.  
  894. <!-- Fallback Text --> 
  895. <p><?php echo __( '<b>Don\'t worry! Better Font Awesome will still render using the included fallback version:</b> ', 'better-font-awesome' ) . '<code>' . $this->fallback_data['version'] . '</code>' ; ?></p> 
  896.  
  897. <!-- Solution Text --> 
  898. <p> 
  899. <b><?php _e( 'Solution', 'better-font-awesome' ); ?></b><br /> 
  900. <?php 
  901. printf( __( 'This may be the result of a temporary server or connectivity issue which will resolve shortly. However if the problem persists please file a support ticket on the %splugin forum%s, citing the errors listed above. ', 'better-font-awesome' ),  
  902. '<a href="http://wordpress.org/support/plugin/better-font-awesome" target="_blank" title="Better Font Awesome support forum">',  
  903. '</a>' 
  904. ); 
  905. ?> 
  906. </p> 
  907. </div> 
  908. <?php 
  909. endif; 
  910.  
  911. /**----------------------------------------------------------------------------* 
  912. * Helper Functions 
  913. *----------------------------------------------------------------------------*/ 
  914.  
  915. /** 
  916. * Get the contents of a local file. 
  917. * @since 1.0.0 
  918. * @param string $file_path Path to local file. 
  919. * @return string $contents Content of local file. 
  920. */ 
  921. private function get_local_file_contents( $file_path ) { 
  922.  
  923. ob_start(); 
  924. include $file_path; 
  925. $contents = ob_get_clean(); 
  926.  
  927. return $contents; 
  928.  
  929.  
  930. /** 
  931. * Determine whether or not to use the .min suffix on Font Awesome 
  932. * stylesheet URLs. 
  933. * @since 1.0.0 
  934. * @return string '.min' if minification is specified, empty string if not. 
  935. */ 
  936. private function get_min_suffix() { 
  937. return ( $this->args['minified'] ) ? '.min' : ''; 
  938.  
  939. /** 
  940. * Add an error to the $this->errors array. 
  941. * @since 1.0.0 
  942. * @param string $error_type Type of error (api, css, etc). 
  943. * @param string $code Error code. 
  944. * @param string $message Error message. 
  945. */ 
  946. private function set_error( $error_type, $code, $message ) { 
  947. $this->errors[ $error_type ] = new WP_Error( $code, $message ); 
  948.  
  949. /** 
  950. * Retrieve a library error. 
  951. * @since 1.0.0 
  952. * @param string $process Slug of the process to check (e.g. 'api'). 
  953. * @return WP_ERROR The error for the specified process. 
  954. */ 
  955. public function get_error( $process ) { 
  956. return isset( $this->errors[ $process ] ) ? $this->errors[ $process ] : ''; 
  957.  
  958. /** 
  959. * Check if API version data has been retrieved. 
  960. * @since 1.0.0 
  961. * @return boolean Whether or not the API version info was successfully fetched. 
  962. */ 
  963. public function api_data_exists() { 
  964.  
  965. if ( $this->api_data ) { 
  966. return true; 
  967. } else { 
  968. return false; 
  969.  
  970.  
  971. /** 
  972. * Get a specific API value. 
  973. * @since 1.0.0 
  974. * @param string $key Array key of the API data to get. 
  975. * @return mixed $value Value associated with specified key. 
  976. */ 
  977. public function get_api_value( $key ) { 
  978.  
  979. if ( $this->api_data ) { 
  980. $value = $this->api_data->$key; 
  981. } else { 
  982. $value = ''; 
  983.  
  984. return $value; 
  985.  
  986.  
  987. /**----------------------------------------------------------------------------* 
  988. * Public User Functions 
  989. *----------------------------------------------------------------------------*/ 
  990.  
  991. /** 
  992. * Get the version of Font Awesome currently in use. 
  993. * @since 1.0.0 
  994. * @return string Font Awesome version. 
  995. */ 
  996. public function get_version() { 
  997. return $this->font_awesome_version; 
  998.  
  999. /** 
  1000. * Get the fallback version of Font Awesome included locally. 
  1001. * @since 1.0.0 
  1002. * @return string Font Awesome fallback version. 
  1003. */ 
  1004. public function get_fallback_version() { 
  1005. return $this->fallback_data['version']; 
  1006.  
  1007. /** 
  1008. * Get the stylesheet URL. 
  1009. * @since 1.0.0 
  1010. * @return string Stylesheet URL. 
  1011. */ 
  1012. public function get_stylesheet_url() { 
  1013. return $this->stylesheet_url; 
  1014.  
  1015. /** 
  1016. * Get the array of available icons. 
  1017. * @since 1.0.0 
  1018. * @return array Available Font Awesome icons. 
  1019. */ 
  1020. public function get_icons() { 
  1021. return $this->icons; 
  1022.  
  1023. /** 
  1024. * Get the icon prefix ('fa' or 'icon'). 
  1025. * @since 1.0.0 
  1026. * @return string Font Awesome prefix. 
  1027. */ 
  1028. public function get_prefix() { 
  1029. return $this->prefix; 
  1030.  
  1031. /** 
  1032. * Get version data for the remote jsDelivr CDN. 
  1033. * @since 1.0.0 
  1034. * @return object jsDelivr API data. 
  1035. */ 
  1036. public function get_api_data() { 
  1037. return $this->api_data; 
  1038.  
  1039. /** 
  1040. * Get errors. 
  1041. * @since 1.0.0 
  1042. * @return array All library errors that have occured. 
  1043. */ 
  1044. public function get_errors() { 
  1045. return $this->errors; 
  1046.