$this->getUser() ]); } public function activityFeedJson() { if (!UserConfig::get('social_user_feeds')) { return response()->json(['message' => 'Activity feeds not enabled']); } $user = $this->getUser(); $result = []; $activities = UserActivity::with('photo') ->with('photoComment') ->with('user') ->join('user_followers', 'user_followers.following_user_id', '=', 'user_activity.user_id') ->where([ 'user_followers.user_id' => $user->id ]) ->orderBy('activity_at', 'desc') ->limit(100) // TODO: make this configurable ->select('user_activity.*') ->get(); /** @var UserActivity $activity */ foreach ($activities as $activity) { $userName = $activity->user->name; $userProfileUrl = $activity->user->profileUrl(); $userAvatar = Theme::gravatarUrl($activity->user->email, 32); $newItem = [ 'activity_at' => date(UserConfig::get('date_format'), strtotime($activity->activity_at)), 'avatar' => $userAvatar, 'description' => trans(sprintf('gallery.user_feed_type.%s', $activity->type)) ]; $params = []; $params['user_name'] = $userName; $params['user_url'] = $userProfileUrl; if (!is_null($activity->photo)) { // Check the user has access if (!$this->getUser()->can('view', $activity->photo)) { continue; } $params['photo_name'] = $activity->photo->name; $params['photo_url'] = $activity->photo->url(); } if (!is_null($activity->album)) { // Check the user has access if (!$this->getUser()->can('view', $activity->album)) { continue; } $params['album_name'] = $activity->album->name; $params['album_url'] = $activity->album->url(); } $newItem['params'] = $params; $result[] = $newItem; } return response()->json($result); } public function confirmEmailChangeState(Request $request) { $user = $this->getUser(); if (!$user->is_email_change_in_progress) { return redirect(route('userSettings')); } // Update the e-mail address $user->email = $user->new_email_address; // Reset the e-mail change state $user->is_email_change_in_progress = false; $user->new_email_address = null; $user->save(); $request->session()->flash('success', trans('auth.change_email_success_message')); return redirect(route('userSettings')); } public function followUser($idOrAlias) { $user = $this->loadUserProfilePage($idOrAlias); $isFollowing = $this->getUser()->following()->where('following_user_id', $user->id)->count() > 0; if (!$isFollowing) { $this->getUser()->following()->attach( $user->id, [ 'created_at' => new \DateTime(), 'updated_at' => new \DateTime() ] ); } return response()->json(true); } public function resetEmailChangeState(Request $request) { $user = $this->getUser(); if (!$user->is_email_change_in_progress) { return redirect(route('userSettings')); } $data = $request->all(); if (isset($data['resend_email'])) { $this->sendEmailChangeConfirmationEmail($user, $user->new_email_address); $request->session()->flash('info', trans('auth.change_email_required_message')); } if (isset($data['cancel_change'])) { $user->is_email_change_in_progress = false; $user->new_email_address = null; $user->save(); } return redirect(route('userSettings')); } public function saveSettings(SaveUserSettingsRequest $request) { $data = $request->only(['name', 'email', 'profile_alias', 'enable_profile_page']); $user = $this->getUser(); if ( UserConfig::get('require_email_verification') && isset($data['email']) && $data['email'] != $user->email && !$user->is_email_change_in_progress ) { // Can't update the e-mail directly until the new e-mail address has been verified. // TODO - send e-mail and handle response, flag e-mail as being "change in-progress" // Send activation e-mail $this->sendEmailChangeConfirmationEmail($user, $data['email']); $request->session()->flash('info', trans('auth.change_email_required_message')); // Flag the user as a change e-mail in progress $user->new_email_address = $data['email']; $user->is_email_change_in_progress = true; $user->save(); unset($data['email']); $request->session()->flash('info', trans('auth.change_email_required_message')); } // Don't allow e-mail address to be changed if a change is in progress if ($user->is_email_change_in_progress) { unset($data['email']); } $user->fill($data); $user->enable_profile_page = (isset($data['enable_profile_page']) && strtolower($data['enable_profile_page']) == 'on'); $user->save(); $request->session()->flash('success', trans('gallery.user_settings.settings_saved')); return redirect(route('userSettings')); } public function settings(Request $request) { return Theme::render('gallery.user_settings', [ 'info' => $request->session()->get('info'), 'success' => $request->session()->get('success'), 'user' => $this->getUser() ]); } public function show(Request $request, $idOrAlias) { $user = $this->loadUserProfilePage($idOrAlias); $albums = $this->getAlbumsForUser($user); $albumIDs = $this->getAlbumIDsForUser($user); $cameras = $this->getCamerasUsedInAlbums($albumIDs); $activity = $this->getActivityDatesInAlbums($albumIDs); $daysInMonth = $this->getDaysInMonths(); // Only logged-in users can follow other users (and if it's not their own page!) $canFollow = !$this->getUser()->isAnonymous() && $this->getUser()->id != $user->id; $isFollowing = false; if ($canFollow) { // Is the current user following this user? $isFollowing = $this->getUser()->following()->where('following_user_id', $user->id)->count() > 0; } return Theme::render('gallery.user_profile', [ 'active_tab' => $request->get('tab'), 'activity_taken' => $this->constructActivityGrid($activity['taken']), 'activity_uploaded' => $this->constructActivityGrid($activity['uploaded']), 'albums' => $albums, 'cameras' => $cameras, 'can_follow' => $canFollow, 'is_following' => $isFollowing, 'month_days' => $daysInMonth, 'user' => $user ]); } public function showFeedJson(Request $request, $idOrAlias) { $user = $this->loadUserProfilePage($idOrAlias); $result = []; $activities = UserActivity::with('photo') ->with('photoComment') ->with('album') ->where([ 'user_id' => $user->id ]) ->orderBy('activity_at', 'desc') ->limit(100) // TODO: make this configurable ->get(); $userName = $user->name; $userProfileUrl = $user->profileUrl(); $userAvatar = Theme::gravatarUrl($user->email, 32); /** @var UserActivity $activity */ foreach ($activities as $activity) { $newItem = [ 'activity_at' => date(UserConfig::get('date_format'), strtotime($activity->activity_at)), 'avatar' => $userAvatar, 'description' => trans(sprintf('gallery.user_feed_type.%s', $activity->type)) ]; $params = []; $params['user_name'] = $userName; $params['user_url'] = $userProfileUrl; if (!is_null($activity->photo)) { // Check the user has access if (!$this->getUser()->can('view', $activity->photo)) { continue; } $params['photo_name'] = $activity->photo->name; $params['photo_url'] = $activity->photo->url(); } if (!is_null($activity->album)) { // Check the user has access if (!$this->getUser()->can('view', $activity->album)) { continue; } $params['album_name'] = $activity->album->name; $params['album_url'] = $activity->album->url(); } $newItem['params'] = $params; $result[] = $newItem; } return response()->json($result); } public function unFollowUser($idOrAlias) { $user = $this->loadUserProfilePage($idOrAlias); $isFollowing = $this->getUser()->following()->where('following_user_id', $user->id)->count() > 0; if ($isFollowing) { $this->getUser()->following()->detach($user->id); } return response()->json(true); } private function constructActivityGrid(Collection $collection) { $results = []; $lastYearFrom = new \DateTime(); $lastYearFrom->sub(new \DateInterval('P1Y')); $lastYearFrom->add(new \DateInterval('P1D')); $today = new \DateTime(); $current = clone $lastYearFrom; while ($current < $today) { $year = intval($current->format('Y')); $month = intval($current->format('m')); $date = intval($current->format('d')); if (!isset($results[$year])) { $results[$year] = []; } if (!isset($results[$year][$month])) { $results[$year][$month] = []; } if (!isset($results[$year][$month][$date])) { $results[$year][$month][$date] = 0; } $current->add(new \DateInterval('P1D')); } // Now update the totals from the collection foreach ($collection as $photoInfo) { $date = \DateTime::createFromFormat('Y-m-d', $photoInfo->the_date); $year = intval($date->format('Y')); $month = intval($date->format('m')); $date = intval($date->format('d')); $results[$year][$month][$date] = $photoInfo->photos_count; } // Replace the month names foreach ($results as $year => &$months) { foreach ($months as $month => $dates) { $monthDate = \DateTime::createFromFormat('m', $month); $months[$monthDate->format('M')] = $dates; unset($months[$month]); } } return $results; } private function getActivityDatesInAlbums(array $albumIDs) { $createdAt = DB::table('photos') ->whereIn('album_id', $albumIDs) ->whereRaw(DB::raw('DATE(created_at) > DATE(DATE_SUB(NOW(), INTERVAL 1 year))')) ->select([ DB::raw('DATE(created_at) AS the_date'), DB::raw('COUNT(photos.id) AS photos_count') ]) ->groupBy(DB::raw('DATE(created_at)')) ->orderBy(DB::raw('DATE(created_at)')) ->get(); $takenAt = DB::table('photos') ->whereIn('album_id', $albumIDs) ->whereRaw(DB::raw('DATE(taken_at) > DATE(DATE_SUB(NOW(), INTERVAL 1 year))')) ->select([ DB::raw('DATE(taken_at) AS the_date'), DB::raw('COUNT(photos.id) AS photos_count') ]) ->groupBy(DB::raw('DATE(taken_at)')) ->orderBy(DB::raw('DATE(taken_at)')) ->get(); return ['uploaded' => $createdAt, 'taken' => $takenAt]; } private function getAlbumsForUser(User $user) { return DbHelper::getAlbumsForCurrentUser_NonPaged() ->where('user_id', $user->id) ->paginate(UserConfig::get('items_per_page')); } private function getAlbumIDsForUser(User $user) { $results = []; $albums = DbHelper::getAlbumsForCurrentUser_NonPaged() ->where('user_id', $user->id) ->select('albums.id') ->get(); foreach ($albums as $album) { $results[] = intval($album->id); } return $results; } private function getCamerasUsedInAlbums(array $albumIDs) { return DB::table('photos') ->whereIn('album_id', $albumIDs) ->where([ ['camera_make', '!=', ''], ['camera_model', '!=', ''] ]) ->groupBy('camera_make', 'camera_model', 'camera_software') ->select('camera_make', 'camera_model', 'camera_software', DB::raw('count(*) as photo_count')) ->orderBy('photo_count', 'desc') ->orderBy('camera_make') ->orderBy('camera_model') ->orderBy('camera_software') ->get(); } private function getDaysInMonths() { $results = []; $lastYearFrom = new \DateTime(); $lastYearFrom->sub(new \DateInterval('P1Y')); $lastYearFrom->sub(new \DateInterval(sprintf('P%dD', $lastYearFrom->format('d') - 1))); $today = new \DateTime(); $current = clone $lastYearFrom; while ($current < $today) { $year = intval($current->format('Y')); $month = intval($current->format('m')); $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year); $results[$year][$current->format('M')] = $daysInMonth; $current->add(new \DateInterval('P1M')); } return $results; } /** * @param $idOrAlias * @return User */ private function loadUserProfilePage($idOrAlias) { // If a user has a profile alias set, their profile page cannot be accessed by the ID $user = User::where(DB::raw('COALESCE(profile_alias, id)'), strtolower($idOrAlias))->first(); if (is_null($user)) { App::abort(404); return null; } $this->authorizeForUser($this->getUser(), 'view', $user); return $user; } private function sendEmailChangeConfirmationEmail(User $user, $newEmailAddress) { $oldEmailAddress = $user->email; $user->email = $newEmailAddress; Mail::to($user)->send(new UserChangeEmailRequired($user)); $user->email = $oldEmailAddress; } }