File: /home/vanessatli/www/wp-content/themes/hestia/inc/admin/dashboard/class-hestia-dashboard-render.php
<?php
/**
* Render class fot the dashboard page.
*
* @package Hestia
*/
/**
* Class Hestia_Dashboard_Render
*
* @package Hestia
*/
class Hestia_Dashboard_Render {
/**
* The theme args.
*
* @var array<string, mixed>
*/
private $theme = array();
/**
* Regular tabs, any theme should have this information in the About Page.
*
* @var array<string, mixed>
*/
private $tabs = array();
/**
* The instance.
*
* @var Hestia_Dashboard|null
*/
private $about_page = null;
/**
* Custom tabs based on theme's particularities.
*
* @var array<string, mixed>
*/
private $custom_tabs = array();
/**
* Branding notice.
*
* @var array<string, string>
*/
private $branding_notice = array();
/**
* Constructor.
*
* @param array<string, mixed> $theme_args Current theme args.
* @param array<string, mixed> $data About page content.
* @param Hestia_Dashboard $about_page About page content.
*/
public function __construct( $theme_args, $data, $about_page ) {
$this->theme = $theme_args;
$this->tabs = $data;
$this->about_page = $about_page;
if ( isset( $data['branding_notice'] ) ) {
$this->branding_notice = $data['branding_notice'];
}
if ( isset( $this->tabs['custom_tabs'] ) ) {
$this->custom_tabs = $data['custom_tabs'];
unset( $this->tabs['custom_tabs'] );
}
$this->render();
}
/**
* The main render function.
*
* @return void
*/
private function render() {
if ( empty( $this->tabs ) ) {
return;
}
echo '<div class="loading-screen">';
echo '<div class="updating-message">';
echo '<p>' . esc_html__( 'Loading', 'hestia' ) . '...</p>';
echo '</div>';
echo '</div>';
echo '<div class="ti-about-wrap">';
$this->render_header();
echo '<div id="tsdk_banner" class="ti-about-banner"></div>';
echo '<div class="main-content">';
echo '<div id="about-tabs">';
$this->render_tabs_content();
echo '</div>';
$this->render_sidebar();
echo '</div>';
echo '</div>';
}
/**
* Render the header.
*
* @return void
*/
private function render_header() {
?>
<div class="header">
<div class="header-info">
<h1>Welcome to <?php echo esc_html( $this->theme['name'] ); ?>! - Version <span
class="version-container"><?php echo esc_html( $this->theme['version'] ); ?></span></h1>
<?php
$white_label_options = get_option( 'ti_white_label_inputs' );
$white_label_options = json_decode( $white_label_options, true );
if ( empty( $white_label_options['theme_name'] ) ) {
?>
<span class="ti-logo"><img
src="<?php echo esc_url( get_template_directory_uri() . '/assets/img/themeisle.png' ); ?>"
alt="logo"/>
</span>
<?php
}
?>
</div>
<?php $this->render_tabs_list(); ?>
<?php $this->render_branding_notice(); ?>
</div>
<?php
}
/**
* Render tabs list.
*
* @return void
*/
private function render_tabs_list() {
echo '<ul class="ti-about-tablist">';
foreach ( $this->tabs as $slug => $tab_data ) {
if ( ! array_key_exists( 'type', $tab_data ) ) {
continue;
}
if ( $tab_data['type'] === 'recommended_actions' && $this->about_page->get_recommended_actions_left() === 0 ) {
continue;
}
if ( $slug === 'welcome_notice' || $slug === 'footer_messages' ) {
continue;
}
echo '<li data-tab-id="' . esc_attr( $slug ) . '">';
echo '<a class="tab';
if ( $tab_data['type'] === 'recommended_actions' ) {
echo ' recommended_actions';
}
if ( $slug === 'getting_started' ) {
echo ' active';
}
echo '" href="#' . esc_attr( $slug ) . '">' . esc_html( $tab_data['title'] ) . '</a>';
echo '</li>';
}
foreach ( $this->custom_tabs as $slug => $tab_data ) {
echo '<li data-tab-id="' . esc_attr( $slug ) . '">';
echo '<a class="tab" href="#' . esc_attr( $slug ) . '">' . esc_html( $tab_data['title'] ) . '</a>';
echo '</li>';
}
echo '</ul>';
}
/**
* Render the branding notice.
*
* @return void
*/
private function render_branding_notice() {
if ( empty( $this->branding_notice ) ) {
return;
}
$style = '
.ti-notice-wrap{
background: #f0f0f1;
width: 100%
}
.ti-branding-notice{
margin: 30px 40px 0 40px;
padding: 30px 40px;
background: #2271b1;
color: #fff;
display: flex;
align-items: center;
}
.ti-upgrade-btn{
padding: 10px 15px;
background-color: transparent;
border: 2px solid #fff;
border-radius: 2px;
box-shadow: none;
color: #fff;
flex-shrink: 0;
font-size: 14px;
font-weight: 600;
height: auto;
line-height: normal;
margin-left: auto;
}
.ti-upgrade-btn:hover{
background: #fff;
box-shadow: none;
color: #0073aa;
}
';
echo '<style>' . $style . '</style>';
echo '<div class="ti-notice-wrap">';
echo '<div class="ti-branding-notice">';
if ( isset( $this->branding_notice['text'] ) ) {
echo '<p>' . wp_kses_post( $this->branding_notice['text'] ) . '</p>';
}
if ( isset( $this->branding_notice['url'] ) && isset( $this->branding_notice['cta'] ) ) {
echo '<a target="_blank" class="ti-upgrade-btn" href="' . esc_url( $this->branding_notice['url'] ) . '">';
echo wp_kses_post( $this->branding_notice['cta'] );
echo '</a>';
}
echo '</div>';
echo '</div>';
}
/**
* Render tab content.
*
* @return void
*/
private function render_tabs_content() {
foreach ( $this->tabs as $slug => $tab_data ) {
if ( ! array_key_exists( 'type', $tab_data ) ) {
continue;
}
if ( $slug === 'recommended_actions' && $this->about_page->get_recommended_actions_left() === 0 ) {
continue;
}
if ( $slug === 'welcome_notice' || $slug === 'footer_messages' ) {
continue;
}
echo '<div id="' . esc_attr( $slug ) . '" class="' . esc_attr( $tab_data['type'] ) . ' tab-content ' . ( $slug === 'getting_started' ? 'active' : '' ) . '">';
switch ( $tab_data['type'] ) {
case 'recommended_actions':
$this->render_recommended_actions( $tab_data['plugins'] );
break;
case 'plugins':
$external_plugins = isset( $tab_data['external'] ) ? $tab_data['external'] : array();
$this->render_plugins_tab( $tab_data['plugins'], $external_plugins );
break;
case 'changelog':
$this->render_changelog();
break;
default:
$this->render_default_tab( $tab_data );
break;
}
echo '</div>';
}
foreach ( $this->custom_tabs as $slug => $tab_data ) {
echo '<div id="' . esc_attr( $slug ) . '" class="custom tab-content">';
call_user_func( $tab_data['render_callback'] );
echo '</div>';
}
}
/**
* Render recommended actions
*
* @param array<string, array<string, mixed>> $plugins_list Recommended plugins.
* @return void
*/
private function render_recommended_actions( $plugins_list ) {
if ( empty( $plugins_list ) || $this->about_page->get_recommended_actions_left() === 0 ) {
return;
}
$recommended_plugins_visibility = get_theme_mod( 'ti_about_recommended_plugins' );
foreach ( $plugins_list as $slug => $plugin ) {
if (
isset( $recommended_plugins_visibility[ $slug ] ) &&
(
'hidden' === $recommended_plugins_visibility[ $slug ] ||
'deactivate' === Hestia_Dashboard_Plugin_Helper::instance()->check_plugin_state( $slug )
)
) {
continue;
}
echo '<div class="ti-about-page-action-required-box ' . esc_attr( $slug ) . '">';
echo '<span class="dashicons dashicons-visibility ti-about-page-required-action-button" data-slug="' . esc_attr( $slug ) . '"></span>';
echo '<h3>' . $plugin['name'] . '</h3>';
if ( ! empty( $plugin['description'] ) ) {
echo '<p>' . $plugin['description'] . '</p>';
} else {
$plugin_description = $this->call_plugin_api( $slug );
if ( ! is_wp_error( $plugin_description ) && isset( $plugin_description->short_description ) ) {
echo '<p>' . $plugin_description->short_description . '</p>';
}
}
echo Hestia_Dashboard_Plugin_Helper::instance()->get_button_html( $slug, array( 'redirect' => add_query_arg( 'page', $this->theme['slug'] . '-welcome', admin_url( 'themes.php#recommended_actions' ) ) ) );
echo '</div>';
}
}
/**
* Call plugin api
*
* @param string $slug Plugin slug.
* @return array|object|WP_Error
*/
private function call_plugin_api( $slug ) {
include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
$call_api = get_transient( 'ti_about_plugin_info_' . $slug );
if ( false === $call_api ) {
$call_api = plugins_api(
'plugin_information',
array(
'slug' => $slug,
'fields' => array(
'downloaded' => false,
'rating' => false,
'description' => false,
'short_description' => true,
'donate_link' => false,
'tags' => false,
'sections' => true,
'homepage' => true,
'added' => false,
'last_updated' => false,
'compatibility' => false,
'tested' => false,
'requires' => false,
'downloadlink' => false,
'icons' => true,
'banners' => true,
),
)
);
set_transient( 'ti_about_plugin_info_' . $slug, $call_api, 30 * MINUTE_IN_SECONDS );
}
return $call_api;
}
/**
* Render the plugin card in recommended plugins tab.
*
* @param string $plugin_slug Plugin slug.
* @param array<string, mixed> $data Plugin data.
* @return void
*/
private function render_plugin_card( $plugin_slug, $data ) {
echo '<div class="plugin_box">';
if ( isset( $data['premium'] ) && $data['premium'] === true ) {
echo '<span class="premium-label">Premium</span>';
}
if ( isset( $data['banners']['low'] ) ) {
echo '<img class="plugin-banner" src="' . esc_attr( $data['banners']['low'] ) . '">';
}
echo '<div class="title-action-wrapper">';
echo '<span class="plugin-name">' . esc_html( $data['name'] ) . '</span>';
echo '<span class="plugin-desc">' . esc_html( $data['short_description'] ) . '</span>';
echo '</div>';
echo '<div class="plugin-box-footer">';
echo '<div class="button-wrap">';
if ( isset( $data['url'] ) ) {
echo '<a class="external-link" href="' . esc_url( $data['url'] ) . '" target="_blank" rel="external noreferrer noopener">';
echo esc_html__( 'Learn More', 'hestia' );
echo $this->get_external_link_icon();
echo '</a>';
} else {
echo Hestia_Dashboard_Plugin_Helper::instance()->get_button_html( $plugin_slug );
}
echo '</div>';
echo '<div class="version-wrapper">';
if ( isset( $data['version'] ) ) {
echo '<span class="version">' . esc_html( $data['version'] ) . '</span>';
echo '<span class="separator"> | </span>';
}
echo strtok( strip_tags( $data['author'] ), ',' );
echo '</div>';
echo '</div>';
echo '</div>';
}
/**
* Check if the plugin has the required data to be displayed.
*
* @param array<string, mixed> $data Plugin data.
* @return bool
*/
private function has_required_data( $data ) {
$required_data = array( 'banners', 'name', 'short_description', 'author' );
return 0 === count(
array_filter(
$required_data,
function ( $element ) use ( $data ) {
return ! array_key_exists( $element, $data );
}
)
);
}
/**
* Render plugins tab content.
*
* @param string[] $plugins_list List of useful plugins.
* @param array<string, mixed>[] $external List of plugins outside wp.org.
* @return void
*/
private function render_plugins_tab( $plugins_list, $external = array() ) {
if ( empty( $plugins_list ) ) {
return;
}
echo '<div class="recommended-plugins">';
foreach ( $plugins_list as $plugin ) {
$plugin_data = $this->call_plugin_api( $plugin );
if ( ! is_object( $plugin_data ) ) {
continue;
}
$plugin_data = get_object_vars( $plugin_data );
if ( ! $this->has_required_data( $plugin_data ) ) {
continue;
}
$this->render_plugin_card( $plugin, $plugin_data );
}
foreach ( $external as $plugin => $plugin_data ) {
if ( ! $this->has_required_data( $plugin_data ) ) {
continue;
}
$this->render_plugin_card( $plugin, $plugin_data );
}
echo '</div>';
}
/**
* Render changelog.
*
* @return void
*/
private function render_changelog() {
$changelog = $this->parse_changelog();
if ( empty( $changelog ) ) {
return;
}
echo '<div class="featured-section changelog">';
foreach ( $changelog as $release ) {
echo '<div class="release-wrap">';
if ( ! empty( $release['title'] ) ) {
echo '<h3>' . str_replace( '#', '', $release['title'] ) . ' </h3 > ';
}
echo '<ul class="release">';
if ( ! empty( $release['changes'] ) ) {
foreach ( $release['changes'] as $change ) {
if ( empty( trim( $change ) ) ) {
continue;
}
echo '<li>' . esc_html( ltrim( $change ) ) . '</li>';
}
}
echo '</ul>';
echo '</div>';
}
echo '</div>';
}
/**
* Return the releases changes array.
*
* @return array<int, array<string, mixed>>
*/
private function parse_changelog() {
WP_Filesystem();
global $wp_filesystem;
$changelog = $wp_filesystem->get_contents( get_template_directory() . '/CHANGELOG.md' );
if ( is_wp_error( $changelog ) ) {
$changelog = '';
}
$changelog = explode( PHP_EOL, $changelog );
$releases = array();
foreach ( $changelog as $changelog_line ) {
if ( strpos( $changelog_line, '**Changes:**' ) !== false || empty( $changelog_line ) ) {
continue;
}
if ( substr( ltrim( $changelog_line ), 0, 3 ) === '###' ) {
if ( isset( $release ) ) {
$releases[] = $release;
}
$release = array(
'title' => substr( $changelog_line, 3 ),
'changes' => array(),
);
} else {
$release['changes'][] = str_replace( '*', '', $changelog_line );
}
}
return $releases;
}
/**
* Render default tab content.
*
* @param array<string, mixed> $tab_data Tab content, video.
* @return void
*/
private function render_default_tab( $tab_data ) {
if ( ! isset( $tab_data['content'] ) || ! is_array( $tab_data['content'] ) ) {
return;
}
$tab_content = $tab_data['content'];
foreach ( $tab_content as $content ) {
echo '<div class="about-col">';
echo '<h3>';
if ( ! empty( $content['icon'] ) ) {
echo '<i class="dashicons dashicons-' . esc_attr( $content['icon'] ) . '"></i>';
}
echo esc_html( $content['title'] ) . '</h3>';
if ( ! empty( $content['text'] ) ) {
echo '<p>' . esc_html( $content['text'] ) . '</p>';
}
if ( ! empty( $content['html_content'] ) ) {
echo $content['html_content'];
}
if ( ! empty( $content['button'] ) ) {
$this->render_button( $content['button'] );
}
echo '</div>';
}
if ( ! isset( $tab_data['video'] ) || ! is_array( $tab_data['video'] ) || ! isset( $tab_data['video']['url'] ) ) {
return;
}
echo '<div style="display: grid; place-items: center; margin: 0 auto">';
if ( isset( $tab_data['video']['heading'] ) ) {
echo '<h3>' . esc_html( $tab_data['video']['heading'] ) . '</h3>';
}
echo '<iframe width="560" height="315" src="' . esc_url( $tab_data['video']['url'] ) . '" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>';
echo '</div>';
}
/**
* Render button.
*
* @param array<string, mixed> $button Args: label, link, new tab.
* @return void
*/
private function render_button( $button ) {
if ( empty( $button ) ) {
return;
}
if ( $button['link'] === '#recommended_actions' && $this->about_page->get_recommended_actions_left() === 0 ) {
echo '<span>' . esc_html__( 'Recommended actions', 'hestia' ) . '</span>';
return;
}
echo '<a href="' . esc_url( $button['link'] ) . '" ';
echo $button['is_button'] ? 'class="button button-primary" ' : '';
echo $button['blank'] ? 'class="external-link" ' : '';
echo $button['blank'] ? 'target="_blank" rel="external noreferrer noopener" ' : '';
echo '>';
echo $button['label'];
echo $button['blank'] && ! $button['is_button'] ? $this->get_external_link_icon() : '';
echo '</a>';
}
/**
* Render footer messages.
*
* @return void
*/
private function render_sidebar() {
if ( ! array_key_exists( 'footer_messages', $this->tabs ) ) {
return;
}
$footer_data = $this->tabs['footer_messages']['messages'];
echo '<div class="about-sidebar">';
do_action( 'ti_about_before_sidebar_content' );
foreach ( $footer_data as $data ) {
$heading = ! empty( $data['heading'] ) ? $data['heading'] : '';
$text = ! empty( $data['text'] ) ? $data['text'] : '';
$link_text = ! empty( $data['link_text'] ) ? $data['link_text'] : '';
$link = ! empty( $data['link'] ) ? $data['link'] : '';
$target = ! empty( $data['blank'] ) ? '_blank' : '_self';
$rel_attr = ! empty( $data['blank'] ) ? 'external noreferrer noopener' : '';
$svg_icon = ! empty( $data['blank'] ) ? $this->get_external_link_icon() : '';
if ( empty( $heading ) && empty( $text ) && ( empty( $link_text ) || empty( $link ) ) ) {
continue;
}
echo '<div class="about-sidebar-item">';
if ( ! empty( $heading ) ) {
echo '<h4>' . wp_kses_post( $heading ) . '</h4>';
}
echo '<div class="inside">';
if ( ! empty( $text ) ) {
echo '<p>' . wp_kses_post( $text ) . '</p>';
}
if ( ! empty( $link_text ) && ! empty( $link ) ) {
printf(
'<a href="%1$s" target="%2$s" rel="%3$s">%4$s %5$s</a>',
esc_url( $link ),
$target,
esc_attr( $rel_attr ),
wp_kses_post( $link_text ),
$svg_icon
);
}
echo '</div>';
echo '</div>';
}
do_action( 'ti_about_after_sidebar_content' );
echo '</div>';
}
/**
* Get open a link in a new tab icon.
*
* @return string
*/
private function get_external_link_icon() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" class="components-external-link__icon css-6wogo1-StyledIcon etxm6pv0" role="img" aria-hidden="true" focusable="false"><path d="M18.2 17c0 .7-.6 1.2-1.2 1.2H7c-.7 0-1.2-.6-1.2-1.2V7c0-.7.6-1.2 1.2-1.2h3.2V4.2H7C5.5 4.2 4.2 5.5 4.2 7v10c0 1.5 1.2 2.8 2.8 2.8h10c1.5 0 2.8-1.2 2.8-2.8v-3.6h-1.5V17zM14.9 3v1.5h3.7l-6.4 6.4 1.1 1.1 6.4-6.4v3.7h1.5V3h-6.3z"></path></svg>';
}
}