REDROOM
PHP 8.0.30
Path:
Logout
Edit File
Size: 30.10 KB
Close
/home/certprox/template.certproxywizard.com/wp-content/plugins/he-simple-post-layout/he-simple-post-layout.php
Text
Base64
<?php /** * Plugin Name: HE Simple Post Layout * Plugin URI: https://example.com/he-simple-post-layout * Description: A beautiful, modern single blog post layout for Hello Elementor theme. Includes next/previous navigation, suggested posts sidebar, and a 1200px reading experience. Zero configuration required. * Version: 2.0.0 * Requires at least: 5.8 * Requires PHP: 7.4 * Author: Your Name * License: GPL v2 or later * License URI: https://www.gnu.org/licenses/gpl-2.0.html * Text Domain: he-simple-post-layout */ if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'HE_Simple_Post_Layout' ) ) { final class HE_Simple_Post_Layout { const VERSION = '2.0.0'; private static ?HE_Simple_Post_Layout $instance = null; public static function get_instance(): HE_Simple_Post_Layout { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } private function __construct() { add_action( 'wp_head', [ $this, 'inject_styles' ] ); add_filter( 'the_content', [ $this, 'wrap_post_content' ], 99 ); } private function should_apply(): bool { if ( ! is_singular( 'post' ) || ! is_main_query() ) { return false; } if ( class_exists( '\Elementor\Plugin' ) && isset( \Elementor\Plugin::$instance->preview ) && method_exists( \Elementor\Plugin::$instance->preview, 'is_preview_mode' ) && \Elementor\Plugin::$instance->preview->is_preview_mode() ) { return false; } if ( class_exists( '\Elementor\Plugin' ) && isset( \Elementor\Plugin::$instance->editor ) && method_exists( \Elementor\Plugin::$instance->editor, 'is_edit_mode' ) && \Elementor\Plugin::$instance->editor->is_edit_mode() ) { return false; } return true; } public function inject_styles(): void { if ( ! $this->should_apply() ) return; ?> <style id="hesl-post-styles"> /* ── Reset & base ─────────────────────────────────────────── */ *, *::before, *::after { box-sizing: border-box; } .hesl-page { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; color: #1e293b; background: #f8fafc; margin: 0; } /* ── Outer shell ──────────────────────────────────────────── */ .hesl-container { max-width: 1200px; margin: 0 auto; padding: 48px 32px 64px; } /* ── Two-column grid: article + sidebar ───────────────────── */ .hesl-grid { display: grid; grid-template-columns: 1fr 340px; gap: 48px; align-items: start; } /* ══════════════════════════════════════════════════════════ ARTICLE COLUMN ══════════════════════════════════════════════════════════ */ /* Category badge above title */ .hesl-category-badge { display: inline-flex; align-items: center; gap: 6px; background: #1B2F6B; color: #fff; font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; padding: 5px 14px; border-radius: 100px; margin-bottom: 20px; text-decoration: none; } /* Article card */ .hesl-article-card { background: #ffffff; border-radius: 16px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 8px 24px rgba(0,0,0,0.06); } /* Featured image */ .hesl-featured-image { width: 100%; position: relative; overflow: hidden; max-height: 480px; background: #e2e8f0; } .hesl-featured-image img { width: 100%; height: 480px; object-fit: cover; display: block; transition: transform 0.4s ease; } /* Article inner padding */ .hesl-article-inner { padding: 40px 48px 48px; } /* Title */ .hesl-post-title { font-size: 2.25rem; font-weight: 800; line-height: 1.2; letter-spacing: -0.03em; color: #0f172a; margin: 0 0 20px 0; } /* Meta row */ .hesl-meta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 20px; padding: 16px 0; border-top: 1px solid #f1f5f9; border-bottom: 1px solid #f1f5f9; margin-bottom: 36px; } .hesl-meta-item { display: flex; align-items: center; gap: 7px; font-size: 13.5px; color: #64748b; font-weight: 500; } .hesl-meta-item svg { width: 15px; height: 15px; flex-shrink: 0; color: #94a3b8; } .hesl-meta-dot { width: 3px; height: 3px; border-radius: 50%; background: #cbd5e1; } /* ── Post body typography ─────────────────────────────────── */ .hesl-post-body { font-size: 17px; line-height: 1.8; letter-spacing: -0.01em; color: #374151; } .hesl-post-body p { margin: 0 0 1.6em; } .hesl-post-body h2 { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em; color: #0f172a; margin: 2.2em 0 0.8em; line-height: 1.3; } .hesl-post-body h3 { font-size: 1.2rem; font-weight: 700; color: #1e293b; margin: 1.8em 0 0.6em; } .hesl-post-body h4, .hesl-post-body h5, .hesl-post-body h6 { font-weight: 600; color: #1e293b; margin: 1.5em 0 0.5em; } .hesl-post-body ul, .hesl-post-body ol { padding-left: 1.6em; margin: 0 0 1.6em; } .hesl-post-body li { margin-bottom: 0.55em; } .hesl-post-body blockquote { margin: 2.2em 0; padding: 1.2em 1.8em; border-left: 4px solid #1B2F6B; background: #f0f4ff; border-radius: 0 10px 10px 0; font-size: 1.05em; font-style: italic; color: #475569; } .hesl-post-body a { color: #1B2F6B; text-decoration: underline; text-underline-offset: 3px; font-weight: 500; } .hesl-post-body a:hover { color: #F5A623; } .hesl-post-body img { max-width: 100%; height: auto; border-radius: 10px; display: block; margin: 1.8em auto; } .hesl-post-body hr { border: none; border-top: 1px solid #e2e8f0; margin: 2.5em 0; } .hesl-post-body code { background: #f1f5f9; border-radius: 5px; padding: 0.15em 0.5em; font-size: 0.875em; color: #1B2F6B; } .hesl-post-body pre { background: #0f172a; color: #e2e8f0; border-radius: 10px; padding: 1.4em 1.6em; overflow-x: auto; font-size: 0.875rem; line-height: 1.65; margin: 0 0 1.8em; } .hesl-post-body pre code { background: transparent; padding: 0; color: inherit; } .hesl-post-body table { width: 100%; border-collapse: collapse; font-size: 0.9rem; margin: 0 0 1.6em; } .hesl-post-body th, .hesl-post-body td { border: 1px solid #e2e8f0; padding: 0.7em 1em; text-align: left; } .hesl-post-body th { background: #f8fafc; font-weight: 600; color: #0f172a; } /* ── Tags strip ───────────────────────────────────────────── */ .hesl-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 40px; padding-top: 28px; border-top: 1px solid #f1f5f9; } .hesl-tags-label { font-size: 13px; font-weight: 600; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.07em; align-self: center; margin-right: 4px; } .hesl-tag { display: inline-block; background: #f1f5f9; color: #475569; font-size: 12.5px; font-weight: 500; padding: 5px 14px; border-radius: 100px; text-decoration: none; transition: background 0.2s, color 0.2s; } .hesl-tag:hover { background: #1B2F6B; color: #fff; } /* ══════════════════════════════════════════════════════════ PREV / NEXT NAVIGATION ══════════════════════════════════════════════════════════ */ .hesl-post-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 24px; } .hesl-nav-link { display: flex; flex-direction: column; gap: 6px; background: #ffffff; border: 1.5px solid #e2e8f0; border-radius: 14px; padding: 20px 22px; text-decoration: none; transition: border-color 0.2s, box-shadow 0.2s, transform 0.2s; color: inherit; } .hesl-nav-link:hover { border-color: #1B2F6B; box-shadow: 0 4px 16px rgba(27,47,107,0.1); transform: translateY(-2px); color: inherit; } .hesl-nav-link.hesl-nav-next { text-align: right; } .hesl-nav-label { font-size: 11px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: #94a3b8; display: flex; align-items: center; gap: 5px; } .hesl-nav-link.hesl-nav-next .hesl-nav-label { justify-content: flex-end; } .hesl-nav-title { font-size: 14.5px; font-weight: 600; color: #1e293b; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .hesl-nav-thumb { width: 42px; height: 42px; border-radius: 8px; object-fit: cover; flex-shrink: 0; } .hesl-nav-content { display: flex; align-items: center; gap: 12px; } .hesl-nav-link.hesl-nav-next .hesl-nav-content { flex-direction: row-reverse; } /* ══════════════════════════════════════════════════════════ SIDEBAR ══════════════════════════════════════════════════════════ */ .hesl-sidebar { display: flex; flex-direction: column; gap: 24px; position: sticky; top: 32px; } .hesl-widget { background: #ffffff; border-radius: 16px; padding: 24px; box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 12px rgba(0,0,0,0.04); } .hesl-widget-title { font-size: 13px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: #94a3b8; margin: 0 0 18px; padding-bottom: 14px; border-bottom: 1px solid #f1f5f9; } /* Author card */ .hesl-author-card { text-align: center; padding: 8px 0; } .hesl-author-avatar { width: 72px; height: 72px; border-radius: 50%; margin: 0 auto 12px; display: block; border: 3px solid #f1f5f9; object-fit: cover; } .hesl-author-avatar-fallback { width: 72px; height: 72px; border-radius: 50%; background: linear-gradient(135deg, #1B2F6B 0%, #3b5998 100%); display: flex; align-items: center; justify-content: center; margin: 0 auto 12px; font-size: 28px; font-weight: 700; color: #fff; } .hesl-author-name { font-size: 16px; font-weight: 700; color: #0f172a; margin: 0 0 5px; } .hesl-author-bio { font-size: 13px; color: #64748b; line-height: 1.6; margin: 0; } /* Suggested posts */ .hesl-suggested-list { display: flex; flex-direction: column; gap: 16px; } .hesl-suggested-item { display: flex; gap: 14px; align-items: flex-start; text-decoration: none; color: inherit; transition: opacity 0.2s; } .hesl-suggested-item:hover { opacity: 0.75; } .hesl-suggested-thumb { width: 72px; height: 72px; border-radius: 10px; object-fit: cover; flex-shrink: 0; background: #e2e8f0; } .hesl-suggested-thumb-placeholder { width: 72px; height: 72px; border-radius: 10px; background: #f1f5f9; flex-shrink: 0; display: flex; align-items: center; justify-content: center; } .hesl-suggested-thumb-placeholder svg { color: #cbd5e1; } .hesl-suggested-info { flex: 1; min-width: 0; } .hesl-suggested-title { font-size: 13.5px; font-weight: 600; color: #1e293b; line-height: 1.4; margin: 0 0 5px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .hesl-suggested-date { font-size: 11.5px; color: #94a3b8; font-weight: 500; } .hesl-suggested-divider { height: 1px; background: #f1f5f9; margin: 0; border: none; } /* ══════════════════════════════════════════════════════════ RESPONSIVE ══════════════════════════════════════════════════════════ */ @media (max-width: 1024px) { .hesl-grid { grid-template-columns: 1fr; } .hesl-sidebar { position: static; } .hesl-container { padding: 32px 24px 48px; } } @media (max-width: 768px) { .hesl-article-inner { padding: 24px 20px 32px; } .hesl-post-title { font-size: 1.65rem; } .hesl-post-body { font-size: 16px; } .hesl-post-nav { grid-template-columns: 1fr; } .hesl-featured-image img { height: 260px; } .hesl-container { padding: 16px 16px 40px; } } @media (max-width: 480px) { .hesl-post-title { font-size: 1.4rem; } .hesl-meta-dot { display: none; } .hesl-meta-row { gap: 10px; } } </style> <?php } /* ── Helpers ─────────────────────────────────────────────────── */ private function get_post_thumbnail_html( int $post_id, string $size, string $css_class, string $fallback_text = '' ): string { $url = get_the_post_thumbnail_url( $post_id, $size ); if ( $url ) { $alt = esc_attr( get_the_title( $post_id ) ); return sprintf( '<img src="%s" alt="%s" class="%s" loading="lazy" decoding="async" />', esc_url( $url ), $alt, esc_attr( $css_class ) ); } if ( $fallback_text ) { return sprintf( '<div class="hesl-suggested-thumb-placeholder"><svg width="28" height="28" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg></div>' ); } return ''; } private function get_categories_html( int $post_id ): string { $cats = get_the_category( $post_id ); if ( empty( $cats ) ) return ''; $cat = $cats[0]; return sprintf( '<a href="%s" class="hesl-category-badge">%s</a>', esc_url( get_category_link( $cat->term_id ) ), esc_html( $cat->name ) ); } private function get_tags_html( int $post_id ): string { $tags = get_the_tags( $post_id ); if ( empty( $tags ) ) return ''; $out = '<div class="hesl-tags"><span class="hesl-tags-label">Tags</span>'; foreach ( $tags as $tag ) { $out .= sprintf( '<a href="%s" class="hesl-tag">%s</a>', esc_url( get_tag_link( $tag->term_id ) ), esc_html( $tag->name ) ); } $out .= '</div>'; return $out; } private function get_nav_html(): string { $prev = get_previous_post(); $next = get_next_post(); if ( ! $prev && ! $next ) return ''; $html = '<nav class="hesl-post-nav" aria-label="Post navigation">'; if ( $prev ) { $thumb = get_the_post_thumbnail_url( $prev->ID, 'thumbnail' ); $thumb_html = $thumb ? sprintf( '<img src="%s" class="hesl-nav-thumb" alt="" loading="lazy" />', esc_url( $thumb ) ) : ''; $html .= sprintf( '<a href="%s" class="hesl-nav-link hesl-nav-prev"> <span class="hesl-nav-label"><svg width="13" height="13" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M19 12H5M12 5l-7 7 7 7"/></svg> Previous Post</span> <div class="hesl-nav-content">%s<span class="hesl-nav-title">%s</span></div> </a>', esc_url( get_permalink( $prev->ID ) ), $thumb_html, esc_html( get_the_title( $prev->ID ) ) ); } else { $html .= '<div></div>'; } if ( $next ) { $thumb = get_the_post_thumbnail_url( $next->ID, 'thumbnail' ); $thumb_html = $thumb ? sprintf( '<img src="%s" class="hesl-nav-thumb" alt="" loading="lazy" />', esc_url( $thumb ) ) : ''; $html .= sprintf( '<a href="%s" class="hesl-nav-link hesl-nav-next"> <span class="hesl-nav-label">Next Post <svg width="13" height="13" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M5 12h14M12 5l7 7-7 7"/></svg></span> <div class="hesl-nav-content">%s<span class="hesl-nav-title">%s</span></div> </a>', esc_url( get_permalink( $next->ID ) ), $thumb_html, esc_html( get_the_title( $next->ID ) ) ); } else { $html .= '<div></div>'; } $html .= '</nav>'; return $html; } private function get_author_widget_html( int $post_id ): string { $author_id = (int) get_post_field( 'post_author', $post_id ); $name = esc_html( get_the_author_meta( 'display_name', $author_id ) ); $bio = esc_html( get_the_author_meta( 'description', $author_id ) ); $avatar_url = esc_url( get_avatar_url( $author_id, [ 'size' => 144 ] ) ); $initial = strtoupper( mb_substr( $name, 0, 1 ) ); $avatar_html = $avatar_url ? sprintf( '<img src="%s" class="hesl-author-avatar" alt="%s" loading="lazy" />', $avatar_url, $name ) : sprintf( '<div class="hesl-author-avatar-fallback">%s</div>', esc_html( $initial ) ); return sprintf( '<aside class="hesl-widget"> <p class="hesl-widget-title">About the Author</p> <div class="hesl-author-card"> %s <p class="hesl-author-name">%s</p> %s </div> </aside>', $avatar_html, $name, $bio ? sprintf( '<p class="hesl-author-bio">%s</p>', $bio ) : '' ); } private function get_suggested_posts_html( int $current_id ): string { $args = [ 'post_type' => 'post', 'posts_per_page' => 4, 'post__not_in' => [ $current_id ], 'ignore_sticky_posts' => 1, 'orderby' => 'rand', ]; // Prefer posts from same category $cats = wp_get_post_categories( $current_id ); if ( ! empty( $cats ) ) { $args['category__in'] = $cats; } $query = new WP_Query( $args ); if ( ! $query->have_posts() ) return ''; $html = '<aside class="hesl-widget"> <p class="hesl-widget-title">You Might Also Like</p> <div class="hesl-suggested-list">'; $first = true; while ( $query->have_posts() ) { $query->the_post(); $pid = get_the_ID(); $thumb = get_the_post_thumbnail_url( $pid, 'thumbnail' ); if ( ! $first ) { $html .= '<hr class="hesl-suggested-divider" />'; } $first = false; $thumb_html = $thumb ? sprintf( '<img src="%s" class="hesl-suggested-thumb" alt="%s" loading="lazy" />', esc_url( $thumb ), esc_attr( get_the_title() ) ) : '<div class="hesl-suggested-thumb-placeholder"><svg width="28" height="28" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg></div>'; $html .= sprintf( '<a href="%s" class="hesl-suggested-item"> %s <div class="hesl-suggested-info"> <p class="hesl-suggested-title">%s</p> <span class="hesl-suggested-date">%s</span> </div> </a>', esc_url( get_permalink() ), $thumb_html, esc_html( get_the_title() ), esc_html( get_the_date() ) ); } wp_reset_postdata(); $html .= '</div></aside>'; return $html; } /* ── Main content wrapper ───────────────────────────────────── */ public function wrap_post_content( string $content ): string { if ( ! $this->should_apply() ) return $content; $post_id = get_the_ID(); $title = esc_html( get_the_title( $post_id ) ); $date = esc_html( get_the_date( 'F j, Y', $post_id ) ); $author = esc_html( get_the_author() ); $read_time = max( 1, (int) ceil( str_word_count( wp_strip_all_tags( $content ) ) / 200 ) ); /* Featured image */ $thumb_url = get_the_post_thumbnail_url( $post_id, 'full' ); $thumb_html = ''; if ( $thumb_url ) { $thumb_html = sprintf( '<div class="hesl-featured-image"> <img src="%s" alt="%s" loading="eager" decoding="async" /> </div>', esc_url( $thumb_url ), esc_attr( $title ) ); } /* Calendar icon */ $icon_date = '<svg width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>'; /* Author icon */ $icon_author = '<svg width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 3.6-7 8-7s8 3 8 7"/></svg>'; /* Clock icon */ $icon_clock = '<svg width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 3"/></svg>'; ob_start(); ?> <div class="hesl-page"> <div class="hesl-container"> <div class="hesl-grid"> <!-- ── Article column ── --> <div class="hesl-article-col"> <?php echo $this->get_categories_html( $post_id ); ?> <article class="hesl-article-card"> <?php echo $thumb_html; ?> <div class="hesl-article-inner"> <h1 class="hesl-post-title"><?php echo $title; ?></h1> <div class="hesl-meta-row"> <span class="hesl-meta-item"><?php echo $icon_date; ?><?php echo $date; ?></span> <span class="hesl-meta-dot"></span> <span class="hesl-meta-item"><?php echo $icon_author; ?><?php echo $author; ?></span> <span class="hesl-meta-dot"></span> <span class="hesl-meta-item"><?php echo $icon_clock; ?><?php echo $read_time; ?> min read</span> </div> <div class="hesl-post-body"> <?php echo $content; ?> </div> <?php echo $this->get_tags_html( $post_id ); ?> </div><!-- /.hesl-article-inner --> </article><!-- /.hesl-article-card --> <?php echo $this->get_nav_html(); ?> </div><!-- /.hesl-article-col --> <!-- ── Sidebar ── --> <aside class="hesl-sidebar"> <?php echo $this->get_author_widget_html( $post_id ); ?> <?php echo $this->get_suggested_posts_html( $post_id ); ?> </aside> </div><!-- /.hesl-grid --> </div><!-- /.hesl-container --> </div><!-- /.hesl-page --> <?php return ob_get_clean(); } } // end class } // end if class_exists add_action( 'plugins_loaded', static function (): void { HE_Simple_Post_Layout::get_instance(); } );
Save
Close
Exit & Reset
Text mode: syntax highlighting auto-detects file type.
Directory Contents
Dirs: 0 × Files: 1
Delete Selected
Select All
Select None
Sort:
Name
Size
Modified
Enable drag-to-move
Name
Size
Perms
Modified
Actions
he-simple-post-layout.php
30.10 KB
lrw-r--r--
2026-06-20 08:03:21
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
Zip Selected
If ZipArchive is unavailable, a
.tar
will be created (no compression).