Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions VKAPI/Handlers/Photos.php
Original file line number Diff line number Diff line change
Expand Up @@ -334,11 +334,11 @@ public function getAlbums(int $owner_id = null, string $album_ids = "", int $off
$albums_list = null;
if ($owner_id > 0) {
# TODO rewrite to offset
$albums_list = array_slice(iterator_to_array((new Albums())->getUserAlbums($owner, 1, $count + $offset)), $offset);
$res["count"] = (new Albums())->getUserAlbumsCount($owner);
$albums_list = array_slice(iterator_to_array((new Albums())->getUserAlbums($owner, $this->getUser(), 1, $count + $offset)), $offset);
$res["count"] = (new Albums())->getUserAlbumsCount($owner, $this->getUser());
} else {
$albums_list = array_slice(iterator_to_array((new Albums())->getClubAlbums($owner, 1, $count + $offset)), $offset);
$res["count"] = (new Albums())->getClubAlbumsCount($owner);
$res["count"] = (new Albums())->getClubAlbumsCount($owner, $this->getUser());
}
} else {
$album_ids = explode(',', $album_ids);
Expand Down Expand Up @@ -377,7 +377,7 @@ public function getAlbumsCount(int $user_id = null, int $group_id = null)
$this->fail(15, "Access denied");
}

return (new Albums())->getUserAlbumsCount($__user);
return (new Albums())->getUserAlbumsCount($__user, $this->getUser());
}
if (!is_null($group_id)) {
$__club = (new Clubs())->get($group_id);
Expand Down
2 changes: 1 addition & 1 deletion VKAPI/Handlers/Users.php
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ public function get(string $user_ids = "0", string $fields = "", int $offset = 0
"online_friends" => $usr->getFriendsOnlineCount(),
"mutual_friends" => 0, // FIXME: not implemented
"user_photos" => 0, // FIXME: not implemented
"albums" => (new Albums())->getUserAlbumsCount($usr),
"albums" => (new Albums())->getUserAlbumsCount($usr, $authuser),
"followers" => $usr->getFollowersCount(),
"gifts" => $usr->getGiftCount(),
];
Expand Down
15 changes: 12 additions & 3 deletions Web/Models/Entities/Album.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ class Album extends MediaCollection
{
public const SPECIAL_AVATARS = 16;
public const SPECIAL_WALL = 32;
public const SPECIAL_SAVED = 64;

protected $tableName = "albums";
protected $relTableName = "album_relations";
protected $entityTableName = "photos";
protected $entityClassName = 'openvk\Web\Models\Entities\Photo';

protected $specialNames = [
16 => "_avatar_album",
32 => "_wall_album",
64 => "_saved_photos_album",
self::SPECIAL_AVATARS => "_avatar_album",
self::SPECIAL_WALL => "_wall_album",
self::SPECIAL_SAVED => "_saved_photos_album",
];

public function getCoverURL(): ?string
Expand Down Expand Up @@ -75,13 +76,21 @@ public function hasPhoto(Photo $photo): bool
return $this->has($photo);
}

public function getSpecialType(): ?int
{
return $this->getRecord()->special_type;
}

public function canBeViewedBy(?User $user = null): bool
{
if ($this->isDeleted()) {
return false;
}

$owner = $this->getOwner();
if ($this->getSpecialType() === self::SPECIAL_SAVED && !$owner->getPrivacyPermission('photos.read_saved', $user)) {
return false;
}

if (get_class($owner) == "openvk\\Web\\Models\\Entities\\User") {
return $owner->canBeViewedBy($user) && $owner->getPrivacyPermission('photos.read', $user);
Expand Down
16 changes: 16 additions & 0 deletions Web/Models/Entities/Photo.php
Original file line number Diff line number Diff line change
Expand Up @@ -463,4 +463,20 @@ public function toNotifApiStruct()

return $res;
}

public function isAvailableForSaving(): bool
{
return $this->canBeViewedBy(); // разрешаем сохранять только общедоступные фото (?)
}

public function copyFrom(Photo $photo): void
{
$record = $photo->getRecord();

$this->stateChanges("hash", $record->hash);
$this->setSizes($record->sizes);
$this->setWidth($record->width);
$this->setHeight($record->height);
}

}
46 changes: 18 additions & 28 deletions Web/Models/Entities/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ class User extends RowModel
public const NSFW_TOLERANT = 1;
public const NSFW_FULL_TOLERANT = 2;

public const SETTINGS_PRIVACY = [
"page.read",
"page.info.read",
"groups.read",
"photos.read",
"videos.read",
"notes.read",
"friends.read",
"friends.add",
"wall.write",
"messages.write",
"audios.read",
"likes.read",
"photos.read_saved",
];

/* aggressive caching */
private $_avatarAlbum = null;
private $_avatarPhoto = false; // false - not resolved, null - no avatar
Expand Down Expand Up @@ -598,20 +614,7 @@ public function getPrivacySetting(string $id): int
{
return (int) bmask($this->getRecord()->privacy, [
"length" => 2,
"mappings" => [
"page.read",
"page.info.read",
"groups.read",
"photos.read",
"videos.read",
"notes.read",
"friends.read",
"friends.add",
"wall.write",
"messages.write",
"audios.read",
"likes.read",
],
"mappings" => User::SETTINGS_PRIVACY,
])->get($id);
}

Expand Down Expand Up @@ -1306,20 +1309,7 @@ public function setPrivacySetting(string $id, int $status): void
{
$this->stateChanges("privacy", bmask($this->changes["privacy"] ?? $this->getRecord()->privacy, [
"length" => 2,
"mappings" => [
"page.read",
"page.info.read",
"groups.read",
"photos.read",
"videos.read",
"notes.read",
"friends.read",
"friends.add",
"wall.write",
"messages.write",
"audios.read",
"likes.read",
],
"mappings" => self::SETTINGS_PRIVACY,
])->set($id, $status)->toInteger());
}

Expand Down
82 changes: 45 additions & 37 deletions Web/Models/Repositories/Albums.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,29 @@ public function get(int $id): ?Album
return self::$cache[$id] ??= $this->toAlbum($this->albums->get($id));
}

