This commit is contained in:
mrilyew 2024-12-28 18:33:09 +03:00
parent ab5bb6b459
commit a91563fdf6
16 changed files with 347 additions and 24 deletions

View file

@ -117,6 +117,11 @@ final class Wall extends VKAPIRequestHandler
"type" => "audio",
"audio" => $attachment->toVkApiStruct($this->getUser()),
];
} else if ($attachment instanceof \openvk\Web\Models\Entities\Document) {
$attachments[] = [
"type" => "doc",
"doc" => $attachment->toVkApiStruct($this->getUser()),
];
} else if ($attachment instanceof \openvk\Web\Models\Entities\Post) {
$repostAttachments = [];
@ -333,6 +338,11 @@ final class Wall extends VKAPIRequestHandler
"type" => "audio",
"audio" => $attachment->toVkApiStruct($this->getUser())
];
} else if ($attachment instanceof \openvk\Web\Models\Entities\Document) {
$attachments[] = [
"type" => "doc",
"doc" => $attachment->toVkApiStruct($this->getUser()),
];
} else if ($attachment instanceof \openvk\Web\Models\Entities\Post) {
$repostAttachments = [];
@ -577,7 +587,7 @@ final class Wall extends VKAPIRequestHandler
if($signed == 1)
$flags |= 0b01000000;
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'poll', 'audio']);
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'poll', 'audio', 'doc']);
$final_attachments = [];
$should_be_suggested = $owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2;
foreach($parsed_attachments as $attachment) {
@ -670,7 +680,7 @@ final class Wall extends VKAPIRequestHandler
if(preg_match('/(wall|video|photo)((?:-?)[0-9]+)_([0-9]+)/', $object, $postArray) == 0)
$this->fail(100, "One of the parameters specified was missing or invalid: object is incorrect");
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio']);
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio', 'doc']);
$final_attachments = [];
foreach($parsed_attachments as $attachment) {
if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) &&
@ -780,6 +790,11 @@ final class Wall extends VKAPIRequestHandler
"type" => "audio",
"audio" => $attachment->toVkApiStruct($this->getUser()),
];
} else if ($attachment instanceof \openvk\Web\Models\Entities\Document) {
$attachments[] = [
"type" => "doc",
"doc" => $attachment->toVkApiStruct($this->getUser()),
];
}
}
@ -867,6 +882,11 @@ final class Wall extends VKAPIRequestHandler
"type" => "audio",
"audio" => $attachment->toVkApiStruct($this->getUser()),
];
} else if ($attachment instanceof \openvk\Web\Models\Entities\Document) {
$attachments[] = [
"type" => "doc",
"doc" => $attachment->toVkApiStruct($this->getUser()),
];
}
}
@ -928,7 +948,7 @@ final class Wall extends VKAPIRequestHandler
if($post->getTargetWall() < 0)
$club = (new ClubsRepo)->get(abs($post->getTargetWall()));
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio']);
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio', 'doc']);
$final_attachments = [];
foreach($parsed_attachments as $attachment) {
if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) &&
@ -1014,7 +1034,7 @@ final class Wall extends VKAPIRequestHandler
$this->requireUser();
$this->willExecuteWriteAction();
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio', 'poll']);
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio', 'poll', 'doc']);
$final_attachments = [];
foreach($parsed_attachments as $attachment) {
if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) &&
@ -1083,7 +1103,7 @@ final class Wall extends VKAPIRequestHandler
$this->willExecuteWriteAction();
$comment = (new CommentsRepo)->get($comment_id);
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio']);
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio', 'doc']);
$final_attachments = [];
foreach($parsed_attachments as $attachment) {
if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) &&

View file

@ -111,7 +111,7 @@ class Document extends Media
throw new \ValueError("Invalid filesize");
$hash = hash_file("whirlpool", $file["tmp_name"]);
$this->stateChanges("original_name", $original_name);
$this->stateChanges("original_name", ovk_proc_strtr($original_name, 255));
$this->tmp_format = $file_format;
$this->stateChanges("format", $file_format);
$this->stateChanges("filesize", $file_size);

