Part of the 4.1 API Enablement milestone. Full plan: docs/plans/api-torrent-management.md. Depends on #62 (path-per-action structure).
Add a read endpoint returning every torrent — listed and unlisted, any owner — with swarm stats, the API analogue of the admin list in #56. API keys are operator-issued, so holders are trusted with the full list (per-key scopes are a deferred follow-up; note the disclosure in the endpoint docs).
Path
public/api/torrents.php → /api/torrents (GET; authenticated via api_authenticate_request()). torrents.php (file) and the torrent/ directory don't collide.
New model (shared with #56)
src/model/torrents.select.all.php → torrents_select_all() — copy of torrents_select_listed() (src/model/torrents.select.listed.php) with the WHERE t.listed = 1 clause removed and listed + user added to the SELECT/return shape. Reuse its LEFT JOIN peers ... GROUP BY and intval() normalisation idiom. This is the same model #56's admin list page needs — build once, reuse there.
Views
src/views/json.torrents.php / xml.torrents.php — collection views: {"torrents": [...]} / <torrents><torrent>...</torrent></torrents>, rows in the torrents_select_all() shape. Follow view_index_xml()'s xml_escape() usage for name and user.
Controller
src/controller/api.torrents.php → api_torrents_controller() — auth → torrents_select_all() → render JSON (default) or XML (?xml).
Tests
TorrentsSelectAllTest (seed __TEST_% rows incl. an unlisted one, clean in tearDown()), ApiTorrentsControllerTest, view tests for both collection views; extend the API smoke test to assert an added torrent appears in /api/torrents with its user and listed flag.
Part of the 4.1 API Enablement milestone. Full plan:
docs/plans/api-torrent-management.md. Depends on #62 (path-per-action structure).Add a read endpoint returning every torrent — listed and unlisted, any owner — with swarm stats, the API analogue of the admin list in #56. API keys are operator-issued, so holders are trusted with the full list (per-key scopes are a deferred follow-up; note the disclosure in the endpoint docs).
Path
public/api/torrents.php→/api/torrents(GET; authenticated viaapi_authenticate_request()).torrents.php(file) and thetorrent/directory don't collide.New model (shared with #56)
src/model/torrents.select.all.php→torrents_select_all()— copy oftorrents_select_listed()(src/model/torrents.select.listed.php) with theWHERE t.listed = 1clause removed andlisted+useradded to the SELECT/return shape. Reuse itsLEFT JOIN peers ... GROUP BYandintval()normalisation idiom. This is the same model #56's admin list page needs — build once, reuse there.Views
src/views/json.torrents.php/xml.torrents.php— collection views:{"torrents": [...]}/<torrents><torrent>...</torrent></torrents>, rows in thetorrents_select_all()shape. Followview_index_xml()'sxml_escape()usage fornameanduser.Controller
src/controller/api.torrents.php→api_torrents_controller()— auth →torrents_select_all()→ render JSON (default) or XML (?xml).Tests
TorrentsSelectAllTest(seed__TEST_%rows incl. an unlisted one, clean intearDown()),ApiTorrentsControllerTest, view tests for both collection views; extend the API smoke test to assert an added torrent appears in/api/torrentswith itsuserandlistedflag.