public function getUserAlbums(User $user, int $page = 1, ?int $perPage = null): \Traversable
private function getUserQuery(User $user, ?User $for): \Nette\Database\Table\Selection
{
$perPage ??= OPENVK_DEFAULT_PER_PAGE;
$albums = $this->albums->where("owner", $user->getId())->where("deleted", false);

if (!$user->getPrivacyPermission('photos.read_saved', $for)) {
$albums->where("special_type NOT", [Album::SPECIAL_SAVED]);
}
return $albums;
}

public function getUserAlbums(User $user, ?User $for, int $page = 1, ?int $perPage = null): \Traversable
{
$perPage ??= OPENVK_DEFAULT_PER_PAGE;
$albums = $this->getUserQuery($user, $for);

foreach ($albums->page($page, $perPage) as $album) {
yield new Album($album);
}
}

public function getUserAlbumsCount(User $user): int
public function getUserAlbumsCount(User $user, ?User $for): int
{
$albums = $this->albums->where("owner", $user->getId())->where("deleted", false);
$albums = $this->getUserQuery($user, $for);
return sizeof($albums);
}

Expand All @@ -76,23 +87,8 @@ public function getClubAlbumsCount(Club $club): int

public function getAvatarAlbumById(int $id, int $regTime): Album
{
$data = $this->getSpecialConditions($id, 16);
$album = $this->albums->where([
"owner" => $id,
"special_type" => 16,
])->fetch();
if (!$album) {
$album = new Album();
$album->setName("[!!! internal album]");
$album->setOwner($id);
$album->setSpecial_Type(16);
$album->setCreated($regTime);
$album->save();

return $album;
}

return new Album($album);
$data = $this->getSpecialConditions($id, Album::SPECIAL_AVATARS);
return $this->getOrCreateSpecialAlbum($id, Album::SPECIAL_AVATARS, $regTime);
}

public function getUserAvatarAlbum(User $user): Album
Expand All @@ -107,23 +103,9 @@ public function getClubAvatarAlbum(Club $club): Album

public function getUserWallAlbum(User $user): Album
{
$data = $this->getSpecialConditions($user->getId(), 32);
$album = $this->albums->where([
"owner" => $user->getId(),
"special_type" => 32,
])->fetch();
if (!$album) {
$album = new Album();
$album->setName("[!!! internal album]");
$album->setOwner($user->getId());
$album->setSpecial_Type(32);
$album->setCreated($user->getRegistrationTime()->timestamp());
$album->save();
$data = $this->getSpecialConditions($user->getId(), Album::SPECIAL_WALL);

return $album;
}

return new Album($album);
return $this->getOrCreateSpecialAlbum($user->getId(), Album::SPECIAL_WALL, $user->getRegistrationTime()->timestamp());
}

public function getAlbumByPhotoId(Photo $photo): ?Album
Expand All @@ -142,4 +124,30 @@ public function getAlbumByOwnerAndId(int $owner, int $id)

return $album ? new Album($album) : null;
}

public function getUserSavedAlbum(User $user): Album
{
return $this->getOrCreateSpecialAlbum($user->getId(), Album::SPECIAL_SAVED, $user->getRegistrationTime()->timestamp());
}

private function getOrCreateSpecialAlbum(int $ownerId, int $specialType, int $regTime): Album
{
$album = $this->albums->where([
"owner" => $ownerId,
"special_type" => $specialType,
])->fetch();

if (!$album) {
$album = new Album();
$album->setName("[!!! internal album]");
$album->setOwner($ownerId);
$album->setSpecial_Type($specialType);
$album->setCreated($regTime);
$album->save();

return $album;
}

return new Album($album);
}
}
35 changes: 33 additions & 2 deletions Web/Presenters/PhotosPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public function renderAlbumList(int $owner): void
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
}

