| Server IP : 158.247.231.215 / Your IP : 216.73.216.159 Web Server : Apache/2.4.41 (Ubuntu) System : Linux CTMS 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 User : www-data ( 33) PHP Version : 8.0.30 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /mnt/blockstorage/ctms/wp-content/themes/zakra/ |
Upload File : |
<?php
/**
* Template Name: APK List
* Template Post Type: page
*/
if ( ! is_user_logged_in() ) {
wp_redirect( wp_login_url( get_permalink() ) );
exit;
}
global $wpdb;
$search = isset( $_GET['search'] ) ? sanitize_text_field( wp_unslash( $_GET['search'] ) ) : '';
$paged = isset( $_GET['paged'] ) ? max( 1, intval( $_GET['paged'] ) ) : 1;
$per_page = 12;
$offset = ( $paged - 1 ) * $per_page;
if ( $search ) {
$like = '%' . $wpdb->esc_like( $search ) . '%';
$where = $wpdb->prepare( "WHERE c.status = 'active' AND (c.title LIKE %s OR c.description LIKE %s)", $like, $like );
} else {
$where = "WHERE c.status = 'active'";
}
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$total = (int) $wpdb->get_var( "SELECT COUNT(DISTINCT c.id) FROM vr_contents c $where" );
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$contents = $wpdb->get_results(
$wpdb->prepare(
"SELECT c.id, c.title, c.description, c.created_at,
thumb.image_path AS thumbnail_path,
COUNT(DISTINCT v.id) AS version_count
FROM vr_contents c
LEFT JOIN vr_content_versions v ON c.id = v.content_id AND v.status = 'active'
LEFT JOIN vr_content_images thumb ON c.id = thumb.content_id AND thumb.image_type = 'thumbnail'
$where
GROUP BY c.id, c.title, c.description, c.created_at, thumb.image_path
ORDER BY c.created_at DESC
LIMIT %d OFFSET %d",
$per_page,
$offset
)
);
$total_pages = $total > 0 ? ceil( $total / $per_page ) : 1;
$detail_pages = get_pages(
array(
'meta_key' => '_wp_page_template',
'meta_value' => 'page-apk-detail.php',
'number' => 1,
)
);
$detail_base = $detail_pages ? get_permalink( $detail_pages[0]->ID ) : home_url( '/apk-down/detail/' );
// Remove default .zak-container/.zak-row so hero can span full viewport width.
remove_action( 'zakra_action_before_content', 'zakra_content_start', 20 );
remove_action( 'zakra_action_after_content', 'zakra_content_end', 10 );
get_header();
?>
<style>
.apkl-hero {
background: #7B3FBE;
padding: 36px 20px;
text-align: center;
}
.apkl-hero h1 {
font-size: 28px;
font-weight: 700;
margin: 0;
color: #fff;
}
.apkl-wrap {
max-width: 1200px;
margin: 40px auto;
padding: 0 20px;
}
.apkl-search {
display: flex;
gap: 10px;
margin-bottom: 32px;
}
.apkl-search input {
flex: 1;
padding: 12px 16px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 15px;
outline: none;
transition: border-color .2s;
}
.apkl-search input:focus { border-color: #7B3FBE; }
.apkl-search button {
padding: 12px 24px;
background: #7B3FBE;
color: #fff;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 15px;
font-weight: 600;
}
.apkl-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
}
.apkl-card {
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,.08);
overflow: hidden;
transition: transform .2s, box-shadow .2s;
display: flex;
flex-direction: column;
}
.apkl-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(123,63,190,.18);
}
.apkl-thumb {
width: 100%;
height: 180px;
object-fit: cover;
background: #f0e8ff;
display: flex;
align-items: center;
justify-content: center;
font-size: 52px;
flex-shrink: 0;
}
.apkl-thumb img { width: 100%; height: 180px; object-fit: cover; display: block; }
.apkl-body { padding: 18px; display: flex; flex-direction: column; flex: 1; }
.apkl-title {
font-size: 17px;
font-weight: 700;
margin: 0 0 8px;
color: #1a1a1a;
line-height: 1.4;
}
.apkl-desc {
font-size: 13px;
color: #666;
margin-bottom: 14px;
flex: 1;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
line-height: 1.5;
}
.apkl-badges { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 16px; }
.apkl-badge {
padding: 3px 10px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
}
.apkl-badge-purple { background: #f0e8ff; color: #7B3FBE; }
.apkl-badge-green { background: #e8f5e9; color: #2e7d32; }
.apkl-btn {
display: block;
padding: 10px;
background: #7B3FBE;
color: #fff;
text-align: center;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
font-size: 14px;
transition: background .2s;
}
.apkl-btn:hover { background: #6a2fa8; color: #fff; text-decoration: none; }
.apkl-empty {
grid-column: 1/-1;
text-align: center;
padding: 60px;
color: #888;
font-size: 16px;
}
.apkl-pagination { margin-top: 40px; text-align: center; }
.apkl-pagination a {
display: inline-block;
margin: 0 4px;
padding: 7px 14px;
border: 1px solid #7B3FBE;
border-radius: 6px;
color: #7B3FBE;
text-decoration: none;
font-size: 14px;
transition: background .2s, color .2s;
}
.apkl-pagination a:hover,
.apkl-pagination a.current {
background: #7B3FBE;
color: #fff;
}
</style>
<div class="apkl-hero">
<h1>Learn with Nuguna VR World</h1>
</div>
<div class="apkl-wrap">
<form class="apkl-search" method="get" action="">
<input
type="text"
name="search"
placeholder="콘텐츠 검색..."
value="<?php echo esc_attr( $search ); ?>"
/>
<button type="submit">검색</button>
</form>
<div class="apkl-grid">
<?php if ( $contents ) : ?>
<?php foreach ( $contents as $item ) : ?>
<?php
$thumb_url = $item->thumbnail_path
? 'https://training.contentsda.kr/vr-content-uploads/' . esc_attr( $item->thumbnail_path )
: '';
$detail_url = add_query_arg( 'id', $item->id, $detail_base );
?>
<div class="apkl-card">
<div class="apkl-thumb">
<?php if ( $thumb_url ) : ?>
<img src="<?php echo esc_url( $thumb_url ); ?>" alt="<?php echo esc_attr( $item->title ); ?>" />
<?php else : ?>
📱
<?php endif; ?>
</div>
<div class="apkl-body">
<h3 class="apkl-title"><?php echo esc_html( $item->title ); ?></h3>
<p class="apkl-desc"><?php echo esc_html( $item->description ); ?></p>
<div class="apkl-badges">
<span class="apkl-badge apkl-badge-purple">버전 <?php echo intval( $item->version_count ); ?>개</span>
<span class="apkl-badge apkl-badge-green">APK 다운로드</span>
</div>
<a href="<?php echo esc_url( $detail_url ); ?>" class="apkl-btn">APK 다운로드 →</a>
</div>
</div>
<?php endforeach; ?>
<?php else : ?>
<div class="apkl-empty">
<?php echo $search ? '검색 결과가 없습니다.' : '등록된 콘텐츠가 없습니다.'; ?>
</div>
<?php endif; ?>
</div>
<?php if ( $total_pages > 1 ) : ?>
<div class="apkl-pagination">
<?php
$base_args = $search ? array( 'search' => $search ) : array();
for ( $i = 1; $i <= $total_pages; $i++ ) :
$page_url = add_query_arg( array_merge( $base_args, array( 'paged' => $i ) ) );
?>
<a href="<?php echo esc_url( $page_url ); ?>" class="<?php echo $i === $paged ? 'current' : ''; ?>"><?php echo $i; ?></a>
<?php endfor; ?>
</div>
<?php endif; ?>
</div>
<?php
// Close #zak-content opened by zakra_main_start in header.php
echo '</div><!-- /#zak-content -->';
get_footer();