View file

@ -512,6 +512,7 @@ class User extends RowModel
"links",
"poster",
"apps",
"docs",
],
])->get($id);
}
@ -1117,6 +1118,7 @@ class User extends RowModel
"links",
"poster",
"apps",
"docs",
],
])->set($id, (int) $status)->toInteger();

View file

@ -21,7 +21,7 @@ class Documents
return is_null($ar) ? NULL : new Document($ar);
}
function get(int $id): ?Comment
function get(int $id): ?Document
{
return $this->toDocument($this->documents->get($id));
}
@ -85,6 +85,14 @@ class Documents
];
}
if(sizeof($response) < 1) {
return [[
"count" => 0,
"type" => 0,
"name" => tr("document_type_0"),
]];
}
return $response;
}

View file

@ -1,6 +1,6 @@
<?php declare(strict_types=1);
namespace openvk\Web\Presenters;
use openvk\Web\Models\Repositories\Documents;
use openvk\Web\Models\Repositories\{Documents, Clubs};
use openvk\Web\Models\Entities\Document;
final class DocumentsPresenter extends OpenVKPresenter
@ -8,9 +8,47 @@ final class DocumentsPresenter extends OpenVKPresenter
protected $presenterName = "documents";
protected $silent = true;
function renderList(?int $gid = NULL): void
function renderList(?int $owner_id = NULL): void
{
$this->template->_template = "Documents/List.xml";
if($owner_id > 0)
$this->notFound();
if($owner_id < 0) {
$owner = (new Clubs)->get(abs($owner_id));
if(!$owner || $owner->isBanned())
$this->notFound();
else
$this->template->group = $owner;
}
if(!$owner_id)
$owner_id = $this->user->id;
$current_tab = (int)($this->queryParam("tab") ?? 0);
$current_order = (int)($this->queryParam("order") ?? 0);
$page = (int)($this->queryParam("p") ?? 1);
$order = in_array($current_order, [0,1,2]) ? $current_order : 0;
$tab = in_array($current_tab, [0,1,2,3,4,5,6,7,8]) ? $current_tab : 0;
$docs = (new Documents)->getDocumentsByOwner($owner_id, (int)$order, (int)$tab);
$this->template->tabs = (new Documents)->getTypes($owner_id);
$this->template->current_tab = $tab;
$this->template->count = $docs->size();
$this->template->docs = iterator_to_array($docs->page($page, OPENVK_DEFAULT_PER_PAGE));
$this->template->locale_string = "you_have_x_documents";
if($owner_id < 0) {
$this->template->locale_string = "group_has_x_documents";
} elseif($current_tab != 0) {
$this->template->locale_string = "x_documents_in_tab";
}
$this->template->paginatorConf = (object) [
"count" => $this->template->count,
"page" => $page,
"amount" => sizeof($this->template->docs),
"perPage" => OPENVK_DEFAULT_PER_PAGE,
];
}
function renderListGroup(?int $gid)

View file

@ -1,7 +1,7 @@
<?php declare(strict_types=1);
namespace openvk\Web\Presenters;
use openvk\Web\Models\Entities\{User, Club};
use openvk\Web\Models\Repositories\{Users, Clubs, Posts, Videos, Applications, Audios};
use openvk\Web\Models\Repositories\{Users, Clubs, Posts, Videos, Applications, Audios, Documents};
use Chandler\Database\DatabaseConnection;
final class SearchPresenter extends OpenVKPresenter
@ -12,6 +12,7 @@ final class SearchPresenter extends OpenVKPresenter
private $videos;
private $apps;
private $audios;
private $documents;
function __construct()
{
@ -21,6 +22,7 @@ final class SearchPresenter extends OpenVKPresenter
$this->videos = new Videos;
$this->apps = new Applications;
$this->audios = new Audios;
$this->documents = new Documents;
parent::__construct();
}
@ -45,7 +47,8 @@ final class SearchPresenter extends OpenVKPresenter
"videos" => "videos",
"audios" => "audios",
"apps" => "apps",
"audios_playlists" => "audios"
"audios_playlists" => "audios",
"docs" => "documents"
];
$parameters = [
"ignore_private" => true,

View file

@ -611,7 +611,8 @@ final class UserPresenter extends OpenVKPresenter
"menu_novajoj" => "news",
"menu_ligiloj" => "links",
"menu_standardo" => "poster",
"menu_aplikoj" => "apps"
"menu_aplikoj" => "apps",
"menu_doxc" => "docs",
];
foreach($settings as $checkbox => $setting)
$user->setLeftMenuItemStatus($setting, $this->checkbox($checkbox));

