2020-06-07 19:04:43 +03:00
|
|
|
|
<?php declare(strict_types=1);
|
|
|
|
|
namespace openvk\Web\Models\Entities;
|
2021-09-20 15:19:15 +03:00
|
|
|
|
use Chandler\Database\DatabaseConnection as DB;
|
2022-10-08 23:47:21 +03:00
|
|
|
|
use openvk\Web\Models\Repositories\{Clubs, Users};
|
2020-06-07 19:04:43 +03:00
|
|
|
|
use openvk\Web\Models\RowModel;
|
2021-11-13 23:28:17 +03:00
|
|
|
|
use openvk\Web\Models\Entities\Notifications\LikeNotification;
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
class Post extends Postable
|
|
|
|
|
{
|
|
|
|
|
protected $tableName = "posts";
|
|
|
|
|
protected $upperNodeReferenceColumnName = "wall";
|
2021-11-13 23:28:17 +03:00
|
|
|
|
|
|
|
|
|
private function setLikeRecursively(bool $liked, User $user, int $depth): void
|
|
|
|
|
{
|
|
|
|
|
$searchData = [
|
|
|
|
|
"origin" => $user->getId(),
|
|
|
|
|
"model" => static::class,
|
|
|
|
|
"target" => $this->getRecord()->id,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if((sizeof(DB::i()->getContext()->table("likes")->where($searchData)) > 0) !== $liked) {
|
2021-11-29 14:23:17 +03:00
|
|
|
|
if($this->getOwner(false)->getId() !== $user->getId() && !($this->getOwner() instanceof Club) && !$this instanceof Comment)
|
2021-11-13 23:28:17 +03:00
|
|
|
|
(new LikeNotification($this->getOwner(false), $this, $user))->emit();
|
|
|
|
|
|
|
|
|
|
parent::setLike($liked, $user);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($depth < ovkGetQuirk("wall.repost-liking-recursion-limit"))
|
|
|
|
|
foreach($this->getChildren() as $attachment)
|
|
|
|
|
if($attachment instanceof Post)
|
|
|
|
|
$attachment->setLikeRecursively($liked, $user, $depth + 1);
|
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* May return fake owner (group), if flags are [1, (*)]
|
|
|
|
|
*
|
|
|
|
|
* @param bool $honourFlags - check flags
|
|
|
|
|
*/
|
2021-11-15 22:45:48 +03:00
|
|
|
|
function getOwner(bool $honourFlags = true, bool $real = false): RowModel
|
2020-06-07 19:04:43 +03:00
|
|
|
|
{
|
2021-11-24 22:24:44 +03:00
|
|
|
|
if($honourFlags && $this->isPostedOnBehalfOfGroup()) {
|
2020-06-07 19:04:43 +03:00
|
|
|
|
if($this->getRecord()->wall < 0)
|
|
|
|
|
return (new Clubs)->get(abs($this->getRecord()->wall));
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-15 22:45:48 +03:00
|
|
|
|
return parent::getOwner($real);
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getPrettyId(): string
|
|
|
|
|
{
|
|
|
|
|
return $this->getRecord()->wall . "_" . $this->getVirtualId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getTargetWall(): int
|
|
|
|
|
{
|
|
|
|
|
return $this->getRecord()->wall;
|
|
|
|
|
}
|
2022-10-08 23:47:21 +03:00
|
|
|
|
|
|
|
|
|
function getWallOwner()
|
|
|
|
|
{
|
|
|
|
|
$w = $this->getRecord()->wall;
|
|
|
|
|
if($w < 0)
|
|
|
|
|
return (new Clubs)->get(abs($w));
|
|
|
|
|
|
|
|
|
|
return (new Users)->get($w);
|
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
function getRepostCount(): int
|
|
|
|
|
{
|
|
|
|
|
return sizeof(
|
|
|
|
|
$this->getRecord()
|
|
|
|
|
->related("attachments.attachable_id")
|
|
|
|
|
->where("attachable_type", get_class($this))
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-20 15:19:15 +03:00
|
|
|
|
function isPinned(): bool
|
|
|
|
|
{
|
|
|
|
|
return (bool) $this->getRecord()->pinned;
|
|
|
|
|
}
|
2024-10-26 23:50:40 +03:00
|
|
|
|
|
|
|
|
|
function hasSource(): bool
|
|
|
|
|
{
|
|
|
|
|
return $this->getRecord()->source != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getSource(bool $format = false)
|
|
|
|
|
{
|
|
|
|
|
$orig_source = $this->getRecord()->source;
|
|
|
|
|
if(!str_contains($orig_source, "https://") && !str_contains($orig_source, "http://"))
|
|
|
|
|
$orig_source = "https://" . $orig_source;
|
|
|
|
|
|
|
|
|
|
if(!$format)
|
|
|
|
|
return $orig_source;
|
|
|
|
|
|
|
|
|
|
return $this->formatLinks($orig_source);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setSource(string $source)
|
|
|
|
|
{
|
|
|
|
|
$result = check_copyright_link($source);
|
|
|
|
|
|
|
|
|
|
$this->stateChanges("source", $source);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getVkApiCopyright(): object
|
|
|
|
|
{
|
|
|
|
|
return (object)[
|
|
|
|
|
'id' => 0,
|
|
|
|
|
'link' => $this->getSource(false),
|
|
|
|
|
'name' => $this->getSource(false),
|
|
|
|
|
'type' => 'link',
|
|
|
|
|
];
|
|
|
|
|
}
|
2021-09-20 15:19:15 +03:00
|
|
|
|
|
2020-06-07 19:04:43 +03:00
|
|
|
|
function isAd(): bool
|
|
|
|
|
{
|
|
|
|
|
return (bool) $this->getRecord()->ad;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isPostedOnBehalfOfGroup(): bool
|
|
|
|
|
{
|
|
|
|
|
return ($this->getRecord()->flags & 0b10000000) > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isSigned(): bool
|
|
|
|
|
{
|
|
|
|
|
return ($this->getRecord()->flags & 0b01000000) > 0;
|
|
|
|
|
}
|
2022-08-05 23:00:52 +03:00
|
|
|
|
|
|
|
|
|
function isDeactivationMessage(): bool
|
|
|
|
|
{
|
2022-11-17 00:39:48 +03:00
|
|
|
|
return (($this->getRecord()->flags & 0b00100000) > 0) && ($this->getRecord()->owner > 0);
|
2022-08-05 23:00:52 +03:00
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
2023-05-14 23:49:33 +03:00
|
|
|
|
function isUpdateAvatarMessage(): bool
|
|
|
|
|
{
|
|
|
|
|
return (($this->getRecord()->flags & 0b00010000) > 0) && ($this->getRecord()->owner > 0);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-07 19:04:43 +03:00
|
|
|
|
function isExplicit(): bool
|
|
|
|
|
{
|
2021-01-07 19:19:36 +03:00
|
|
|
|
return (bool) $this->getRecord()->nsfw;
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isDeleted(): bool
|
|
|
|
|
{
|
|
|
|
|
return (bool) $this->getRecord()->deleted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getOwnerPost(): int
|
|
|
|
|
{
|
2021-11-17 19:27:11 +03:00
|
|
|
|
return $this->getOwner(false)->getId();
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
2022-12-17 02:03:02 +03:00
|
|
|
|
|
|
|
|
|
function getPlatform(bool $forAPI = false): ?string
|
|
|
|
|
{
|
|
|
|
|
$platform = $this->getRecord()->api_source_name;
|
|
|
|
|
if($forAPI) {
|
|
|
|
|
switch ($platform) {
|
2023-02-03 14:22:19 +03:00
|
|
|
|
case 'openvk_refresh_android':
|
2022-12-17 02:03:02 +03:00
|
|
|
|
case 'openvk_legacy_android':
|
|
|
|
|
return 'android';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'openvk_ios':
|
|
|
|
|
case 'openvk_legacy_ios':
|
|
|
|
|
return 'iphone';
|
|
|
|
|
break;
|
2023-12-27 03:34:18 +03:00
|
|
|
|
|
|
|
|
|
case 'windows_phone':
|
|
|
|
|
return 'wphone';
|
|
|
|
|
break;
|
2022-12-17 02:03:02 +03:00
|
|
|
|
|
|
|
|
|
case 'vika_touch': // кика хохотач ахахахаххахахахахах
|
|
|
|
|
case 'vk4me':
|
|
|
|
|
return 'mobile';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NULL:
|
|
|
|
|
return NULL;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return 'api';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return $platform;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getPlatformDetails(): array
|
|
|
|
|
{
|
|
|
|
|
$clients = simplexml_load_file(OPENVK_ROOT . "/data/clients.xml");
|
|
|
|
|
|
|
|
|
|
foreach($clients as $client) {
|
|
|
|
|
if($client['tag'] == $this->getPlatform()) {
|
|
|
|
|
return [
|
|
|
|
|
"tag" => $client['tag'],
|
|
|
|
|
"name" => $client['name'],
|
|
|
|
|
"url" => $client['url'],
|
|
|
|
|
"img" => $client['img']
|
|
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
"tag" => $this->getPlatform(),
|
|
|
|
|
"name" => NULL,
|
|
|
|
|
"url" => NULL,
|
|
|
|
|
"img" => NULL
|
|
|
|
|
];
|
|
|
|
|
}
|
api: add some fields and 2 new methods и jsonp
- Изменения коснулись методов account.getProfileInfo, account.getBalance, account.getOvkSettings, gifts.get, gifts.getCategories, groups.get, groups.getById, users.get, wall.get, wall.getById, wall.getComments, wall.getComment.
- Добавлена поддержка JSONP
2024-10-15 20:42:59 +03:00
|
|
|
|
|
|
|
|
|
function getPostSourceInfo(): array
|
|
|
|
|
{
|
|
|
|
|
$post_source = ["type" => "vk"];
|
|
|
|
|
if($this->getPlatform(true) !== NULL) {
|
|
|
|
|
$post_source = [
|
|
|
|
|
"type" => "api",
|
|
|
|
|
"platform" => $this->getPlatform(true)
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($this->isUpdateAvatarMessage())
|
|
|
|
|
$post_source['data'] = 'profile_photo';
|
|
|
|
|
|
|
|
|
|
return $post_source;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getVkApiType(): string
|
|
|
|
|
{
|
|
|
|
|
$type = 'post';
|
|
|
|
|
if($this->getSuggestionType() != 0)
|
|
|
|
|
$type = 'suggest';
|
|
|
|
|
|
|
|
|
|
return $type;
|
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
2021-09-20 15:19:15 +03:00
|
|
|
|
function pin(): void
|
|
|
|
|
{
|
|
|
|
|
DB::i()
|
|
|
|
|
->getContext()
|
|
|
|
|
->table("posts")
|
|
|
|
|
->where([
|
|
|
|
|
"wall" => $this->getTargetWall(),
|
|
|
|
|
"pinned" => true,
|
|
|
|
|
])
|
|
|
|
|
->update(["pinned" => false]);
|
|
|
|
|
|
|
|
|
|
$this->stateChanges("pinned", true);
|
|
|
|
|
$this->save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function unpin(): void
|
|
|
|
|
{
|
|
|
|
|
$this->stateChanges("pinned", false);
|
|
|
|
|
$this->save();
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-20 16:46:55 +03:00
|
|
|
|
function canBePinnedBy(User $user): bool
|
2020-06-18 14:22:32 +03:00
|
|
|
|
{
|
|
|
|
|
if($this->getTargetWall() < 0)
|
2021-09-20 16:46:55 +03:00
|
|
|
|
return (new Clubs)->get(abs($this->getTargetWall()))->canBeModifiedBy($user);
|
2020-06-18 14:22:32 +03:00
|
|
|
|
|
2021-09-20 16:46:55 +03:00
|
|
|
|
return $this->getTargetWall() === $user->getId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function canBeDeletedBy(User $user): bool
|
|
|
|
|
{
|
2023-11-16 19:44:12 +03:00
|
|
|
|
if($this->getTargetWall() < 0 && !$this->getWallOwner()->canBeModifiedBy($user) && $this->getWallOwner()->getWallType() != 1 && $this->getSuggestionType() == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
2021-09-20 16:46:55 +03:00
|
|
|
|
return $this->getOwnerPost() === $user->getId() || $this->canBePinnedBy($user);
|
2020-06-18 14:22:32 +03:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-07 19:04:43 +03:00
|
|
|
|
function setContent(string $content): void
|
|
|
|
|
{
|
|
|
|
|
if(ctype_space($content))
|
|
|
|
|
throw new \LengthException("Content length must be at least 1 character (not counting whitespaces).");
|
2020-08-20 15:58:40 +03:00
|
|
|
|
else if(iconv_strlen($content) > OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxSize"])
|
|
|
|
|
throw new \LengthException("Content is too large.");
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
$this->stateChanges("content", $content);
|
|
|
|
|
}
|
2021-11-13 23:28:17 +03:00
|
|
|
|
|
|
|
|
|
function toggleLike(User $user): bool
|
|
|
|
|
{
|
|
|
|
|
$liked = parent::toggleLike($user);
|
|
|
|
|
|
2021-11-29 14:23:17 +03:00
|
|
|
|
if($this->getOwner(false)->getId() !== $user->getId() && !($this->getOwner() instanceof Club) && !$this instanceof Comment)
|
2021-11-13 23:28:17 +03:00
|
|
|
|
(new LikeNotification($this->getOwner(false), $this, $user))->emit();
|
|
|
|
|
|
|
|
|
|
foreach($this->getChildren() as $attachment)
|
|
|
|
|
if($attachment instanceof Post)
|
|
|
|
|
$attachment->setLikeRecursively($liked, $user, 2);
|
|
|
|
|
|
|
|
|
|
return $liked;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setLike(bool $liked, User $user): void
|
|
|
|
|
{
|
|
|
|
|
$this->setLikeRecursively($liked, $user, 1);
|
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
function deletePost(): void
|
|
|
|
|
{
|
|
|
|
|
$this->setDeleted(1);
|
|
|
|
|
$this->unwire();
|
|
|
|
|
$this->save();
|
|
|
|
|
}
|
2023-12-02 20:21:16 +03:00
|
|
|
|
|
|
|
|
|
function canBeViewedBy(?User $user = NULL): bool
|
|
|
|
|
{
|
|
|
|
|
if($this->isDeleted()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->getWallOwner()->canBeViewedBy($user);
|
|
|
|
|
}
|
2023-11-16 19:44:12 +03:00
|
|
|
|
|
|
|
|
|
function getSuggestionType()
|
|
|
|
|
{
|
|
|
|
|
return $this->getRecord()->suggested;
|
|
|
|
|
}
|
2023-11-14 22:44:39 +03:00
|
|
|
|
|
|
|
|
|
function toNotifApiStruct()
|
|
|
|
|
{
|
|
|
|
|
$res = (object)[];
|
|
|
|
|
|
|
|
|
|
$res->id = $this->getVirtualId();
|
|
|
|
|
$res->to_id = $this->getOwner() instanceof Club ? $this->getOwner()->getId() * -1 : $this->getOwner()->getId();
|
|
|
|
|
$res->from_id = $res->to_id;
|
|
|
|
|
$res->date = $this->getPublicationTime()->timestamp();
|
|
|
|
|
$res->text = $this->getText(false);
|
|
|
|
|
$res->attachments = []; # todo
|
|
|
|
|
|
|
|
|
|
$res->copy_owner_id = NULL; # todo
|
|
|
|
|
$res->copy_post_id = NULL; # todo
|
2023-09-14 20:54:22 +03:00
|
|
|
|
|
2023-11-14 22:44:39 +03:00
|
|
|
|
return $res;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-14 20:54:22 +03:00
|
|
|
|
function canBeEditedBy(?User $user = NULL): bool
|
|
|
|
|
{
|
|
|
|
|
if(!$user)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if($this->isDeactivationMessage() || $this->isUpdateAvatarMessage())
|
|
|
|
|
return false;
|
|
|
|
|
|
2023-09-16 19:14:23 +03:00
|
|
|
|
if($this->getTargetWall() > 0)
|
2023-09-16 19:51:36 +03:00
|
|
|
|
return $this->getPublicationTime()->timestamp() + WEEK > time() && $user->getId() == $this->getOwner(false)->getId();
|
2023-11-16 19:44:12 +03:00
|
|
|
|
else {
|
|
|
|
|
if($this->isPostedOnBehalfOfGroup())
|
|
|
|
|
return $this->getWallOwner()->canBeModifiedBy($user);
|
|
|
|
|
else
|
|
|
|
|
return $user->getId() == $this->getOwner(false)->getId();
|
|
|
|
|
}
|
2023-09-16 19:14:23 +03:00
|
|
|
|
|
2023-09-14 20:54:22 +03:00
|
|
|
|
return $user->getId() == $this->getOwner(false)->getId();
|
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
use Traits\TRichText;
|
|
|
|
|
}
|