page_title = sprintf( __( 'Add %s Snippet', 'insert-headers-and-footers' ), 'WPCode' ); $this->menu_title = sprintf( '+ %s', __( 'Add Snippet', 'insert-headers-and-footers' ) ); parent::__construct(); } /** * Load the snippet if we're editing one. * * @return void */ public function load_snippet() { if ( isset( $_GET['snippet_id'] ) ) { $snippet_post = get_post( absint( $_GET['snippet_id'] ) ); if ( ! is_null( $snippet_post ) && $this->get_post_type() === $snippet_post->post_type ) { $this->snippet_id = $snippet_post->ID; $this->snippet = wpcode_get_snippet( $snippet_post ); // Let's check if it's not already being edited by someone else. $snippet_locked = wp_check_post_lock( $this->snippet_id ); if ( $snippet_locked ) { $locked_by = get_user_by( 'id', $snippet_locked ); if ( $locked_by ) { $this->locked_by = $locked_by->display_name; $this->is_locked = true; } } else { wp_set_post_lock( $this->snippet_id ); } } } } /** * Page-specific hooks. * * @return void */ public function page_hooks() { $this->can_edit = current_user_can( 'wpcode_edit_snippets' ); // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( isset( $_GET['snippet_id'] ) ) { $this->load_snippet(); // If the post type does not match the page will act as an add new snippet page, the id will be ignored. } elseif ( ! isset( $_GET['custom'] ) ) { $this->show_library = apply_filters( 'wpcode_add_snippet_show_library', true ); } // phpcs:enable WordPress.Security.NonceVerification.Recommended $this->publish_button_text = __( 'Save Snippet', 'insert-headers-and-footers' ); $this->header_title = __( 'Create Custom Snippet', 'insert-headers-and-footers' ); if ( isset( $this->snippet ) ) { $this->header_title = __( 'Edit Snippet', 'insert-headers-and-footers' ); $this->publish_button_text = __( 'Update', 'insert-headers-and-footers' ); } if ( $this->show_library ) { $this->header_title = __( 'Add Snippet', 'insert-headers-and-footers' ); } $this->process_message(); add_action( 'admin_init', array( $this, 'check_status' ) ); add_filter( 'submenu_file', array( $this, 'change_current_menu' ) ); add_filter( 'admin_title', array( $this, 'change_page_title' ), 15, 2 ); add_action( 'admin_init', array( $this, 'submit_listener' ) ); add_action( 'admin_init', array( $this, 'set_code_type' ) ); add_filter( 'wpcode_admin_js_data', array( $this, 'add_conditional_rules_to_script' ) ); add_filter( 'admin_body_class', array( $this, 'body_class_code_type' ) ); add_filter( 'admin_body_class', array( $this, 'maybe_editor_height_auto' ) ); add_filter( 'admin_body_class', array( $this, 'maybe_syntax_highlighting_disabled' ) ); add_filter( 'admin_head', array( $this, 'maybe_editor_height' ) ); add_action( 'wpcode_admin_notices', array( $this, 'maybe_show_error_notice' ) ); add_filter( 'user_can_richedit', '__return_true', 150 ); // Override other plugins that disable TinyMCE. } /** * Make sure we can't edit a trashed snippet. * * @return void */ public function check_status() { if ( ! isset( $this->snippet ) ) { return; } $post_data = $this->snippet->get_post_data(); if ( 'trash' === $post_data->post_status ) { wp_die( esc_html__( 'You cannot edit this snippet because it is in the Trash. Please restore it and try again.', 'insert-headers-and-footers' ) ); } } /** * Process messages specific to this page. * * @return void */ public function process_message() { // phpcs:disable WordPress.Security.NonceVerification if ( ! isset( $_GET['message'] ) ) { $snippet_types = array_keys( wpcode()->execute->get_options() ); if ( in_array( 'html', $snippet_types, true ) && ! current_user_can( 'unfiltered_html', 'wpcode-editor' ) ) { $this->set_error_message( __( 'Sorry, you only have read-only access to this page. Ask your administrator for assistance editing.', 'insert-headers-and-footers' ) ); } return; } $error_details = ''; if ( isset( $_GET['error'] ) ) { $error_details = sanitize_text_field( wp_unslash( $_GET['error'] ) ); } $messages = array( 1 => __( 'Snippet updated.', 'insert-headers-and-footers' ), 2 => __( 'Snippet created & Saved.', 'insert-headers-and-footers' ), 3 => __( 'We encountered an error activating your snippet, please check the syntax and try again.', 'insert-headers-and-footers' ), 4 => __( 'Sorry, you are not allowed to change the status of the snippet.', 'insert-headers-and-footers' ), 5 => __( 'Snippet updated & executed.', 'insert-headers-and-footers' ), 6 => __( 'Your changes are saved but your snippet was deactivated due to an error, please check the syntax and try again.', 'insert-headers-and-footers' ), ); $message = absint( $_GET['message'] ); // phpcs:enable WordPress.Security.NonceVerification if ( ! isset( $messages[ $message ] ) ) { return; } if ( in_array( $message, array( 3, 6 ), true ) && ! empty( $error_details ) ) { $error_message = sprintf( /* translators: %s: Error message. */ esc_html__( 'Error message: %s', 'insert-headers-and-footers' ), '' . $error_details . '' ); $messages[ $message ] .= ' ' . $error_message; } if ( $message > 2 && $message < 5 || 6 === $message ) { $this->set_error_message( $messages[ $message ] ); } else { $this->set_success_message( $messages[ $message ] ); } if ( in_array( $message, array( 1, 2 ), true ) ) { // The first time the user saves a snippet, if they did not activate it, highlight that and save a user meta to avoid the message from being displayed again. add_action( 'wpcode_admin_notices', array( $this, 'maybe_show_saved_without_activation_notice' ), 5 ); } } /** * The first time a snippet is saved without being activated, show a notice to the user. * * @return void */ public function maybe_show_saved_without_activation_notice() { if ( ! isset( $this->snippet ) ) { return; } $snippet = $this->snippet; if ( ! $snippet->is_active() && ! get_user_meta( get_current_user_id(), 'wpcode_snippet_activate_notice_shown', true ) ) { update_user_meta( get_current_user_id(), 'wpcode_snippet_activate_notice_shown', true ); ?>

snippet_id ) ) { // Only change this for when editing a snippet. return $submenu_file; } return 'wpcode'; } /** * Change the admin page title when editing a snippet. * * @param string $title The admin page title to be displayed. * @param string $original_title The page title before adding the WP suffix. * * @return string */ public function change_page_title( $title, $original_title ) { if ( isset( $this->snippet ) ) { // If the snippet post is loaded (so we're editing) replace the original page title with our edit snippet one. // Translators: this changes the edit page title to show the snippet title. return str_replace( $original_title, sprintf( __( 'Edit snippet "%s"', 'insert-headers-and-footers' ), $this->snippet->get_title() ), $title ); } return $title; } /** * The main page content. * * @return void */ public function output_content() { if ( $this->show_library ) { $this->show_snippet_library(); } else { $this->show_snippet_editor(); } } /** * Show the snippet editor markup. * * @return void */ public function show_snippet_editor() { $this->field_title(); $this->field_code_editor(); $this->field_insert_options(); $this->field_device_type(); $this->field_conditional_logic(); $this->field_code_revisions(); $this->field_basic_info(); $this->hidden_fields(); wp_nonce_field( $this->action, $this->nonce_name ); } /** * Static items to be displayed in the library list when adding a new snippet. * * @param string $default_category The default category slug. * * @return array */ public function get_static_snippet_items( $default_category ) { return array( array( 'library_id' => 0, 'title' => esc_html__( 'Add Your Custom Code (New Snippet)', 'insert-headers-and-footers' ), 'note' => esc_html__( 'Choose this blank snippet to start from scratch and paste any custom code or simply write your own.', 'insert-headers-and-footers' ), 'categories' => array( $default_category, ), 'url' => add_query_arg( array( 'page' => 'wpcode-snippet-manager', 'custom' => true, ), $this->admin_url( 'admin.php' ) ), 'extra_classes' => array( 'wpcode-custom-snippet' ), 'button_text' => '+ ' . esc_html__( 'Add Custom Snippet', 'insert-headers-and-footers' ), ), array( 'library_id' => 0, 'title' => esc_html__( 'Generate snippet using AI', 'insert-headers-and-footers' ), 'note' => esc_html__( 'Generate a new snippet specific to your needs leveraging the power of WPCode\'s AI integration.', 'insert-headers-and-footers' ), 'categories' => array( $default_category, ), 'pill_text' => 'pro', 'pill_class' => 'light', 'url' => '#', 'extra_classes' => array( 'wpcode-library-item-ai', 'wpcode-library-item-ai-not-available' ), 'button_text' => '+ ' . esc_html__( 'Generate Snippet', 'insert-headers-and-footers' ), ), ); } /** * Show the snippet library markup. * * @return void */ public function show_snippet_library() { $library_data = wpcode()->library->get_data(); $categories = $library_data['categories']; $snippets = $library_data['snippets']; $default_category = isset( $categories[0]['slug'] ) ? $categories[0]['slug'] : ''; $snippets = array_merge( $this->get_static_snippet_items( $default_category ), $snippets ); ?>
'wpcode-snippet-manager', 'custom' => 1, ), admin_url( 'admin.php' ) ); printf( // Translators: The placeholders add links to create a new custom snippet or the suggest-a-snippet form. esc_html__( 'To speed up the process you can select from one of our pre-made library, or you can start with a %1$sblank snippet%2$s and %1$screate your own%2$s. Have a suggestion for new snippet? %3$sWe’d love to hear it!%4$s', 'insert-headers-and-footers' ), '', '', '', '' ); ?>
get_library_markup( $categories, $snippets ); ?>
generator()->get_categories(); ?>
get_items_list_sidebar( $categories, __( 'All Generators', 'insert-headers-and-footers' ), __( 'Search Generators', 'insert-headers-and-footers' ) ); ?>
    generator()->get_all_generators(); foreach ( $generators as $generator ) { $url = add_query_arg( array( 'page' => 'wpcode-generator', 'generator' => $generator->get_name(), ), admin_url( 'admin.php' ) ); $button_1 = array( 'tag' => 'a', 'url' => $url, 'text' => __( 'Generate', 'insert-headers-and-footers' ), ); $this->get_list_item( $generator->get_name(), $generator->get_title(), $generator->get_description(), $button_1, array(), $generator->get_categories() ); } ?>
library->get_username_snippets(); $username_categories = $username_library['categories']; $username_snippets = $username_library['snippets']; if ( empty( $username_snippets ) ) { $library_plugins = WPCode_Suggested_Plugins::get_library_plugins(); ?>

$plugin ) { ?>
<?php echo esc_attr( $plugin['name'] ); ?>

get_library_markup( $username_categories, $username_snippets ); } ?>
get_my_library_markup(); ?>
library_preview_modal_content(); $this->library_connect_banner_template(); } /** * Output the snippet title field. * * @return void */ public function field_title() { $value = isset( $this->snippet ) ? $this->snippet->get_title() : ''; ?>
snippet ) ? $this->snippet->get_code() : ''; ?>

