getLocale(); $homepageData = Cache::remember($cacheKey, 1800, function () { $featured = App::active() ->featured() ->with('category') ->limit(8) ->get(); $latest = App::active() ->latest() ->with('category') ->limit(12) ->get(); $mostDownloaded = App::active() ->mostDownloaded() ->with('category') ->limit(12) ->get(); $topCategories = Category::active() ->ordered() ->withCount(['apps as apps_count' => function ($query) { return $query->active(); }]) ->limit(9) ->get(); $importSources = collect(config('import_sources.sources', [])) ->pluck('name') ->values() ->all(); return [ 'featuredApps' => $featured, 'latestApps' => $latest, 'mostDownloadedApps' => $mostDownloaded, 'topCategories' => $topCategories, 'importSources' => $importSources, // values computed server-side for use in the view 'totalDownloads' => App::active()->sum('downloads_count'), 'featuredCount' => $featured->count(), 'categoriesCount' => $topCategories->count(), 'hasImportSources' => !empty($importSources), ]; }); return view('homepage', array_merge($homepageData, [ 'title' => __('Download latest Android apps and games for free'), ])); } /** * Display the latest apps page. */ public function latest(Request $request): View { // تم إلغاء التخزين المؤقت الثابت لهذه الدالة لضمان عمل التنقل بين الصفحات (Pagination) بشكل صحيح. // يمكن تخزين النتائج مؤقتاً إذا تم تضمين رقم الصفحة في المفتاح، لكن الأداء أفضل بدون تخزين مؤقت هنا. $latestApps = App::active() ->latest() ->with('category') ->paginate(24); // **الإصلاح:** تمرير المتغير بالاسم المتوقع في ملف latest.blade.php وهو $latestApps return view('apps.latest', [ 'latestApps' => $latestApps, // لاحظ تغيير المفتاح إلى latestApps 'title' => __('Latest Apps'), ]); } /** * Display the games apps page (Filtering by 'games' category slug). */ public function games(): View { $gamesCategory = Cache::remember('games_category_finder', 3600, function () { return Category::where('slug', 'games')->first(); }); if ($gamesCategory) { $appsQuery = $gamesCategory->apps() ->active() ->latest() ->with('category'); $title = $gamesCategory->getTranslatedName(); } else { $appsQuery = App::active() ->latest() ->with('category'); $title = __('Games'); } $games = $appsQuery->paginate(24); return view('apps.games', [ 'games' => $games, 'title' => $title, ]); } /** * Display all categories. */ public function categories(): View { $categories = Category::active() ->ordered() ->withCount(['apps as apps_count' => function ($query) { return $query->active(); }]) ->get(); return view('apps.categories', [ 'categories' => $categories, 'title' => __('All Categories'), ]); } /** * Display the most downloaded apps. */ public function popular(): View { $apps = App::active() ->mostDownloaded() ->with('category') ->paginate(24); return view('apps.popular', [ 'apps' => $apps, 'title' => __('Most Downloaded'), ]); } /** * Display apps by category. */ public function category(Category $category): View { $category->loadCount(['apps as apps_count' => function ($query) { return $query->active(); }]); $apps = $category->apps() ->active() ->latest() ->with('category') ->paginate(24); $relatedCategories = Category::active() ->where('id', '!=', $category->id) ->ordered() ->limit(6) ->get(); return view('apps.category', [ 'category' => $category, 'apps' => $apps, 'relatedCategories' => $relatedCategories, 'title' => $category->getTranslatedName(), ]); } /** * Display a single app details. */ public function show(App $app): View { // **التحديث هنا: تحميل العلاقة 'category' بشكل سريع** // هذا يقلل من استعلامات قاعدة البيانات ويضمن توفر بيانات الفئة. $app->load('category'); // Increment view count $app->increment('views_count'); // Get related apps from the same category $relatedApps = Cache::remember( "related_apps_{$app->id}_{$app->category_id}", 1800, function () use ($app) { return App::active() ->where('category_id', $app->category_id) ->where('id', '!=', $app->id) ->inRandomOrder() ->limit(8) ->get(); } ); // Get app versions $versions = $app->versions() ->active() ->orderBy('version_code', 'desc') ->paginate(10); // Prepare SEO schema data $schemaData = $this->generateAppSchema($app); return view('apps.show', [ 'app' => $app, 'relatedApps' => $relatedApps, 'versions' => $versions, 'schemaData' => $schemaData, 'title' => $app->getTranslatedName(), ]); } /** * Search apps. */ public function search(Request $request) { $query = $request->get('q'); if (empty($query)) { return redirect()->route('home'); } $apps = App::active() ->where(function ($q) use ($query) { $q->where('name', 'LIKE', "%{$query}%") ->orWhere('description', 'LIKE', "%{$query}%") ->orWhere('package_name', 'LIKE', "%{$query}%") ->orWhere('developer', 'LIKE', "%{$query}%"); }) ->with('category') ->paginate(24) ->appends(['q' => $query]); return view('apps.search', [ 'apps' => $apps, 'query' => $query, 'title' => __('Search Results for ":query"', ['query' => $query]), ]); } /** * API endpoint for latest apps. */ public function apiLatest(): JsonResponse { $apps = App::active() ->latest() ->with('category') ->limit(10) ->get() ->map(function ($app) { return [ 'id' => $app->id, 'package_name' => $app->package_name, 'name' => $app->getTranslatedName(), 'description' => $app->getTranslatedDescription(), 'icon_url' => $app->icon_url, 'latest_version' => $app->latest_version, 'rating' => $app->rating, 'downloads_count' => $app->downloads_count, 'category' => [ 'id' => $app->category->id, 'name' => $app->category->getTranslatedName(), 'slug' => $app->category->slug, ], 'updated_at' => $app->updated_at, ]; }); return response()->json([ 'success' => true, 'data' => $apps, ]); } /** * API endpoint for apps by category. */ public function apiByCategory(Category $category, Request $request): JsonResponse { $appsQuery = $category->apps() ->active() ->with('category'); $apps = $appsQuery ->paginate($request->get('per_page', 20)) ->through(function ($app) { return [ 'id' => $app->id, 'package_name' => $app->package_name, 'name' => $app->getTranslatedName(), 'description' => $app->getTranslatedDescription(), 'icon_url' => $app->icon_url, 'latest_version' => $app->latest_version, 'rating' => $app->rating, 'downloads_count' => $app->downloads_count, 'updated_at' => $app->updated_at, ]; }); return response()->json([ 'success' => true, 'data' => $apps->items(), 'pagination' => [ 'current_page' => $apps->currentPage(), 'last_page' => $apps->lastPage(), 'per_page' => $apps->perPage(), 'total' => $apps->total(), 'next_page_url' => $apps->nextPageUrl(), 'prev_page_url' => $apps->previousPageUrl(), ], ]); } /** * API endpoint for single app details. */ public function apiShow(string $package_name): JsonResponse { $app = App::where('package_name', $package_name) ->with(['category', 'versions' => function ($query) { $query->active()->orderBy('version_code', 'desc'); }]) ->first(); if (!$app) { return response()->json([ 'success' => false, 'message' => 'App not found', ], 404); } $appData = [ 'id' => $app->id, 'package_name' => $app->package_name, 'slug' => $app->slug, 'name' => $app->getTranslatedName(), 'description' => $app->getTranslatedDescription(), 'icon_url' => $app->icon_url, 'latest_version' => $app->latest_version, 'rating' => $app->rating, 'downloads_count' => $app->downloads_count, 'os_requirement' => $app->os_requirement, 'developer' => $app->developer, 'size' => $app->size, 'mod_info' => $app->mod_info, 'screenshots' => $app->screenshots, 'category' => [ 'id' => $app->category->id, 'name' => $app->category->getTranslatedName(), 'slug' => $app->category->slug, ], 'versions' => $app->versions->map(function ($version) { return [ 'id' => $version->id, 'version_name' => $version->version_name, 'version_code' => $version->version_code, 'release_date' => $version->release_date, 'changelog' => $version->changelog, 'size' => $version->size, 'is_beta' => $version->is_beta, 'download_url' => $version->download_url, ]; }), 'updated_at' => $app->updated_at, ]; return response()->json([ 'success' => true, 'data' => $appData, ]); } /** * Generate JSON-LD schema for SEO. */ private function generateAppSchema(App $app): array { // هنا يتم التعامل مع التواريخ التي قد تكون NULL بأمان $datePublished = $app->created_at?->format('Y-m-d') ?? '1970-01-01'; $dateModified = $app->updated_at?->format('Y-m-d') ?? now()->format('Y-m-d'); $applicationCategory = match ($app->category?->slug) { 'games' => 'GameApplication', null => 'Application', default => 'MobileApplication', }; return [ '@context' => 'https://schema.org', '@type' => 'SoftwareApplication', 'name' => $app->getTranslatedName(), 'description' => $app->getTranslatedDescription(), 'applicationCategory' => $applicationCategory, 'operatingSystem' => $app->os_requirement ?: 'Android', 'offers' => [ '@type' => 'Offer', 'price' => '0', 'priceCurrency' => 'USD', ], 'aggregateRating' => [ '@type' => 'AggregateRating', 'ratingValue' => $app->rating, 'ratingCount' => $app->downloads_count, ], 'author' => [ '@type' => 'Organization', 'name' => $app->developer ?: 'Unknown', ], 'image' => $app->icon_url, 'softwareVersion' => $app->latest_version, // استخدام المتغيرات الآمنة الجديدة بدلاً من الوصول المباشر 'datePublished' => $datePublished, 'dateModified' => $dateModified, 'downloadUrl' => route('download.show', $app->slug), ]; } }