bc([ ['text' => $ctx->lang('files_archives')] ])}
{$ctx->for_each($collections, fn(FilesItemInterface $file) => $ctx->file( file: $file, disabled: !$file->isAvailable()))}
{$ctx->bc([ ['text' => $ctx->lang('files_books')] ], mt: true)}
{$ctx->for_each($books, fn(FilesItemInterface $file) => $ctx->file(file: $file))}
{$ctx->bc([ ['text' => $ctx->lang('files_misc')] ], mt: true)}
{$ctx->for_each($misc, fn(FilesItemInterface $file) => $ctx->file(file: $file))}
HTML; } function folder($ctx, BookItem $folder, array $files, ?array $parents) { $svg = svg(); $svg->folder_20(preload_symbol: true); $svg->file_20(preload_symbol: true); $bc = [ ['text' => $ctx->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]; return <<bc($bc)}
{$ctx->collection_files($files)}
HTML; } function collection(SkinContext $ctx, FilesCollection $collection, array $files, ?array $parents, int $search_results_per_page, int $search_min_query_length, ?string $search_query = null, ?int $search_count = null, ?array $text_excerpts = null) { $widgets = skin('widgets'); $svg = svg(); $svg->folder_20(preload_symbol: true); $svg->file_20(preload_symbol: true); $bc = [ ['text' => $ctx->lang('files'), 'url' => '/files/'], ]; if ($parents) { $bc[] = ['text' => $ctx->lang('files_'.$collection->value.'_collection_short'), 'url' => "/files/{$collection->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' => $ctx->lang('files_'.$collection->value.'_collection')]; } $do_show_search = empty($parents); $do_show_more = $search_count > 0 && count($files) < $search_count; $html = <<bc($bc)} {$ctx->if_true($do_show_search, fn() => $ctx->collection_search($search_count, $search_query, $ctx->lang('files_'.$collection->value.'_search_ph')))}
{$ctx->collection_files($files, $search_query, $text_excerpts)}
if_not($do_show_more, ' style="display: none"')}> {$ctx->lang('files_show_more')} {$widgets->spinner('files_show_more_spinner')}
HTML; if ($do_show_search) { $opts = [ 'container' => 'files_list', 'per_page' => $search_results_per_page, 'min_query_length' => $search_min_query_length, 'base_url' => "/files/{$collection->value}/", 'query' => $search_query, 'count' => $search_count, 'collection_name' => $collection->value, 'inited_with_search' => !!$search_query ]; $opts = jsonEncode($opts); $js = <<for_each($files, fn(FilesItemInterface $f) => $ctx->file( file: $f, unsafe_query: $search_query, text_excerpts: $text_excerpts)); } function collection_search(SkinContext $ctx, $count, $query, ?string $placeholder = null) { $icons = svg(); $widgets = skin('widgets'); $clear_dsp = $query ? 'block' : 'none'; return <<
{$widgets->spinner()}
{$ctx->if_then_else($query, fn() => $ctx->lang_num('files_search_results_count', $count), ' ')}
HTML; } function file(SkinContext $ctx, FilesItemInterface $file, ?SkinString $unsafe_query = null, bool $disabled = false, ?array $text_excerpts = null,) { $icons = svg(); if ($file instanceof BookItem && $file->fileType == BookFileType::BOOK) $icon = $icons->book_20(); else $icon = $file->isFile() ? $icons->file_20() : $icons->folder_20(); $class = 'files-list-item clearfix'; if ($disabled) $class .= ' is-disabled'; $mapper = function($s) use ($unsafe_query) { if ($unsafe_query !== null) { return hl_matched($s, $unsafe_query); } else { return htmlescape($s); } }; $title = $file->getTitleHtml(); if ($title === null) { // we don't apply $mapper to already htmlescaped string $title = $mapper($file->getTitle()); } $meta = $file->getMeta($unsafe_query); $meta_is_inline = $meta['inline'] ?? false; $meta_items = $meta['items'] ?? []; $url = htmlescape($file->getUrl()); $subtitle = $file->getSubtitle(); return <<if_true($file->isTargetBlank(), ' target="_blank"')}>
{$icon}
{$title} {$ctx->if_true($file->isFolder() && $file->isTargetBlank(), fn() => ''.$icons->arrow_up_right_out_square_outline_12().'')} {$ctx->if_true($subtitle, fn() => ''.htmlescape($subtitle).'')} {$ctx->if_true($meta_is_inline, $ctx->for_each($meta_items, fn($s) => '
'.$s.'
'))}
{$ctx->if_true($meta_items && !$meta_is_inline, $ctx->meta($meta_items))} {$ctx->if_true(is_array($text_excerpts) && isset($text_excerpts[$file->getId()]), fn() => $ctx->text_excerpt($text_excerpts[$file->getId()]['excerpt'], $text_excerpts[$file->getId()]['index'], $unsafe_query))}
HTML; } /** * @param SkinContext $ctx * @param string[] $meta strings are already html-safe * @return string */ function meta($ctx, array $meta) { return << {$ctx->for_each($meta, fn($s) => '
'.$s.'
')} HTML; } function text_excerpt($ctx, $unsafe_excerpt, $index, $unsafe_query) { if ($index > 0) $unsafe_excerpt = '...'.$unsafe_excerpt; $unsafe_excerpt .= '...'; $text = hl_matched($unsafe_excerpt, $unsafe_query); return <<{$text} HTML; }