ai_generate_button(); ?> smart_tags->smart_tags_picker( 'wpcode_snippet_code' ); ?> field_code_type(); ?>
false, 'default_editor' => 'tinymce', 'tinymce' => array( 'height' => 330, ), ) ); ?>
execute->get_options(); ?>

execute->get_code_types(); foreach ( $code_types as $key => $code_type ) { $class = 'wpcode-code-type'; if ( $key === $this->code_type ) { $class .= ' wpcode-code-type-selected'; } ?>

get_input_insert_toggle(); $shortcode_field = $this->get_input_shortcode(); // Build the field markup here. ob_start(); ?>

metabox_row( __( 'Insert Method', 'insert-headers-and-footers' ), $insert_toggle ); ?>
metabox_row( __( 'Location', 'insert-headers-and-footers' ), $this->get_selected_auto_insert_location() ); ?>
metabox_row( __( 'Shortcode', 'insert-headers-and-footers' ), $shortcode_field, 'wpcode_shortcode' ); $this->get_input_row_custom_shortcode(); $this->get_input_row_shortcode_attributes(); ?>
get_input_auto_insert_options(); ?>
get_input_row_as_file(); ?> get_input_row_schedule(); ?>
metabox( $title, $content, __( 'Your snippet can be either automatically executed or only used as a shortcode. When using the "Auto Insert" option you can choose the location where your snippet will be placed automatically.', 'insert-headers-and-footers' ) ); } /** * Get all the descriptions for the insert number input with conditional rules. * * @return string */ public function get_insert_number_descriptions() { $descriptions = array( 'before_paragraph' => __( 'before paragraph number', 'insert-headers-and-footers' ), 'after_paragraph' => __( 'after paragraph number', 'insert-headers-and-footers' ), 'archive_before_post' => __( 'before post number', 'insert-headers-and-footers' ), 'archive_after_post' => __( 'after post number', 'insert-headers-and-footers' ), 'after_words' => __( 'minimum number of words', 'insert-headers-and-footers' ), 'every_words' => __( 'number of words', 'insert-headers-and-footers' ), ); $markup = ''; foreach ( $descriptions as $value => $description ) { $markup .= sprintf( '', $value, esc_html( $description ) ); } return $markup; } /** * Get the input insert toggle markup. * * @return string */ public function get_input_insert_toggle() { ob_start(); ?>
get_auto_insert_value(); if ( absint( $value ) !== $current_value ) { return 'wpcode-button-secondary-inactive'; } return ''; } /** * Get the auto-insert value consistently. * * @return int */ private function get_auto_insert_value() { return isset( $this->snippet ) ? $this->snippet->get_auto_insert() : 1; } /** * Get the markup for the conditional logic picker. * * @return void */ public function get_conditional_logic_dropdown() { $options = wpcode()->conditional_logic->get_all_admin_options(); $categories = array( array( 'slug' => 'who', 'name' => __( 'Who (visitor)', 'insert-headers-and-footers' ), ), array( 'slug' => 'where', 'name' => __( 'Where (page)', 'insert-headers-and-footers' ), ), array( 'slug' => 'ecommerce', 'name' => __( 'eCommerce', 'insert-headers-and-footers' ), ), array( 'slug' => 'advanced', 'name' => __( 'Advanced', 'insert-headers-and-footers' ), ), ); ?>
get_items_list_sidebar( $categories, '', __( 'Search Options', 'insert-headers-and-footers' ), '*' ); ?>
code_type; $current_location = $this->get_current_snippet_location(); $locations_by_category = wpcode()->auto_insert->get_type_categories(); // Let's find the active category from the selected location. $active_category = 'global'; foreach ( $locations_by_category as $category_key => $category_data ) { /** * @var WPCode_Auto_Insert_Type $type */ foreach ( $category_data['types'] as $type ) { $locations = $type->get_locations(); if ( array_key_exists( $current_location, $locations ) ) { $active_category = $category_key; break 2; } } } ?>
get_items_list_sidebar( wpcode()->auto_insert->get_type_categories_for_sidebar(), '', __( 'Search locations', 'insert-headers-and-footers' ), $active_category ); ?>
get_current_snippet_location(); if ( empty( $current_location ) ) { $current_location = 'site_wide_header'; } $location_extra = isset( $this->snippet ) ? $this->snippet->get_location_extra() : ''; // Show a faux select box with the current location. $location_label = wpcode()->auto_insert->get_location_label( $current_location ); $markup = ''; $markup .= '
' . esc_html( $location_label ) . '
'; $markup .= '
'; $markup .= '
'; $markup .= $this->get_insert_number_descriptions(); $markup .= $this->get_input_number( 'wpcode_auto_insert_number', $this->get_auto_insert_number_value(), '', 1 ); $markup .= '
'; /** * Filter the markup for the location display inputs. * This is used to add the number input for auto insert locations. * * @param string $markup The markup to display. * @param WPCode_Snippet|false $snippet The snippet object. * @param WPCode_Admin_Page $this The admin page object. */ $markup = apply_filters( 'wpcode_location_display_inputs', $markup, isset( $this->snippet ) ? $this->snippet : false, $this ); $markup .= '
';// End wpcode-extra-location-fields. return $markup; } /** * Grab the current snippet location. * * @return mixed|string */ public function get_current_snippet_location() { $current_location = 'site_wide_header'; if ( ! isset( $this->snippet_id ) ) { return $current_location; } return $this->snippet->get_location(); } /** * Get the shortcode field. * * @return string */ public function get_input_shortcode() { $shortcode = __( 'Please save the snippet first', 'insert-headers-and-footers' ); if ( isset( $this->snippet_id ) ) { $shortcode = sprintf( '[wpcode id="%d"]', $this->snippet_id ); $attributes = $this->snippet->get_shortcode_attributes(); if ( ! empty( $attributes ) ) { $attributes_string = implode( '="" ', $attributes ); $shortcode = str_replace( ']', ' ' . $attributes_string . '=""]', $shortcode ); } } $input = sprintf( '', $shortcode ); $button = wpcode_get_copy_target_button( 'wpcode-shortcode' ); return sprintf( '
%1$s %2$s
', $input, $button ); } /** * Generic input number function. * * @param string $id The id of the input field. * @param string|int $value The value of the input. * @param string $description The description to display under the field. * @param int $min The minimum value. * * @return string */ public function get_input_number( $id, $value = '', $description = '', $min = 0 ) { $input = ''; if ( ! empty( $description ) ) { $input .= '

