moved in a tab in the new options page ) /* ------------------------------------------------------------------------- */ add_action('admin_menu', '\Nimble\sek_plugin_menu'); function sek_plugin_menu() { if ( !current_user_can( 'update_plugins' ) || !sek_current_user_can_access_nb_ui() ) return; // system infos should be displayed to users with admin capabilities only add_plugins_page(__( 'System info', 'text_domain' ), __( 'System info', 'text_domain' ), 'read', 'nimble-builder', '\Nimble\sek_plugin_page'); } // May 2020 => redirect to a system-info tab in the new options page add_action( 'admin_init' , '\Nimble\sek_redirect_system_info' ); function sek_redirect_system_info() { if ( isset( $_GET['page'] ) && 'nimble-builder' === sanitize_text_field($_GET['page']) ) { wp_safe_redirect( urldecode( admin_url( NIMBLE_OPTIONS_PAGE_URL . '&tab=system-info' ) ) ); exit; } } /* ------------------------------------------------------------------------- * * VERSIONNING /* ------------------------------------------------------------------------- */ add_action( 'plugins_loaded', '\Nimble\sek_versionning'); // @see https://wordpress.stackexchange.com/questions/144870/wordpress-update-plugin-hook-action-since-3-9 function sek_versionning() { // Add Upgraded From Option + update current version if needed $current_version = get_option( 'nimble_version' ); if ( $current_version != NIMBLE_VERSION ) { update_option( 'nimble_version_upgraded_from', $current_version, 'no' ); update_option( 'nimble_version', NIMBLE_VERSION ); } // Write the version that the user started with. // Note : this has been implemented starting from v1.1.8 in October 2018. At this time 4000+ websites were already using the plugin, and therefore started with a version <= 1.1.7. $started_with = get_option( 'nimble_started_with_version' ); if ( empty( $started_with ) ) { update_option( 'nimble_started_with_version', $current_version ); } $start_date = get_option( 'nimble_start_date' ); if ( empty( $start_date ) ) { update_option( 'nimble_start_date', date("Y-m-d H:i:s") ); } } // /* ------------------------------------------------------------------------- * // * ENQUEUE ADMIN STYLE // /* ------------------------------------------------------------------------- */ add_action( 'admin_init' , '\Nimble\sek_admin_style' ); function sek_admin_style() { if ( skp_is_customizing() || !sek_current_user_can_access_nb_ui() ) return; wp_enqueue_style( 'nimble-admin-css', sprintf( '%1$s/assets/admin/css/%2$s' , NIMBLE_BASE_URL, 'nimble-admin.css' ), array(), NIMBLE_ASSETS_VERSION, 'all' ); } // /* ------------------------------------------------------------------------- * // * ENQUEUE ADMIN STYLE // /* ------------------------------------------------------------------------- */ /* beautify admin notice text using some defaults the_content filter callbacks */ foreach ( array( 'wptexturize', 'convert_smilies' ) as $callback ) { add_filter( 'nimble_parse_admin_text', $callback ); } // /* ------------------------------------------------------------------------- * // * EDIT WITH NIMBLE BUILDER // Introduced for https://github.com/presscustomizr/nimble-builder/issues/449 // /* ------------------------------------------------------------------------- */ // introduced to fix https://github.com/presscustomizr/nimble-builder/issues/528 function sek_is_forbidden_post_type_for_nimble_edit_button( $post_type = '' ) { // updated in dec 2019 to allow public post types only : posts, pages, woocommerce products, etc // not post types like ACF, contact forms, etc, // @see https://github.com/presscustomizr/nimble-builder/issues/573 $post_type_obj = get_post_type_object( $post_type ); $authorized_post_types = apply_filters( 'nimble-authorized-post-types' , array( 'post', 'page', 'product' ) ); if ( is_string($post_type) && !in_array($post_type, $authorized_post_types) ) return true; return is_object($post_type_obj) && true !== $post_type_obj->public; } // When using classic editor add_action( 'edit_form_after_title', '\Nimble\sek_print_edit_with_nimble_btn_for_classic_editor' ); // @hook 'edit_form_after_title' function sek_print_edit_with_nimble_btn_for_classic_editor( $post ) { if ( !sek_current_user_can_access_nb_ui() || !apply_filters('nb_post_edit_btn_enabled', true ) ) return; // introduced to fix https://github.com/presscustomizr/nimble-builder/issues/528 if ( is_object($post) && sek_is_forbidden_post_type_for_nimble_edit_button( $post->post_type ) ) return; // Void if ( 'post' != $current_screen->base ) <= only printed when editing posts, CPTs, and pages $current_screen = get_current_screen(); if ( 'post' !== $current_screen->base ) return; // Only print html button when Gutenberg editor is NOT enabled if ( did_action( 'enqueue_block_editor_assets' ) ) { return; } // Void if user can't edit the post or can't customize if ( !sek_current_user_can_edit( $post->ID ) || !current_user_can( 'customize' ) ) { return; } sek_print_nb_btn_edit_with_nimble( 'classic' ); } // When using gutenberg editor add_action( 'enqueue_block_editor_assets', '\Nimble\sek_enqueue_js_asset_for_gutenberg_edit_button'); function sek_enqueue_js_asset_for_gutenberg_edit_button() { if ( !sek_current_user_can_access_nb_ui() || !apply_filters('nb_post_edit_btn_enabled', true ) ) return; // Void if ( 'post' != $current_screen->base ) <= only printed when editing posts, CPTs, and pages $current_screen = get_current_screen(); if ( 'post' !== $current_screen->base ) return; $post = get_post(); // Void if user can't edit the post or can't customize if ( !sek_current_user_can_edit( $post->ID ) || !current_user_can( 'customize' ) ) { return; } wp_enqueue_script( 'nb-gutenberg', sprintf( '%1$s/assets/admin/js/%2$s' , NIMBLE_BASE_URL, 'nimble-gutenberg.js' ), array('jquery'), NIMBLE_ASSETS_VERSION, true ); } // Handle both classic and gutenberg editors add_action( 'admin_head', '\Nimble\sek_print_js_for_nimble_edit_btn', PHP_INT_MAX ); // @hook 'admin_footer' // If Gutenberg editor is active : // => print the button as a js template // // If Classic editor, print the javascript listener to open the customizer url // @see assets/admin/js/nimble-gutenberg.js function sek_print_js_for_nimble_edit_btn() { if ( !sek_current_user_can_access_nb_ui() || !apply_filters('nb_post_edit_btn_enabled', true ) ) return; // Void if ( 'post' != $current_screen->base ) <= only printed when editing posts, CPTs, and pages $current_screen = get_current_screen(); if ( 'post' !== $current_screen->base ) return; $post = get_post(); // introduced to fix https://github.com/presscustomizr/nimble-builder/issues/528 if ( is_object($post) && sek_is_forbidden_post_type_for_nimble_edit_button( $post->post_type ) ) return; // Void if user can't edit the post or can't customize if ( !sek_current_user_can_edit( $post->ID ) || !current_user_can( 'customize' ) ) { return; } // Only print when Gutenberg editor is enabled ?> (function ($) { var _doRedirectToCustomizer = function( post_id, $clickedEl ) { wp.ajax.post( 'sek_get_customize_url_for_nimble_edit_button', { nimble_edit_post_id : post_id }).done( function( resp ) { //$clickedEl.removeClass('sek-loading-customizer'); window.location.href = resp; }).fail( function( resp ) { $clickedEl.removeClass('sek-loading-customizer').addClass('button-primary'); // If the ajax request fails, let's save the draft with a Nimble Builder title, and refresh the page, so the url is generated server side on next load. // var $postTitle = $('#title'); // post_title = $postTitle.val(); // if ( !post_title ) { // $postTitle.val( 'Nimble Builder #' + post_id ); // } // if (wp.autosave) { // wp.autosave.server.triggerSave(); // } _.delay(function () { // off the javascript pop up warning if post not saved yet $( window ).off( 'beforeunload' ); location.href = location.href; //wp-admin/post.php?post=70&action=edit }, 300 ); }); }; // Attach event listener with delegation $('body').on( 'click', '#sek-edit-with-nimble', function(evt) { evt.preventDefault(); var $clickedEl = $(this), _url = $clickedEl.data('cust-url'); if ( _.isEmpty( _url ) ) { // introduced for https://github.com/presscustomizr/nimble-builder/issues/509 $clickedEl.addClass('sek-loading-customizer').removeClass('button-primary'); // for new post, the url is empty, let's generate it server side with an ajax call var post_id = $('#post_ID').val(); _doRedirectToCustomizer( post_id, $clickedEl ); } else { window.location.href = _url; } }); })(jQuery); when using the classical editor, the html is printed with add_action( 'edit_form_after_title', ... ) // => when using gutenberg, we render the button with a js template @see assets/admin/js/nimble-gutenberg.js function sek_print_nb_btn_edit_with_nimble( $editor_type ) { if ( !sek_current_user_can_access_nb_ui() || !apply_filters('nb_post_edit_btn_enabled', true ) ) return; $post = get_post(); $manually_built_skope_id = strtolower( NIMBLE_SKOPE_ID_PREFIX . 'post_' . $post->post_type . '_' . $post->ID ); $customize_url = sek_get_customize_url_when_is_admin( $post ); if ( !empty( $customize_url ) ) { $customize_url = add_query_arg( array( 'autofocus' => array( 'section' => '__content_picker__' ) ), $customize_url ); } $btn_css_classes = 'classic' === $editor_type ? 'button button-primary button-hero classic-ed' : 'button button-primary button-large guten-ed'; ?> post_type ); if ( !isset( $post_type_object->cap->edit_post ) ) { return false; } $edit_cap = $post_type_object->cap->edit_post; if ( !current_user_can( $edit_cap, $post_id ) ) { return false; } if ( get_option( 'page_for_posts' ) === $post_id ) { return false; } return true; } // WP core filter documented in wp-admin/includes/template.php // Allows us to add a 'Nimble Builder' status next to posts, pages and CPT when displayed in posts list table // introduced in sept 2019 for https://github.com/presscustomizr/nimble-builder/issues/436 add_filter( 'display_post_states', '\Nimble\sek_add_nimble_post_state', 10, 2 ); function sek_add_nimble_post_state( $post_states, $post ) { // Not relevant when customizing if ( skp_is_customizing() ) return $post_states; if ( !sek_current_user_can_access_nb_ui() ) return $post_states; $manually_built_skope_id = strtolower( NIMBLE_SKOPE_ID_PREFIX . 'post_' . $post->post_type . '_' . $post->ID ); if ( $post && current_user_can( 'edit_post', $post->ID ) && sek_local_skope_has_been_customized( $manually_built_skope_id ) ) { $post_states['nimble'] = __( 'Nimble Builder', 'text-doma' ); } return $post_states; } // WP core filters documented in wp-admin\includes\class-wp-posts-list-table.php // Allows us to add an edit link below posts, pages and CPT when displayed in posts list table // introduced in sept 2019 for https://github.com/presscustomizr/nimble-builder/issues/436 add_filter( 'post_row_actions', '\Nimble\sek_filter_post_row_actions', 11, 2 ); add_filter( 'page_row_actions', '\Nimble\sek_filter_post_row_actions', 11, 2 ); function sek_filter_post_row_actions( $actions, $post ) { if ( !sek_current_user_can_access_nb_ui() ) return $actions; $manually_built_skope_id = strtolower( NIMBLE_SKOPE_ID_PREFIX . 'post_' . $post->post_type . '_' . $post->ID ); if ( $post && current_user_can( 'edit_post', $post->ID ) && sek_local_skope_has_been_customized( $manually_built_skope_id ) ) { $actions['edit_with_nimble_builder'] = sprintf( '%2$s', esc_url(sek_get_customize_url_for_post_id( $post->ID )), __( 'Edit with Nimble Builder', 'text-doma' ) ); } return $actions; } // /* ------------------------------------------------------------------------- * // * SEO PLUGINS COMPAT // /* ------------------------------------------------------------------------- */ // May 2020 : introduced this helper for SEO plugin compat // @return html string function sek_get_raw_html_from_skope_id( $skope_id = '' ) { $html = ''; if ( empty( $skope_id ) ) return $html; // Register contextually active modules // ( because normally not registered when in admin ) sek_register_modules_when_not_customizing_and_not_ajaxing( $skope_id ); // Capture Nimble content normally rendered on front // Make sure to skip header and footer sections ob_start(); foreach ( sek_get_locations() as $loc_id => $loc_params ) { $loc_params = is_array($loc_params) ? $loc_params : array(); $loc_params = wp_parse_args( $loc_params, array('is_header_location' => false, 'is_footer_location' => false ) ); if ( $loc_params['is_header_location'] || $loc_params['is_footer_location'] ) continue; Nimble_Manager()->_render_seks_for_location( $loc_id, array(), $skope_id ); } $html = ob_get_clean(); // Remove script tags that could break seo analysis $html = preg_replace('##is', '', $html); // apply filter the_content => sure of that ? $html = apply_filters( 'the_content', $html ); // Minify html $html = preg_replace('/>\s*', '><', $html);//https://stackoverflow.com/questions/466437/minifying-html return $html; } add_action( 'wp_ajax_sek_get_nimble_content_for_seo_plugins', '\Nimble\sek_ajax_get_nimble_content_for_seo_plugins' ); function sek_ajax_get_nimble_content_for_seo_plugins() { if ( !is_user_logged_in() ) { wp_send_json_error( __FUNCTION__ . ' error => unauthenticated' ); } if ( !isset( $_POST['skope_id'] ) || empty( $_POST['skope_id'] ) ) { wp_send_json_error( __FUNCTION__ . ' error => missing skope_id' ); } $html = sek_get_raw_html_from_skope_id( sanitize_text_field($_POST['skope_id']) ); wp_send_json_success($html); } // APRIL 2020 : implement compatibility with Yoast content analyzer // for https://github.com/presscustomizr/nimble-builder/issues/657 // documented here : https://github.com/Yoast/javascript/blob/master/packages/yoastseo/docs/Customization.md add_action( 'admin_head', '\Nimble\sek_print_js_for_yoast_analysis', PHP_INT_MAX ); function sek_print_js_for_yoast_analysis() { if ( !defined( 'WPSEO_VERSION' ) ) return; // This script is only printed when editing posts and pages $current_screen = get_current_screen(); if ( 'post' !== $current_screen->base ) return; $post = get_post(); $manually_built_skope_id = strtolower( NIMBLE_SKOPE_ID_PREFIX . 'post_' . $post->post_type . '_' . $post->ID ); ob_start(); ?> jQuery(function($){ var NimblePlugin = function() { YoastSEO.app.registerPlugin( 'nimblePlugin', {status: 'loading'} ); wp.ajax.post( 'sek_get_nimble_content_for_seo_plugins', { skope_id : '' }).done( function( nimbleContent ) { YoastSEO.app.pluginReady('nimblePlugin'); YoastSEO.app.registerModification( 'content', function(originalContent) { return originalContent + nimbleContent; }, 'nimblePlugin', 5 ); }).fail( function( er ) { console.log('NimblePlugin for Yoast => error when fetching Nimble content.'); }); } $(window).on('YoastSEO:ready', function() { try { new NimblePlugin(); } catch(er){ console.log('Yoast NimblePlugin error', er );} }); }); post_type . '_' . $post->ID ); $nb_content = sek_get_raw_html_from_skope_id( $manually_built_skope_id ); return is_string($nb_content) ? $content.$nb_content : $content; } // NOVEMBER 2020 : implement compatibility with Rank Math content analyzer // for https://github.com/presscustomizr/nimble-builder/issues/755 // documented here : https://rankmath.com/kb/content-analysis-api/ // 1) Enqueue the script that hooks on RM analyzer add_action( 'admin_init' , '\Nimble\sek_enqueue_js_for_rank_math_analyser' ); function sek_enqueue_js_for_rank_math_analyser() { if ( !defined( 'RANK_MATH_VERSION' ) ) return; wp_enqueue_script( 'nb-rank-math-integration', sprintf( '%1$s/assets/admin/js/%2$s' , NIMBLE_BASE_URL, 'nimble-rank-seo-analyzer.js' ), [ 'wp-hooks', 'rank-math-analyzer' ], NIMBLE_ASSETS_VERSION, true ); } // 2) Provide the current skope_id to the script add_action( 'admin_head', '\Nimble\sek_print_js_for_rank_math_analyser', PHP_INT_MAX ); function sek_print_js_for_rank_math_analyser() { if ( !defined( 'RANK_MATH_VERSION' ) ) return; // This script is only printed when editing posts and pages $current_screen = get_current_screen(); if ( 'post' !== $current_screen->base ) return; $post = get_post(); $manually_built_skope_id = strtolower( NIMBLE_SKOPE_ID_PREFIX . 'post_' . $post->post_type . '_' . $post->ID ); ob_start(); ?> jQuery(function($){ // Write skope_id as a global var + trigger an event => solves the problem of nimble-rank-seo-analyzer.js being loaded before window.nb_skope_id_for_rank_math_seo = ''; $(document).trigger('nb-skope-id-ready.rank-math', { skope_id : '' } ); }); $dashboard['presscustomizr-dashboard'] ); $wp_meta_boxes['dashboard']['normal']['core'] = array_merge( $nimble_widget, $dashboard ); } // @return void() // callback of wp_add_dashboard_widget() function sek_nimble_dashboard_callback_fn() { $post_data = sek_get_latest_posts_api_data(); $theme_name = sek_get_parent_theme_slug(); ?>
( %1$s X ) ', __('close' , 'text_doma') ); ?>
any context of your site, including search results or 404 pages. You can edit your pages in real time from the live customizer, and then publish when you are happy of the result, or save for later.', 'nimble' ); ?>
%2$s', esc_url( add_query_arg( array( array( 'autofocus' => array( 'section' => '__content_picker__' ) ), 'return' => urlencode( remove_query_arg( wp_removable_query_args(), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) ), admin_url( 'customize.php' ) ) ), __( 'Start creating content in live preview', 'nimble' ) ); ?>