Initial commit

This commit is contained in:
vsphim
2026-05-20 11:47:28 +07:00
commit a1b567ab6e
43 changed files with 2051 additions and 0 deletions

View File

@@ -0,0 +1,290 @@
<?php
namespace VsMov\ThemeHoly\Controllers;
use Backpack\Settings\app\Models\Setting;
use Illuminate\Http\Request;
use VsMov\Core\Models\Actor;
use VsMov\Core\Models\Catalog;
use VsMov\Core\Models\Category;
use VsMov\Core\Models\Director;
use VsMov\Core\Models\Episode;
use VsMov\Core\Models\Movie;
use VsMov\Core\Models\Region;
use VsMov\Core\Models\Tag;
use Illuminate\Support\Facades\Cache;
class ThemeHolyController
{
public function index(Request $request)
{
if ($request['search'] || $request['filter']) {
$data = Movie::when(!empty($request['filter']['category']), function ($movie) {
$movie->whereHas('categories', function ($categories) {
$categories->where('id', request('filter')['category']);
});
})->when(!empty($request['filter']['region']), function ($movie) {
$movie->whereHas('regions', function ($regions) {
$regions->where('id', request('filter')['region']);
});
})->when(!empty($request['filter']['year']), function ($movie) {
$movie->where('publish_year', request('filter')['year']);
})->when(!empty($request['filter']['type']), function ($movie) {
$movie->where('type', request('filter')['type']);
})->when(!empty($request['search']), function ($query) {
$query->where(function ($query) {
$query->where('name', 'like', '%' . request('search') . '%')
->orWhere('origin_name', 'like', '%' . request('search') . '%');
})->orderBy('name', 'desc');
})->when(!empty($request['filter']['sort']), function ($movie) {
if (request('filter')['sort'] == 'create') {
return $movie->orderBy('created_at', 'desc');
}
if (request('filter')['sort'] == 'update') {
return $movie->orderBy('updated_at', 'desc');
}
if (request('filter')['sort'] == 'year') {
return $movie->orderBy('publish_year', 'desc');
}
if (request('filter')['sort'] == 'view') {
return $movie->orderBy('view_total', 'desc');
}
})->paginate(get_theme_option('per_page_limit'));
return view('themes::themeholy.catalog', [
'data' => $data,
'search' => $request['search'],
'section_name' => "Tìm kiếm phim: $request->search"
]);
}
return view('themes::themeholy.index', [
'title' => Setting::get('site_homepage_title')
]);
}
public function getMovieOverview(Request $request)
{
/** @var Movie */
$movie = Movie::fromCache()->find($request->movie ?: $request->id);
if (is_null($movie)) abort(404);
$movie->generateSeoTags();
$movie->increment('view_total', 1);
$movie->increment('view_day', 1);
$movie->increment('view_week', 1);
$movie->increment('view_month', 1);
$movie_related_cache_key = 'movie_related:' . $movie->id;
$movie_related = Cache::get($movie_related_cache_key);
if(is_null($movie_related)) {
$movie_related = $movie->categories[0]->movies()->inRandomOrder()->limit(get_theme_option('movie_related_limit', 10))->get();
Cache::put($movie_related_cache_key, $movie_related, setting('site_cache_ttl', 5 * 60));
}
return view('themes::themeholy.single', [
'currentMovie' => $movie,
'title' => $movie->getTitle(),
'movie_related' => $movie_related
]);
}
public function getEpisode(Request $request)
{
$movie = Movie::fromCache()->find($request->movie ?: $request->movie_id)->load('episodes');
if (is_null($movie)) abort(404);
/** @var Episode */
$episode_id = $request->id;
$episode = $movie->episodes->when($episode_id, function ($collection, $episode_id) {
return $collection->where('id', $episode_id);
})->firstWhere('slug', $request->episode);
if (is_null($episode)) abort(404);
$episode->generateSeoTags();
$movie->increment('view_total', 1);
$movie->increment('view_day', 1);
$movie->increment('view_week', 1);
$movie->increment('view_month', 1);
$movie_related_cache_key = 'movie_related:' . $movie->id;
$movie_related = Cache::get($movie_related_cache_key);
if(is_null($movie_related)) {
$movie_related = $movie->categories[0]->movies()->inRandomOrder()->limit(get_theme_option('movie_related_limit', 10))->get();
Cache::put($movie_related_cache_key, $movie_related, setting('site_cache_ttl', 5 * 60));
}
return view('themes::themeholy.episode', [
'currentMovie' => $movie,
'movie_related' => $movie_related,
'episode' => $episode,
'title' => $episode->getTitle()
]);
}
public function getMovieOfCategory(Request $request)
{
/** @var Category */
$category = Category::fromCache()->find($request->category ?: $request->id);
if (is_null($category)) abort(404);
$category->generateSeoTags();
$movies = $category->movies()->orderBy('created_at', 'desc')->paginate(get_theme_option('per_page_limit'));
return view('themes::themeholy.catalog', [
'data' => $movies,
'category' => $category,
'title' => $category->seo_title ?: $category->getTitle(),
'section_name' => "Phim thể loại $category->name"
]);
}
public function getMovieOfRegion(Request $request)
{
/** @var Region */
$region = Region::fromCache()->find($request->region ?: $request->id);
if (is_null($region)) abort(404);
$region->generateSeoTags();
$movies = $region->movies()->orderBy('created_at', 'desc')->paginate(get_theme_option('per_page_limit'));
return view('themes::themeholy.catalog', [
'data' => $movies,
'region' => $region,
'title' => $region->seo_title ?: $region->getTitle(),
'section_name' => "Phim quốc gia $region->name"
]);
}
public function getMovieOfActor(Request $request)
{
/** @var Actor */
$actor = Actor::fromCache()->find($request->actor ?: $request->id);
if (is_null($actor)) abort(404);
$actor->generateSeoTags();
$movies = $actor->movies()->orderBy('created_at', 'desc')->paginate(get_theme_option('per_page_limit'));
return view('themes::themeholy.catalog', [
'data' => $movies,
'person' => $actor,
'title' => $actor->getTitle(),
'section_name' => "Diễn viên $actor->name"
]);
}
public function getMovieOfDirector(Request $request)
{
/** @var Director */
$director = Director::fromCache()->find($request->director ?: $request->id);
if (is_null($director)) abort(404);
$director->generateSeoTags();
$movies = $director->movies()->orderBy('created_at', 'desc')->paginate(get_theme_option('per_page_limit'));
return view('themes::themeholy.catalog', [
'data' => $movies,
'person' => $director,
'title' => $director->getTitle(),
'section_name' => "Đạo diễn $director->name"
]);
}
public function getMovieOfTag(Request $request)
{
/** @var Tag */
$tag = Tag::fromCache()->find($request->tag ?: $request->id);
if (is_null($tag)) abort(404);
$tag->generateSeoTags();
$movies = $tag->movies()->orderBy('created_at', 'desc')->paginate(get_theme_option('per_page_limit'));
return view('themes::themeholy.catalog', [
'data' => $movies,
'tag' => $tag,
'title' => $tag->getTitle(),
'section_name' => "Tags: $tag->name"
]);
}
public function getMovieOfType(Request $request)
{
/** @var Catalog */
$catalog = Catalog::fromCache()->find($request->type ?: $request->id);
if (is_null($catalog)) abort(404);
$catalog->generateSeoTags();
$cache_key = 'catalog:' . $catalog->id . ':page:' . ($request['page'] ?: 1);
$movies = Cache::get($cache_key);
if(is_null($movies)) {
$value = explode('|', trim($catalog->value));
[$relation_config, $field, $val, $sortKey, $alg] = array_merge($value, ['', 'is_copyright', 0, 'created_at', 'desc']);
$relation_config = explode(',', $relation_config);
[$relation_table, $relation_field, $relation_val] = array_merge($relation_config, ['', '', '']);
try {
$movies = \VsMov\Core\Models\Movie::when($relation_table, function ($query) use ($relation_table, $relation_field, $relation_val, $field, $val) {
$query->whereHas($relation_table, function ($rel) use ($relation_field, $relation_val, $field, $val) {
$rel->where($relation_field, $relation_val)->where(array_combine(explode(",", $field), explode(",", $val)));
});
})->when(!$relation_table, function ($query) use ($field, $val) {
$query->where(array_combine(explode(",", $field), explode(",", $val)));
})
->orderBy($sortKey, $alg)
->paginate($catalog->paginate);
Cache::put($cache_key, $movies, setting('site_cache_ttl', 5 * 60));
} catch (\Exception $e) {}
}
return view('themes::themeholy.catalog', [
'data' => $movies,
'section_name' => "Danh sách $catalog->name"
]);
}
public function reportEpisode(Request $request, $movie, $slug)
{
$movie = Movie::fromCache()->find($movie)->load('episodes');
$episode = $movie->episodes->when(request('id'), function ($collection) {
return $collection->where('id', request('id'));
})->firstWhere('slug', $slug);
$episode->update([
'report_message' => request('message', ''),
'has_report' => true
]);
return response([], 204);
}
public function rateMovie(Request $request, $movie)
{
$movie = Movie::fromCache()->find($movie);
$movie->refresh()->increment('rating_count', 1, [
'rating_star' => $movie->rating_star + ((int) request('rating') - $movie->rating_star) / ($movie->rating_count + 1)
]);
return response([], 204);
}
}