' . $description . '

'; } return $input; } /** * Get a simple textarea field. * * @param string $id The id of the input field. * @param string $value The value of the input. * @param string $description The description to display under the field. * * @return string */ public function get_input_textarea( $id, $value = '', $description = '' ) { $input = ''; if ( ! empty( $description ) ) { $input .= '

' . $description . '

'; } return $input; } /** * Get the auto-insert value consistently. * * @return int */ private function get_auto_insert_number_value() { return isset( $this->snippet ) ? $this->snippet->get_auto_insert_number() : 1; } /** * Markup for the basic info metabox. * * @return void */ public function field_basic_info() { $priority = isset( $this->snippet ) ? $this->snippet->get_priority() : 10; $note = isset( $this->snippet ) ? $this->snippet->get_note() : ''; ob_start(); $this->metabox_row( __( 'Tag', 'insert-headers-and-footers' ), $this->get_input_tag_picker() ); $this->metabox_row( __( 'Priority', 'insert-headers-and-footers' ), $this->get_input_number( 'wpcode_priority', $priority ), 'wpcode_priority' ); $this->metabox_row( __( 'Note', 'insert-headers-and-footers' ), $this->get_input_textarea( 'wpcode_note', $note ), 'wpcode_note' ); if ( isset( $this->snippet ) && $this->snippet->is_generated() ) { $this->metabox_row( __( 'Generator', 'insert-headers-and-footers' ), $this->get_input_generator() ); } $this->metabox( __( 'Basic info', 'insert-headers-and-footers' ), ob_get_clean(), __( 'Tags: Use tags to make it easier to group similar snippets together.
Priority: A lower priority will result in the snippet being executed before others with a higher priority.
Note: Add a private note related to this snippet.', 'insert-headers-and-footers' ) ); } /** * The conditional logic field. * * @return void */ public function field_conditional_logic() { $enable_logic = isset( $this->snippet ) && $this->snippet->conditional_rules_enabled(); $content = '

' . __( 'Using conditional logic you can limit the pages where you want the snippet to be auto-inserted.', 'insert-headers-and-footers' ) . '

'; $content .= '
'; ob_start(); $this->metabox_row( __( 'Enable Logic', 'insert-headers-and-footers' ), $this->get_checkbox_toggle( $enable_logic, 'wpcode_conditional_logic_enable' ), 'wpcode_conditional_logic_enable' ); $this->metabox_row( __( 'Conditions', 'insert-headers-and-footers' ), $this->get_conditional_logic_input(), 'wpcode_contional_logic_conditions', '#wpcode_conditional_logic_enable', '1' ); $content .= ob_get_clean(); $this->metabox( __( 'Smart Conditional Logic', 'insert-headers-and-footers' ), $content, __( 'Enable logic to add rules and limit where your snippets are inserted automatically. Use multiple groups for different sets of rules.', 'insert-headers-and-footers' ) ); $this->get_conditional_logic_dropdown(); } /** * Get the tag picker markup. * * @return string */ public function get_input_tag_picker() { $tags = isset( $this->snippet ) ? $this->snippet->get_tags() : array(); $tags_string = isset( $this->snippet ) ? implode( ',', $this->snippet->get_tags() ) : ''; $markup = ''; $markup .= ''; return $markup; } /** * Get the link to the generator page for the current snippet. * * @return string */ public function get_input_generator() { $generator = $this->snippet->get_generator(); return sprintf( '%2$s', add_query_arg( array( 'generator' => $generator, 'page' => 'wpcode-generator', 'snippet' => $this->snippet->get_id(), ), admin_url( 'admin.php' ) ), esc_html__( 'Update Generated Snippet', 'insert-headers-and-footers' ) ); } /** * The hidden fields needed to identify the form submission. * * @return void */ public function hidden_fields() { if ( ! isset( $this->snippet_id ) ) { return; } ?> show_library ) { // Don't wrap with form when showing library. parent::output(); return; } ?>

header_title ); ?>

show_library ) { return; } ?>
header_buttons(); ?>
snippet ) && $this->snippet->is_active(); $this->save_to_library_button(); ?> get_checkbox_toggle( $active, 'wpcode_active' ); ?> update_button(); } /** * The Update snippet button. * * @return void */ public function update_button() { ?> nonce_name ] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST[ $this->nonce_name ] ), $this->action ) ) { // Nonce is missing, so we're not even going to try. return; } if ( ! $this->can_edit ) { return; } $code_type = isset( $_POST['wpcode_snippet_type'] ) ? sanitize_text_field( wp_unslash( $_POST['wpcode_snippet_type'] ) ) : 'html'; $snippet_code = isset( $_POST['wpcode_snippet_code'] ) ? $_POST['wpcode_snippet_code'] : ''; if ( WPCode_Snippet_Execute::is_code_not_allowed( $snippet_code ) ) { $title = esc_html__( 'Restricted Code Detected', 'insert-headers-and-footers' ); wp_die( '

' . $title . '

' . sprintf( // Translators: %1$s is the opening link tag, %2$s is the closing link tag. esc_html__( 'For your protection, we blocked the addition of certain types of code that could compromise your website\'s security. If you believe this is in error or need assistance, please %1$scontact our support team%2$s.', 'insert-headers-and-footer' ), '', '' ), $title ); } if ( 'text' === $code_type ) { $snippet_code = wpautop( $snippet_code ); } $tags = array(); if ( isset( $_POST['wpcode_tags'] ) ) { $tags = trim( sanitize_text_field( wp_unslash( $_POST['wpcode_tags'] ) ) ); if ( ! empty( $tags ) ) { $tags = explode( ',', $tags ); } } if ( 'php' === $code_type ) { $snippet_code = preg_replace( '|^\s*<\?(php)?|', '', $snippet_code ); // Let's also replace the closing php tag if any. $snippet_code = preg_replace( '|\?>\s*$|', '', $snippet_code ); } if ( 'js' === $code_type && apply_filters( 'wpcode_strip_script_tags_for_js', true ) ) { $snippet_code = preg_replace( '|^\s*]*>|', '', $snippet_code ); $snippet_code = preg_replace( '|\s*$|', '', $snippet_code ); } $rules = isset( $_POST['wpcode_cl_rules'] ) ? json_decode( sanitize_textarea_field( wp_unslash( $_POST['wpcode_cl_rules'] ) ), true ) : array(); if ( isset( $_POST['wpcode_shortcode_attributes'] ) ) { $attributes = array_map( 'sanitize_key', wp_unslash( $_POST['wpcode_shortcode_attributes'] ) ); } else { $attributes = array(); } $active = isset( $_REQUEST['wpcode_active'] ); $location = isset( $_POST['wpcode_auto_insert_location'] ) ? sanitize_text_field( wp_unslash( $_POST['wpcode_auto_insert_location'] ) ) : ''; $execute_now = isset( $_POST['execute_now'] ) && 'execute_now' === $_POST['execute_now'] && 'on_demand' === $location; if ( $execute_now ) { // If we are executing now we should never save the snippet as active. $active = false; } $snippet_id = empty( $_REQUEST['id'] ) ? 0 : absint( $_REQUEST['id'] ); $previous_snippet = wpcode_get_snippet( $snippet_id ); $previously_active = $previous_snippet->is_active(); $snippet = wpcode_get_snippet( array( 'id' => $snippet_id, 'title' => isset( $_POST['wpcode_snippet_title'] ) ? sanitize_text_field( wp_unslash( $_POST['wpcode_snippet_title'] ) ) : '', 'code' => $snippet_code, 'active' => $active, 'code_type' => $code_type, 'location' => $location, 'insert_number' => isset( $_POST['wpcode_auto_insert_number'] ) ? absint( $_POST['wpcode_auto_insert_number'] ) : 0, 'auto_insert' => isset( $_POST['wpcode_auto_insert'] ) ? absint( $_POST['wpcode_auto_insert'] ) : 0, 'tags' => $tags, 'use_rules' => isset( $_POST['wpcode_conditional_logic_enable'] ), 'rules' => $rules, 'priority' => isset( $_POST['wpcode_priority'] ) ? intval( $_POST['wpcode_priority'] ) : 10, 'note' => isset( $_POST['wpcode_note'] ) ? sanitize_textarea_field( wp_unslash( $_POST['wpcode_note'] ) ) : '', 'location_extra' => isset( $_POST['wpcode_auto_insert_location_extra'] ) ? sanitize_text_field( wp_unslash( $_POST['wpcode_auto_insert_location_extra'] ) ) : '', 'shortcode_attributes' => $attributes, ) ); if ( empty( $snippet->title ) ) { $snippet->title = $snippet->get_untitled_title(); } $message_number = 1; $active_wanted = $snippet->active; if ( 0 === $snippet->id ) { // If it's a new snippet display a different message. $message_number = 2; } $this->add_extra_snippet_data( $snippet ); $id = $snippet->save(); // Save the last used code type. update_user_meta( get_current_user_id(), 'wpcode_default_code_type', $code_type ); if ( $active_wanted !== $snippet->is_active() ) { // If the snippet failed to change status display an error message. $message_number = 3; // If the current user is not allowed to change snippet status, display a different message. if ( ! current_user_can( 'wpcode_activate_snippets' ) ) { $message_number = 4; } if ( $previously_active ) { $message_number = 6; } } // Now that we saved the data, let's execute the snippet if needed. if ( $execute_now ) { wpcode()->execute->doing_activation(); // Mark this to unslash the code. $snippet->execute( apply_filters( 'wpcode_on_demand_ignore_conditional_logic', false ) ); $message_number = 5; } if ( $id ) { wp_safe_redirect( $this->get_after_save_redirect_url( $id, $message_number ) ); exit; } } /** * Get the URL to redirect to after a snippet is saved. * * @param int $snippet_id The snippet id that was just saved. * @param int $message_number The message number to display. * * @return string */ protected function get_after_save_redirect_url( $snippet_id, $message_number = 1 ) { return add_query_arg( array( 'snippet_id' => $snippet_id, 'message' => $message_number, 'error' => wpcode()->error->get_last_error_message(), ), $this->get_page_action_url() ); } /** * Load page-specific scripts. * * @return void */ public function page_scripts() { if ( $this->show_library ) { return; } $editor = new WPCode_Code_Editor( $this->code_type ); $editor->load_hint_scripts(); $editor->set_setting( 'autoCloseTags', true ); $editor->set_setting( 'matchTags', array( 'bothTags' => true ) ); $editor->register_editor( 'wpcode_snippet_code' ); $editor->init_editor(); } /** * Get the snippet type based on the context. * * @return void */ public function set_code_type() { if ( isset( $this->snippet ) ) { $this->code_type = $this->snippet->get_code_type(); } else { $user_code_type = get_user_meta( get_current_user_id(), 'wpcode_default_code_type', true ); if ( ! empty( $user_code_type ) ) { $this->code_type = $user_code_type; } $this->code_type = apply_filters( 'wpcode_default_code_type', $this->code_type ); $snippet_types = wpcode()->execute->get_options(); // If the selected code type is not in the available types, change the selected type to the first available type. if ( ! isset( $snippet_types[ $this->code_type ] ) ) { $this->code_type = key( $snippet_types ); } } } /** * Get the conditional logic options input markup. * * @return string */ public function get_conditional_logic_input() { $conditional_rules = isset( $this->snippet ) ? wp_json_encode( $this->snippet->get_conditional_rules() ) : ''; $markup = $this->get_conditional_select_show_hide(); $markup .= sprintf( '
%s
', $this->build_conditional_rules_form() ); $markup .= sprintf( '', __( '+ Add new group', 'insert-headers-and-footers' ) ); $markup .= sprintf( '', $this->get_conditions_group_markup() ); $markup .= sprintf( '', $this->get_conditions_group_row_markup() ); $markup .= sprintf( '', esc_attr( $conditional_rules ) ); return $markup; } /** * Markup for the show/hide select input. * * @return string */ public function get_conditional_select_show_hide() { $rules = isset( $this->snippet ) ? $this->snippet->get_conditional_rules() : array(); $selected = empty( $rules ) ? 'show' : $rules['show']; $options = array( 'show' => __( 'Show', 'insert-headers-and-footers' ), 'hide' => __( 'Hide', 'insert-headers-and-footers' ), ); $markup = '
'; $markup .= ''; $markup .= ''; $markup .= '
'; return $markup; } /** * Build back the form markup from the stored conditions. * * @return string|void */ public function build_conditional_rules_form() { if ( ! isset( $this->snippet ) ) { return; } $options = wpcode()->conditional_logic->get_all_admin_options(); $rules = $this->snippet->get_conditional_rules(); if ( empty( $rules ) || empty( $rules['groups'] ) ) { return; } $form_groups = array(); foreach ( $rules['groups'] as $group_rows ) { $rows = array(); foreach ( $group_rows as $row ) { $type_options = $options[ $row['type'] ]; $value_option = $type_options['options'][ $row['option'] ]; // Construct the meta array $meta = array( 'post' => isset( $row['meta_key'] ) ? $row['meta_key'] : '', 'user' => isset( $row['user_meta_key'] ) ? $row['user_meta_key'] : '', ); $rows[] = $this->get_conditions_group_row_markup( $row['option'], $row['relation'], $this->get_input_markup_by_type( $value_option, $row['value'] ), $meta ); } $form_groups[] = $this->get_conditions_group_markup( implode( '', $rows ) ); } return implode( '', $form_groups ); } /** * Process the type options and return the input markup. * * @param array $data The data with the settings/options. * @param string $value The value currently selected. * * @return string */ private function get_input_markup_by_type( $data, $value ) { $markup = ''; switch ( $data['type'] ) { case 'select': $multiple = isset( $data['multiple'] ) && $data['multiple'] ? 'multiple' : ''; $class = isset( $data['multiple'] ) && $data['multiple'] ? 'wpcode-select2' : ''; $markup = ''; break; case 'text': $markup = sprintf( '', esc_attr( $value ) ); break; case 'time': $markup = sprintf( '', esc_attr( $value ) ); break; case 'date': $value = ! empty( $value ) ? date_i18n( 'Y-m-d', strtotime( $value ) ) : ''; $markup = sprintf( '', esc_attr( $value ) ); break; case 'datetime': $value = ! empty( $value ) ? date_i18n( 'Y-m-d H:i', strtotime( $value ) ) : ''; $markup = sprintf( '', esc_attr( $value ) ); break; case 'ajax': $options = isset( $data['labels_callback'] ) ? $data['labels_callback']( $value ) : array(); $multiple = isset( $data['multiple'] ) && $data['multiple'] ? 'multiple' : ''; $markup = ''; break; } return $markup; } /** * Build the markup for an empty conditional logic group. * * @param string $rows Optional, already-built rows markup. * * @return string */ private function get_conditions_group_markup( $rows = '' ) { $markup = '
'; $markup .= $this->get_conditions_group_or_markup(); $markup .= '
' . $rows . '
'; $markup .= sprintf( '', _x( 'AND', 'Conditional logic add another "and" rules row.', 'insert-headers-and-footers' ), esc_attr__( 'Add another "AND" rules row.', 'insert-headers-and-footers' ) ); $markup .= '
'; return $markup; } /** * Build the markup for a conditional logic row. All parameters are optional and if * left empty it will return the template to be used in JS. * * @param string $type The value for the type input. * @param string $relation The value for the relation field. * @param string $value The value selected for this row. * * @return string */ private function get_conditions_group_row_markup( $type = '', $relation = '', $value = '', $meta = array() ) { $options = wpcode()->conditional_logic->get_all_admin_options(); $markup = '
'; $markup .= '
'; $markup .= ''; $markup .= ''; $markup .= ''; // wpcode-cl-rule-type-container. // Display the appropriate input based on the type if ( $type === 'user_meta' || $type === 'post_meta' ) { $meta_key = ''; if ( $type === 'post_meta' && isset( $meta['post'] ) ) { $meta_key = $meta['post']; $identifier = 'wpcode-cl-rule-meta-key'; } elseif ( $type === 'user_meta' && isset( $meta['user'] ) ) { $meta_key = $meta['user']; $identifier = 'wpcode-cl-rule-user-meta-key'; } $markup .= '
'; $markup .= ''; $markup .= '
'; } $markup .= $this->get_conditions_relation_select( $relation ); $markup .= '
' . $value . '
'; $markup .= '
'; // rules-row-options. $markup .= ''; $markup .= '
'; // rules-row. return $markup; } /** * Get the markup for the relation field. * * @param string $relation Optional selected relation. * * @return string */ private function get_conditions_relation_select( $relation = '' ) { $options = wpcode_get_conditions_relation_labels(); $markup = ''; return $markup; } /** * The markup for the "or" displayed between groups. * * @return string */ private function get_conditions_group_or_markup() { $markup = '
'; $markup .= '
'; $markup .= '
' . _x( 'OR', 'Conditional logic "or" another rule', 'insert-headers-and-footers' ) . '
'; $markup .= '
'; return $markup; } /** * Add conditions to the admin script when on this page. * * @param array $data The localized data used in wp_localize_script. * * @return array * @see wpcode_admin_scripts */ public function add_conditional_rules_to_script( $data ) { if ( ! isset( $data['conditions'] ) ) { $data['conditions'] = wpcode()->conditional_logic->get_all_admin_options( true ); } $data['snippet_id'] = isset( $this->snippet_id ) ? $this->snippet_id : 0; $data['save_to_library_url'] = wpcode_utm_url( 'https://wpcode.com/lite/', 'snippet-editor', 'save-to-library', 'upgrade-to-pro' ); $data['save_to_library_title'] = __( 'Save to Library is a Pro Feature', 'insert-headers-and-footers' ); $data['save_to_library_text'] = __( 'Upgrade to PRO today and save your private snippets to the WPCode library for easy access. You can also share your snippets with other users or load them on other sites.', 'insert-headers-and-footers' ); $data['save_to_library_button'] = $data['upgrade_button']; $data['shortcode_title'] = __( 'Custom Shortcode is a Pro Feature', 'insert-headers-and-footers' ); $data['shortcode_text'] = __( 'Upgrade today to use a custom shortcode and nerver worry about changing snippet ids again, even when importing your snippets to another site. You\'ll also get access to a private library that makes setting up new sites a lot easier.', 'insert-headers-and-footers' ); $data['shortcode_url'] = wpcode_utm_url( 'https://wpcode.com/lite/', 'snippet-editor', 'custom-shortcode', 'modal' ); $data['device_title'] = __( 'Device Type is a Pro Feature', 'insert-headers-and-footers' ); $data['device_text'] = __( 'Upgrade to PRO today and unlock one-click device targeting for your snippets.', 'insert-headers-and-footers' ); $data['device_url'] = wpcode_utm_url( 'https://wpcode.com/lite/', 'snippet-editor', 'device-type', 'modal' ); $data['datetime_title'] = __( 'Scheduling snippets is a Pro Feature', 'insert-headers-and-footers' ); $data['datetime_text'] = __( 'Upgrade to PRO today and unlock powerful scheduling options to limit when your snippet is active on the site.', 'insert-headers-and-footers' ); $data['datetime_url'] = wpcode_utm_url( 'https://wpcode.com/lite/', 'snippet-editor', 'schedule', 'modal' ); $data['blocks_title'] = __( 'Blocks snippets is a Pro Feature', 'insert-headers-and-footers' ); $data['blocks_text'] = __( 'Upgrade to PRO today and unlock building snippets using the Gutenberg Block Editor. Create templates using blocks and use the full power of WPCode to insert them in your site.', 'insert-headers-and-footers' ); $data['blocks_url'] = wpcode_utm_url( 'https://wpcode.com/lite/', 'snippet-editor', 'blocks', 'modal' ); $data['blocks_button'] = $data['save_to_library_button']; $data['scss_title'] = __( 'SCSS snippets is a Pro Feature', 'insert-headers-and-footers' ); $data['scss_text'] = __( 'Upgrade to PRO today and unlock editing snippets using SCSS code with optimized compiling directly in the WordPress admin.', 'insert-headers-and-footers' ); $data['scss_url'] = wpcode_utm_url( 'https://wpcode.com/lite/', 'snippet-editor', 'scss', 'modal' ); $data['scss_button'] = $data['save_to_library_button']; $data['shortcode_attributes'] = __( 'Shortcode Attributes', 'insert-headers-and-footers' ); $data['laf_title'] = __( 'Load as file is a Pro Feature', 'insert-headers-and-footers' ); $data['laf_text'] = __( 'Upgrade to PRO today and unlock loading your CSS and JS snippets as files for better performance and improved compatibility with caching plugins.', 'insert-headers-and-footers' ); $data['laf_url'] = wpcode_utm_url( 'https://wpcode.com/lite/', 'snippet-editor', 'laf', 'modal' ); $data['php_cl_location_notice'] = sprintf( // Translators: %1$s Opening anchor tag. %2$s Closing anchor tag. __( 'For better results using conditional logic with PHP snippets we automatically switched the auto-insert location to "Frontend Conditional Logic" that runs later. If you want to run the snippet earlier please switch back to "Run Everywhere" but note not all conditional logic options will be available. %1$sRead more%2$s', 'insert-headers-and-footers' ), '', '' ); $error_line = 0; if ( isset( $this->snippet ) ) { $last_error = $this->snippet->get_last_error(); if ( ! empty( $last_error['error_line'] ) ) { $error_line = $last_error['error_line']; } } $data['cl_labels'] = wpcode_get_conditions_relation_labels(); $data['cl_labels_custom'] = $this->get_conditional_logic_operators_custom_labels(); $data['error_line'] = $error_line; $data['error_line_message'] = esc_html__( 'The snippet has been recently deactivated due to an error on this line', 'insert-headers-and-footers' ); $data['is_locked'] = $this->is_locked; $data['locked_by'] = $this->locked_by; // Translators: The name of the user that is currently editing the snippet is appended at the end. $data['edited'] = esc_html__( 'This snippet is currently being edited by ', 'insert-headers-and-footers' ); $data['ai_title'] = esc_html__( 'AI Snippet Generation is a Pro Feature', 'insert-headers-and-footers' ); $data['ai_improve_title'] = esc_html__( 'Improving Snippets with AI is a Pro Feature', 'insert-headers-and-footers' ); $data['ai_text'] = esc_html__( 'Upgrade today to access the WPCode AI code generator, which allows you to create code snippets simply by describing their functionality using the power of AI.', 'insert-headers-and-footers' ); $data['ai_url'] = wpcode_utm_url( 'https://wpcode.com/lite/', 'snippet-editor', 'ai', 'generate' ); $data['ai_improve_url'] = wpcode_utm_url( 'https://wpcode.com/lite/', 'snippet-editor', 'ai', 'improve' ); $data['ai_button'] = esc_html__( 'Upgrade to PRO', 'insert-headers-and-footers' ); return $data; } /** * Add a body class specific to the code type of the current snippet. * * @param string $body_class The body class. * * @return string */ public function body_class_code_type( $body_class ) { $body_class .= ' wpcode-code-type-' . $this->code_type; if ( empty( $this->snippet ) ) { $body_class .= ' wpcode-new-snippet'; } return $body_class; } /** * If the editor should grow with the code, add a body class. * * @param string $body_class The body class. * * @return string */ public function maybe_editor_height_auto( $body_class ) { $height_auto = wpcode()->settings->get_option( 'editor_height_auto' ); if ( false !== $height_auto ) { $body_class .= ' wpcode-editor-auto '; } return $body_class; } /** * If the current user has syntax_highlighting disabled add a body class. * * @param string $body_class The body class. * * @return string */ public function maybe_syntax_highlighting_disabled( $body_class ) { $user = wp_get_current_user(); if ( ! isset( $user->syntax_highlighting ) || 'false' === $user->syntax_highlighting || ! function_exists( 'wp_enqueue_code_editor' ) ) { $body_class .= ' wpcode-syntax-highlighting-disabled '; } return $body_class; } /** * If we have a custom height set, output the styles to change that. * Also, check if the auto-height is set. * * @return void */ public function maybe_editor_height() { // Let's check if the auto-height is not enabled. $height_auto = wpcode()->settings->get_option( 'editor_height_auto' ); if ( false !== $height_auto ) { return; } $height = wpcode()->settings->get_option( 'editor_height' ); if ( ! $height ) { return; } echo ''; } /** * Get the markup of the custom shortcode row. * * @return void */ public function get_input_row_custom_shortcode() { $this->metabox_row( __( 'Custom Shortcode', 'insert-headers-and-footers' ), sprintf( '', __( 'Shortcode name', 'insert-headers-and-footers' ) ), '', '', '', __( 'Use this field to define a custom shortcode name instead of the id-based one.', 'insert-headers-and-footers' ), true ); } /** * Method used to output the markup for the shortcode attributes input. * * @return void */ public function get_input_row_shortcode_attributes() { $button = sprintf( '', get_wpcode_icon( 'plus', 16, 16, '0 96 960 960' ), __( 'Add Attribute', 'insert-headers-and-footers' ) ); $input = sprintf( '
%2$s
', __( 'Attribute name', 'insert-headers-and-footers' ), $button ); $input .= $this->help_icon( sprintf( // Translators: %1$s is the opening tag, %2$s is the closing tag. __( 'Use this field to define the attribute name for your shortcode and click Add Attribute. Attributes added here will be available to use as smart tags and as variables inside snippets. E.g. an attribute named "keyword" will be available in a PHP snippet as %1$s$keyword%2$s. %3$sLearn more%4$s.', 'insert-headers-and-footers' ), '', '', '', '' ), false ); $input .= '
'; $input .= $this->get_shortcode_attributes_list(); $input .= ''; $input .= '
'; $this->metabox_row( __( 'Shortcode Attributes', 'insert-headers-and-footers' ), $input, 'wpcode-shortcode-attribute-name', '', '' ); } /** * Get the markup of the shortcode attributes list. * * @return string|void */ public function get_shortcode_attributes_list() { if ( ! isset( $this->snippet ) ) { return ''; } $attributes = $this->snippet->get_shortcode_attributes(); if ( empty( $attributes ) ) { return ''; } $output = ''; return $output; } /** * Get the markup of the shortcode attribute list item. * * @return string */ public function get_shortcode_attribute_list_item() { return sprintf( '
  • %1$s
  • ', '%1$s', get_wpcode_icon( 'trash' ) ); } /** * Get the markup of the schedule main dates inputs. * * @return void */ public function get_input_row_schedule() { ?>
    metabox_row( $schedule_label, $this->get_input_row_schedule_contents( '', '', true ), 'wpcode_schedule', '', '', '', true ); ?>
    ', '' ); } /** * Get the markup for displaying an option to load the snippet as a file if the code type is CSS or JS. * * @return void */ public function get_input_row_as_file() { $this->metabox_row( esc_html__( 'Load as file', 'insert-headers-and-footers' ), $this->get_checkbox_toggle( false, 'wpcode_snippet_as_file' ), 'wpcode_snippet_as_file', '#wpcode_snippet_type', 'js,css', $this->get_input_row_as_file_description(), true, 'wpcode_snippet_as_file_option' ); } /** * Get the markup of the schedule inputs. * * @param string $start Start date. * @param string $end End date. * @param bool $read_only If the inputs should be read-only. * * @return string */ public function get_input_row_schedule_contents( $start = '', $end = '', $read_only = false ) { $markup = '
    '; $markup .= $this->get_input_datetime( 'wpcode-schedule-start', $start, esc_html__( 'Start Date', 'insert-headers-and-footers' ), esc_html__( 'Start Date', 'insert-headers-and-footers' ), esc_html__( 'Clear start date', 'insert-headers-and-footers' ), $read_only ); $markup .= $this->get_input_datetime( 'wpcode-schedule-end', $end, esc_html__( 'End Date', 'insert-headers-and-footers' ), esc_html__( 'End Date', 'insert-headers-and-footers' ), esc_html__( 'Clear end date', 'insert-headers-and-footers' ), $read_only ); $markup .= '
    '; $markup .= $this->help_icon( sprintf( // Translators: %1$s and %2$s are HTML tags for a link to the documentation article. __( 'Looking for more scheduling options? %1$sClick here%2$s to read more about all the available options.', 'insert-headers-and-footers' ), '', '' ), false ); return $markup; } /** * Get the markup of the schedule main dates inputs. * * @param string $id The id of the input. * @param string $value The value of the input. * @param string $label The label of the input. * @param string $placeholder The placeholder of the input. * @param string $clear_text The text of the clear button. * * @return string */ public function get_input_datetime( $id, $value = '', $label = '', $placeholder = '', $clear_text = '', $readonly = false ) { $markup = ''; if ( $label ) { $markup .= sprintf( '
    ', esc_attr( $id ), esc_html( $label ) ); } $markup .= '
    '; $markup .= sprintf( '', esc_attr( $id ), esc_attr( $value ), esc_attr( $placeholder ), $readonly ? 'readonly' : '' ); if ( ! empty( $clear_text ) ) { $markup .= sprintf( '', esc_attr( $clear_text ), get_wpcode_icon( 'close', 16, 16 ), ! empty( $value ) ? '' : 'display:none;' ); } $markup .= '
    '; return $markup; } /** * Add extra snippet data. * * @param WPCode_Snippet $snippet Snippet about to be saved, passed by reference. * * @return void */ public function add_extra_snippet_data( &$snippet ) { } /** * Markup for the code revisions metabox. * * @return void */ public function field_code_revisions() { $html = sprintf( '

    %s


    ', esc_html__( 'As you make changes to your snippet and save, you will get a list of previous versions with all the changes made in each revision. You can compare revisions to the current version or see changes as they have been saved by going through each revision. Any of the revisions can then be restored as needed.', 'insert-headers-and-footers' ) ); $html .= $this->code_revisions_list(); $this->metabox( __( 'Code Revisions', 'insert-headers-and-footers' ), $html, __( 'Easily switch back to a previous version of your snippet.', 'insert-headers-and-footers' ) ); } /** * Markup for the device type metabox. * * @return void */ public function field_device_type() { $html = sprintf( '

    %s

    ', esc_html__( 'Limit where you want this snippet to be loaded by device type. By default, snippets are loaded on all devices.', 'insert-headers-and-footers' ) ); $html .= '
    '; $html .= $this->device_type_picker(); $this->metabox( __( 'Device Type', 'insert-headers-and-footers' ), $html ); } /** * This method returns the markup for the device type radio input picker, the * three options available are Any device type, Desktop only and Mobile only. * By default, any device type is selected. * * @return string */ public function device_type_picker() { $html = '
    '; $html .= $this->get_radio_field_icon( 'devices', __( 'Any device type', 'insert-headers-and-footers' ), 'any', '', true ); $html .= $this->get_radio_field_icon( 'desktop', __( 'Desktop only', 'insert-headers-and-footers' ), 'desktop', '', false, '', true ); $html .= $this->get_radio_field_icon( 'mobile', __( 'Mobile only', 'insert-headers-and-footers' ), 'mobile', '', false, '', true ); $html .= '
    '; return $html; } /** * Get a styled radio input with an icon. * * @param string $icon Icon to use for label, @see get_wpcode_icon * @param string $label The text of the label to display. * @param string $value The value of the radio input. * @param string $name The input name (for PHP). * @param bool $checked Whether the input is checked or not. * @param string $id Unique id for the input, by default name + value will be used. * @param bool $disabled Whether the input should be disabled. * * @return string */ public function get_radio_field_icon( $icon = '', $label = '', $value = '', $name = '', $checked = false, $id = '', $disabled = false ) { $id = empty( $id ) ? $name . '-' . $value : $id; $html = '
    '; $html .= sprintf( '', esc_attr( $name ), esc_attr( $id ), esc_attr( $value ), checked( $checked, true, false ), disabled( $disabled, true, false ) ); $html .= sprintf( '', esc_attr( $id ), get_wpcode_icon( $icon, 48, 48 ), wp_kses_post( $label ) ); $html .= '
    '; return $html; } /** * List of code revision items. * * @return string */ public function code_revisions_list() { return $this->code_revisions_list_with_notice( esc_html__( 'Code Revisions is a Pro Feature', 'insert-headers-and-footers' ), sprintf( '

    %s

    ', esc_html__( 'Upgrade to WPCode Pro today and start tracking revisions and see exactly who, when and which changes were made to your snippet.', 'insert-headers-and-footers' ) ), array( 'text' => esc_html__( 'Upgrade to Pro and Unlock Revisions', 'insert-headers-and-footers' ), 'url' => wpcode_utm_url( 'https://wpcode.com/lite/', 'snippet-editor', 'revisions', 'upgrade-to-pro' ), ), array( 'text' => esc_html__( 'Learn more about all the features', 'insert-headers-and-footers' ), 'url' => wpcode_utm_url( 'https://wpcode.com/lite/', 'snippet-editor', 'revisions', 'features' ), ) ); } /** * Display a notice if the snippet loaded for editing triggered an error. * * @return void */ public function maybe_show_error_notice() { if ( ! isset( $this->snippet ) ) { return; } if ( $this->is_locked ) { ?>

    locked_by ) ); ?>

    snippet->get_last_error(); if ( empty( $last_error ) ) { return; } $error_line = isset( $last_error['error_line'] ) ? $last_error['error_line'] : false; $time = $last_error['time']; $logging_enabled = wpcode()->settings->get_option( 'error_logging' ); if ( $logging_enabled ) { $button_text = esc_html__( 'View Error Logs', 'insert-headers-and-footers' ); $button_url = add_query_arg( array( 'page' => 'wpcode-tools', 'view' => 'logs', ), admin_url( 'admin.php' ) ); } else { $button_text = esc_html__( 'Enable Error Logging', 'insert-headers-and-footers' ); $button_url = add_query_arg( array( 'page' => 'wpcode-settings', 'view' => 'errors', ), admin_url( 'admin.php' ) ); } ?>

    %s', esc_html__( 'Error message:', 'insert-headers-and-footers' ) ); ?>

    error->get_error_message_short( $last_error['message'] ) ); ?>

    ', '', absint( $error_line ) ); ?>

    ' . esc_url( $last_error['url'] ) . '' ); ?>

    ', '', absint( $this->snippet->get_id() ) ); } else { esc_html_e( 'You can enable error logging to get more details about the error that caused this.', 'insert-headers-and-footers' ); } ?>

    conditional_logic->get_all_admin_options(); $labels = array(); foreach ( $options as $option ) { foreach ( $option['options'] as $key => $opt_group ) { if ( ! empty( $opt_group['operator_labels'] ) ) { $labels[ $key ] = $opt_group['operator_labels']; } if ( ! empty( $opt_group['placeholder'] ) ) { if ( ! isset( $labels[ $key ] ) ) { $labels[ $key ] = array(); } $labels[ $key ]['placeholder'] = $opt_group['placeholder']; } } } return $labels; } /** * Get the markup for the AI generate button. * * @param string $class The class to add to the button. * * @return void */ public function ai_generate_button( $class = 'wpcode-button-ai-not-available' ) { ?>