Articles
Cross-journal article search and browse on the root public site — the quick search box embedded on the Landing module's home screen feeds into these forms and results, all dispatched inline by main/index.php into class/article.class.php's ArticleManager running in cross-journal (adm=1) mode.
| Page | Status | E2E | Enhanced | Legacy Ref | Route | Roles |
|---|---|---|---|---|---|---|
| Author Search | Full | Yes | typed-facet-search | main/index.php?aut | /?aut | Public |
| Advanced Search | Full | Yes | faceted-filters | main/index.php?adv | /?adv | Public |
| Article Search Results | Full | Yes | pagination | main/index.php?_action=article | /?_action=article&keywords=... | Public |
| Article Detail | Full | — | copy-to-clipboard | main/index.php?_action=articleInfo | /article_....html | Public |
Features
| Feature | Status | E2E | Description |
|---|---|---|---|
| Reader can free-text search articles across all journals from the landing quick-search box and land on a shared results screen | Full | Yes | The landing quick search, author search, and advanced search all converge on the same results view, mirroring the legacy single _action=article consolidation point. |
| Reader can search articles by author name | Full | Yes | Legacy was a standalone first/last-name form (?aut); the port makes author search one facet of the unified sidebar. |
| Reader can filter results by subject, keyword, journal title, DOI, and publication-year range (advanced search) | Full | Yes | Replaces the legacy ?adv static form; per parity note neither side exposes an article-type filter on the portal path. |
| Reader can combine up to three search terms with field selectors and boolean operators (legacy advanced form kw1/field1/op2/kw2/op3/kw3) | Dropped | — | Boolean AND/OR term composition across chosen fields has no port counterpart; facet intersection is the replacement model. |
| Reader can bound the publication date range to the day/month (legacy start_day/start_month/end_day/end_month) | Dropped | Yes | Year-level filtering is preserved; sub-year precision was abandoned in the faceted redesign. |
| Reader can remove any active filter via chips and see all active filters at a glance | New | Yes | No legacy equivalent — legacy forms could only be resubmitted from scratch. |
| Reader can page through results and change page size | Full | Yes | Both stacks paginate; the port makes it uniformly URL-driven with a results summary. |
| Reader can sort search results | Full | Yes | Sorting moved from an advanced-form field to persistent controls on the results screen. |
| Reader sees a results summary (total count) and an explicit empty state when nothing matches | Full | Yes | Legacy echoed the search terms as a heading; the port adds an explicit count and designed empty state. |
| Reader can open a cross-journal article detail page showing title, authors, journal title, DOI, and abstract | Full | — | The portal-root detail route exists, though the results cards currently deep-link to the per-journal detail instead (see flags). |
| Reader can copy the article DOI and share the article via copy-URL, with toast feedback | New | — | No legacy predecessor; added convenience actions on the ported detail page. |
| Reader sees a truncated abstract preview that can be expanded/collapsed | New | — | Legacy rendered the full abstract statically. |
| Reader sees article view and download statistics on the detail page | New | — | Legacy tracked views (saveArticleTracking) but did not surface counts on the portal detail render. |
| Article content is selected per locale (language-based content) on the detail page | New | — | Locale-aware content selection has no legacy portal equivalent (legacy served one LANG_CODE build). |
| Reader can download article full-text PDF (and purchase-gated variants) from the results list and detail page | Pending | — | Legacy articleList/articleInfo emitted full-text PDF links (incl. purchase and annotation-service variants, class/article.class.php:448-460); the port has PDF buttons only as commented-out code in ArticleCard.tsx and ArticleContent.tsx. |
| Reader can access per-article export/citation links (XML export, external ar_ext_link services, citation-count badges, supplementary file downloads) | Pending | — | Legacy list rows carried export_links (file type 37/59 downloads, configurable external links with {doi}/{code}/{title} templating, citation badges) and issue-level XML export; no apps/web counterpart. |
| Search engines and Google Scholar receive citation metadata (citation_author, citation_*, DC.* meta tags) on the article detail page | Pending | — | Legacy main/index.php:117-200 emitted a full citation/Dublin Core meta block for articleInfo; apps/web/app/[locale]/(public)/articles/[id]/page.tsx has no generateMetadata. |
| Reader can reach a publication-year archive of articles via friendly URL (year_....html) | Basic | Yes | Year filtering is ported; the archive-style inbound URL is not. |
| Each search result links to its journal's own site | New | Yes | The port surfaces journal identity and navigation per result, which the legacy portal list omitted. |
| Reader on mobile gets a dedicated filters/sort experience | New | — | Responsive filter UI designed from scratch; legacy had a single desktop-era layout. |
| Reader sees filter-aware skeleton loading while results and facets stream in | New | — | No legacy equivalent — legacy was a blocking full server render. |
| Article page views are tracked to power view statistics | Pending | — | Legacy recorded views via ArticleManager::saveArticleTracking (class/article.class.php:3109); no evidence in apps/web that rendering the portal detail records a view, though statistics are displayed. |
class/index.class.php.IndexManager, the per-journal "indexing services" (DOAJ/Scopus-style) CRUD invoked from the role-portal's manager.php — unrelated to article search. The actual dispatch for every row below is the inline if/elseif chain in main/index.php itself, which instantiates class/article.class.php's ArticleManager directly and passes $_PARAMS['adm'] = 1 to switch its shared articleList/articleInfo/articleSearchForm methods into cross-journal (portal-wide) behavior — e.g. showing the journal title on the Article Detail page (showArticleOld(), gated on adm/orgs), dropping the per-journal "article type" filter from Advanced Search, and adding a "Journal Title" search field to Advanced Search. Note the Article Search Results list itself does not render a per-result journal title in this HTML path — articleList()'s row-render loop never echoes it; the field only reaches $__article['journal_title'] in the JSON data_only branch (used by the separate service JSON endpoint, out of scope here), and only when both adm and json are set.article_<code>.html friendly URL (and its underlying ?_action=articleInfo dispatch) is reused verbatim on every journal's own site — a different PHP entry file (top-level index.php / mainm / mainn, claimed by the Journal segment's issues-articles module) rendering a per-journal-scoped page without the cross-journal journal-title line. This module's "Article Detail" row is specifically the portal-root (main/) instance. Flagging so the two aren't merged or confused during Phase D triage._action=article) is the shared landing point for the plain keyword box on the Landing module's home screen, the Author Search form, the Advanced Search form above, the friendly-URL year archive route (main/.htaccess: year_....html → ?_action=article&year=...), and the friendly-URL issue archive route (main/.htaccess: issue_<vol>_<issue>_<slug>.html → ?_action=article&vol=...&issue=...&_is=..., main/.htaccess:18) — all reaching the same _action=article branch. The three forms submit via GET with a hidden _action=article field, differing only in which extra parameters they attach (keywords; vs. first_name/last_name; vs. kw1/field1/op2/kw2/op3/kw3 and date-range fields from the advanced form — the portal's Advanced Search has no articleType[] field, since that block is gated !isset($_PARAMS['adm']) and adm=1 is always set on this portal path). The year-archive route attaches year, and the issue-archive route attaches vol/issue/_is; both are consumed by articleList()/searchArticles() to filter this same results screen (searchArticles() filters on related_issue when issue is a plain digit string, class/article.class.php:811).
Verified: main/.htaccess:18 matches exactly; main/index.php:279-295 confirms _action=article passes full $_GET (including vol/issue/_is) into ArticleManager::articleList(); article.class.php:529-530 confirms the non-data_only render path calls searchArticles($_PARAMS) with that same array; article.class.php:811 matches exactly. Cross-checked mainm/.htaccess and mainn/.htaccess, which carry an identical issue_... rule but dispatch through different entry files — that per-journal route is already, correctly, a separate row in journal/issues-articles.html ("Issue Archive (Single Issue View)"), so this note does not create a cross-module duplicate.