View file

@ -198,6 +198,11 @@
<a n:if="$thisUser->getLeftMenuItemStatus('apps')" href="/apps?act=installed" class="link">{_my_apps}</a>
<a href="/settings" class="link">{_my_settings}</a>
{if $thisUser->getLeftMenuItemStatus('docs')}
<div class="menu_divider"></div>
<a href="/docs" class="link">{_my_documents}</a>
{/if}
{var $canAccessAdminPanel = $thisUser->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)}
{var $canAccessHelpdesk = $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
{var $menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
@ -397,6 +402,7 @@
{script "js/scroll.js"}
{script "js/player.js"}
{script "js/al_wall.js"}
{script "js/al_docs.js"}
{script "js/al_api.js"}
{script "js/al_mentions.js"}
{script "js/al_polls.js"}

View file

@ -1,11 +1,51 @@
{extends "../@layout.xml"}
{block title}
{if !isset($group)}
{_my_documents_objectively}
{else}
{_documents_of_group}
{/if}
{/block}
{block header}{/block}
{block header}
{if !isset($group)}
{_my_documents}
{else}
<a href="{$group->getURL()}">{$group->getCanonicalName()}</a> »
{_my_documents}
{/if}
{/block}
{block content}
загрузить
<div id="docs_page_wrapper">
<div class="docs_page_search">
<form action="/search" method="get">
<input type="hidden" name="section" value="docs">
<input type="search" name="q" class="input_with_search_icon" placeholder="{_search_by_documents}">
</form>
<input class="button" type="button" value="{_upload_button}">
</div>
<div class="docs_page_tabs">
<div class="mb_tabs">
<div n:foreach="$tabs as $tab" class="mb_tab" n:attr="id => $tab['type'] == $current_tab ? active">
<a href="?tab={$tab['type']}">{$tab["name"]}</a>
</div>
</div>
</div>
<div class="docs_page_content">
<div class="summaryBar">
<div class="summary">{tr($locale_string, $count)}.</div>
</div>
<div class="container_white">
{if $count > 0}
{foreach $docs as $doc}
{include "components/doc.xml", doc => $doc}
{/foreach}
{else}
{include "../components/error.xml", description => tr("there_is_no_documents_alright")}
{/if}
</div>
</div>
</div>
{/block}

View file

@ -19,18 +19,18 @@
{block content}
<form method="post" enctype="multipart/form-data">
<table cellspacing="7" cellpadding="0" width="60%" border="0" align="center">
<table>
<tbody>
<tr>
<td width="120" valign="top"><span class="nobold">{_name}:</span></td>
<td><span class="nobold">{_name}:</span></td>
<td><input type="text" name="name" /></td>
</tr>
<tr>
<td width="120" valign="top"><span class="nobold">{_tags}:</span></td>
<td><span class="nobold">{_tags}:</span></td>
<td><textarea name="tags"></textarea></td>
</tr>
<tr>
<td width="120" valign="top"><span class="nobold">{_accessbility}:</span></td>
<td><span class="nobold">{_accessbility}:</span></td>
<td>
<select name="folder">
<option value="0">Private file</option>
@ -39,7 +39,7 @@
</td>
</tr>
<tr>
<td width="120" valign="top"></td>
<td></td>
<td>
<label>
<input type="checkbox" name="owner_hidden">
@ -48,7 +48,7 @@
</td>
</tr>
<tr>
<td width="120" valign="top"><span class="nobold">{_file}:</span></td>
<td><span class="nobold">{_file}:</span></td>
<td>
<label class="button" style="">{_browse}
<input type="file" id="blob" name="blob" style="display: none;" onchange="filename.innerHTML=blob.files[0].name" />
@ -57,7 +57,7 @@
</td>
</tr>
<tr>
<td width="120" valign="top"></td>
<td></td>
<td>
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" class="button" name="submit" value="{_upload_button}" />

View file

@ -0,0 +1,37 @@
{var $preview = $doc->hasPreview() ? $doc->getPreview() : NULL}
{var $tags = $doc->getTags()}
{var $copied = $doc->isCopiedBy($thisUser)}
{var $modifiable = $doc->canBeModifiedBy($thisUser)}
<div class="docListViewItem" data-id="{$doc->getId()}">
<a>
{if $preview}
<img class="doc_icon" alt="document_preview" src="{$preview->getURLBySizeId('tiny')}">
{else}
<div class="doc_icon no_image">
<span>{$doc->getFileExtension()}</span>
</div>
{/if}
</a>
<div class="doc_content noOverflow">
<a><b class="noOverflow">{$doc->getName()}</b></a>
<div class="doc_content_info">
<span>{$doc->getPublicationTime()}</span>,
<span>{readable_filesize($doc->getFilesize())}</span>{if sizeof($tags) > 0} -
<span>
{foreach $tags as $tag}
<a href="/search?section=docs&tags={urlencode($tag)}">
{$tag}{if $tag != $tags[sizeof($tags) - 1]},{/if}
</a>
{/foreach}
</span>{/if}
</div>
</div>
<div class="doc_volume">
<div n:if="!$$modifiable" id="report_icon"></div>
<div n:if="$modifiable" id="edit_icon"></div>
<div n:if="!$copied" id="add_icon"></div>
<div n:if="$copied" id="remove_icon"></div>
</div>
</div>

View file

@ -684,7 +684,19 @@
<td>
<span class="nobold">{_my_apps}</span>
</td>
</tr><tr n:if="sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0">
</tr>
<tr>
<td width="120" valign="top" align="right" align="right">
<input
n:attr="checked => $user->getLeftMenuItemStatus('docs')"
type="checkbox"
name="menu_doxc" />
</td>
<td>
<span class="nobold">{_my_documents}</span>
</td>
</tr>
<tr n:if="sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0">
<td width="120" valign="top" align="right" align="right">
<input
n:attr="checked => $user->getLeftMenuItemStatus('links')"

View file

@ -2826,7 +2826,7 @@ a.poll-retract-vote {
height: 20px;
background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px;
background-color: #fff;
padding-left: 18px;
padding-left: 18px !important;
width: 120px;
}
@ -3967,3 +3967,118 @@ hr {
margin-bottom: -2px;
fill: #7d7d7d;
}
/* Documents */
#docs_page_wrapper {
margin-left: -10px;
margin-top: -10px;
margin-bottom: -10px;
display: block;
width: 102.8%;
}
#docs_page_wrapper .docs_page_search {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
gap: 10px;
padding: 10px 10px;
border-bottom: 1px solid #CCCCCC;
background: #F0F0F0;
}
#docs_page_wrapper .docs_page_search input[type="search"] {
height: 23px;
background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 5px;
background-color: #fff;
padding-left: 18px !important;
}
#docs_page_wrapper .docs_page_search input[type="search"], #docs_page_wrapper .docs_page_search form {
width: 100%;
}
#docs_page_wrapper .container_white {
display: flex;
flex-direction: column;
padding: 5px 10px;
}
.docListViewItem {
max-height: 52px;
height: 38px;
display: grid;
grid-template-columns: 0fr 1fr 0fr;
gap: 10px;
padding: 7px 7px;
border-bottom: 1px solid #EDEDED;
}
.docListViewItem:last-of-type {
border-bottom: unset !important;
}
.docListViewItem:hover {
background: #f7f7f7;
}
.docListViewItem .doc_icon {
width: 50px;
height: 38px;
background: #E6E6E6;
user-select: none;
object-fit: cover;
border-radius: 2px;
}
.docListViewItem .doc_content {
display: flex;
flex-direction: column;
margin-top: 1px;
/*gap: 5px;*/
}
.docListViewItem .doc_content b {
color: black;
}
.docListViewItem .doc_content .doc_content_info, .docListViewItem .doc_content span {
color: #6d6d6d;
}
.docListViewItem .doc_icon.no_image {
display: flex;
align-items: center;
justify-content: center;
border-radius: 2px;
height: 17px;
padding: 2px 0px;
}
.docListViewItem .doc_icon.no_image span {
color: #6b6b6b;
}
.docListViewItem .doc_icon img {
width: 100%;
height: 100%;
object-fit: cover;
}
.docListViewItem .doc_volume {
display: none;
align-items: center;
gap: 5px;
}
.docListViewItem .doc_volume > div {
width: 20px;
height: 20px;
background-color: gray;
}
.docListViewItem:hover .doc_volume {
display: flex;
}

