4in1_ws_web/src/handlers/foreignone/FilesHandler.php
2025-04-28 14:47:25 +03:00

216 lines
8.1 KiB
PHP

<?php
namespace app\foreignone;
use app\foreignone\files\Archive;
use app\foreignone\files\ArchiveType;
use app\foreignone\files\Book;
use app\foreignone\files\Util as FilesUtil;
use app\foreignone\files\SectionType;
use engine\http\AjaxOk;
use engine\http\errors\NotFound;
use engine\http\Response;
class FilesHandler
extends BaseHandler
{
const int SEARCH_RESULTS_PER_PAGE = 50;
const int SEARCH_MIN_QUERY_LENGTH = 3;
public function GET_files(): Response {
$collections = array_map(fn(ArchiveType $c) => new Archive($c), ArchiveType::cases());
$books = Book::getList(section: SectionType::BOOKS_AND_ARTICLES);
$misc = Book::getList(section: SectionType::MISC);
$this->skin->meta->title = lang('meta_files_title');
$this->skin->meta->description = lang('meta_files_description');
$this->skin->title = lang('files');
$this->skin->options->headSection = 'files';
return $this->skin->renderPage('files_index.twig', [
'collections' => $collections,
'books' => $books,
'misc' => $misc
]);
}
public function GET_folder(): Response {
list($folder_id) = $this->input('i:folder_id');
$parents = Book::getFolder($folder_id, with_parents: true);
if (!$parents)
throw new NotFound();
if (count($parents) > 1)
$parents = array_reverse($parents);
$folder = $parents[count($parents)-1];
$files = Book::getList($folder->section, $folder_id);
$bc = [
['text' => lang('files'), 'url' => '/files/'],
];
if ($parents) {
for ($i = 0; $i < count($parents)-1; $i++) {
$parent = $parents[$i];
$bc_item = ['text' => $parent->getTitle()];
if ($i < count($parents)-1)
$bc_item['url'] = $parent->getUrl();
$bc[] = $bc_item;
}
}
$bc[] = ['text' => $folder->title];
$this->skin->meta->title = lang('meta_files_book_folder_title', $folder->getTitle());
$this->skin->meta->description = lang('meta_files_book_folder_description', $folder->getTitle());
$this->skin->title = lang('files').' - '.$folder->title;
return $this->skin->renderPage('files_folder.twig', [
'folder' => $folder,
'bc' => $bc,
'files' => $files
]);
}
public function GET_collection(): Response {
list($archive, $folder_id, $query, $offset) = $this->input('collection, i:folder_id, q, i:offset');
$archive = ArchiveType::from($archive);
$parents = null;
$query = trim($query);
if (!$query)
$query = null;
$this->skin->exportStrings('/^files_(.*?)_collection$/');
$this->skin->exportStrings([
'files_search_results_count'
]);
$vars = [];
$text_excerpts = null;
$func_prefix = $archive->value;
if ($query !== null) {
$files = FilesUtil::searchArchive($archive, $query, $offset, self::SEARCH_RESULTS_PER_PAGE);
$vars += [
'search_count' => $files['count'],
'search_query' => $query
];
$files = $files['items'];
$query_words = array_map('mb_strtolower', preg_split('/\s+/', $query));
$found = [];
$result_ids = [];
foreach ($files as $file) {
if ($file->type == 'folder')
continue;
$result_ids[] = $file->id;
$candidates = [];
switch ($archive) {
case ArchiveType::MercureDeFrance:
$candidates = [
$file->date,
(string)$file->issue
];
break;
case ArchiveType::WilliamFriedman:
$candidates = [
mb_strtolower($file->getTitle()),
strtolower($file->documentId)
];
break;
}
foreach ($candidates as $haystack) {
foreach ($query_words as $qw) {
if (mb_strpos($haystack, $qw) !== false) {
$found[$file->id] = true;
continue 2;
}
}
}
}
$found = array_map('intval', array_keys($found));
$not_found = array_diff($result_ids, $found);
if (!empty($not_found))
$text_excerpts = FilesUtil::getTextExcerpts($archive, $not_found, $query_words);
if (isXHRRequest()) {
return new AjaxOk(
[
...$vars,
'new_offset' => $offset + count($files),
'html' => $this->skin->render('files_list.twig', [
'files' => $files,
'search_query' => $query,
'text_excerpts' => $text_excerpts
])
]
);
}
} else {
if (in_array($archive, [ArchiveType::WilliamFriedman, ArchiveType::Baconiana]) && $folder_id) {
$parents = $archive->getFolderGetter()($folder_id, with_parents: true);
if (!$parents)
throw new NotFound();
if (count($parents) > 1)
$parents = array_reverse($parents);
}
$files = $archive->getListGetter()($folder_id);
}
$title = lang('files_'.$archive->value.'_collection');
if ($folder_id && $parents)
$title .= ' - '.htmlescape($parents[count($parents)-1]->getTitle());
if ($query)
$title .= ' - '.htmlescape($query);
$this->skin->title = $title;
if (!$folder_id && !$query) {
$this->skin->meta->title = lang('4in1').' - '.lang('meta_files_collection_title', lang('files_'.$archive->value.'_collection'));
$this->skin->meta->description = lang('meta_files_'.$archive->value.'_description');
} else if ($query || $parents) {
$this->skin->meta->title = lang('4in1').' - '.$title;
$this->skin->meta->description = lang('meta_files_'.($query ? 'search' : 'folder').'_description',
$query ?: $parents[count($parents)-1]->getTitle(),
lang('files_'.$archive->value.'_collection'));
}
$bc = [
['text' => lang('files'), 'url' => '/files/'],
];
if ($parents) {
$bc[] = ['text' => lang('files_'.$archive->value.'_collection_short'), 'url' => "/files/{$archive->value}/"];
for ($i = 0; $i < count($parents); $i++) {
$parent = $parents[$i];
$bc_item = ['text' => $parent->getTitle()];
if ($i < count($parents)-1)
$bc_item['url'] = $parent->getUrl();
$bc[] = $bc_item;
}
} else {
$bc[] = ['text' => lang('files_'.$archive->value.'_collection')];
}
$js_params = [
'container' => 'files_list',
'per_page' => self::SEARCH_RESULTS_PER_PAGE,
'min_query_length' => self::SEARCH_MIN_QUERY_LENGTH,
'base_url' => "/files/{$archive->value}/",
'query' => $vars['search_query'] ?? '',
'count' => $vars['search_count'] ?? 0,
'collection_name' => $archive->value,
'inited_with_search' => !!($vars['search_query'] ?? "")
];
$this->skin->set($vars);
$this->skin->set([
'collection' => $archive->value,
'files' => $files,
'bc' => $bc,
'do_show_search' => empty($parents),
'do_show_more' => ($vars['search_count'] ?? 0) > 0 && count($files) < ($vars['search_count'] ?? 0),
'text_excerpts' => $text_excerpts,
'js_params' => $js_params,
]);
return $this->skin->renderPage('files_collection.twig');
}
}