| @@ -7,8 +7,9 @@ | ||
| 7 | 7 | |
| 8 | 8 | use ABlocks\Classes\AssetsGenerator; |
| 9 | 9 | use ABlocks\Helper; |
| 10 | 10 | use ABlocks\Classes\FileUpload; |
| 11 | +use ABlocks\Classes\FontLoadLocally; | |
| 11 | 12 | use ABlocks\Blocks\FormBuilder\BlockAttrSanitizer\Sanitizer as BlockSanitizer; |
| 12 | 13 | use ABlocks\Blocks\FormBuilder\Helper as FormBuilderHelper; |
| 13 | 14 | |
| 14 | 15 | class Blocks { |
| @@ -19,8 +20,23 @@ | ||
| 19 | 20 | add_action( 'enqueue_block_assets', [ $self, 'load_academy_core_scripts' ] ); |
| 20 | 21 | add_filter( 'block_categories_all', [ $self, 'register_block_category' ], 10, 2 ); |
| 21 | 22 | // Assets Generator |
| 22 | 23 | add_action( 'save_post', [ $self, 'generate_block_assets' ], 10, 3 ); |
| 24 | + add_action( 'switch_theme', [ $self, 'clear_generated_block_assets' ] ); | |
| 25 | + add_action( 'save_post', [ $self, 'download_google_fonts_locally' ], 20, 3 ); | |
| 26 | + add_action( 'deleted_post', [ $self, 'flush_site_fonts_on_delete' ], 10, 2 ); | |
| 27 | + // Self-hosting template fonts discovered on a front-end request happens | |
| 28 | + // here, off the visitor's request. | |
| 29 | + add_action( 'ablocks/download_site_fonts', [ '\ABlocks\Classes\FontCollector', 'update_site_fonts' ] ); | |
| 30 | + // A theme swap changes which templates and template parts exist. | |
| 31 | + add_action( 'switch_theme', [ '\ABlocks\Classes\FontCollector', 'flush_site_fonts' ] ); | |
| 32 | + // PERF-2: pre-warm the page's generated assets in the background after save, | |
| 33 | + // so the first visitor doesn't pay the parse/generate/write cost. | |
| 34 | + add_action( 'save_post', [ $self, 'prewarm_page_assets' ], 30, 3 ); | |
| 35 | + // Recompute global typography fonts whenever the plugin's global settings change. | |
| 36 | + add_action( 'ablocks/after_save_settings', [ $self, 'refresh_global_fonts' ] ); | |
| 37 | + // Bust the cached global CSS variables when global settings change. | |
| 38 | + add_action( 'ablocks/after_save_settings', [ $self, 'clear_global_css_cache' ] ); | |
| 23 | 39 | |
| 24 | 40 | $self->register_block_sanitizer(); |
| 25 | 41 | $self->form_builder_default_data(); |
| 26 | 42 | } |
| @@ -25,8 +41,18 @@ | ||
| 25 | 41 | $self->form_builder_default_data(); |
| 26 | 42 | } |
| 27 | 43 | |
| 28 | 44 | public function blocks_init() { |
| 45 | + // keep it common for Academy LMS and QuizPress | |
| 46 | + if ( ( helper::is_gutenberg_editor() && ( Helper::check_post_type_from_admin( 'academy_certificate' ) || Helper::check_post_type_from_admin( 'qp_certificate' ) ) ) || ( ! helper::is_gutenberg_editor() && ! is_admin() ) ) { | |
| 47 | + new \ABlocks\Blocks\AcademyCertificate\Block(); | |
| 48 | + new \ABlocks\Blocks\AcademyCertificateText\Block(); | |
| 49 | + new \ABlocks\Blocks\AcademyContainer\Block(); | |
| 50 | + if ( Helper::is_plugin_active( 'academy-pro/academy-pro.php' ) ) { | |
| 51 | + new \ABlocks\Blocks\AcademyCertificateId\Block(); | |
| 52 | + } | |
| 53 | + } | |
| 54 | + // Academy LMS Block Register Here | |
| 29 | 55 | if ( Helper::is_plugin_active( 'academy/academy.php' ) ) { |
| 30 | 56 | add_filter( 'academy/is_load_common_scripts', '__return_true' ); |
| 31 | 57 | if ( Helper::is_gutenberg_editor() ) { |
| 32 | 58 | add_filter( 'academy/is_load_common_js_scripts', '__return_false' ); |
| @@ -38,20 +64,75 @@ | ||
| 38 | 64 | new \ABlocks\Blocks\AcademyInstructorRegistrationForm\Block(); |
| 39 | 65 | new \ABlocks\Blocks\AcademyPdf\Block(); |
| 40 | 66 | new \ABlocks\Blocks\AcademyPasswordResetForm\Block(); |
| 41 | 67 | new \ABlocks\Blocks\AcademyLoginForm\Block(); |
| 68 | + new \ABlocks\Blocks\AcademyCourseMedia\Block(); | |
| 42 | 69 | |
| 43 | - if ( ( helper::is_gutenberg_editor() && Helper::check_post_type_from_admin( 'academy_certificate' ) ) || ( ! helper::is_gutenberg_editor() && ! is_admin() ) ) { | |
| 44 | - new \ABlocks\Blocks\AcademyCertificate\Block(); | |
| 45 | - new \ABlocks\Blocks\AcademyCertificateText\Block(); | |
| 46 | - if ( Helper::is_plugin_active( 'academy-pro/academy-pro.php' ) ) { | |
| 47 | - new \ABlocks\Blocks\AcademyCertificateId\Block(); | |
| 48 | - } | |
| 49 | - } | |
| 70 | + new \ABlocks\Blocks\AcademyCourseCurriculums\Block(); | |
| 71 | + new \ABlocks\Blocks\AcademyCourseReviews\Block(); | |
| 72 | + new \ABlocks\Blocks\AcademyReviewForm\Block(); | |
| 73 | + new \ABlocks\Blocks\AcademyReviewList\Block(); | |
| 74 | + new \ABlocks\Blocks\AcademyAdditionInfo\Block(); | |
| 75 | + new \ABlocks\Blocks\AcademyCourseDescription\Block(); | |
| 76 | + new \ABlocks\Blocks\AcademyCourseInstructor\Block(); | |
| 77 | + new \ABlocks\Blocks\AcademyEnrollContent\Block(); | |
| 50 | 78 | }//end if |
| 79 | + // StoreEngine Register Block | |
| 80 | + if ( Helper::is_plugin_active( 'storeengine/storeengine.php' ) ) { | |
| 81 | + new \ABlocks\Blocks\StoreengineProducts\Block(); | |
| 82 | + new \ABlocks\Blocks\StoreengineCouponForm\Block(); | |
| 83 | + new \ABlocks\Blocks\StoreengineCartList\Block(); | |
| 84 | + new \ABlocks\Blocks\StoreengineLoginForm\Block(); | |
| 85 | + new \ABlocks\Blocks\StoreengineProductFilter\Block(); | |
| 86 | + new \ABlocks\Blocks\StoreengineCheckoutForm\Block(); | |
| 87 | + new \ABlocks\Blocks\StoreengineContinueButton\Block(); | |
| 88 | + new \ABlocks\Blocks\StoreengineCheckoutButton\Block(); | |
| 89 | + new \ABlocks\Blocks\StoreengineCartSubTable\Block(); | |
| 90 | + new \ABlocks\Blocks\StoreengineCartButton\Block(); | |
| 91 | + new \ABlocks\Blocks\StoreengineOrderInfo\Block(); | |
| 92 | + new \ABlocks\Blocks\StoreengineBillingInfo\Block(); | |
| 93 | + new \ABlocks\Blocks\StoreengineShippingInfo\Block(); | |
| 94 | + new \ABlocks\Blocks\StoreengineCartNotice\Block(); | |
| 95 | + new \ABlocks\Blocks\StoreengineOrderDetails\Block(); | |
| 96 | + // Funnel Builder blocks (render the funnel shortcodes). | |
| 97 | + new \ABlocks\Blocks\StoreengineFunnelCheckout\Block(); | |
| 98 | + new \ABlocks\Blocks\StoreengineFunnelOffer\Block(); | |
| 99 | + new \ABlocks\Blocks\StoreengineFunnelAccept\Block(); | |
| 100 | + new \ABlocks\Blocks\StoreengineFunnelDecline\Block(); | |
| 101 | + new \ABlocks\Blocks\StoreengineFunnelContinue\Block(); | |
| 102 | + new \ABlocks\Blocks\StoreengineMiniCart\Block(); | |
| 103 | + new \ABlocks\Blocks\StoreengineProductGallery\Block(); | |
| 104 | + new \ABlocks\Blocks\StoreengineProductSummary\Block(); | |
| 105 | + new \ABlocks\Blocks\StoreengineProductDescription\Block(); | |
| 106 | + new \ABlocks\Blocks\StoreengineProductReview\Block(); | |
| 107 | + }//end if | |
| 108 | + | |
| 109 | + if ( class_exists('EasyContentManager') ) { | |
| 110 | + // Easy Content Manager Register Block | |
| 111 | + new \ABlocks\Blocks\EcmBookmarkButton\Block(); | |
| 112 | + new \ABlocks\Blocks\EcmBookmarkBadge\Block(); | |
| 113 | + new \ABlocks\Blocks\EcmBookmarkList\Block(); | |
| 114 | + new \ABlocks\Blocks\EcmBookmarkCount\Block(); | |
| 115 | + new \ABlocks\Blocks\EcmReactionList\Block(); | |
| 116 | + new \ABlocks\Blocks\EcmReaction\Block(); | |
| 117 | + new \ABlocks\Blocks\EcmUpvote\Block(); | |
| 118 | + new \ABlocks\Blocks\EcmUpvoteCount\Block(); | |
| 119 | + new \ABlocks\Blocks\EcmUpvoteList\Block(); | |
| 120 | + new \ABlocks\Blocks\EcmClaimButton\Block(); | |
| 121 | + new \ABlocks\Blocks\EcmClaimBadge\Block(); | |
| 122 | + new \ABlocks\Blocks\EcmClaimList\Block(); | |
| 123 | + new \ABlocks\Blocks\EcmClaimCount\Block(); | |
| 124 | + } | |
| 125 | + | |
| 51 | 126 | new \ABlocks\Blocks\Container\Block(); |
| 52 | 127 | new \ABlocks\Blocks\Heading\Block(); |
| 53 | 128 | new \ABlocks\Blocks\Paragraph\Block(); |
| 129 | + new \ABlocks\Blocks\AtomicText\Block(); | |
| 130 | + new \ABlocks\Blocks\AtomicImage\Block(); | |
| 131 | + new \ABlocks\Blocks\AtomicSvg\Block(); | |
| 132 | + new \ABlocks\Blocks\AtomicDiv\Block(); | |
| 133 | + new \ABlocks\Blocks\AtomicFlex\Block(); | |
| 134 | + new \ABlocks\Blocks\AtomicGrid\Block(); | |
| 54 | 135 | new \ABlocks\Blocks\Image\Block(); |
| 55 | 136 | new \ABlocks\Blocks\Button\Block(); |
| 56 | 137 | new \ABlocks\Blocks\DualButton\Block(); |
| 57 | 138 | new \ABlocks\Blocks\Icon\Block(); |
| @@ -61,8 +142,12 @@ | ||
| 61 | 142 | new \ABlocks\Blocks\StarRatings\Block(); |
| 62 | 143 | new \ABlocks\Blocks\Divider\Block(); |
| 63 | 144 | new \ABlocks\Blocks\Spacer\Block(); |
| 64 | 145 | new \ABlocks\Blocks\Video\Block(); |
| 146 | + new \ABlocks\Blocks\LoopBuilder\Block(); | |
| 147 | + new \ABlocks\Blocks\LoopTemplate\Block(); | |
| 148 | + new \ABlocks\Blocks\LoopFilter\Block(); | |
| 149 | + new \ABlocks\Blocks\LoopLoadMore\Block(); | |
| 65 | 150 | new \ABlocks\Blocks\Search\Block(); |
| 66 | 151 | new \ABlocks\Blocks\Carousel\Block(); |
| 67 | 152 | new \ABlocks\Blocks\CarouselChild\Block(); |
| 68 | 153 | new \ABlocks\Blocks\Chart\Block(); |
| @@ -107,9 +192,12 @@ | ||
| 107 | 192 | new \ABlocks\Blocks\PriceMenuItem\Block(); |
| 108 | 193 | new \ABlocks\Blocks\SocialShares\Block(); |
| 109 | 194 | new \ABlocks\Blocks\Notice\Block(); |
| 110 | 195 | new \ABlocks\Blocks\SvgDraw\Block(); |
| 196 | + new \ABlocks\Blocks\FrontendDashboard\Block(); | |
| 197 | + new \ABlocks\Blocks\LottieAnimation\Block(); | |
| 111 | 198 | new \ABlocks\Blocks\Marquee\Block(); |
| 199 | + new \ABlocks\Blocks\DynamicText\Block(); | |
| 112 | 200 | new \ABlocks\Blocks\MarqueeChild\Block(); |
| 113 | 201 | new \ABlocks\Blocks\Logout\Block(); |
| 114 | 202 | new \ABlocks\Blocks\FilterableCards\Block(); |
| 115 | 203 | new \ABlocks\Blocks\FilterableCardsItem\Block(); |
| @@ -114,8 +202,13 @@ | ||
| 114 | 202 | new \ABlocks\Blocks\FilterableCards\Block(); |
| 115 | 203 | new \ABlocks\Blocks\FilterableCardsItem\Block(); |
| 116 | 204 | new \ABlocks\Blocks\AdvanceLists\Block(); |
| 117 | 205 | new \ABlocks\Blocks\AdvanceListItem\Block(); |
| 206 | + new \ABlocks\Blocks\QrCode\Block(); | |
| 207 | + new \ABlocks\Blocks\FeaturedImage\Block(); | |
| 208 | + new \ABlocks\Blocks\ScrollToTop\Block(); | |
| 209 | + new \ABlocks\Blocks\Breadcrumb\Block(); | |
| 210 | + new \ABlocks\Blocks\InteractiveCircleInfographic\Block(); | |
| 118 | 211 | // Form Builder |
| 119 | 212 | new \ABlocks\Blocks\FormBuilder\Block(); |
| 120 | 213 | new \ABlocks\Blocks\FormInput\Block(); |
| 121 | 214 | new \ABlocks\Blocks\FormPassword\Block(); |
| @@ -125,8 +218,10 @@ | ||
| 125 | 218 | new \ABlocks\Blocks\FormMultiStep\Block(); |
| 126 | 219 | new \ABlocks\Blocks\FormMultiStepChild\Block(); |
| 127 | 220 | new \ABlocks\Blocks\FormRadio\Block(); |
| 128 | 221 | new \ABlocks\Blocks\TextPath\Block(); |
| 222 | + new \ABlocks\Blocks\taxonomyListing\Block(); | |
| 223 | + new \ABlocks\Blocks\Player\Block(); | |
| 129 | 224 | } |
| 130 | 225 | |
| 131 | 226 | public function register_block_category( $categories, $post ) { |
| 132 | 227 | return array_merge( |
| @@ -131,8 +226,12 @@ | ||
| 131 | 226 | public function register_block_category( $categories, $post ) { |
| 132 | 227 | return array_merge( |
| 133 | 228 | [ |
| 134 | 229 | [ |
| 230 | + 'slug' => 'ablocks-atomic', | |
| 231 | + 'title' => __( 'aBlocks Atomic', 'ablocks' ), | |
| 232 | + ], | |
| 233 | + [ | |
| 135 | 234 | 'slug' => 'ablocks', |
| 136 | 235 | 'title' => __( 'ABlocks', 'ablocks' ), |
| 137 | 236 | ], |
| 138 | 237 | [ |
| @@ -138,8 +237,16 @@ | ||
| 138 | 237 | [ |
| 139 | 238 | 'slug' => 'academy', |
| 140 | 239 | 'title' => __( 'Academy LMS', 'ablocks' ), |
| 141 | 240 | ], |
| 241 | + [ | |
| 242 | + 'slug' => 'storeengine', | |
| 243 | + 'title' => __( 'StoreEngine', 'ablocks' ), | |
| 244 | + ], | |
| 245 | + [ | |
| 246 | + 'slug' => 'easy-content-manager', | |
| 247 | + 'title' => __( 'Easy Content Manager', 'ablocks' ), | |
| 248 | + ], | |
| 142 | 249 | ], |
| 143 | 250 | $categories |
| 144 | 251 | ); |
| 145 | 252 | } |
| @@ -168,16 +275,140 @@ | ||
| 168 | 275 | if ( false !== wp_is_post_revision( $post_id ) ) { |
| 169 | 276 | return; |
| 170 | 277 | } |
| 171 | 278 | |
| 172 | - // Don't save FSE theme assets | |
| 173 | - if ( ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() ) ) { | |
| 279 | + $uploader = new \ABlocks\Classes\FileUpload(); | |
| 280 | + | |
| 281 | + // Template-like content is shared across many pages, so a change there must | |
| 282 | + // invalidate every page's combined assets. Regular content only affects its | |
| 283 | + // own page — scope the invalidation to that one post so a single edit can't | |
| 284 | + // wipe the whole site's asset cache and cause a regeneration stampede. | |
| 285 | + $global_impact_post_types = apply_filters( | |
| 286 | + 'ablocks/global_asset_invalidation_post_types', | |
| 287 | + [ 'ablocks_tb', 'wp_template', 'wp_template_part', 'wp_block' ] | |
| 288 | + ); | |
| 289 | + | |
| 290 | + if ( in_array( get_post_type( $post_id ), $global_impact_post_types, true ) ) { | |
| 291 | + $this->clear_generated_block_assets(); | |
| 174 | 292 | return; |
| 175 | 293 | } |
| 176 | 294 | |
| 177 | - AssetsGenerator::write_frontend_css_in_uploads_folder( $post_id ); | |
| 295 | + // Drop just this post's cached files; they regenerate on next visit. | |
| 296 | + $uploader->delete_file( $post_id . '.min.css' ); | |
| 297 | + $uploader->delete_file( $post_id . '.min.js' ); | |
| 178 | 298 | } |
| 179 | 299 | |
| 300 | + public function download_google_fonts_locally( $post_id, $post, $update ) { | |
| 301 | + if ( isset( $post->post_status ) && 'auto-draft' === $post->post_status ) { | |
| 302 | + return; | |
| 303 | + } | |
| 304 | + | |
| 305 | + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { | |
| 306 | + return; | |
| 307 | + } | |
| 308 | + | |
| 309 | + if ( false !== wp_is_post_revision( $post_id ) ) { | |
| 310 | + return; | |
| 311 | + } | |
| 312 | + | |
| 313 | + // Only process content that can contain aBlocks fonts (aBlocks blocks or | |
| 314 | + // reusable blocks that might wrap them). | |
| 315 | + if ( empty( $post->post_content ) | |
| 316 | + || ( false === strpos( $post->post_content, 'wp:ablocks' ) && false === strpos( $post->post_content, 'wp:block' ) ) ) { | |
| 317 | + return; | |
| 318 | + } | |
| 319 | + | |
| 320 | + // Collect the fonts this post actually uses from its saved attributes, | |
| 321 | + // cache them in post meta, and self-host them locally. | |
| 322 | + // See docs/FONT-MANAGEMENT-PLAN.md. | |
| 323 | + \ABlocks\Classes\FontCollector::save_post_fonts( $post_id ); | |
| 324 | + | |
| 325 | + // Templates, template parts and theme builder layouts render on pages that | |
| 326 | + // are not the queried post, so their fonts are tracked site-wide. Recompute | |
| 327 | + // (and download) here rather than on a visitor's request. | |
| 328 | + if ( in_array( get_post_type( $post_id ), \ABlocks\Classes\FontCollector::get_site_font_post_types(), true ) ) { | |
| 329 | + \ABlocks\Classes\FontCollector::update_site_fonts(); | |
| 330 | + } | |
| 331 | + } | |
| 332 | + | |
| 333 | + /** | |
| 334 | + * Deleting a template/part/layout can remove the last user of a font. | |
| 335 | + * | |
| 336 | + * @param int $post_id Post being deleted. | |
| 337 | + * @param \WP_Post $post The deleted post — by this point it is gone from the | |
| 338 | + * database, so the type has to come from here. | |
| 339 | + */ | |
| 340 | + public function flush_site_fonts_on_delete( $post_id, $post = null ) { | |
| 341 | + $post_type = $post instanceof \WP_Post ? $post->post_type : get_post_type( $post_id ); | |
| 342 | + | |
| 343 | + if ( in_array( $post_type, \ABlocks\Classes\FontCollector::get_site_font_post_types(), true ) ) { | |
| 344 | + \ABlocks\Classes\FontCollector::flush_site_fonts(); | |
| 345 | + } | |
| 346 | + } | |
| 347 | + | |
| 348 | + /** | |
| 349 | + * Pre-warm a published page's combined CSS/JS in the background after save, | |
| 350 | + * via a non-blocking loopback request. This moves the parse/generate/write | |
| 351 | + * cost off the first visitor's request (PERF-2). If loopback is unavailable, | |
| 352 | + * the existing on-request generation still runs as a fallback. | |
| 353 | + */ | |
| 354 | + public function prewarm_page_assets( $post_id, $post, $update ) { | |
| 355 | + if ( ! Helper::is_enabled_assets_generation() ) { | |
| 356 | + return; | |
| 357 | + } | |
| 358 | + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { | |
| 359 | + return; | |
| 360 | + } | |
| 361 | + if ( false !== wp_is_post_revision( $post_id ) ) { | |
| 362 | + return; | |
| 363 | + } | |
| 364 | + if ( ! ( $post instanceof \WP_Post ) ) { | |
| 365 | + $post = get_post( $post_id ); | |
| 366 | + } | |
| 367 | + if ( ! $post || 'publish' !== $post->post_status || ! is_post_type_viewable( $post->post_type ) ) { | |
| 368 | + return; | |
| 369 | + } | |
| 370 | + // Only for content that actually has aBlocks (or wrapping) blocks. | |
| 371 | + if ( empty( $post->post_content ) | |
| 372 | + || ( false === strpos( $post->post_content, 'wp:ablocks' ) && false === strpos( $post->post_content, 'wp:block' ) ) ) { | |
| 373 | + return; | |
| 374 | + } | |
| 375 | + if ( ! (bool) apply_filters( 'ablocks/perf/prewarm_assets', true, $post_id ) ) { | |
| 376 | + return; | |
| 377 | + } | |
| 378 | + | |
| 379 | + $url = get_permalink( $post_id ); | |
| 380 | + if ( ! $url ) { | |
| 381 | + return; | |
| 382 | + } | |
| 383 | + | |
| 384 | + wp_remote_get( | |
| 385 | + $url, | |
| 386 | + [ | |
| 387 | + 'blocking' => false, | |
| 388 | + 'timeout' => 0.01, | |
| 389 | + 'sslverify' => false, | |
| 390 | + 'headers' => [ 'X-ABlocks-Prewarm' => '1' ], | |
| 391 | + ] | |
| 392 | + ); | |
| 393 | + } | |
| 394 | + | |
| 395 | + /** | |
| 396 | + * Recompute the global typography font set after settings are saved. | |
| 397 | + * Re-primes the in-memory settings so the collector reads fresh values. | |
| 398 | + */ | |
| 399 | + public function refresh_global_fonts() { | |
| 400 | + $GLOBALS['ablocks_settings'] = json_decode( get_option( ABLOCKS_SETTINGS_NAME, '{}' ) ); | |
| 401 | + \ABlocks\Classes\FontCollector::update_global_fonts(); | |
| 402 | + } | |
| 403 | + | |
| 404 | + /** | |
| 405 | + * Invalidate the cached global CSS variables (see Assets::global_css_variable). | |
| 406 | + */ | |
| 407 | + public function clear_global_css_cache() { | |
| 408 | + delete_transient( 'ablocks_global_css_vars' ); | |
| 409 | + } | |
| 410 | + | |
| 180 | 411 | public function form_builder_default_data(): void { |
| 181 | 412 | add_filter( |
| 182 | 413 | 'ablocks/assets/editor_scripts_data', |
| 183 | 414 | [ FormBuilderHelper::class, 'form_builder_default_data' ] |
| @@ -184,6 +415,12 @@ | ||
| 184 | 415 | ); |
| 185 | 416 | } |
| 186 | 417 | public function register_block_sanitizer(): void { |
| 187 | 418 | BlockSanitizer::init(); |
| 419 | + } | |
| 420 | + | |
| 421 | + public function clear_generated_block_assets() { | |
| 422 | + $uploader = new \ABlocks\Classes\FileUpload(); | |
| 423 | + $uploader->delete_files(); | |
| 424 | + Helper::clear_third_party_plugin_cache(); | |
| 188 | 425 | } |
| 189 | 426 | } |