1
Web/static/js/al_docs.js Normal file
View file

@ -0,0 +1 @@
u()

View file

@ -261,6 +261,10 @@ function parseAttachments($attachments, array $allow_types = ['photo', 'video',
'method' => 'get',
'onlyId' => true,
],
'doc' => [
'repo' => 'openvk\Web\Models\Repositories\Documents',
'method' => 'getDocumentById',
]
];
foreach($exploded_attachments as $attachment_string) {
@ -371,6 +375,18 @@ function escape_html(string $unsafe): string
return htmlspecialchars($unsafe, ENT_DISALLOWED | ENT_XHTML);
}
function readable_filesize($bytes, $precision = 2): string
{
$units = ['B', 'Kb', 'Mb', 'Gb', 'Tb', 'Pb'];
$bytes = max($bytes, 0);
$power = $bytes > 0 ? floor(log($bytes, 1024)) : 0;
$power = min($power, count($units) - 1);
$bytes /= pow(1024, $power);
return round($bytes, $precision) . $units[$power];
}
return (function() {
_ovk_check_environment();
require __DIR__ . "/vendor/autoload.php";

View file

@ -2206,6 +2206,10 @@
/* Documents */
"my_documents" = "Документы";
"my_documents_objectively" = "Мои Документы";
"documents_of_group" = "Документы группы";
"search_by_documents" = "Поиск по документам...";
"documents" = "Документы";
"document_uploading_in_general" = "Загрузка документа";
"file" = "Файл";
@ -2221,3 +2225,23 @@
"document_type_6" = "Видео";
"document_type_7" = "Книги";
"document_type_8" = "Остальные";
"you_have_x_documents_one" = "У Вас $1 документ";
"you_have_x_documents_few" = "У Вас $1 документа";
"you_have_x_documents_many" = "У Вас $1 документов";
"you_have_x_documents_other" = "У Вас $1 документов";
"you_have_x_documents_zero" = "У Вас $1 документов";
"group_has_x_documents_one" = "У этой группы $1 документ";
"group_has_x_documents_few" = "У этой группы $1 документа";
"group_has_x_documents_many" = "У этой группы $1 документов";
"group_has_x_documents_other" = "У этой группы $1 документов";
"group_has_x_documents_zero" = "У этой группы $1 документов";
"x_documents_in_tab_one" = "В этой вкладке $1 документ";
"x_documents_in_tab_few" = "В этой вкладке $1 документа";
"x_documents_in_tab_many" = "В этой вкладке $1 документов";
"x_documents_in_tab_other" = "В этой вкладке $1 документов";
"x_documents_in_tab_zero" = "В этой вкладке $1 документов";
"there_is_no_documents_alright" = "Здесь нет документов.";