PHPackages                             mbsoft31/slr-ranking - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. mbsoft31/slr-ranking

ActiveLibrary

mbsoft31/slr-ranking
====================

This is my package slr-ranking

v0.0.3(8mo ago)05MITPHPPHP ^8.3CI failing

Since Sep 5Pushed 8mo agoCompare

[ Source](https://github.com/mbsoft31/slr-ranking)[ Packagist](https://packagist.org/packages/mbsoft31/slr-ranking)[ Docs](https://github.com/mbsoft31/slr-ranking)[ GitHub Sponsors](https://github.com/mbsoft31)[ RSS](/packages/mbsoft31-slr-ranking/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (12)Versions (4)Used By (0)

SLR Ranking (Laravel Package)
=============================

[](#slr-ranking-laravel-package)

[![Latest Version on Packagist](https://camo.githubusercontent.com/8f0f02967895855f9ea8c90079e4ae6f4ef2978366fdf79e57b40c19c83bac67/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d62736f667433312f736c722d72616e6b696e672e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mbsoft31/slr-ranking)[![GitHub Tests Action Status](https://camo.githubusercontent.com/01cfc1f1c07d2eed235773d90bce359f718e25075a9a1e347170630399f09873/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d62736f667433312f736c722d72616e6b696e672f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/mbsoft31/slr-ranking/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/ff9c4264b7d93e36094f750d33514e4db87ea3ca80d364b4e23a58f3748f4f7f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d62736f667433312f736c722d72616e6b696e672f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/mbsoft31/slr-ranking/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/00361000c33521034f24f4731c6f4d96cc255e84d2efddce1e9516a0e82b3500/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6d62736f667433312f736c722d72616e6b696e672e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mbsoft31/slr-ranking)

> **Headless, auditable SLR pipeline** for open-source evidence ranking — protocol → connectors (OpenAlex/Crossref/arXiv/Semantic Scholar) → normalization &amp; dedup → enrichment (OA/code/data/citations) → **scoring** (venue, recency, OA/repro, novelty, realism, breadth) → **exports**. Built as a **Laravel package** (no UI), following **Spatie Package Tools** conventions.

---

Table of Contents
-----------------

[](#table-of-contents)

- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Environment Variables](#environment-variables)
- [Data Model](#data-model)
- [Connectors](#connectors)
- [Normalization &amp; Dedup](#normalization--dedup)
- [Enrichment](#enrichment)
- [Scoring](#scoring)
- [CLI Commands](#cli-commands)
- [Quickstart](#quickstart)
- [Scheduling (optional)](#scheduling-optional)
- [Search Integration (optional)](#search-integration-optional)
- [Testing](#testing)
- [FAQ](#faq)
- [Roadmap](#roadmap)
- [Contributing](#contributing)
- [Security &amp; ToS](#security--tos)
- [License](#license)

---

Features
--------

[](#features)

- **Package-only (no UI):** pure Eloquent models, services, jobs, and CLI commands.
- **Protocol storage:** projects keep objective, weights, half-life, search strings, and eligibility rules.
- **Open connectors:** **OpenAlex**, **Crossref**, **arXiv**, **Semantic Scholar (S2)** with cursor/offset paging.
- **Normalization &amp; dedup:** unified “work” per paper (DOI favored; fuzzy title match fallback).
- **Enrichment:** Unpaywall (OA), code/data link detection, citation counts &amp; fields.
- **Scoring engine:** venue quality, recency (half-life), OA &amp; reproducibility, novelty, realism, breadth → **composite 0–100**.
- **Exports:** JSON project bundle (CSV/Markdown planned).
- **Lookups:** SJR quartiles &amp; CORE ranks via CSV uploads (versioned snapshots).
- **Auditable:** minimal audit log events &amp; immutable derived scores.

---

Requirements
------------

[](#requirements)

- **PHP**: ≥8.3
- **Laravel**: 11.x and above
- **Database**: any supported by Laravel (PostgreSQL recommended)
- **Queues**: Redis (recommended) or any Laravel queue backend
- **HTTP**: Guzzle (already required)
- Optional:

    - **Laravel Scout** + **Meilisearch** for full-text indexing
    - **Laravel Horizon** for queue monitoring

---

Installation
------------

[](#installation)

### 1) Require the package

[](#1-require-the-package)

**Monorepo / local path:**

```
// composer.json (of your host app)
{
  "repositories": [
    { "type": "path", "url": "packages/mbsoft/slr-ranking" }
  ]
}
```

```
composer require mbsoft/slr-ranking:dev-main
```

**Standalone (from VCS):**

```
composer require mbsoft/slr-ranking
```

### 2) Publish config &amp; migrations

[](#2-publish-config--migrations)

```
php artisan slr:install
php artisan migrate
```

### 3) Set environment

[](#3-set-environment)

Add at least:

```
UNPAYWALL_EMAIL=you@example.com
OPENALEX_BASE=https://api.openalex.org
CROSSREF_BASE=https://api.crossref.org
S2_BASE=https://api.semanticscholar.org/graph/v1
ARXIV_BASE=https://export.arxiv.org/api
```

### 4) Run queues

[](#4-run-queues)

```
php artisan queue:work
# (or) php artisan horizon
```

---

Configuration
-------------

[](#configuration)

`config/slr-ranking.php` (published by `slr:install`):

```
return [
    'half_life' => 3.0,  // years for recency decay
    'default_weights' => [
        'venue' => 0.30, 'recency' => 0.15, 'oa' => 0.05,
        'novelty' => 0.20, 'realism' => 0.20, 'breadth' => 0.10,
    ],
    'user_model' => \App\Models\User::class,

    'endpoints' => [
        'openalex' => env('OPENALEX_BASE', 'https://api.openalex.org'),
        'crossref' => env('CROSSREF_BASE', 'https://api.crossref.org'),
        'unpaywall'=> 'https://api.unpaywall.org/v2',
        's2'       => env('S2_BASE', 'https://api.semanticscholar.org/graph/v1'),
        'arxiv'    => env('ARXIV_BASE', 'https://export.arxiv.org/api'),
    ],
    'unpaywall_email' => env('UNPAYWALL_EMAIL'),

    // Optional search: set to 'scout' to enable Laravel Scout indexing
    'search_driver' => env('SLR_SEARCH', null),

    'features' => [
        // If true, venue quality falls back to a capped percentile of citations when SJR/CORE missing.
        'citations_percentile_fallback' => true,
    ],
];
```

---

Environment Variables
---------------------

[](#environment-variables)

- `UNPAYWALL_EMAIL` — required by Unpaywall.
- `OPENALEX_BASE`, `CROSSREF_BASE`, `S2_BASE`, `ARXIV_BASE` — override endpoints if needed.
- `SLR_SEARCH=scout` — enable Scout indexing (host app must configure Scout + Meilisearch).
- Usual Laravel queue/database configuration as per your app.

---

Data Model
----------

[](#data-model)

Tables (all prefixed `slr_`):

- **projects** — protocol store: name, objective, weights, search strings, inclusion rules, half-life.
- **sources** — connector catalog (openalex, crossref, arxiv, semanticscholar, manual).
- **raw\_records** — raw JSON per source pull (for audit/replay).
- **works** — **normalized** unique works (per project).
- **enrichments** — OA flags, OA URL, code/data links, citations, fields.
- **venue\_metrics** — versioned SJR/CORE snapshots.
- **screenings** — TA/FT screening decisions (reviewer morphs).
- **criterion\_scores** — per-criterion scores.
- **composite\_scores** — final composite (breakdown + timestamp).
- **expert\_reviews** — expert notes, adjustment deltas, overrides.
- **audit\_logs** — lightweight action trail.
- **lookups\_sjr**, **lookups\_core** — uploaded CSV snapshots.

### ER (Mermaid)

[](#er-mermaid)

 ```
erDiagram
  slr_projects ||--o{ slr_works : has
  slr_sources ||--o{ slr_raw_records : provides
  slr_projects ||--o{ slr_raw_records : collects
  slr_works ||--|| slr_enrichments : has
  slr_works ||--|| slr_criterion_scores : has
  slr_works ||--|| slr_composite_scores : has
  slr_works ||--o{ slr_screenings : reviewed_by
  slr_works ||--o{ slr_expert_reviews : adjusted_by
```

      Loading ---

Connectors
----------

[](#connectors)

Each connector is queued and writes **raw\_records** → normalization job → enrichment → scoring.

- **OpenAlex**: `/works` endpoint with cursor paging.
- **Crossref**: `/works` with query + filter (e.g., `type:journal-article`).
- **arXiv**: Atom feed (XML) paginated with `start`/`max_results`.
- **Semantic Scholar (S2)**: `/paper/search` offset/limit; optional DOI lookups for enrichment fallback.

**Project `search_strings` structure** (JSON):

```
{
  "openalex": { "q": "vision transformer agriculture", "filter": "from_publication_date:2023-01-01" },
  "crossref": { "q": "agriculture transformer", "filter": "type:journal-article,from-pub-date:2023-01-01" },
  "arxiv":    { "q": "ti:(agriculture) AND (cat:cs.CV OR cs.LG)" },
  "s2":       { "q": "agriculture transformer" }
}
```

> **Rate limits &amp; ToS:** Be polite; the package does not bypass rate limits. You are responsible for adhering to each source’s ToS.

---

Normalization &amp; Dedup
-------------------------

[](#normalization--dedup)

- **Precedence:** DOI &gt; OpenAlex &gt; Crossref &gt; arXiv &gt; S2 (field-by-field best-effort).
- **Title normalization:** lowercase, strip punctuation, collapse whitespace.
- **Fuzzy match:** token-set ratio ≥ **92** within **year ±1** to merge when DOI missing.
- **Provenance:** raw source preserved in `slr_raw_records` (replayable).

---

Enrichment
----------

[](#enrichment)

- **OA (Unpaywall):** `is_oa` + best OA URL (PDF or landing).
- **Code links:** detects GitHub/GitLab/Zenodo record URLs from title/abstract.
- **Data links:** detects Zenodo/Figshare/Dataverse from title/abstract.
- **Citations &amp; fields:** OpenAlex by ID; fallback to S2 by DOI if missing.

---

Scoring
-------

[](#scoring)

**Default weights** (configurable per project):

- Venue 0.30, Recency 0.15, OA/Repro 0.05, Novelty 0.20, Realism 0.20, Breadth 0.10

**Venue quality:**

- Journal (SJR): Q1=1.00, Q2=0.75, Q3=0.50, Q4=0.25 (fallback 0.40)
- Conference (CORE): A\*=1.00, A=0.85, B=0.65, C=0.45 (fallback 0.50)
- Preprint: 0.35
- Optional fallback: `min(0.6, citations_percentile)` within project if no SJR/CORE.

**Recency:** `exp(-ln(2) * Δt / H)` with **H = half-life years**.

**OA &amp; Reproducibility:** base **0.6** if OA +0.25 code +0.15 data (capped 1.0).

**Novelty / Realism / Breadth:** reviewer-provided 0..1 checklist scores (persisted in `criterion_scores`).

**Composite:** `100 * Σ (w_i * criterion_i)` stored with breakdown &amp; timestamp.

---

CLI Commands
------------

[](#cli-commands)

```
# 1) Publish config + migrations
php artisan slr:install

# 2) Run connectors (choose flags)
php artisan slr:run {project-uuid} --openalex --crossref --arxiv --s2

# 3) Recompute scores for all works in a project
php artisan slr:score {project-uuid}

# 4) Export bundle (JSON)
php artisan slr:export {project-uuid} --type=json --out=slr

# 5) Upload lookups
php artisan slr:upload-sjr  storage/app/sjr_snapshot.csv    # issn,quartile,snapshot_date
php artisan slr:upload-core storage/app/core_snapshot.csv   # conference,rank,snapshot_date
```

> Queues: jobs use queues `pull`, `normalize`, `enrich`, `score` (you can route these via Laravel’s queue config).

---

Quickstart
----------

[](#quickstart)

1. **Create a project** (via Tinker/Seeder):

```
use Illuminate\Support\Str;
use Mbsoft\SlrRanking\Models\Project;

$proj = Project::create([
  'id' => (string) Str::uuid(),
  'name' => 'Demo SLR',
  'objective' => 'custom',
  'weights' => config('slr-ranking.default_weights'),
  'search_strings' => [
    'openalex' => ['q' => 'vision transformer agriculture'],
    'crossref' => ['q' => 'agriculture transformer', 'filter' => 'type:journal-article,from-pub-date:2023-01-01'],
    'arxiv'    => ['q' => 'ti:(agriculture) AND (cat:cs.CV OR cs.LG)'],
    's2'       => ['q' => 'agriculture transformer']
  ],
  'inclusion_criteria' => [],
  'half_life' => 3
]);
$proj->id;
```

2. **Run pulls &amp; processing:**

```
php artisan slr:run {project-uuid} --openalex --crossref --arxiv --s2
php artisan slr:score {project-uuid}
```

3. **Export bundle:**

```
php artisan slr:export {project-uuid} --type=json --out=slr
# => storage/app/slr/{project-uuid}.json
```

---

Scheduling (optional)
---------------------

[](#scheduling-optional)

In your **app’s** `app/Console/Kernel.php`:

```
protected function schedule(Schedule $s): void {
    $s->command('slr:run YOUR-PROJECT-UUID --openalex --crossref')->dailyAt('01:30');
    $s->command('slr:score YOUR-PROJECT-UUID')->dailyAt('03:00');
}
```

---

Search Integration (optional)
-----------------------------

[](#search-integration-optional)

Enable Scout + Meilisearch in your app:

```
composer require laravel/scout meilisearch/meilisearch-php http-interop/http-factory-guzzle
```

Set `SLR_SEARCH=scout` and configure Scout as usual. **Note:** This package does not ship searchable repositories by default; you can call `Work::search($q)` if Scout is enabled and you add indexing calls in your app.

---

Testing
-------

[](#testing)

- Uses **Pest** + **Orchestra Testbench**.
- Run:

```
composer install
vendor/bin/pest
```

Write unit tests for:

- `NormalizationService` mappings (OpenAlex/Crossref/arXiv/S2)
- `DedupService` title/DOI logic
- `ScoreService` math &amp; edge cases
- Command smoke tests for `slr:run`, `slr:score`, `slr:export`

---

FAQ
---

[](#faq)

**Q: Does this store PDFs?**A: No. Only metadata + OA links. Respect publisher ToS.

**Q: Can I change weights or half-life later?**A: Yes—update the project record and re-run `slr:score`.

**Q: How do I add my own connector?**A: Implement `Contracts\Connector`, create a pull job, and register a facade accessor (copy the existing patterns).

---

Roadmap
-------

[](#roadmap)

- CSV &amp; Markdown exports (tables for works, scores, top-N, by-venue heatmap)
- Mermaid PRISMA diagram export
- Crossref abstract JATS parsing (sanitized plain text)
- Additional code/data link heuristics &amp; GitHub API probe (stars, license)
- Reviewer role policies (left to host app)

---

Contributing
------------

[](#contributing)

- Follow PSR-12, run Pest tests, and include fixtures for new connectors or mappings.
- Open a PR with a clear description and reproduction steps.

---

Security &amp; ToS
------------------

[](#security--tos)

- This package is **read-only** against public APIs; you are responsible for:

    - Obeying rate limits &amp; identifying with a valid **User-Agent** (set this in your app’s HTTP client if desired).
    - Complying with the **terms of service** of each data source.
- Report vulnerabilities via a private issue or email.

---

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance62

Regular maintenance activity

Popularity4

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 95.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~3 days

Total

3

Last Release

242d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/288f14daea877ea6b5b49d25bf1647f75eab2870b3e143e2a35b17a0666f1bd8?d=identicon)[mbsoft](/maintainers/mbsoft)

---

Top Contributors

[![mbsoft31](https://avatars.githubusercontent.com/u/14237661?v=4)](https://github.com/mbsoft31 "mbsoft31 (22 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

laravelmbsoft31slr-ranking

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/mbsoft31-slr-ranking/health.svg)

```
[![Health](https://phpackages.com/badges/mbsoft31-slr-ranking/health.svg)](https://phpackages.com/packages/mbsoft31-slr-ranking)
```

###  Alternatives

[vormkracht10/laravel-mails

Laravel Mails can collect everything you might want to track about the mails that has been sent by your Laravel app.

24149.7k](/packages/vormkracht10-laravel-mails)[spatie/laravel-prometheus

Export Laravel metrics to Prometheus

2651.3M6](/packages/spatie-laravel-prometheus)[hydrat/filament-table-layout-toggle

Filament plugin adding a toggle button to tables, allowing user to switch between Grid and Table layouts.

6292.3k1](/packages/hydrat-filament-table-layout-toggle)[scalar/laravel

Render your OpenAPI-based API reference

6183.9k2](/packages/scalar-laravel)[ralphjsmit/laravel-helpers

A package containing handy helpers for your Laravel-application.

13704.6k2](/packages/ralphjsmit-laravel-helpers)[musahmusah/laravel-multipayment-gateways

A Laravel Package that makes implementation of multiple payment Gateways endpoints and webhooks seamless

852.2k1](/packages/musahmusah-laravel-multipayment-gateways)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