View File

@@ -0,0 +1,141 @@
<?php
namespace VsMov\ThemeHoly;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class ThemeHolyServiceProvider extends ServiceProvider
{
public function register()
{
$this->setupDefaultThemeCustomizer();
}
public function boot()
{
$this->loadViewsFrom(__DIR__ . '/../resources/views/', 'themes');
$this->publishes([
__DIR__ . '/../resources/assets' => public_path('themes/holy')
], 'holy-assets');
}
protected function setupDefaultThemeCustomizer()
{
config(['themes' => array_merge(config('themes', []), [
'holy' => [
'name' => 'Theme Holy',
'author' => 'vsmov@gmail.com',
'package_name' => 'vsmov/theme-holy',
'publishes' => ['holy-assets'],
'preview_image' => '',
'options' => [
[
'name' => 'per_page_limit',
'label' => 'Pages limit',
'type' => 'number',
'value' => 20,
'wrapperAttributes' => [
'class' => 'form-group col-md-6',
],
'tab' => 'List'
],
[
'name' => 'movie_related_limit',
'label' => 'Movies related limit',
'type' => 'number',
'value' => 10,
'wrapperAttributes' => [
'class' => 'form-group col-md-6',
],
'tab' => 'List'
],
[
'name' => 'latest',
'label' => 'Home Page',
'type' => 'code',
'hint' => 'display_label|display_description|relation|find_by_field|value|sort_by_field|sort_algo|limit|show_more_url',
'value' => <<<EOT
Phim đề cử|Những bộ phim đang được quan tâm nhiều nhất||is_recommended|1|updated_at|desc|20|#
Phim chiếu rạp mới|Tổng hợp phim chiếu rạp vietsub||is_shown_in_theater|1|created_at|desc|10|/danh-sach/phim-chieu-rap
Phim bộ mới|Phim bộ mới cập nhật||type|series|updated_at|desc|10|/danh-sach/phim-bo
Phim lẻ mới|Phim lẻ mới cập nhật||type|single|updated_at|desc|10|/danh-sach/phim-le
Phim hoạt hình mới|Phim hoạt hình mới cập nhật|categories|slug|hoat-hinh|updated_at|desc|10|/the-loai/hoat-hinh
Top phim|Những phim được xem nhiều nhất||is_copyright|0|view_week|desc|10|#
EOT,
'attributes' => [
'rows' => 5
],
'tab' => 'List'
],
[
'name' => 'additional_css',
'label' => 'Additional CSS',
'type' => 'code',
'value' => "",
'tab' => 'Custom CSS'
],
[
'name' => 'body_attributes',
'label' => 'Body attributes',
'type' => 'text',
'value' => 'style="color: rgb(33, 37, 41); background: rgb(20,20,20); font-family: Kodchasan, sans-serif;"',
'tab' => 'Custom CSS'
],
[
'name' => 'additional_header_js',
'label' => 'Header JS',
'type' => 'code',
'value' => "",
'tab' => 'Custom JS'
],
[
'name' => 'additional_body_js',
'label' => 'Body JS',
'type' => 'code',
'value' => "",
'tab' => 'Custom JS'
],
[
'name' => 'additional_footer_js',
'label' => 'Footer JS',
'type' => 'code',
'value' => "",
'tab' => 'Custom JS'
],
[
'name' => 'footer',
'label' => 'Footer',
'type' => 'code',
'value' => <<<EOT
<footer class="page-footer dark" style="background: rgb(20,20,20);">
<div class="text-uppercase footer-copyright" style="background: rgba(20,20,20,0.07);border-style: none;">
<p><strong>Elune Media Team 2021</strong></p>
</div>
</footer>
EOT,
'tab' => 'Custom HTML'
],
[
'name' => 'ads_header',
'label' => 'Ads header',
'type' => 'code',
'value' => <<<EOT
<img src="" alt="">
EOT,
'tab' => 'Ads'
],
[
'name' => 'ads_catfish',
'label' => 'Ads catfish',
'type' => 'code',
'value' => <<<EOT
<img src="" alt="">
EOT,
'tab' => 'Ads'
]
],
]
])]);
}
}

BIN
src/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 KiB