Skip to content

Add View Counter plugin (OJS 3.4 and 3.5) - #505

Open
edersotto wants to merge 2 commits into
pkp:mainfrom
edersotto:add-viewcounter
Open

Add View Counter plugin (OJS 3.4 and 3.5)#505
edersotto wants to merge 2 commits into
pkp:mainfrom
edersotto:add-viewcounter

Conversation

@edersotto

Copy link
Copy Markdown

New plugin: View Counter

Adds a gallery entry for View Counter (generic, product viewcounter).

  • What it does: shows each article's abstract views and downloads (sum of galleys),
    discreetly next to the title on the summary lists and on the article landing page;
    configurable per journal. On OJS 3.5 the counts are computed via the statistics service
    with safe fallbacks.
  • Repository: https://github.com/OJSBR/viewcounter (GPL-3.0)
  • Maintainer: OJSBR (STNT Tecnologia da Informação LTDA)
  • Releases in this entry (public GitHub release tarballs, md5 verified):
    • 1.2.0.0 → OJS 3.5.0.0 / 3.5.0.1
    • 1.1.0.0 → OJS 3.4.0.0–3.4.0.9

Provenance / credit

The plugin was rewritten and is maintained by OJSBR, based on an original OJS 3.3
access/downloads counter by STI-FFLCH/USP and ABCD/USP. That origin is credited in
the entry description. We couldn't find an actively maintained upstream repository for the
original, and OJSBR now maintains it under GPL-3.0.

Notes

  • plugins.xml validated against plugins.xsd (xmllint --schema).
  • No <certification> was set — happy for the reviewers to assign the appropriate one.
  • Entry appended at the end of plugins.xml; glad to reorder if you prefer a specific spot.

Adds an entry for the View Counter plugin, which shows each article's abstract
views and downloads on summary lists and the article page. Maintained by OJSBR;
rewritten from an original OJS 3.3 access/downloads counter by STI-FFLCH/USP and
ABCD/USP (credited in the description). Validated against plugins.xsd.
@bozana

bozana commented Sep 1, 2026

Copy link
Copy Markdown

Hi @edersotto,

Thanks for the submission, and for carefully crediting.

There are a few issues that would need to be fixed:

plugins.xml metadata

  1. Please use the tilde form:
<compatibility application="ojs2"><version>~3.5.0.0</version></compatibility>
<compatibility application="ojs2"><version>~3.4.0.0</version></compatibility>

~3.5.0.0 matches every 3.5.0.x. ~3.4.0.0 matches every 3.4.0.x.
The explicit 3.5.0.0 / 3.5.0.1 only match those exact patch releases, so an install on 3.5.0.2+ won't see the plugin as compatible.

  1. Locale codes. The entry uses only locale="en_US" (plugin name, summary, description, and the per-release ). OJS 3.4/3.5 use the short code en internally, so these don't locale-match on current installs (they fall back to first-available, so nothing is blank, but it's not correct). The gallery convention is to provide both, locale="en" and locale="en_US" with identical text. Please add the en variants alongside the en_US ones. pt_BR is fine as-is.

Code — blocking

  1. Whole-template override frozen at 3.5.0.0. The plugin ships copies of templates/frontend/objects/article_summary.tpl and article_details.tpl and swaps them in via TemplateResource::getFilename. The copies are pinned to 3.5.0.0, and core has already changed both templates within the 3.5.0.x line, so installing the plugin silently reverts those changes. More importantly, this is structural: any future core fix to these templates won't reach sites running the plugin.

Could you please rework this to inject via the content hooks instead of replacing templates. As example, see https://github.com/pkp/pflPlugin/:

  1. Hook::add('Templates::Issue::Issue::Article', …) for the summary list and Hook::add('Templates::Article::Main', …) (or ::Details) for the article page — covers displaying the badge on both pages; the counting logic is PHP and is unaffected.
  2. A small stylesheet added via $templateMgr->addStyleSheet(…) from your existing TemplateManager::display hook to position .viewcounter-stats next to the title (see PflPlugin::addPflJsAndCss()). If core markup shifts, the badge just stays at its hook location instead of breaking the page.
  3. If you want it pixel-exact at the title, $templateMgr->registerFilter('output', …) is the pattern you could use for insertions where no hook exists (PflPlugin::authorCiFilter).

This solution keeps the plugin forward-compatible with 3.5.x releases.

Code — minor

  1. clearTemplateCache() on every settings save. ViewcounterSettingsForm::execute() calls TemplateManager::clearTemplateCache(), which flushes the entire installation's compiled-template and Smarty cache (cache/t_compile/ + cache/t_cache/, all journals) — triggered by any journal manager. Once the override is replaced with hooks this is no longer needed and can be removed.

  2. Uncached statistics queries during list rendering. Both releases run a stats aggregation query per article while rendering article lists — 1.1.0.0 through the deprecated Submission::getViews() / Galley::getViews() (one per galley, and getViews() is called twice per article in the 1.1.0.0 template), 1.2.0.0 about two per article. On an issue TOC with 20–30 articles that's dozens of aggregation queries per page load.

