feat: copy questions from another form - #3636
Open
global-prog wants to merge 1 commit into
Open
Conversation
Rebuilding the same question set by hand for each new form is tedious, and the server already knew how to clone a question together with its options - it simply refused to do so across forms. That restriction is lifted for forms the user is allowed to EDIT. Simply dropping the same-form test would not have been safe: any question could then be read out of any form by guessing ids, so the source form is permission-checked. One bug had to be fixed for this to work at all: Question::read() carries the source question's formId, so a clone taken from another form would have been created back in that form rather than in the target one. The target id is now set explicitly. A dialog lists the forms the user can edit, then the questions of the chosen one, with select-all. Copies are made sequentially because each is appended at the end of the form, and issuing them in parallel would give an unpredictable resulting order. A partial failure reports that some questions were copied rather than implying none were. No schema change, and no change to the API surface: the existing fromId parameter and its documented behaviour are unchanged for same-form cloning. Signed-off-by: global-prog <raqeeb@uosamarra.edu.iq>
global-prog
force-pushed
the
contrib/import-questions
branch
from
September 9, 2026 00:58
0040fcd to
2ea0955
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Rebuilding the same set of questions by hand for every new form is tedious. The server already knows how to clone a question together with its options — it simply refuses to do so across forms.
This lifts that restriction for forms the user is allowed to edit, and adds a small dialog to pick them.
Why the restriction could not just be removed
Two things needed handling:
Permission. Dropping the same-form test alone would let any question be read out of any form by guessing ids, so the source form is now checked with
getFormIfAllowed($sourceFormId, PERMISSION_EDIT).A latent bug.
Question::read()includes the source question'sformId, and the clone path passes that straight intoQuestion::fromParams(). For same-form cloning that is harmless because the value matches; for a cross-form copy the new question would have been created back in the source form. The target id is now set explicitly.UI
A dialog lists the forms you can edit, then the questions of the chosen one, with select-all.
Copies are issued sequentially because each is appended at the end of the form — in parallel the resulting order would be unpredictable. If some copies succeed and one fails, the message says some were copied rather than implying none were.
Scope
fromIdparameter and its documented behaviour are unchanged for same-form cloning, soopenapi.jsonis unaffectedlib/Controller/ApiController.phpchanges by 10 insertions / 2 deletionsTesting
npm run lintandnpm run stylelintclean,php -lcleanmainwith no errorsHappy to drop the dialog and ship only the backend change if you would rather design the entry point differently.