/** * Save Views and WPA title and description section. * * Expects following $_POST variables: * - wpnonce * - id * - title * - slug * - description * - is_title_escaped * * @since unknown */ function wpv_update_title_description_callback() { wpv_ajax_authenticate( 'wpv_view_title_description_nonce', array( 'type_of_death' => 'data' ) ); $view_id = intval( wpv_getpost( 'id', 0 ) ); // This is full Views, so we will allways get WPV_View, WPV_WordPress_Archive or null. $view = WPV_View_Base::get_instance( $view_id ); // Fail if the View/WPA doesn't exist. if ( null == $view ) { wp_send_json_error( array( 'type' => 'id', 'message' => __( 'Wrong or missing ID.', 'wpv-views' ) ) ); } // Try to update all three properties at once. $transaction_result = $view->update_transaction( array( 'title' => wpv_getpost( 'title' ), 'slug' => wpv_getpost( 'slug' ), 'description' => wpv_getpost( 'description' ) ) ); // On failure, return the first available error message (there should be only one anyway). if( !$transaction_result['success'] ) { $error_message = wpv_getarr( $transaction_result, 'first_error_message', __( 'An unexpected error happened.', 'wpv-views' ) ); wp_send_json_error( array( 'type' => 'update', 'message' => $error_message ) ); } // Success. // Use special success message if title was changed by escaping in JS. $is_title_escaped = intval( wpv_getpost( 'is_title_escaped', 0 ) ); if( $is_title_escaped ) { $success_message = __( 'We escaped the title before saving.', 'wpv-views' ); } else { $success_message = __( 'Title and Description saved', 'wpv-views' ); } wp_send_json_success( array( 'id' => $view_id, 'message' => $success_message ) ); }
/** * Show information about how a CT is being used. * * @param $item WPV_Content_Template_Embedded Content template. * * @return string Content of the table cell. */ public function column_used_on( $item ) { if( $item->is_owned_by_view ) { // This CT is used as a template for Loop Output in a View or WPA. // Get a View or WPA object. We'll be using only methods from their base, so it doesn't matter which one is it. $owner_view = WPV_View_Base::get_instance( $item->loop_output_id ); if( $owner_view == null ) { // Something is wrong - most probably the owner doesn't exist. return ''; } // Display the appropriate message. if( $owner_view->is_published ) { $edit_page = 'views-embedded'; if ( WPV_View_Base::is_archive_view( $owner_view->id ) ) { $edit_page = 'view-archives-embedded'; } return sprintf( '<span>%s</span>', sprintf( __( 'This Content Template is used as the loop block for the %s <a href="%s" target="_blank">%s</a>', 'wpv-views' ), $owner_view->query_mode_display_name, esc_url( add_query_arg( array( 'page' => $edit_page, 'view_id' => $owner_view->id ), admin_url( 'admin.php' ) ) ), $owner_view->title ) ); } else { return sprintf( '<span>%s</span>', sprintf( __( 'This Content Template is used as the loop block for the trashed %s <strong>%s</strong>', 'wpv-views' ), $owner_view->query_mode_display_name, $owner_view->title ) ); } } else { // This is a normal CT. Obtain information about assignments and display them in a tag-like list. $list = array(); // "single posts" $assigned_single_pts = $item->get_assigned_single_post_types(); foreach( $assigned_single_pts as $loop ) { $list[] = sprintf( '<li>%s%s</li>', $loop['display_name'], __(' (single)', 'wpv-views') ); } // post type archives $assigned_pt_loops = $item->get_assigned_loops( 'post_type' ); foreach( $assigned_pt_loops as $loop ) { $list[] = sprintf( '<li>%s%s</li>', $loop['display_name'], __(' (post type archive)', 'wpv-views') ); } // taxonomy archives $assigned_ta_loops = $item->get_assigned_loops( 'taxonomy' ); foreach( $assigned_ta_loops as $loop ) { $list[] = sprintf( '<li>%s%s</li>', $loop['display_name'], __(' (taxonomy archive)', 'wpv-views') ); } if( !empty( $list ) ) { return sprintf( '<ul class="wpv-taglike-list">%s</ul>', implode( $list ) ); } else { return sprintf( '<span>%s</span>', __( 'No Post types/Taxonomies assigned', 'wpv-views' ) ); } } }
function wpv_update_layout_extra_callback() { // Authentication if ( ! current_user_can( 'manage_options' ) ) { $data = array( 'type' => 'capability', 'message' => __( 'You do not have permissions for that.', 'wpv-views' ) ); wp_send_json_error( $data ); } if ( ! isset( $_POST["wpnonce"] ) || ! wp_verify_nonce( $_POST["wpnonce"], 'wpv_view_layout_extra_nonce' ) ) { $data = array( 'type' => 'nonce', 'message' => __( 'Your security credentials have expired. Please reload the page to get new ones.', 'wpv-views' ) ); wp_send_json_error( $data ); } $view_id = (int) wpv_getpost( 'id', 0 ); // This will give us a View, a WPA or null. $view = WPV_View_Base::get_instance( $view_id ); if ( $view_id < 1 || ( null == $view ) ) { $data = array( 'type' => 'id', 'message' => __( 'Wrong or missing ID.', 'wpv-views' ) ); wp_send_json_error( $data ); } try { // We're updating multiple properties at once. $view->defer_after_update_actions(); // Actually we're changing only View settings and loop settings here. // If any of those changes fails, the database will not be updated. $view->begin_modifying_view_settings(); $view->begin_modifying_loop_settings(); $view->css = wpv_getpost( 'layout_css_val' ); $view->js = wpv_getpost( 'layout_js_val' ); $view->loop_meta_html = wpv_getpost( 'layout_val' ); // Save the wizard settings if ( isset( $_POST['include_wizard_data'] ) ) { $view->loop_style = wpv_getpost( 'style' ); $view->loop_table_column_count = wpv_getpost( 'table_cols' ); $view->loop_bs_column_count = wpv_getpost( 'bootstrap_grid_cols' ); $view->loop_bs_grid_container = wpv_getpost( 'bootstrap_grid_container' ); $view->loop_row_class = wpv_getpost( 'bootstrap_grid_row_class' ); $view->loop_bs_individual = wpv_getpost( 'bootstrap_grid_individual' ); $view->loop_include_field_names = wpv_getpost( 'include_field_names' ); $view->loop_fields = wpv_getpost( 'fields' ); // @todo sanitize this $view->loop_real_fields = wpv_getpost( 'real_fields' ); // @todo sanitize this // Remove unused Content Template $ct_to_delete = (int) wpv_getpost( 'delete_view_loop_template', 0 ); if( $ct_to_delete > 0 ) { $view->delete_unused_loop_template( $ct_to_delete ); } } // Now store changes. $view->finish_modifying_view_settings(); $view->finish_modifying_loop_settings(); $view->resume_after_update_actions(); } catch ( WPV_RuntimeExceptionWithMessage $e ) { // Validation errors go here. wp_send_json_error( array( 'type' => 'update', 'message' => $e->getUserMessage() ) ); } catch ( Exception $e ) { wp_send_json_error( array( 'type' => 'update', 'message' => __( 'An unexpected error ocurred.', 'wpv-views' ) ) ); } // Success! $data = array( 'id' => $view_id, 'message' => __( 'Loop Output saved', 'wpv-views' ) ); wp_send_json_success( $data ); }
/** * Render list items with information about usage of this Content Template. * * Also render "Bind posts" buttons where applicable. * Different info shows when CT is a loop template of some View/WPA. * * @param int $ct_id Content template ID * @return string Rendered HTML code. * * @since unknown * * @todo this needs refactoring to get rid of wpv_get_pt_tax_array() etc. */ function wpv_content_template_used_for_list( $ct_id ) { global $WPV_settings; $list = ''; $ct = WPV_Content_Template::get_instance( $ct_id ); if( null == $ct ) { // this should never happen; still, there is a serious lack of error handling return ''; } if ( ! $ct->is_owned_by_view ) { $post_types_array = wpv_get_pt_tax_array(); $count_single_post = count( $post_types_array['single_post'] ); $count_archive_post = count( $post_types_array['archive_post'] ); $count_taxonomy_post = count( $post_types_array['taxonomy_post'] ); for ( $i=0; $i<$count_single_post; $i++ ) { $type = $post_types_array['single_post'][$i][0]; $label = $post_types_array['single_post'][$i][1]; if ( isset( $WPV_settings['views_template_for_' . $type] ) && $WPV_settings['views_template_for_' . $type] == $ct_id ) { $list .= '<li>' . $label . __(' (single)', 'wpv-views'); // @todo We do not need the exact number here, let's create a has_dissident_posts method instead with a LIMITed query $dissident_post_count = $ct->get_dissident_posts( $type, 'count' ); if ( $dissident_post_count > 0 ) { $list .= sprintf( '<span class="%s"><a class="%s" data-type="%s" data-id="%s" data-nonce="%s"> %s</a></span>', 'js-wpv-apply-ct-to-cpt-single-' . $type, 'button button-small button-leveled icon-warning-sign js-wpv-apply-ct-to-all-cpt-single-dialog', $type, $ct_id, wp_create_nonce( 'work_view_template' ), sprintf( __( 'Bind %u %s ', 'wpv-views' ), $dissident_post_count, $label ) ); } $list .= '</li>'; } } for ( $i=0; $i < $count_archive_post; $i++ ) { $type = $post_types_array['archive_post'][$i][0]; $label = $post_types_array['archive_post'][$i][1]; if ( isset( $WPV_settings['views_template_archive_for_' . $type] ) && $WPV_settings['views_template_archive_for_' . $type] == $ct_id ) { $list .= '<li>' . $label . __(' (post type archive)','wpv-views') . '</li>'; } } for ( $i=0; $i < $count_taxonomy_post; $i++ ) { $type = $post_types_array['taxonomy_post'][$i][0]; $label = $post_types_array['taxonomy_post'][$i][1]; if ( isset( $WPV_settings['views_template_loop_' . $type] ) && $WPV_settings['views_template_loop_' . $type] == $ct_id ) { $list .= '<li>' . $label . __(' (taxonomy archive)','wpv-views') . '</li>'; } } if ( ! empty( $list ) ) { $list = '<ul class="wpv-taglike-list">' . $list . '</ul>'; } else { $list = '<span>' . __( 'No Post types/Taxonomies assigned', 'wpv-views' ) . '</span>'; } } else { // This CT is owned by a View/WPA and used as a loop template $owner_view = WPV_View_Base::get_instance( $ct->loop_output_id ); if( null == $owner_view ) { // again, there was no check for missing View before! return ''; } // Show usage information depending on owner View post status. if ( $owner_view->is_published ) { $edit_page = 'views-editor'; if ( WPV_View_Base::is_archive_view( $owner_view->id ) ) { $edit_page = 'view-archives-editor'; } $list = sprintf( __( 'This Content Template is used as the loop block for the %s <a href="%s" target="_blank">%s</a>', 'wpv-views' ), $owner_view->query_mode_display_name, add_query_arg( array( 'page' => $edit_page, 'view_id' => $owner_view->id ), admin_url( 'admin.php' ) ), $owner_view->title ); } else { $list = sprintf( __( 'This Content Template is used as the loop block for the trashed %s <strong>%s</strong>', 'wpv-views' ), $owner_view->query_mode_display_name, $owner_view->title ); } } return "<span>$list</span>"; }
function wpv_ct_editor_usage_section( $ct ) { ob_start(); $parent_view = null; if( $ct->is_owned_by_view ) { $parent_view = WPV_View_Base::get_instance($ct->loop_output_id); } if( null != $parent_view ) { if( $parent_view->is_published ) { $edit_page = 'views-editor'; if ( WPV_View_Base::is_archive_view( $parent_view->id ) ) { $edit_page = 'view-archives-editor'; } $loop_template_notice = sprintf( __( 'This Content Template is used as the loop block for the %s <a href="%s" target="_blank">%s</a>.', 'wpv-views' ), $parent_view->query_mode_display_name, esc_attr( add_query_arg( array( 'page' => $edit_page, 'view_id' => $parent_view->id ), admin_url( 'admin.php' ) ) ), $parent_view->title ); } else { $loop_template_notice = sprintf( __( 'This Content Template is used as the loop block for the trashed %s %s.', 'wpv-views' ), $parent_view->query_mode_display_name, "<strong>{$parent_view->title}</strong>" ); } printf( '<div class="wpv-advanced-setting"><p>%s</p></div>', $loop_template_notice ); } else { $asterisk_explanation = '<span data-bind="fadeVisibility: isAsteriskExplanationVisible(\'%s\', \'%s\')"><span style="color:red">*</span> ' . __('A different Content Template is already assigned to this item.', 'wpv-views') . '</span>'; // Render checkboxes for each type of assignment. $single_post_types_with_other_ct = wpv_ct_editor_usage_section_single_pages($ct, $asterisk_explanation); $cpt_archives_with_other_ct = wpv_ct_editor_usage_section_post_archives($ct, $asterisk_explanation); $taxonomy_archives_with_other_ct = wpv_ct_editor_usage_section_taxonomy_archives($ct, $asterisk_explanation); // Print information about other CT assignments for JS $other_assignments = array( 'single_posts' => $single_post_types_with_other_ct, 'cpt_archives' => $cpt_archives_with_other_ct, 'taxonomy_archives' => $taxonomy_archives_with_other_ct ); printf( '<span style="visibility: hidden" class="js-wpv-usage-other-assignments" data-value="%s"></span>', htmlentities(json_encode($other_assignments)) ); ?> <p class="update-button-wrap"> <span class="update-action-wrap"> <span class="js-wpv-message-container"></span> <span class="spinner ajax-loader" data-bind="spinnerActive: isUsageSectionUpdating"></span> </span> <button data-bind=" enable: isUsageSectionUpdateNeeded, attr: { class: isUsageSectionUpdateNeeded() ? 'button-primary' : 'button-secondary' }, click: usageSectionUpdate"> <?php _e('Update', 'wpv-views'); ?> </button> </p> <?php } $content = ob_get_contents(); ob_end_clean(); wpv_ct_editor_render_section( __( 'Usage', 'wpv-views' ), 'js-wpv-usage-section', $content, false, '', '', array( 'section' => 'usage_section', 'pointer_slug' => 'ptr_section' ) ); }