| 1 |
<?php |
| 2 |
|
| 3 |
/** |
| 4 |
* Plugin Name: Price Table Block |
| 5 |
* Plugin URI: https://essential-blocks.com |
| 6 |
* Description: Instantly create beautiful pricing menu for eCommerce website |
| 7 |
* Version: 1.3.0 |
| 8 |
* Author: WPDeveloper |
| 9 |
* Author URI: https://wpdeveloper.net |
| 10 |
* License: GPL-3.0-or-later |
| 11 |
* License URI: https://www.gnu.org/licenses/gpl-3.0.html |
| 12 |
* Text Domain: price-table-block |
| 13 |
* Requires at least: 6.0 |
| 14 |
* Requires PHP: 7.4 |
| 15 |
* |
| 16 |
* @package price-table-block |
| 17 |
*/ |
| 18 |
|
| 19 |
// Exit if accessed directly. |
| 20 |
if ( ! defined( 'ABSPATH' ) ) { |
| 21 |
exit; |
| 22 |
} |
| 23 |
|
| 24 |
/** |
| 25 |
* Registers all block assets so that they can be enqueued through the block editor |
| 26 |
* in the corresponding context. |
| 27 |
* |
| 28 |
* @see https://developer.wordpress.org/block-editor/tutorials/block-tutorial/applying-styles-with-stylesheets/ |
| 29 |
*/ |
| 30 |
|
| 31 |
require_once __DIR__ . '/includes/font-loader.php'; |
| 32 |
require_once __DIR__ . '/includes/post-meta.php'; |
| 33 |
require_once __DIR__ . '/includes/helpers.php'; |
| 34 |
|
| 35 |
/** |
| 36 |
* `lib/style-handler` ships as a git submodule. Guard the require so an |
| 37 |
* uninitialised submodule degrades gracefully instead of fataling the site. |
| 38 |
*/ |
| 39 |
if ( file_exists( __DIR__ . '/lib/style-handler/style-handler.php' ) ) { |
| 40 |
require_once __DIR__ . '/lib/style-handler/style-handler.php'; |
| 41 |
} |
| 42 |
|
| 43 |
if ( ! function_exists( 'create_block_pricing_table_block_init' ) ) { |
| 44 |
function create_block_pricing_table_block_init() { |
| 45 |
|
| 46 |
define( 'PRICE_TABLE_BLOCKS_VERSION', '1.3.0' ); |
| 47 |
define( 'PRICE_TABLE_BLOCKS_ADMIN_URL', plugin_dir_url( __FILE__ ) ); |
| 48 |
define( 'PRICE_TABLE_BLOCKS_ADMIN_PATH', dirname( __FILE__ ) ); |
| 49 |
|
| 50 |
$script_asset_path = PRICE_TABLE_BLOCKS_ADMIN_PATH . "/dist/index.asset.php"; |
| 51 |
if ( ! file_exists( $script_asset_path ) ) { |
| 52 |
throw new Error( |
| 53 |
'You need to run `npm start` or `npm run build` for the "price-table-block/pricing-table" block first.' |
| 54 |
); |
| 55 |
} |
| 56 |
|
| 57 |
$index_js = PRICE_TABLE_BLOCKS_ADMIN_URL . 'dist/index.js'; |
| 58 |
$script_asset = require $script_asset_path; |
| 59 |
|
| 60 |
// Generated *.asset.php files are trusted but may be stale/partial. |
| 61 |
if ( ! is_array( $script_asset ) ) { |
| 62 |
$script_asset = array(); |
| 63 |
} |
| 64 |
$asset_dependencies = isset( $script_asset['dependencies'] ) && is_array( $script_asset['dependencies'] ) |
| 65 |
? $script_asset['dependencies'] |
| 66 |
: array(); |
| 67 |
$asset_version = isset( $script_asset['version'] ) ? $script_asset['version'] : PRICE_TABLE_BLOCKS_VERSION; |
| 68 |
|
| 69 |
$all_dependencies = array_merge( $asset_dependencies, [ |
| 70 |
'wp-blocks', |
| 71 |
'wp-i18n', |
| 72 |
'wp-element', |
| 73 |
'wp-block-editor', |
| 74 |
'eb-price-table-blocks-controls-util', |
| 75 |
'essential-blocks-eb-animation' |
| 76 |
] ); |
| 77 |
|
| 78 |
wp_register_script( |
| 79 |
'eb-pricing-table-block-editor', |
| 80 |
$index_js, |
| 81 |
$all_dependencies, |
| 82 |
$asset_version |
| 83 |
); |
| 84 |
|
| 85 |
$load_animation_js = PRICE_TABLE_BLOCKS_ADMIN_URL . 'assets/js/eb-animation-load.js'; |
| 86 |
wp_register_script( |
| 87 |
'essential-blocks-eb-animation', |
| 88 |
$load_animation_js, |
| 89 |
[], |
| 90 |
PRICE_TABLE_BLOCKS_VERSION, |
| 91 |
true |
| 92 |
); |
| 93 |
|
| 94 |
$animate_css = PRICE_TABLE_BLOCKS_ADMIN_URL . 'assets/css/animate.min.css'; |
| 95 |
wp_register_style( |
| 96 |
'essential-blocks-animation', |
| 97 |
$animate_css, |
| 98 |
[], |
| 99 |
PRICE_TABLE_BLOCKS_VERSION |
| 100 |
); |
| 101 |
|
| 102 |
$fontpicker_theme = 'assets/css/fonticonpicker.base-theme.react.css'; |
| 103 |
wp_register_style( |
| 104 |
'fontpicker-default-theme', |
| 105 |
plugins_url( $fontpicker_theme, __FILE__ ), |
| 106 |
[], |
| 107 |
PRICE_TABLE_BLOCKS_VERSION |
| 108 |
); |
| 109 |
|
| 110 |
$fontpicker_material_theme = 'assets/css/fonticonpicker.material-theme.react.css'; |
| 111 |
wp_register_style( |
| 112 |
'fontpicker-matetial-theme', |
| 113 |
plugins_url( $fontpicker_material_theme, __FILE__ ), |
| 114 |
[], |
| 115 |
PRICE_TABLE_BLOCKS_VERSION |
| 116 |
); |
| 117 |
|
| 118 |
/** |
| 119 |
* Font Awesome 6, not 5 — and never at the mercy of a shared handle. |
| 120 |
* |
| 121 |
* `wordpress-icon-picker` ships a Font Awesome 6 icon list while emitting |
| 122 |
* FA5-era prefix classes, so a chosen icon is saved as `fas fa-house`. Under |
| 123 |
* an FA5 stylesheet the `.fas` prefix still resolves and the `<i>` keeps its |
| 124 |
* box, but `.fa-house:before` is never defined, so `content` stays empty and |
| 125 |
* the icon renders as blank space in a correctly positioned container. 798 of |
| 126 |
* the 1873 icons the picker offers are FA6 renames or FA6 additions and fail |
| 127 |
* exactly this way. |
| 128 |
* |
| 129 |
* `fontawesome-frontend-css` is a handle shared with the other Essential |
| 130 |
* Blocks standalone plugins, and `WP_Dependencies::add()` keeps the first |
| 131 |
* registration and silently discards the rest. `active_plugins` is sorted, so |
| 132 |
* `button-group/button-group.php` registers before this file and its Font |
| 133 |
* Awesome 5.15.2 build takes the handle for the whole site — which is what |
| 134 |
* emptied this block's icons in both the picker and the saved markup. |
| 135 |
* |
| 136 |
* The 6.5.1 registration below is still offered, so a sibling that has no |
| 137 |
* Font Awesome of its own inherits FA6. But this block no longer *depends* on |
| 138 |
* the shared handle: when another plugin already owns it, a private handle is |
| 139 |
* registered instead, so the FA6 face and the full FA6 glyph set are on the |
| 140 |
* page no matter who won. |
| 141 |
*/ |
| 142 |
$fontawesome_css = plugins_url( 'assets/css/fontawesome/css/all.min.css', __FILE__ ); |
| 143 |
|
| 144 |
wp_register_style( |
| 145 |
'fontawesome-frontend-css', |
| 146 |
$fontawesome_css, |
| 147 |
[], |
| 148 |
PRICE_TABLE_BLOCKS_VERSION |
| 149 |
); |
| 150 |
|
| 151 |
$shared_fontawesome = wp_styles()->query( 'fontawesome-frontend-css', 'registered' ); |
| 152 |
$fontawesome_handle = ( $shared_fontawesome && $shared_fontawesome->src === $fontawesome_css ) |
| 153 |
? 'fontawesome-frontend-css' |
| 154 |
: 'eb-price-table-fontawesome'; |
| 155 |
|
| 156 |
if ( 'eb-price-table-fontawesome' === $fontawesome_handle ) { |
| 157 |
wp_register_style( |
| 158 |
$fontawesome_handle, |
| 159 |
$fontawesome_css, |
| 160 |
[], |
| 161 |
PRICE_TABLE_BLOCKS_VERSION |
| 162 |
); |
| 163 |
} |
| 164 |
|
| 165 |
/** |
| 166 |
* Loading FA6 alongside a sibling's FA5 is not enough on its own: both files |
| 167 |
* define `.fas` / `.far` / `.fab`, and 28 icon names that exist in both |
| 168 |
* releases carry different codepoints, so the winner would come down to |
| 169 |
* stylesheet order. This layer restates Font Awesome 6 under this block's own |
| 170 |
* scopes — `.eb-pricing-wrapper`, `#wipIcon`, `.wip-iconpicker-popup` — so it |
| 171 |
* wins on specificity instead, and cannot reach any other plugin's icons. |
| 172 |
* |
| 173 |
* It is a dependency of both styles below rather than a separate enqueue so |
| 174 |
* it is always printed directly after the Font Awesome build it corrects. |
| 175 |
*/ |
| 176 |
$fontawesome_compat_css = 'assets/css/fontawesome-compat.css'; |
| 177 |
$fontawesome_compat_path = PRICE_TABLE_BLOCKS_ADMIN_PATH . '/' . $fontawesome_compat_css; |
| 178 |
wp_register_style( |
| 179 |
'eb-price-table-fontawesome-compat', |
| 180 |
plugins_url( $fontawesome_compat_css, __FILE__ ), |
| 181 |
[ $fontawesome_handle ], |
| 182 |
file_exists( $fontawesome_compat_path ) ? filemtime( $fontawesome_compat_path ) : PRICE_TABLE_BLOCKS_VERSION |
| 183 |
); |
| 184 |
|
| 185 |
/** |
| 186 |
* filemtime() emits a warning (PHP 8+) and returns false on a missing file, |
| 187 |
* which would silently drop the cache-busting version. Fall back to the |
| 188 |
* plugin version instead. |
| 189 |
*/ |
| 190 |
$editor_css = 'dist/style.css'; |
| 191 |
$editor_css_path = PRICE_TABLE_BLOCKS_ADMIN_PATH . '/' . $editor_css; |
| 192 |
$editor_css_ver = file_exists( $editor_css_path ) ? filemtime( $editor_css_path ) : PRICE_TABLE_BLOCKS_VERSION; |
| 193 |
/** |
| 194 |
* `dashicons` is a core-registered handle and must be declared here. |
| 195 |
* |
| 196 |
* The block editor canvas is an iframe, and it only receives the stylesheets |
| 197 |
* WordPress collects for it — a block's `editor_style` and that handle's |
| 198 |
* dependency chain. `dashicons` is not in that set on its own: it reaches the |
| 199 |
* admin document only because the `wp-admin` style depends on it, and the |
| 200 |
* iframe is a separate document that never gets `wp-admin`. |
| 201 |
* |
| 202 |
* Without this, a Dashicon chosen in the icon picker rendered in the sidebar |
| 203 |
* (which has `wp-admin`) but came out as an empty box in the canvas, where |
| 204 |
* `.dashicons-*:before` was never defined so `content` computed to `none` and |
| 205 |
* `font-family` fell through to the theme font. Font Awesome was unaffected |
| 206 |
* only because it was already declared as a dependency above. |
| 207 |
*/ |
| 208 |
wp_register_style( |
| 209 |
'eb-pricing-table-block-editor-style', |
| 210 |
plugins_url( $editor_css, __FILE__ ), |
| 211 |
['eb-price-table-fontawesome-compat', 'dashicons', 'fontpicker-default-theme', 'fontpicker-matetial-theme'], |
| 212 |
$editor_css_ver |
| 213 |
); |
| 214 |
|
| 215 |
$style_css = PRICE_TABLE_BLOCKS_ADMIN_URL . 'dist/style.css'; |
| 216 |
$style_css_path = PRICE_TABLE_BLOCKS_ADMIN_PATH . '/dist/style.css'; |
| 217 |
$style_css_ver = file_exists( $style_css_path ) ? filemtime( $style_css_path ) : PRICE_TABLE_BLOCKS_VERSION; |
| 218 |
/** |
| 219 |
* `dashicons` is declared here for the same reason as the editor style above. |
| 220 |
* |
| 221 |
* Nothing pulls it onto a public page: it reached the frontend only for |
| 222 |
* logged-in users, because the admin bar's style depends on it. Logged out — |
| 223 |
* i.e. for every real visitor — a saved Dashicon rendered as an empty box. |
| 224 |
*/ |
| 225 |
wp_register_style( |
| 226 |
'create-block-pricing-table-block', |
| 227 |
$style_css, |
| 228 |
['eb-price-table-fontawesome-compat', 'dashicons', 'essential-blocks-animation'], |
| 229 |
$style_css_ver |
| 230 |
); |
| 231 |
|
| 232 |
if ( ! WP_Block_Type_Registry::get_instance()->is_registered( 'essential-blocks/pricing-table' ) ) { |
| 233 |
register_block_type( |
| 234 |
Price_Table_Helper::get_block_register_path( 'price-table-block/pricing-table', PRICE_TABLE_BLOCKS_ADMIN_PATH ), |
| 235 |
[ |
| 236 |
'editor_script' => 'eb-pricing-table-block-editor', |
| 237 |
'editor_style' => 'eb-pricing-table-block-editor-style', |
| 238 |
'render_callback' => function ( $attributes, $content ) { |
| 239 |
if ( ! is_admin() ) { |
| 240 |
wp_enqueue_script( 'essential-blocks-eb-animation' ); |
| 241 |
wp_enqueue_style( 'create-block-pricing-table-block' ); |
| 242 |
} |
| 243 |
return $content; |
| 244 |
} |
| 245 |
] |
| 246 |
); |
| 247 |
} |
| 248 |
} |
| 249 |
} |
| 250 |
add_action( 'init', 'create_block_pricing_table_block_init' ); |
| 251 |
|