Suggested approach: a single per-submission cache (viewcounter-{submissionId}, 24h TTL). plugins/generic/pflPlugin caches its stats the same way (Cache::remember(...)). Fill it per-context:

  • Article page → fill the one key.
  • List contexts (issue TOC, search) → prime the cache in bulk. There's no {call_hook} in issue_toc.tpl, but from the TemplateManager::display hook on frontend/pages/issue.tpl you can read $templateMgr->getTemplateVars('publishedSubmissions'), collect the submission IDs, and fill all the missing keys with one grouped query ('submissionIds' => [...], getSum(['submission_id'])) instead of one per row.
  1. Hard-coded Portuguese in the 1.1.0.0 template — title="Visualizações", aria-label="Visualizações: …" etc. 1.2.0.0 already fixed this with __(); the 1.1.0.0 template should use locale keys too.

Happy to re-review once the template handling is reworked and the plugins.xml metadata is adjusted.

Thanks!

edersotto added a commit to OJSBR/viewcounter that referenced this pull request Sep 6, 2026
…es; cache counts

Addresses the plugin-gallery review (pkp/plugin-gallery#505):

- No core template is replaced any more. The badge is appended through
  Templates::Issue::Issue::Article (summary lists) and Templates::Article::Main
  (article page); css/viewcounter.css + js/viewcounter.js move it next to the
  title when the default markup is present, otherwise it stays at the hook.
- Counts are cached per submission for 24 h (Cache::remember). On issue TOC,
  journal home and search the cache is primed in bulk with one grouped query
  per metric type instead of one query per article.
- Settings form no longer calls TemplateManager::clearTemplateCache().
- All labels come from locale keys; no hard-coded Portuguese.
- {viewcounterStats} stays registered for themes that copied the old templates.
edersotto added a commit to OJSBR/viewcounter that referenced this pull request Sep 6, 2026
…es; cache counts

Addresses the plugin-gallery review (pkp/plugin-gallery#505):

- No core template is replaced any more. The badge is appended through
  Templates::Issue::Issue::Article (summary lists) and Templates::Article::Main
  (article page); css/viewcounter.css + js/viewcounter.js move it next to the
  title when the default markup is present, otherwise it stays at the hook.
- Counts are cached per submission for 24 h (Cache::remember). On issue TOC,
  journal home and search the cache is primed in bulk with one grouped query
  per metric type instead of one query per article.
- Settings form no longer calls TemplateManager::clearTemplateCache().
- All labels come from locale keys; no hard-coded Portuguese.
- {viewcounterStats} stays registered for themes that copied the old templates.
@edersotto

Copy link
Copy Markdown
Author

Hi @bozana, thank you for the thorough review. Everything is addressed:

  • plugins.xml: tilde compatibility (~3.5.0.0 / ~3.4.0.0) and en + en_US locales alongside pt_BR.
  • Code: the template overrides are gone. The badge is injected via Templates::Issue::Issue::Article and Templates::Article::Main, with a small stylesheet/script added from the TemplateManager::display hook to place it next to the title (it stays at the hook location if the markup differs). Counts are cached per submission for 24 h (Cache::remember) and primed in bulk on list pages with one grouped query (getSum(['submission_id'])). clearTemplateCache() was removed and all labels come from locale keys.

New releases: 1.3.0.0 (OJS 3.5) and 1.1.1.0 (OJS 3.4), both from the same code. Ready for re-review, thanks again!

@bozana

bozana commented Sep 8, 2026

Copy link
Copy Markdown

Hi @edersotto, great!
I have a few more comments:
Blocker (1.1.1.0 / OJS 3.4 only):

  • ViewcounterPlugin::isFeatureEnabled() (line 418) references a constant that does not exist in 3.4:
    $contextId = $context ? $context->getId() : PKPApplication::SITE_CONTEXT_ID;
    SITE_CONTEXT_ID should actually be CONTEXT_SITE.

Would be good to fix:

  • The OJS 3.4 plugin contains 3.5 languages. On 3.4 fr should actually be fr_FR, pt -> pt_PT, nb_NO -> nb, sr_Latn -> sr@latin. (The locale codes were only renamed to the Weblate style in 3.5).
  • "Rewritten and adapted for OJS 3.4/3.5 by OJSBR. Original plugin by STI FFLCH and ABCD/USP" is displayed in the plugin description and in the settings modal. Having it in README , versions.xml and file headers is enough, no? And in the gallery entry here in the PR, the <maintainer> element should be enough — no need to repeat it in <description>?
  • You can add <certification type="reviewed"/> (see other plugin gallery examples).
  • Remove blank line before </plugins>.

Optional/cosmetic:

  • The release tarball includes .github/ and .gitignore. Eventually you would like to remove/ignore them?

Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants