pushword/quiz
Composer 安装命令:
composer require pushword/quiz
包简介
Interactive client-side quizzes (QCM) for Pushword: a {{ quiz(...) }} Twig block, an EditorJS editor, anonymous percentile stats and an optional end-of-quiz conversion form.
README 文档
README
Interactive, (almost) server-less quizzes (QCM) for Pushword.
{% quiz %}{ …json… }{% endquiz %}block (recommended) — declare a quiz inline in a page. The JSON is the raw tag body, so apostrophes/quotes need no escaping and the payload stays readable/diffable. The legacy{{ quiz('…json…') }}function still works (there the JSON is a single-quoted Twig string, so literal'must be escaped as\'). A malformed quiz degrades gracefully (admins see a detailed error panel, visitors see nothing) instead of 500-ing the page — and a missing media file is skipped, not fatal.- EditorJS block — add/remove questions and answers, flag the correct answer(s), attach an image or a video, write the explanation.
pw:quiz:validate <file|->— lint quiz blocks in a flat file (or stdin) with precise{path, message}violations and a non-zero exit, for an edit→check loop without a server.pw:quiz:schemaprints the payload's JSON Schema.- Progressive enhancement — the full quiz is rendered server-side as a
readable, schema.org-tagged Q&A (great for SEO and no-JS);
quiz.jsturns it into a one-question-at-a-time game with immediate feedback and a score donut. - Anonymous percentile —
POST /quiz/resultstores a score (no PII) and returns "better than X% of participants". - Conversion form — set
ctato apushword/conversationform type to show a lead form at the end (pre-filled from a localStorage identity). Optional soft dependency. POST /api/quiz/validate— token-authenticated endpoint (for AI agents) that validates a quiz payload and returns precise{path, message}violations.GET /api/quiz/schemaserves the payload's JSON Schema.
Quiz JSON shape
{
"title": "Montagnes du monde",
"difficulty": "Facile",
"feedback": "immediate",
"cta": "newsletter",
"questions": [
{
"q": "Quel est le plus haut sommet du monde ?",
"media": "everest.jpg",
"alt": "Le mont Everest",
"answers": [
{ "a": "Mont Blanc" },
{ "a": "Everest", "correct": true },
{ "a": "K2" }
],
"explanation": "Le mont Everest culmine à 8 849 mètres."
}
],
"results": [
{ "min": 0, "msg": "À retravailler !" },
{ "min": 80, "msg": "Bravo !" }
]
}
A question may carry an image (media) or a video (video); a video reuses
the media image as its poster, so both media and an alt (accessibility)
are required for one. The single source of truth for validity is the Quiz
model + Symfony Validator, shared by the renderer, the editor lint and the API
endpoint.
Difficulty levels
Add a levels array to offer several difficulty levels behind an accessible tab
selector. Each entry is a full quiz (difficulty, questions, results, …);
the root keeps the shared metadata (title, labels). The tab label is
label ?? difficulty, and a level inherits the root's labels/feedback/
cta/pass when it omits its own.
{
"title": "Mountains",
"cta": "newsletter",
"pass": 50,
"levels": [
{ "difficulty": "Easy", "questions": [ … ], "results": [ … ] },
{ "difficulty": "Intermediate", "questions": [ … ] },
{ "difficulty": "Hard", "questions": [ … ] }
]
}
Tabs are freely clickable (WAI-ARIA: arrow keys, roving focus). Passing a level
(score ≥ its pass, default 50) reveals a "Next level →" button to the next
tab. Each level keeps its own percentile and lead attribution. A quiz
without levels renders exactly as before. In the EditorJS block, tick
"Multiple difficulty levels" to edit one sub-quiz per level.
Personality test (mode: profile)
Set "mode": "profile" to turn the same block into a personality test ("Which X
are you?"). There is no correct answer: each answer carries weights toward one
or more named profiles, and the highest-tallied profile is shown as a result
card (title + description + image). Backward compatible — a quiz without mode
behaves exactly as before.
{
"mode": "profile",
"title": "Which explorer are you?",
"profiles": [
{ "key": "sommet", "title": "The Summiteer", "msg": "Higher, always.", "media": "peak.jpg" },
{ "key": "calm", "title": "The Contemplative", "msg": "The mountain is your refuge." }
],
"questions": [
{
"q": "A free weekend, you…",
"answers": [
{ "a": "climb a peak", "weights": { "sommet": 2 } },
{ "a": "walk by a lake", "profile": "calm" }
]
}
],
"cta": "newsletter"
}
An answer weighs profiles with a weights map, or the profile: "key" shorthand
(== { "key": 1 }). The validator enforces at least one profile and that every
weight references a declared profile key (a typo would otherwise vote for
nothing). feedback is always end (no correct answer to reveal), levels are
not used, and no schema.org/Quiz markup is emitted (there is no accepted answer).
POST /quiz/result accepts { quiz, result } and returns { share } — "X% got
the same profile". Its knowledge-quiz and personality tallies stay separate even
under one page slug. In the EditorJS block, tick "Personality test" to swap the
correct-answer flag for per-answer profile weights and edit the profile cards.
pushword/quiz 适用场景与选型建议
pushword/quiz 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 187 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 06 月 10 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 pushword/quiz 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 pushword/quiz 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 pushword/quiz 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
This module allows drag & drop grouping of items in a GridField
Adds text size controls and text-to-speech controls to Flarum discussion content.
Native Blade date, datetime, and date range pickers.
Symfony and Flysystem integration for the maintained KCFinder continuation.
Laravel integration for the maintained KCFinder continuation.
PHPStan rules shared across KnpLabs organization projects
统计信息
- 总下载量: 187
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 41
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-10