| // +----------------------------------------------------------------------+ /** * Renders visualizer library page. * * @category Visualizer * @package Render * * @since 1.0.0 */ class Visualizer_Render_Library extends Visualizer_Render { /** * Cached result of _isListView() to avoid repeat DB reads per request. * * @var bool|null */ private $_list_view_cached = null; /** * Renders library page. * * @since 1.0.0 * * @access protected */ protected function _toHTML() { echo '
'; echo '

'; echo '

'; esc_html_e( 'Visualizer Library', 'visualizer' ); echo '
'; echo '', esc_html__( 'Add New Chart', 'visualizer' ), ''; echo ''; echo ''; if ( Visualizer_Module::is_pro() ) { echo ' ', esc_html__( 'License Settings', 'visualizer' ), ''; } echo '
'; echo '

'; $this->_renderMessages(); $this->_renderLibrary(); echo '
'; echo '
'; } /** * Renders notification messages if need be. * * @since 1.4.2 * * @access private */ private function _renderMessages() { if ( ! filter_var( ini_get( 'allow_url_fopen' ), FILTER_VALIDATE_BOOLEAN ) ) { echo '
'; echo '

'; printf( // translators: %s - the name of the option. esc_html__( '%s option is disabled in your php.ini config. Please enable it by changing its value to 1. This option increases the speed of remote CSV uploading.', 'visualizer' ), 'allow_url_fopen' ); echo '

'; echo '
'; } } /** * Displays the search form. */ private function getDisplayForm() { echo '
' . $this->_getViewToggleHTML() . ' '; echo ' |
'; } /** * Renders pro charts blocker. * * @access private */ private function _renderProPopupBlocker() { if ( Visualizer_Module::is_pro() ) { return; } $license = get_option( 'visualizer_pro_license_data', 'free' ); $license_key = ''; $download_id = ''; if ( ! empty( $license ) && is_object( $license ) ) { $license_key = isset( $license->key ) ? $license->key : ''; $download_id = isset( $license->download_id ) ? $license->download_id : ''; } $admin_license_url = admin_url( 'options-general.php#visualizer_pro_license' ); $renew_license_url = tsdk_utmify( Visualizer_Plugin::STORE_URL . '?edd_license_key=' . $license_key . '&download_id=' . $download_id, 'visualizer_license_block' ); echo '

Alert!

' . esc_html__( 'In order to edit premium charts, benefit from updates and support for Visualizer Premium plugin, please renew your license code or activate it.', 'visualizer' ) . '

'; } /** * Renders library content. * * @since 1.0.0 * * @access private */ private function _renderLibrary() { // Added by Ash/Upwork $filterBy = ! empty( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended // Added by Ash/Upwork echo $this->custom_css; $this->_renderProPopupBlocker(); echo '
'; echo ''; $this->getDisplayForm(); echo '
'; echo '
'; echo '
'; if ( ! empty( $this->charts ) ) { if ( $this->_isListView() ) { echo '
'; $this->_renderSidebar(); echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; foreach ( $this->charts as $placeholder_id => $chart ) { $enable_controls = false; $settings = isset( $chart['settings'] ) ? $chart['settings'] : array(); if ( ! empty( $settings['controls']['controlType'] ) ) { $column_index = $settings['controls']['filterColumnIndex']; $column_label = $settings['controls']['filterColumnLabel']; if ( 'false' !== $column_index || 'false' !== $column_label ) { $enable_controls = true; } } $this->_renderChartBox( $placeholder_id, $chart['id'], $enable_controls ); } echo '
' . esc_html__( 'ID', 'visualizer' ) . '' . esc_html__( 'Title', 'visualizer' ) . '' . esc_html__( 'Type', 'visualizer' ) . '' . esc_html__( 'Shortcode', 'visualizer' ) . '' . esc_html__( 'Actions', 'visualizer' ) . '
'; echo '
'; } else { echo '
'; $this->_renderSidebar(); foreach ( $this->charts as $placeholder_id => $chart ) { $enable_controls = false; $settings = isset( $chart['settings'] ) ? $chart['settings'] : array(); if ( ! empty( $settings['controls']['controlType'] ) ) { $column_index = $settings['controls']['filterColumnIndex']; $column_label = $settings['controls']['filterColumnLabel']; if ( 'false' !== $column_index || 'false' !== $column_label ) { $enable_controls = true; } } $this->_renderChartBox( $placeholder_id, $chart['id'], $enable_controls ); } echo '
'; } } else { echo '
'; $this->_renderSidebar(); echo '
'; echo '
'; echo '
'; echo esc_html__( 'No charts found. Click \'Add New Chart\' to create one.', 'visualizer' ); echo '

'; echo '
'; echo '', esc_html__( 'Add New Chart', 'visualizer' ), ''; echo ''; echo ''; echo '
'; echo '

'; echo '
'; echo ''; echo '
'; echo '
'; } echo '
'; if ( is_array( $this->pagination ) ) { echo ''; } } /** * Renders chart's box block. * * @since 1.0.0 * * @access private * * @param string $placeholder_id The placeholder's id for the chart. * @param int $chart_id The id of the chart. */ private function _renderChartBox( $placeholder_id, $chart_id, $with_filter = false ) { $settings = get_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS ); $chart_library = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, true ); $title = '#' . $chart_id; if ( ! empty( $settings[0]['title'] ) ) { $title = $settings[0]['title']; } // for ChartJS, title is an array. if ( is_array( $title ) && isset( $title['text'] ) ) { $title = $title['text']; } if ( ! empty( $settings[0]['backend-title'] ) ) { $title = $settings[0]['backend-title']; } if ( empty( $title ) ) { $title = '#' . $chart_id; } $ajax_url = admin_url( 'admin-ajax.php' ); $delete_url = esc_url( add_query_arg( array( 'action' => Visualizer_Plugin::ACTION_DELETE_CHART, 'nonce' => wp_create_nonce(), 'chart' => $chart_id, ), $ajax_url ) ); $clone_url = esc_url( add_query_arg( array( 'action' => Visualizer_Plugin::ACTION_CLONE_CHART, 'nonce' => wp_create_nonce( Visualizer_Plugin::ACTION_CLONE_CHART ), 'chart' => $chart_id, 'type' => $this->type, ), $ajax_url ) ); $export_link = esc_url( add_query_arg( array( 'action' => Visualizer_Plugin::ACTION_EXPORT_DATA, 'chart' => $chart_id, 'security' => wp_create_nonce( Visualizer_Plugin::ACTION_EXPORT_DATA . Visualizer_Plugin::VERSION ), ), admin_url( 'admin-ajax.php' ) ) ); $chart_type = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, true ); $chart_type_label = $chart_type; if ( empty( $chart_type_label ) && 'd3' === strtolower( (string) $chart_library ) ) { $chart_type_label = __( 'AI', 'visualizer' ); } $types = array( 'area', 'geo', 'column', 'bubble', 'scatter', 'gauge', 'candlestick', 'timeline', 'combo', 'polarArea', 'radar' ); $pro_class = ''; if ( ! empty( $chart_type ) && in_array( $chart_type, $types, true ) ) { $pro_class = 'viz-is-pro-chart'; } $chart_status = array( 'date' => get_the_modified_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $chart_id ), 'error' => get_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, true ), 'icon' => 'dashicons-yes-alt', 'title' => 'A-OK!' ); if ( ! empty( $chart_status['error'] ) ) { $chart_status['icon'] = 'error dashicons-dismiss'; $chart_status['title'] = __( 'Click to view the error', 'visualizer' ); } $shortcode = sprintf( '[visualizer id="%s" class=""]', $chart_id ); if ( $this->_isListView() ) { // ── List view: table row ── echo ''; echo '#' . esc_html( (string) $chart_id ) . ''; echo '' . esc_html( $title ) . ''; echo '' . ( ! empty( $chart_type_label ) ? '' . esc_html( $chart_type_label ) . '' : '—' ) . ''; echo '' . esc_html( $shortcode ) . ''; echo '
'; echo '' . esc_html__( 'Delete', 'visualizer' ) . ''; echo '' . esc_html__( 'Copy Shortcode', 'visualizer' ) . ''; echo '' . esc_html__( 'Export CSV', 'visualizer' ) . ''; echo '' . esc_html__( 'Duplicate', 'visualizer' ) . ''; echo '' . esc_html__( 'Edit', 'visualizer' ) . '' . esc_html__( 'Edit', 'visualizer' ) . ''; echo '
'; echo ''; return; } // ── Grid view: card ── $type_badge = ! empty( $chart_type ) ? '' . esc_html( $chart_type ) . '' : ''; echo '
' . esc_html( $title ) . '' . $type_badge . '
'; if ( Visualizer_Module::is_pro() && $with_filter ) { echo '
'; echo '
'; } echo '
'; echo ''; echo '
'; if ( Visualizer_Module::is_pro() && $with_filter ) { echo '
'; } echo ''; echo '
'; } /** * Returns true when the library should render in list (no-preview) mode. * * Priority: ?view= URL param (saves to user meta) → saved user meta → grid default. * * No nonce needed: this is a bookmarkable UI preference URL. A nonce would expire * and break saved/shared links for zero real security gain — the value is allowlisted * to 'list'|'grid' before any write happens. */ private function _isListView(): bool { if ( null !== $this->_list_view_cached ) { return $this->_list_view_cached; } if ( isset( $_GET['view'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $view = sanitize_text_field( wp_unslash( $_GET['view'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( in_array( $view, array( 'list', 'grid' ), true ) ) { update_user_meta( get_current_user_id(), 'visualizer_library_view', $view ); } $this->_list_view_cached = ( 'list' === $view ); } else { $saved = get_user_meta( get_current_user_id(), 'visualizer_library_view', true ); $this->_list_view_cached = ( 'list' === $saved ); } return $this->_list_view_cached; } /** * Returns the HTML for the grid/list view toggle links. */ private function _getViewToggleHTML(): string { $is_list = $this->_isListView(); $grid_url = esc_url( add_query_arg( 'view', 'grid' ) ); $list_url = esc_url( add_query_arg( 'view', 'list' ) ); return '' . ''; } /** * Render 2-col sidebar */ private function _renderSidebar() { if ( ! Visualizer_Module::is_pro() ) { $upgrade_url = tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'sidebarMenuUpgrade', 'index' ); $chart_types = Visualizer_Module_Admin::proFeaturesEnabled() ? __( '6 more chart types', 'visualizer' ) : __( '11 more chart types', 'visualizer' ); echo '
'; echo '
'; echo ''; echo '
'; echo '' . esc_html__( 'Unlock the full power of Visualizer PRO!', 'visualizer' ) . ''; /* translators: %s: number of additional chart types (e.g. "11 more chart types") */ echo '' . sprintf( esc_html__( '%s, periodic data sync, database queries, frontend editor, and more.', 'visualizer' ), esc_html( $chart_types ) ) . ''; echo '
'; echo ''; echo '
'; echo '
'; } } }