$this->template->albums = $this->albums->getUserAlbums($user, (int) ($this->queryParam("p") ?? 1));
$this->template->count = $this->albums->getUserAlbumsCount($user);
$this->template->albums = $this->albums->getUserAlbums($user, $this->user->identity, (int) ($this->queryParam("p") ?? 1));
$this->template->count = $this->albums->getUserAlbumsCount($user, $this->user->identity);
$this->template->owner = $user;
$this->template->canEdit = false;
if (!is_null($this->user->identity)) {
Expand Down Expand Up @@ -203,6 +203,7 @@ public function renderPhoto(int $ownerId, int $photoId): void
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
}

$album = null;
if (!is_null($this->queryParam("from"))) {
if (preg_match("%^album([0-9]++)$%", $this->queryParam("from"), $matches) === 1) {
$album = $this->albums->get((int) $matches[1]);
Expand All @@ -219,6 +220,8 @@ public function renderPhoto(int $ownerId, int $photoId): void
$this->template->cPage = (int) ($this->queryParam("p") ?? 1);
$this->template->comments = iterator_to_array($photo->getComments($this->template->cPage));
$this->template->owner = $photo->getOwner();

$this->template->canSave = $this->user->identity && (!$album || $album->getSpecialType() != Album::SPECIAL_SAVED) && $photo->isAvailableForSaving();
}

public function renderAbsolutePhoto($id): void
Expand Down Expand Up @@ -450,4 +453,32 @@ public function renderLike(int $wall, int $post_id): void

$this->redirect("$_SERVER[HTTP_REFERER]");
}

public function renderSavePhoto(int $owner, int $photoId): void
{
$this->assertUserLoggedIn();
$this->willExecuteWriteAction();
$this->assertNoCSRF();

$photo = $this->photos->getByOwnerAndVID($owner, $photoId);
if (!$photo) {
$this->notFound();
}
if (!$photo->canBeViewedBy($this->user->identity)) {
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
}

$album = $this->albums->getUserSavedAlbum($this->user->identity);

$saved_photo = new Photo();
$saved_photo->copyFrom($photo);
$saved_photo->setOwner($this->user->id);
$saved_photo->setCreated(time());
$saved_photo->save();

$album->addPhoto($saved_photo);

header("HTTP/1.1 204 No Content");
exit("");
}
}
19 changes: 3 additions & 16 deletions Web/Presenters/UserPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Nette\InvalidStateException;
use openvk\Web\Util\Sms;
use openvk\Web\Themes\Themepacks;
use openvk\Web\Models\Entities\{Photo, Post, EmailChangeVerification};
use openvk\Web\Models\Entities\{Photo, Post, EmailChangeVerification, User};
use openvk\Web\Models\Entities\Notifications\{CoinsTransferNotification, RatingUpNotification};
use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Videos, Notes, Vouchers, EmailChangeVerifications, Audios, Faves};
use openvk\Web\Models\Exceptions\InvalidUserNameException;
Expand Down Expand Up @@ -59,7 +59,7 @@ public function renderView(int $id): void
}
} else {
$this->template->avatarAlbum = (new Albums())->getUserAvatarAlbum($user);
$this->template->albums = array_values(array_filter(iterator_to_array((new Albums())->getUserAlbums($user)), function ($album) {
$this->template->albums = array_values(array_filter(iterator_to_array((new Albums())->getUserAlbums($user, null, 1)), function ($album) {
return !$album->isCreatedBySystem();
}));
$this->template->albumsCount = count($this->template->albums);
Expand Down Expand Up @@ -618,20 +618,7 @@ public function renderSettings(): void
$this->flashFail("err", tr("error"), tr("error_shorturl_incorrect"));
}
} elseif ($_GET['act'] === "privacy") {
$settings = [
"page.read",
"page.info.read",
"groups.read",
"photos.read",
"videos.read",
"notes.read",
"friends.read",
"friends.add",
"wall.write",
"messages.write",
"audios.read",
"likes.read",
];
$settings = User::SETTINGS_PRIVACY;
foreach ($settings as $setting) {
$input = $this->postParam(str_replace(".", "_", $setting));
$user->setPrivacySetting($setting, min(3, (int) abs((int) $input ?? $user->getPrivacySetting($setting))));
Expand Down
4 changes: 4 additions & 0 deletions Web/Presenters/templates/Photos/Photo.latte
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@
<a href="/photo{$photo->getPrettyId()}/edit" class="profile_link" style="display:block;width:96%;">{_edit}</a>
<a id="_photoDelete" href="/photo{$photo->getPrettyId()}/delete" class="profile_link" style="display:block;width:96%;">{_delete}</a>
</div>
<form class="save_photo" n:if="$canSave" action="/photo{$photo->getPrettyId()}/save" method="post">
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" id="profile_link" value="{_save_photo}" style="display:block;width:96%;"/>
</form>
<a href="{$photo->getURL()}" class="profile_link" target="_blank" style="display:block;width:96%;">{_"open_original"}</a>
<a n:if="isset($thisUser) && $thisUser->getId() != $photo->getOwner()->getId()" class="profile_link" style="display:block;width:96%;" href="javascript:reportPhoto({$photo->getId()})">{_report}</a>
<a n:if="isset($thisUser)" onclick="javascript:repost({$photo->getPrettyId()}, 'photo')" class="profile_link" style="display:block;width:96%;">
Expand Down
Loading
Loading