Skip to content

Anonymous questions #542

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Jun 15, 2024
Merged

Anonymous questions #542

merged 31 commits into from
Jun 15, 2024

Conversation

viktorcsimma
Copy link
Contributor

@viktorcsimma viktorcsimma commented Jun 6, 2024

Description

Adds anonymous questions to evaluation forms, which can be managed by the Students' Council
and whose results can be exported into an Excel spreadsheet.

Related Issue

Closes #530.

Changes

  • The idea was reusing the Question class from general assemblies with a polymorphic parent relationship (thanks @kdmnk). Answers of an individual are stored under so-called "answer sheets", connected to question options and long answers, and also containing some information (for now, only the year of acceptance).
  • On a panel under Students' Council, authorized people (i.e. the president, the scientific vice president and the admins) can list the semesters, create new questions for a semester and export results.
  • Under the evaluation form, anonymous questions are the last point before setting the status. Here, the user can select their answers (there can also be ones with long, written answers) and save them. They cannot answer more than once, because the fact that they have voted does get recorded (similarly as in the voting system).

Note

It would be nice if we could merge it until Sunday; the form should be opened next week. Thanks in advance:) I will check out #532 until then.

@viktorcsimma viktorcsimma self-assigned this Jun 6, 2024
@viktorcsimma viktorcsimma requested a review from a team as a code owner June 6, 2024 12:12
Copy link
Contributor

coderabbitai bot commented Jun 6, 2024

Walkthrough

Walkthrough

The recent updates add anonymous question functionality to the evaluation forms. This includes new models, migrations, seeders, and views to handle anonymous questions, relationships between entities, and policies for authorisation. An AnonymousQuestionsExport allows exporting responses. Updated factories, locales, and tests ensure appropriate question handling and system integrity.

Changes

Files Change Summaries
app/Models/AnonymousQuestions/AnswerSheet.php Added methods for semesters, chosen options, long answers, and static creation methods, also a toArray() method.
app/Models/AnonymousQuestions/LongAnswer.php Defined relationships with answer sheets and questions, added fillable property and disabled timestamps.
app/Models/GeneralAssemblies/GeneralAssembly.php Changed questions() method to return MorphMany relationship.
app/Models/Question.php Added fillable property, disabled timestamps, various relationships, and methods for opening, closing, and validating questions.
app/Models/Semester.php Added relationships for numerous entities, methods to check closing status, and retrieve unanswered questions by a user.
app/Models/QuestionUser.php Moved model to the root namespace.
app/Policies/AnswerSheetPolicy.php Defined authorisation policies for anonymous questions.
app/Policies/QuestionPolicy.php Updated import statement for the Question model.
database/factories/QuestionFactory.php Changed namespace and model reference, added has_long_answers field in definition method.
database/factories/QuestionOptionFactory.php Updated namespace and model reference.
database/migrations/2023_01_18_201909_create_voting_tables.php Updated import statement for the Question model.
database/migrations/2024_06_01_173029_add_anonymous_questions_to... Introduced schema changes for adding anonymous questions.
database/seeders/AnonymousQuestionSeeder.php Added seeder class to populate database with anonymous questions, including different question types and user answers generation based on conditions.
database/seeders/DatabaseSeeder.php Added call to AnonymousQuestionSeeder.
database/seeders/GeneralAssemblySeeder.php Added has_long_answers attribute, modified vote casting to select random options.
resources/lang/en/anonymous_questions.php Added localisation strings for managing anonymous questions.
resources/views/layouts/navbar.blade.php Added nested @can directive for visibility of anonymous questions list item based on user permissions.
resources/views/livewire/excused-users.blade.php Updated Livewire component attribute from :allowEmpty to allowEmpty.
resources/views/livewire/parent-child-form.blade.php Added parent-child classes to input elements and buttons based on conditions.
resources/views/secretariat/evaluation-form/anonymous_questions... Presents a form for managing anonymous questions and answers without altering exported entities declarations.
resources/views/secretariat/evaluation-form/app.blade.php Updated to display anonymous questions instead of feedback, changing card title, ID, and partial view.
resources/views/student-council/anonymous-questions/create.blad... Introduced for creating anonymous questions within the student council module. Includes form elements for submitting questions.
resources/views/student-council/anonymous-questions/index_semest... New template to display semesters with associated questions and answer sheets dynamically, allows exporting and creating new questions.
resources/views/student-council/general-assemblies/questions/cre... Adjusted form action URLs and included partial views conditionally impacting form submission and UI elements without altering exported entities.
resources/views/student-council/general-assemblies/questions/sho... Updated references in view template for URLs and form actions related to general assemblies without altering exported entities.
tests/Unit/AnonymousQuestionTest.php Added various test cases for anonymous feedback questions, including different scenarios and question types to ensure system integrity.
app/Exports/UsersSheets/AnonymousQuestionsExport.php New class for exporting answers to anonymous questions, defining methods to fetch data, convert to arrays, and provide headings.

Sequence Diagram(s)

sequenceDiagram
    participant Student as Student
    participant App as Application
    participant Model as Model
    participant Database as Database
    Student->>App: Submit anonymous question form
    App->>Model: Save answers to AnswerSheet model
    Model->>Database: Store answers in anonymous_questions table
    Student->>App: Request list of anonymous questions
    App->>Database: Fetch questions based on semester
    Database->>App: Return list of questions
    App->>Student: Display list of questions for semester
Loading

Assessment against linked issues

Objective Addressed Explanation
Add new anonymous questions to the evaluation form (#530)
Ensure answers store year of admission and status

Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between d7c0ef0 and e0dabba.

Files selected for processing (2)
  • app/Exports/UsersSheets/AnonymousQuestionsExport.php (1 hunks)
  • app/Models/AnonymousQuestions/AnswerSheet.php (1 hunks)
Additional context used
Learnings (1)
Common learnings
User: viktorcsimma
PR: EotvosCollegium/mars#542
File: database/migrations/2024_06_01_173029_add_anonymous_questions_to_evaluation_form.php:14-22
Timestamp: 2024-06-14T11:03:09.230Z
Learning: User viktorcsimma confirmed that the inclusion of the `year_of_acceptance` column in the `answer_sheets` table does not affect anonymity and is considered safe following discussions.
Additional comments not posted (6)
app/Exports/UsersSheets/AnonymousQuestionsExport.php (3)

22-25: The constructor is appropriately set up to initialise the semester instance variable.


32-38: The use of inRandomOrder() to enhance anonymity in the data collection process is a prudent choice.


45-47: Ensure that the toArray() method in the AnswerSheet model does not expose any sensitive user information when used here.

Verification successful

The toArray method in the AnswerSheet model does not expose any sensitive information. It constructs an array with semester tags, year of acceptance, long answers, and chosen options, ensuring data privacy.

  • app/Models/AnonymousQuestions/AnswerSheet.php: Implementation of toArray method confirmed to handle data appropriately.
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the implementation of the `toArray()` method in the `AnswerSheet` model to ensure it handles data sensitively.
ast-grep --lang php --pattern $'class AnswerSheet {
  $$$
  public function toArray() {
    $$$
  }
  $$$  
}'

Length of output: 218



Script:

#!/bin/bash
# Description: Locate the implementation of the `toArray()` method in the `AnswerSheet` model using `rg`.
rg --multiline --multiline-dotall 'class AnswerSheet.*?{.*?public function toArray\(\).*?{.*?}' --glob '*.php'

Length of output: 275



Script:

#!/bin/bash
# Description: Locate the implementation of the `toArray()` method in the `AnswerSheet` model using `rg`.
rg --multiline --multiline-dotall 'class AnswerSheet\s*{[^}]*public function toArray\(\)\s*{[^}]*}' --glob '*.php'

Length of output: 283



Script:

#!/bin/bash
# Description: Locate the implementation of the `toArray()` method in the `AnswerSheet` model using `rg`.
rg 'class AnswerSheet' --files-with-matches --glob '*.php' | xargs rg 'public function toArray\(\)'

Length of output: 184



Script:

#!/bin/bash
# Description: Display the implementation of the `toArray()` method in the `AnswerSheet` model.
rg -A 10 'public function toArray\(\): array' app/Models/AnonymousQuestions/AnswerSheet.php

Length of output: 554



Script:

#!/bin/bash
# Description: Display the complete implementation of the `toArray()` method in the `AnswerSheet` model.
rg -A 20 'public function toArray\(\): array' app/Models/AnonymousQuestions/AnswerSheet.php

Length of output: 1048

app/Models/AnonymousQuestions/AnswerSheet.php (3)

24-30: Setting $timestamps to false is a thoughtful approach to enhance anonymity in the data model.


39-41: The relationships defined here are appropriate and follow standard Laravel practices.

Also applies to: 47-49, 55-57


96-117: Ensure that the toArray() method does not inadvertently expose sensitive data, especially given the model's use in exports.

Verification successful

The toArray() method in the AnswerSheet model constructs an array that includes the semester tag, year of acceptance, and answers to questions. Based on the retrieved code, it does not appear to expose sensitive data directly. However, it is crucial to ensure that no sensitive information is inadvertently included in the output.

  • Semester tag and year_of_acceptance are generally not considered sensitive data.
  • The method iterates over questions and gathers responses, ensuring that long answers, multiple-choice options, and other responses are correctly handled.

Given the current context, the method seems to handle data appropriately without exposing sensitive information.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the implementation of the `toArray()` method in the `AnswerSheet` model to ensure it handles data sensitively.
ast-grep --lang php --pattern $'class AnswerSheet {
  $$$
  public function toArray() {
    $$$
  }
  $$$  
}'

Length of output: 218



Script:

#!/bin/bash
# Description: Locate the `toArray()` method in the `AnswerSheet` model to ensure it handles data sensitively.
rg --pcre2 --multiline --multiline-dotall 'class AnswerSheet[\s\S]+?public function toArray\(\)[\s\S]+?\}' 

Length of output: 6670


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

deepsource-autofix bot added a commit that referenced this pull request Jun 6, 2024
This commit fixes the style issues introduced in 7728f1f according to the output
from PHP CS Fixer.

Details: #542
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between cedc643 and 29b3b42.

Files selected for processing (30)
  • app/Exports/UsersSheets/AnonymousQuestionsExport.php (1 hunks)
  • app/Http/Controllers/Secretariat/AnonymousQuestionController.php (1 hunks)
  • app/Http/Controllers/Secretariat/SemesterEvaluationController.php (3 hunks)
  • app/Http/Controllers/StudentsCouncil/GeneralAssemblyQuestionController.php (9 hunks)
  • app/Models/AnonymousQuestions/AnswerSheet.php (1 hunks)
  • app/Models/AnonymousQuestions/LongAnswer.php (1 hunks)
  • app/Models/GeneralAssemblies/GeneralAssembly.php (2 hunks)
  • app/Models/GeneralAssemblies/Question.php (8 hunks)
  • app/Models/Semester.php (4 hunks)
  • app/Policies/AnswerSheetPolicy.php (1 hunks)
  • database/factories/GeneralAssemblies/QuestionFactory.php (1 hunks)
  • database/migrations/2024_06_01_173029_add_anonymous_questions_to_evaluation_form.php (1 hunks)
  • database/seeders/AnonymousQuestionSeeder.php (1 hunks)
  • database/seeders/DatabaseSeeder.php (1 hunks)
  • database/seeders/GeneralAssemblySeeder.php (3 hunks)
  • resources/lang/en/anonymous_questions.php (1 hunks)
  • resources/lang/en/general.php (1 hunks)
  • resources/lang/hu/anonymous_questions.php (1 hunks)
  • resources/lang/hu/general.php (1 hunks)
  • resources/views/layouts/navbar.blade.php (1 hunks)
  • resources/views/livewire/excused-users.blade.php (1 hunks)
  • resources/views/livewire/parent-child-form.blade.php (1 hunks)
  • resources/views/secretariat/evaluation-form/anonymous_questions.blade.php (1 hunks)
  • resources/views/secretariat/evaluation-form/app.blade.php (1 hunks)
  • resources/views/secretariat/evaluation-form/index_semesters.blade.php (1 hunks)
  • resources/views/student-council/general-assemblies/questions/create.blade.php (3 hunks)
  • resources/views/student-council/general-assemblies/questions/show.blade.php (4 hunks)
  • routes/web.php (2 hunks)
  • tests/Unit/AnonymousQuestionTest.php (1 hunks)
  • tests/Unit/GeneralAssemblyTest.php (9 hunks)
Files skipped from review due to trivial changes (7)
  • resources/lang/en/anonymous_questions.php
  • resources/lang/en/general.php
  • resources/lang/hu/anonymous_questions.php
  • resources/lang/hu/general.php
  • resources/views/secretariat/evaluation-form/anonymous_questions.blade.php
  • resources/views/secretariat/evaluation-form/index_semesters.blade.php
  • resources/views/student-council/general-assemblies/questions/create.blade.php
Additional comments not posted (51)
app/Policies/AnswerSheetPolicy.php (1)

14-19: LGTM! The authorization logic correctly restricts access to functionalities related to anonymous questions.

database/seeders/DatabaseSeeder.php (1)

22-22: LGTM! The inclusion of AnonymousQuestionSeeder ensures that the database is populated with data necessary for anonymous questions.

database/factories/GeneralAssemblies/QuestionFactory.php (1)

27-27: LGTM! Setting has_long_answers to false ensures that the factory creates questions appropriate for general assemblies, aligning with the PR's focus on anonymous questions.

app/Models/AnonymousQuestions/LongAnswer.php (1)

26-32: LGTM! Disabling timestamps enhances anonymity, and the configuration of fillable attributes is appropriate for handling mass assignments in the context of anonymous questions.

resources/views/livewire/parent-child-form.blade.php (3)

21-21: LGTM! Ensure the new classes align with the intended CSS and JavaScript functionality.


27-27: LGTM! Ensure the new classes align with the intended CSS and JavaScript functionality.


29-29: LGTM! Ensure the new classes align with the intended CSS and JavaScript functionality.

database/seeders/GeneralAssemblySeeder.php (2)

26-26: LGTM! Ensure the has_long_answers attribute is correctly utilized in the application logic.

Also applies to: 43-43


67-67: LGTM! Ensure the new voting logic correctly handles multiple selections.

app/Models/AnonymousQuestions/AnswerSheet.php (3)

30-30: LGTM! The setting of timestamps to false enhances privacy.


65-74: LGTM! The createForUser method enhances code reusability and maintainability.


39-58: LGTM! The defined relationships support the new functionality of handling anonymous questions.

database/seeders/AnonymousQuestionSeeder.php (1)

19-50: LGTM! The seeder logic supports the new functionality of handling anonymous questions and their answers.

resources/views/livewire/excused-users.blade.php (1)

16-16: Corrected attribute syntax in Blade component.

This change corrects the attribute syntax from :allowEmpty to allowEmpty, ensuring consistency with Blade's expected syntax for non-expression attributes.

app/Exports/UsersSheets/AnonymousQuestionsExport.php (3)

22-25: Constructor correctly initializes the semester property.

The constructor is well-implemented, with clear documentation and appropriate initialization of the semester property.


42-64: Mapping function correctly handles different question types.

The map method is robust, handling both long answers and multiple choice questions efficiently. The logic is clear and well-documented.


70-77: Headings method correctly utilizes localization and dynamic question titles.

The headings method dynamically generates column titles based on the semester's questions, correctly utilizing localization for static fields. This enhances maintainability and user experience.

database/migrations/2024_06_01_173029_add_anonymous_questions_to_evaluation_form.php (3)

14-22: Creation of answer_sheets table is well-defined with appropriate foreign keys.

The answer_sheets table is correctly set up with necessary fields and foreign key constraints, ensuring data integrity.


24-34: Modifications to questions table support polymorphic relationships effectively.

The changes to the questions table, including the introduction of a polymorphic relationship and making parent_type non-nullable, are well-executed and enhance the model's flexibility.


45-54: Creation of long_answers table is well-defined with appropriate foreign keys.

The long_answers table is correctly set up with necessary fields and foreign key constraints, ensuring data integrity and appropriate links to questions and answer sheets.

tests/Unit/GeneralAssemblyTest.php (6)

30-30: Test method correctly uses updated model relationships.

The test method test_voting_on_closed_question correctly uses the parent relationship in the factory method, aligning with the updated model relationships.


47-47: Consistent use of updated model relationships in test method.

The test method test_voting_on_not_opened_question consistently uses the parent relationship, ensuring that the tests align with the updated model structure.


64-64: Correct implementation of model relationships in test for voting restrictions.

The test method test_voting_twice correctly uses the parent relationship, which is crucial for accurately simulating the voting scenario in the context of the updated model structure.


82-82: Proper use of model relationships in radio button voting test.

The test method test_voting_radio correctly uses the parent relationship and includes appropriate assertions to verify the behavior of radio button voting.


125-125: Correct model relationship usage in checkbox voting test.

The test method test_voting_checkbox correctly uses the parent relationship, ensuring accurate testing of checkbox voting functionality.


151-151: Consistent model relationship usage in test for checkbox voting limits.

The test method test_voting_checkbox_with_more_options consistently uses the parent relationship, accurately testing the limits of checkbox voting.

resources/views/student-council/general-assemblies/questions/show.blade.php (3)

5-5: Update breadcrumb links to reflect the new parent-child relationship.


17-17: Ensure the updated form action URLs correctly point to the new routes handling the parent-child relationship.

Also applies to: 101-101, 109-109

Verification successful

The routes for handling the parent-child relationship between general_assemblies and questions are correctly defined in the routes/web.php file. Here are the relevant routes:

  • Route::get('/general_assemblies/{general_assembly}/questions/create', [GeneralAssemblyQuestionController::class, 'create'])->name('general_assemblies.questions.create');
  • Route::post('/general_assemblies/{general_assembly}/questions', [GeneralAssemblyQuestionController::class, 'store'])->name('general_assemblies.questions.store');
  • Route::get('/general_assemblies/{general_assembly}/questions/{question}', [GeneralAssemblyQuestionController::class, 'show'])->name('general_assemblies.questions.show');
  • Route::post('/general_assemblies/{general_assembly}/questions/{question}/open', [GeneralAssemblyQuestionController::class, 'openQuestion'])->name('general_assemblies.questions.open');
  • Route::post('/general_assemblies/{general_assembly}/questions/{question}/close', [GeneralAssemblyQuestionController::class, 'closeQuestion'])->name('general_assemblies.questions.close');
  • Route::post('/general_assemblies/{general_assembly}/questions/{question}/votes', [GeneralAssemblyQuestionController::class, 'saveVote'])->name('general_assemblies.questions.votes.store')->withoutMiddleware(LogRequests::class);

These routes confirm that the form action URLs in the show.blade.php file are correctly pointing to the new routes handling the parent-child relationship.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the new routes are correctly defined in the routes file.

# Test: Search for the new routes in the routes file. Expect: Definitions for the new routes.
rg --type php $'route('general_assemblies.questions.*')' routes/web.php

Length of output: 70



Script:

#!/bin/bash
# Description: Verify the new routes are correctly defined in the routes file.

# Test: Search for general route definitions related to general_assemblies and questions.
rg --type php 'general_assemblies' routes/web.php
rg --type php 'questions' routes/web.php

Length of output: 4918


118-118: Validate the logic that prevents opening questions after the assembly has been closed.

Verification successful

The isOpen method in the GeneralAssembly model correctly checks if the assembly has been opened and not closed. This logic aligns with the conditional check in the show.blade.php file.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the logic that checks if the assembly is open before allowing questions to be opened.

# Test: Search for the method `isOpen` in the `GeneralAssembly` model. Expect: Correct implementation of the `isOpen` method.
ast-grep --lang php --pattern $'class GeneralAssembly {
  $$$
  isOpen($_) {
    $$$
  }
  $$$  
}'

Length of output: 207



Script:

#!/bin/bash
# Description: Verify the logic that checks if the assembly is open before allowing questions to be opened.

# Step 1: Find the `GeneralAssembly` model file.
general_assembly_file=$(fd GeneralAssembly.php)

# Step 2: Search for the `isOpen` method in the `GeneralAssembly` model.
if [[ -n "$general_assembly_file" ]]; then
  rg 'function isOpen' "$general_assembly_file"
else
  echo "GeneralAssembly model file not found."
fi

Length of output: 265



Script:

#!/bin/bash
# Description: Extract and display the implementation of the `isOpen` method in the `GeneralAssembly` model.

# Step 1: Find the `GeneralAssembly` model file.
general_assembly_file=$(fd GeneralAssembly.php)

# Step 2: Extract the implementation of the `isOpen` method.
if [[ -n "$general_assembly_file" ]]; then
  rg -A 10 'function isOpen' "$general_assembly_file"
else
  echo "GeneralAssembly model file not found."
fi

Length of output: 478

app/Http/Controllers/StudentsCouncil/GeneralAssemblyQuestionController.php (3)

7-7: Ensure the Question model is correctly utilized in the controller, especially with the new parent-child relationship.


183-183: Ensure the redirect after voting correctly uses the updated parent-child relationship.


103-103: Validate the conditions under which questions can be opened or closed, ensuring they align with the assembly's state.

Also applies to: 124-124

Verification successful

The isOpen and isClosed methods in the Question model are correctly implemented to check the conditions for opening and closing questions. The isOpen method ensures that a question is considered open if it has been opened and not closed, while the isClosed method checks if the question has a closed_at timestamp that is not null and is in the past.

  • isOpen method:

    public function isOpen(): bool
    {
        return
            $this->isForAssembly()
            ? ($this->hasBeenOpened() && !$this->isClosed())
            : !$this->parent->isClosed();
    }
  • isClosed method:

    public function isClosed(): bool
    {
        return
            $this->isForAssembly()
            ? ($this->closed_at != null && $this->closed_at <= now())
            : $this->parent->isClosed();
    }

These implementations align with the assembly's state and ensure that questions are managed correctly.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the conditions for opening and closing questions are correctly implemented.

# Test: Search for the methods `isOpen` and `isClosed` in the `Question` model. Expect: Correct implementation of these methods.
ast-grep --lang php --pattern $'class Question {
  $$$
  isOpen($_) {
    $$$
  }
  $$$
  isClosed($_) {
    $$$
  }
  $$$  
}'

Length of output: 235



Script:

#!/bin/bash
# Description: Verify the conditions for opening and closing questions are correctly implemented.

# Test: Search for the methods `isOpen` and `isClosed` in the `Question` model. Expect: Correct implementation of these methods.
rg 'function isOpen' --glob '**/Question.php'
rg 'function isClosed' --glob '**/Question.php'

Length of output: 253



Script:

#!/bin/bash
# Description: Extract the implementations of the `isOpen` and `isClosed` methods from the `Question` model.

# Extract the implementation of the `isOpen` method.
rg -A 10 'function isOpen' app/Models/GeneralAssemblies/Question.php

# Extract the implementation of the `isClosed` method.
rg -A 10 'function isClosed' app/Models/GeneralAssemblies/Question.php

Length of output: 720

app/Models/GeneralAssemblies/GeneralAssembly.php (1)

63-65: Update the questions relationship to use MorphMany to support the new polymorphic relationship.

tests/Unit/AnonymousQuestionTest.php (1)

1-206: Comprehensive test coverage for anonymous question functionality, including edge cases for closed semesters and multiple submissions.

app/Http/Controllers/Secretariat/AnonymousQuestionController.php (7)

32-34: Ensure proper authorization checks are in place for viewing semesters.


44-46: Handle attempts to add questions to closed semesters gracefully.


63-69: Validate input data rigorously to prevent invalid data submission.


83-88: Ensure that questions are created with correct attributes and timestamps.


111-113: Check if the question belongs to the correct semester to prevent data inconsistencies.


161-187: Ensure that answer sheets are created and stored correctly, handling all questions at once.


197-200: Facilitate the export of answer sheets to Excel, ensuring data privacy and integrity.

resources/views/secretariat/evaluation-form/app.blade.php (1)

147-150: Integrate the anonymous questions section into the evaluation form.

This change aligns with the PR objectives to include anonymous questions in the evaluation forms.

app/Http/Controllers/Secretariat/SemesterEvaluationController.php (1)

91-91: Update validation rules to include anonymous_questions in the section field.

This change is necessary to support the new functionality of handling anonymous questions within the evaluation forms.

app/Models/GeneralAssemblies/Question.php (4)

62-65: Ensure the parent relationship is polymorphic to support different types of parent entities.


88-91: Support long answers in questions when applicable.


219-255: Handle anonymous answers correctly, ensuring they are associated with the right question and answer sheet.


262-276: Create long answers for questions that accept them, ensuring data integrity.

app/Models/Semester.php (2)

173-173: The new relationships and methods are well-implemented and align with the PR objectives.

Also applies to: 181-181, 225-225, 230-230, 248-248, 257-257, 266-266


162-168: Ensure the isClosed method correctly handles time zones.

resources/views/layouts/navbar.blade.php (1)

119-129: The new navigation item for anonymous questions is correctly gated with permissions.

routes/web.php (1)

268-277: The new routes for handling anonymous questions are well-structured and follow RESTful conventions.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 29b3b42 and eb52d0b.

Files selected for processing (1)
  • app/Policies/AnswerSheetPolicy.php (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • app/Policies/AnswerSheetPolicy.php

@horcsinbalint
Copy link
Member

Thank you, I just quickly ran through the code, and the code quality seems to be quite nice.
Before checking the details of it, I would like to ask some questions to know to what is the exact goal that we want to achieve:

  • Have we got permission from the director that we effectively fire students if they don't answer the questions from the Student Council?
  • What does anonymous mean in this context? Does it mean that the Student Council cannot reconstruct who have submitted the answers for each question? Or does it mean that it is impossible to reconstruct this information from the database's nominal state after data collection has been stopped? (In case of Mr. & Miss, it is possible to get the votes using the database, but in the case of General Assemblies, it is impossible to pair the votes with the votee after the voting AFAIK.) I call the information which can be acquired with some SELECT queries from the tables that store the data the nominal state of the database.

viktorcsimma pushed a commit that referenced this pull request Jun 6, 2024
This commit fixes the style issues introduced in 7728f1f according to the output
from PHP CS Fixer.

Details: #542
@viktorcsimma viktorcsimma force-pushed the anonymous-questions branch from eb52d0b to 2c3892c Compare June 6, 2024 13:09
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between eb52d0b and fc5292f.

Files selected for processing (30)
  • app/Exports/UsersSheets/AnonymousQuestionsExport.php (1 hunks)
  • app/Http/Controllers/Secretariat/AnonymousQuestionController.php (1 hunks)
  • app/Http/Controllers/Secretariat/SemesterEvaluationController.php (4 hunks)
  • app/Http/Controllers/StudentsCouncil/GeneralAssemblyQuestionController.php (9 hunks)
  • app/Models/AnonymousQuestions/AnswerSheet.php (1 hunks)
  • app/Models/AnonymousQuestions/LongAnswer.php (1 hunks)
  • app/Models/GeneralAssemblies/GeneralAssembly.php (2 hunks)
  • app/Models/GeneralAssemblies/Question.php (8 hunks)
  • app/Models/Semester.php (4 hunks)
  • app/Policies/AnswerSheetPolicy.php (1 hunks)
  • database/factories/GeneralAssemblies/QuestionFactory.php (1 hunks)
  • database/migrations/2024_06_01_173029_add_anonymous_questions_to_evaluation_form.php (1 hunks)
  • database/seeders/AnonymousQuestionSeeder.php (1 hunks)
  • database/seeders/DatabaseSeeder.php (1 hunks)
  • database/seeders/GeneralAssemblySeeder.php (3 hunks)
  • resources/lang/en/anonymous_questions.php (1 hunks)
  • resources/lang/en/general.php (1 hunks)
  • resources/lang/hu/anonymous_questions.php (1 hunks)
  • resources/lang/hu/general.php (1 hunks)
  • resources/views/layouts/navbar.blade.php (1 hunks)
  • resources/views/livewire/excused-users.blade.php (1 hunks)
  • resources/views/livewire/parent-child-form.blade.php (1 hunks)
  • resources/views/secretariat/evaluation-form/anonymous_questions.blade.php (1 hunks)
  • resources/views/secretariat/evaluation-form/app.blade.php (1 hunks)
  • resources/views/secretariat/evaluation-form/index_semesters.blade.php (1 hunks)
  • resources/views/student-council/general-assemblies/questions/create.blade.php (3 hunks)
  • resources/views/student-council/general-assemblies/questions/show.blade.php (4 hunks)
  • routes/web.php (2 hunks)
  • tests/Unit/AnonymousQuestionTest.php (1 hunks)
  • tests/Unit/GeneralAssemblyTest.php (9 hunks)
Files skipped from review as they are similar to previous changes (29)
  • app/Exports/UsersSheets/AnonymousQuestionsExport.php
  • app/Http/Controllers/Secretariat/AnonymousQuestionController.php
  • app/Http/Controllers/Secretariat/SemesterEvaluationController.php
  • app/Http/Controllers/StudentsCouncil/GeneralAssemblyQuestionController.php
  • app/Models/AnonymousQuestions/AnswerSheet.php
  • app/Models/AnonymousQuestions/LongAnswer.php
  • app/Models/GeneralAssemblies/GeneralAssembly.php
  • app/Models/Semester.php
  • app/Policies/AnswerSheetPolicy.php
  • database/factories/GeneralAssemblies/QuestionFactory.php
  • database/migrations/2024_06_01_173029_add_anonymous_questions_to_evaluation_form.php
  • database/seeders/AnonymousQuestionSeeder.php
  • database/seeders/DatabaseSeeder.php
  • database/seeders/GeneralAssemblySeeder.php
  • resources/lang/en/anonymous_questions.php
  • resources/lang/en/general.php
  • resources/lang/hu/anonymous_questions.php
  • resources/lang/hu/general.php
  • resources/views/layouts/navbar.blade.php
  • resources/views/livewire/excused-users.blade.php
  • resources/views/livewire/parent-child-form.blade.php
  • resources/views/secretariat/evaluation-form/anonymous_questions.blade.php
  • resources/views/secretariat/evaluation-form/app.blade.php
  • resources/views/secretariat/evaluation-form/index_semesters.blade.php
  • resources/views/student-council/general-assemblies/questions/create.blade.php
  • resources/views/student-council/general-assemblies/questions/show.blade.php
  • routes/web.php
  • tests/Unit/AnonymousQuestionTest.php
  • tests/Unit/GeneralAssemblyTest.php
Additional comments not posted (9)
app/Models/GeneralAssemblies/Question.php (9)

12-12: Ensure the MorphTo import is utilized effectively in the model.


17-18: Addition of AnswerSheet and LongAnswer models supports the new functionality for anonymous questions.


32-32: Update the @property-read annotation to reflect the polymorphic relationship.


62-65: The parent() method correctly implements a polymorphic relationship, which is crucial for associating questions with either a general assembly or a semester.


71-73: The method isForAssembly() provides a clear way to check the type of the parent model. This is useful for conditional logic based on the parent type.
[APROVED]


106-108: The methods hasBeenOpened(), isOpen(), and isClosed() use the new polymorphic relationship to determine the state of the question based on its parent. This is a critical change for the functionality of these methods.

Also applies to: 116-119, 127-130


88-91: The longAnswers() method correctly defines a HasMany relationship. Ensure that the LongAnswer model is properly set up to handle this relationship.

Verification successful

The LongAnswer model includes BelongsTo relationships for answerSheet and question, but it does not define any HasMany relationships. This setup is sufficient for the Question model to have a HasMany relationship with LongAnswer.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the setup of the `LongAnswer` model to ensure it supports the `HasMany` relationship.

# Test: Search for the `LongAnswer` model definition. Expect: Proper relationship methods and properties.
rg --type php 'class LongAnswer' -A 20

Length of output: 1366



Script:

#!/bin/bash
# Description: Verify the setup of the `LongAnswer` model to ensure it supports the `HasMany` relationship.

# Test: Search for relationship methods within the `LongAnswer` model file.
rg --type php 'function ' app/Models/AnonymousQuestions/LongAnswer.php

Length of output: 159


262-276: The giveLongAnswer() method correctly handles the creation of long answers. Ensure that the has_long_answers property is properly managed and that the LongAnswer model supports this functionality.

Verification successful

The has_long_answers property is properly managed across the codebase, including its definition in the Question model, its addition in migrations, and its usage in controllers for validation and creation of questions. The LongAnswer model is also correctly set up and supports the required functionality, with appropriate relationships to the Question and AnswerSheet models.

  • The has_long_answers property is defined in the Question model and used in various parts of the codebase, including views, seeders, migrations, factories, and controllers.
  • The LongAnswer model is properly set up with necessary relationships and properties, and it is used in the Question and AnswerSheet models.
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the management of the `has_long_answers` property and the support in the `LongAnswer` model.

# Test: Search for the `has_long_answers` property usage and the `LongAnswer` model setup. Expect: Proper management and support.
rg --type php -e 'has_long_answers' -e 'LongAnswer' -C 10

Length of output: 47176


53-53: Ensure all newly added fields in $fillable are intended to be mass assignable.

Verification successful

The searches did not reveal any dynamic modifications to the $fillable array or any mass assignment methods involving the Question model. This suggests that the fields in $fillable are not being used in a way that could lead to security vulnerabilities.

  • The $fillable array in the Question model is defined as:

    protected $fillable = ['title', 'sitting_id', 'max_options', 'opened_at', 'closed_at', 'has_long_answers'];
  • No instances of Question::create(, Question::update(, Question::fill(, or Question::updateOrCreate( were found in the codebase.

  • No dynamic modifications to the $fillable array were detected.

Based on this information, it appears that the fields in $fillable are intended to be mass assignable and are used appropriately.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that all fields in `$fillable` are safe for mass assignment and are used appropriately in the application.

# Test: Search for usages of mass assignment in the application. Expect: Safe usage of mass assignment.
rg --type php 'new Question\('

Length of output: 32



Script:

#!/bin/bash
# Description: Verify that all fields in `$fillable` are safe for mass assignment and are used appropriately in the application.

# Test: Search for usages of mass assignment in the application. Expect: Safe usage of mass assignment.
rg --type php 'Question::create\('
rg --type php 'Question::update\('

Length of output: 73



Script:

#!/bin/bash
# Description: Verify that all fields in `$fillable` are safe for mass assignment and are used appropriately in the application.

# Test: Search for usages of mass assignment in the application. Expect: Safe usage of mass assignment.
rg --type php 'Question::fill\('
rg --type php 'Question::updateOrCreate\('

Length of output: 79



Script:

#!/bin/bash
# Description: Verify that the `$fillable` array in the `Question` model is not being modified dynamically elsewhere in the codebase.

# Test: Search for any direct assignments to the `fillable` array in the `Question` model.
rg --type php '\$fillable\s*='

# Test: Ensure that the `fillable` array is not being modified dynamically elsewhere in the codebase.
rg --type php 'Question::\$fillable'

Length of output: 2937

@@ -106,7 +136,7 @@ public function isClosed(): bool
*/
public function open(): void
{
if (!$this->generalAssembly->isOpen()) {
if (!$this->parent->isOpen()) {
Copy link
Contributor

@coderabbitai coderabbitai bot Jun 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

The output from the shell script indicates that the giveAnonymousAnswer() method is called in the app/Http/Controllers/Secretariat/AnonymousQuestionController.php file without explicit exception handling. This confirms that there is a potential issue with exception handling in this specific instance.

To address this, the giveAnonymousAnswer() method calls should be wrapped in try-catch blocks to ensure that any exceptions thrown are properly handled.

Locations that need attention:

  • app/Http/Controllers/Secretariat/AnonymousQuestionController.php

Suggested Action:

Wrap the giveAnonymousAnswer() method calls in try-catch blocks to handle exceptions appropriately.

try {
    $question->giveAnonymousAnswer(user(), $answerSheet, $options);
} catch (\Exception $e) {
    // Handle the exception, e.g., log the error, return an error response, etc.
    return back()->withErrors(['error' => $e->getMessage()]);
}

try {
    $question->giveAnonymousAnswer(user(), $answerSheet, $option);
} catch (\Exception $e) {
    // Handle the exception, e.g., log the error, return an error response, etc.
    return back()->withErrors(['error' => $e->getMessage()]);
}

This ensures that any exceptions thrown by the giveAnonymousAnswer() method are caught and handled appropriately, preventing potential issues during execution.

Analysis chain

Exception handling in the open(), vote(), and giveAnonymousAnswer() methods should be reviewed to ensure that they are thrown appropriately and can be caught or handled where these methods are called.

Also applies to: 187-187, 219-219


The output from the shell script shows that the methods open(), vote(), and giveAnonymousAnswer() are called in various test and controller files. In the test files, exceptions are expected and asserted using $this->expectException(\Exception::class);. In the controller files, exceptions are handled using abort() with appropriate HTTP status codes.

Here are the locations where these methods are called and their exception handling mechanisms:

  • Test Files:

    • tests/Unit/AnonymousQuestionTest.php
    • tests/Unit/GeneralAssemblyTest.php
    • Exceptions are asserted using $this->expectException(\Exception::class);.
  • Controller Files:

    • app/Http/Controllers/StudentsCouncil/GeneralAssemblyQuestionController.php
      • open(): Handled using abort(403, "tried to open a question when the sitting itself was not open"); and abort(403, "tried to open a question which has already been opened");.
      • vote(): Handled using abort(401, "Tried to vote for an option which does not belong to the question");.
    • app/Http/Controllers/Secretariat/AnonymousQuestionController.php
      • giveAnonymousAnswer(): No explicit exception handling observed in the provided snippet.

Given this information, it appears that most instances have proper exception handling. However, the giveAnonymousAnswer() method in app/Http/Controllers/Secretariat/AnonymousQuestionController.php lacks explicit exception handling in the provided snippet.

To ensure comprehensive verification, let's generate a script to search for all instances of giveAnonymousAnswer() in the app/Http/Controllers/Secretariat/AnonymousQuestionController.php file and check for exception handling.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that exceptions thrown in these methods are handled appropriately in the calling code.

# Test: Search for usages of these methods and check for exception handling. Expect: Proper try-catch blocks or error handling mechanisms.
rg --type php -e 'open\(' -e 'vote\(' -e 'giveAnonymousAnswer\(' -C 10

Length of output: 48820



Script:

#!/bin/bash
# Description: Verify exception handling for giveAnonymousAnswer() in app/Http/Controllers/Secretariat/AnonymousQuestionController.php

# Search for all instances of giveAnonymousAnswer() in the specified controller file and check for exception handling.
rg 'giveAnonymousAnswer\(' -C 10 app/Http/Controllers/Secretariat/AnonymousQuestionController.php

Length of output: 1088

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add check in the parent

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kdmnk, could you please clarify what specific check you would like to add in the parent within the open() method? Are you referring to additional conditions to verify before a question can be opened, or is there a particular validation concerning the state or attributes of the parent entity? Any additional details would help ensure the implementation aligns with your expectations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is meant to be for @viktorcsimma

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kdmnk I don't understand this one; are you proposing to remove that check? Or moving it to the controller?

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between fc5292f and e73036e.

Files selected for processing (1)
  • database/seeders/AnonymousQuestionSeeder.php (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • database/seeders/AnonymousQuestionSeeder.php

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between e73036e and 41b8c87.

Files selected for processing (1)
  • app/Policies/AnswerSheetPolicy.php (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • app/Policies/AnswerSheetPolicy.php

@viktorcsimma
Copy link
Contributor Author

@horcsinbalint thanks for checking it out so quickly:)

  • The first one is probably not going to happen; I think it's going to be fine this way (every question will include an option like "I don't want to answer").
  • For the second one: the goal is that no one be able to connect these answers to people (including admins). I don't know whether the logging feature which has caused problems at voting means an obstacle here. Another point is that if there is a year from which only one student has remained (there is one now), they obviously can be tracked.

@horcsinbalint
Copy link
Member

@viktorcsimma

The first one is probably not going to happen; I think it's going to be fine this way (every question will include an option like "I don't want to answer").

I have concerns with making it mandatory to answer anything on these (even if there is an option of "I don't want to answer").

I think I might have spotted some bugs in the code. But as I have major concerns with the planned functionality proposed in this PR, I am unable to process the PR further. Unfortunately, the automatic deployment is not working and I will have to manually sign these changes off. Is it okay with you if I consult with the Ethics Commissioners to put my worries to rest? If there are no issues with the proposed functionality, it should not be a problem. But if they share my concerns, it is much better to resolve the problems before I deploy these changes.

@viktorcsimma
Copy link
Contributor Author

viktorcsimma commented Jun 6, 2024

Huh; the problem is that it would be needed ASAP… what if I took personal responsibility for it? Or if we looked for someone else to approve it? @kdmnk?

@horcsinbalint
Copy link
Member

Okay, I can parallelize processing this issue and discussing my concerns with the Ethics Commissioners if it is okay with you.

@viktorcsimma
Copy link
Contributor Author

OK, thank you:)

@horcsinbalint
Copy link
Member

Wait, is it mandatory to answer anonymous questions? If not, then I have no big concerns

Copy link
Member

@horcsinbalint horcsinbalint left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have found some ways of breaking the anonymity. I have not checked the PR in details, so others should also check the PR

viktorcsimma pushed a commit that referenced this pull request Jun 9, 2024
This commit fixes the style issues introduced in 7728f1f according to the output
from PHP CS Fixer.

Details: #542
@viktorcsimma viktorcsimma force-pushed the anonymous-questions branch from 4aced75 to dccec31 Compare June 9, 2024 17:09
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 41b8c87 and dccec31.

Files selected for processing (30)
  • app/Exports/UsersSheets/AnonymousQuestionsExport.php (1 hunks)
  • app/Http/Controllers/Secretariat/AnonymousQuestionController.php (1 hunks)
  • app/Http/Controllers/Secretariat/SemesterEvaluationController.php (3 hunks)
  • app/Http/Controllers/StudentsCouncil/GeneralAssemblyQuestionController.php (9 hunks)
  • app/Models/AnonymousQuestions/AnswerSheet.php (1 hunks)
  • app/Models/AnonymousQuestions/LongAnswer.php (1 hunks)
  • app/Models/GeneralAssemblies/GeneralAssembly.php (2 hunks)
  • app/Models/GeneralAssemblies/Question.php (8 hunks)
  • app/Models/Semester.php (4 hunks)
  • app/Policies/AnswerSheetPolicy.php (1 hunks)
  • database/factories/GeneralAssemblies/QuestionFactory.php (1 hunks)
  • database/migrations/2024_06_01_173029_add_anonymous_questions_to_evaluation_form.php (1 hunks)
  • database/seeders/AnonymousQuestionSeeder.php (1 hunks)
  • database/seeders/DatabaseSeeder.php (1 hunks)
  • database/seeders/GeneralAssemblySeeder.php (3 hunks)
  • resources/lang/en/anonymous_questions.php (1 hunks)
  • resources/lang/en/general.php (1 hunks)
  • resources/lang/hu/anonymous_questions.php (1 hunks)
  • resources/lang/hu/general.php (1 hunks)
  • resources/views/layouts/navbar.blade.php (1 hunks)
  • resources/views/livewire/excused-users.blade.php (1 hunks)
  • resources/views/livewire/parent-child-form.blade.php (1 hunks)
  • resources/views/secretariat/evaluation-form/anonymous_questions.blade.php (1 hunks)
  • resources/views/secretariat/evaluation-form/app.blade.php (1 hunks)
  • resources/views/secretariat/evaluation-form/index_semesters.blade.php (1 hunks)
  • resources/views/student-council/general-assemblies/questions/create.blade.php (3 hunks)
  • resources/views/student-council/general-assemblies/questions/show.blade.php (4 hunks)
  • routes/web.php (2 hunks)
  • tests/Unit/AnonymousQuestionTest.php (1 hunks)
  • tests/Unit/GeneralAssemblyTest.php (9 hunks)
Files skipped from review as they are similar to previous changes (30)
  • app/Exports/UsersSheets/AnonymousQuestionsExport.php
  • app/Http/Controllers/Secretariat/AnonymousQuestionController.php
  • app/Http/Controllers/Secretariat/SemesterEvaluationController.php
  • app/Http/Controllers/StudentsCouncil/GeneralAssemblyQuestionController.php
  • app/Models/AnonymousQuestions/AnswerSheet.php
  • app/Models/AnonymousQuestions/LongAnswer.php
  • app/Models/GeneralAssemblies/GeneralAssembly.php
  • app/Models/GeneralAssemblies/Question.php
  • app/Models/Semester.php
  • app/Policies/AnswerSheetPolicy.php
  • database/factories/GeneralAssemblies/QuestionFactory.php
  • database/migrations/2024_06_01_173029_add_anonymous_questions_to_evaluation_form.php
  • database/seeders/AnonymousQuestionSeeder.php
  • database/seeders/DatabaseSeeder.php
  • database/seeders/GeneralAssemblySeeder.php
  • resources/lang/en/anonymous_questions.php
  • resources/lang/en/general.php
  • resources/lang/hu/anonymous_questions.php
  • resources/lang/hu/general.php
  • resources/views/layouts/navbar.blade.php
  • resources/views/livewire/excused-users.blade.php
  • resources/views/livewire/parent-child-form.blade.php
  • resources/views/secretariat/evaluation-form/anonymous_questions.blade.php
  • resources/views/secretariat/evaluation-form/app.blade.php
  • resources/views/secretariat/evaluation-form/index_semesters.blade.php
  • resources/views/student-council/general-assemblies/questions/create.blade.php
  • resources/views/student-council/general-assemblies/questions/show.blade.php
  • routes/web.php
  • tests/Unit/AnonymousQuestionTest.php
  • tests/Unit/GeneralAssemblyTest.php

deepsource-autofix bot added a commit that referenced this pull request Jun 9, 2024
This commit fixes the style issues introduced in 6e2dec4 according to the output
from PHP CS Fixer.

Details: #542
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between dccec31 and 1d0bcd6.

Files selected for processing (1)
  • tests/Unit/AnonymousQuestionTest.php (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • tests/Unit/AnonymousQuestionTest.php

@viktorcsimma
Copy link
Contributor Author

viktorcsimma commented Jun 9, 2024

Wait, is it mandatory to answer anonymous questions? If not, then I have no big concerns

Now, it's not technically mandatory to fill them; my personal opinion is that we need not explicitly tell fillers about it, as they otherwise won't fill:D But could you talk to the Ethics Commissioners since then?

I have found some ways of breaking the anonymity. I have not checked the PR in details, so others should also check the PR

Is there anyone here who could check this out ASAP? (I know, I was slow in responding to requests; sorry)

@viktorcsimma viktorcsimma requested a review from kdmnk June 9, 2024 17:40
@horcsinbalint
Copy link
Member

Now, it's not technically mandatory to fill them; my personal opinion is that we need not explicitly tell fillers about it, as they otherwise won't fill:D But could you talk to the Ethics Commissioners since then?

I will respond to the other thread soon which probably needs to be addressed.
As it has been discussed privately, I did not escalate this issue to the Ethics Commissioners, as I don't think that I would violate ethical norms by deploying this.

@viktorcsimma
Copy link
Contributor Author

OK; thank you:)

Copy link
Contributor

@kdmnk kdmnk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, that's nice job. This is a complex problem so I added a lot of comments related how I think the morph relation should work. 2 reasons: without proper abstrabtion levels, it's just simpler to make another, similar module without combining them; this will also enable us to add anonym questions for other modules (eg. mr and miss).
Read through them and let me know if something is not clear.

@kdmnk
Copy link
Contributor

kdmnk commented Jun 12, 2024

Now, it's not technically mandatory to fill them; my personal opinion is that we need not explicitly tell fillers about it, as they otherwise won't fill:D But could you talk to the Ethics Commissioners since then?

I will respond to the other thread soon which probably needs to be addressed. As it has been discussed privately, I did not escalate this issue to the Ethics Commissioners, as I don't think that I would violate ethical norms by deploying this.

About these, if the user does not fill something in, you can still store an empty string or zero voted options in the database to mark the question as filled if you need to.
I also vote for not forcing users to answer about feedback.

@viktorcsimma
Copy link
Contributor Author

Okay; it seems to work now. (For some reason, it was only stable if I used the DB facade directly instead of Eloquent operations. I still don't know what happened, but I'm glad I could find a workaround:D)

If you agree to the others, I think there is only one thing left; this conversation.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

'title' => $request->title,
'max_options' => $hasLongAnswers ? 0 : $request->max_options,
'has_long_answers' => $hasLongAnswers,
'opened_at' => (app(SemesterEvaluationController::class))->getStartDate() ?? Carbon::now(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't the solution I suggested to add HasPeriodicEvents here work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it does:) What about adding a periodicEventForSemester method so that we can access the event for the correct semester? I've tried that; it seems to work for me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not really make sense. We have one periodicEvent which might belong to the semester you are looking for or not. The attached semester to the periodicEvent is only there to fix the semester used by the context. You should set the semester id of the feedback based on that, if you don't have that yet.

Copy link
Contributor

@kdmnk kdmnk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks better! And also I don't really have more time to review. Good for now if the leftover comments are resolved

@kdmnk
Copy link
Contributor

kdmnk commented Jun 14, 2024

And good job on the tests!

@kdmnk
Copy link
Contributor

kdmnk commented Jun 14, 2024

Okay; it seems to work now. (For some reason, it was only stable if I used the DB facade directly instead of Eloquent operations. I still don't know what happened, but I'm glad I could find a workaround:D)

if you want, I can take a look tomorrow

viktorcsimma and others added 3 commits June 14, 2024 12:31
This commit fixes the style issues introduced in 637cdf7 according to the output
from PHP CS Fixer.

Details: #542
Comment on lines 47 to 61
/**
* Get the PeriodicEvent connected to the controller
* and belonging to the given semester
* (by default the current one).
*
* @return PeriodicEvent|null
*/
final public function periodicEventForSemester(?Semester $semester): ?PeriodicEvent
{
if (is_null($semester)) $semester = Semester::current();
return PeriodicEvent::where('event_model', $this->underlyingControllerName)
->where('semester_id', $semester->id)
->first();
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kdmnk that's what I thought of. And we call this method with the semester for which we are creating the question. And if that semester is in the future, this will return null, and the question will not be opened.

Copy link
Contributor

@kdmnk kdmnk Jun 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't give you any data for older semesters.
The information flow should be: you get/set the periodicEvent, and through that, you get the semester that you can use.

When you create a questions, you store them with the semester you get from the current periodicEvent.
Afterwards, you can still query older questions by directly using the semester ids, without the periodicEvent as it might have been updated for a new voting period.

Copy link
Contributor Author

@viktorcsimma viktorcsimma Jun 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh; so those are only there for querying older ones... Maybe the easiest way for now would be to only allow admins to add questions for the current semester. (They probably won't want to do so for future semesters anyway.)

Let me know what you think. If you agree, I'll proceed with that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well if you need this asap I think go back to the embedded google forms :D

We could try to release it, but I'm trying not to release half done features anymore. I will have time during the weekend to have a deeper look again and give some solutions for our uncertainties. (Currently the morph relation's complexity overcomes its advantages, but I have to take another look).

Again, after the previous years of experience, our priority here is to produce software that is easily maintainable and understandable, which is more important to me than releasing new features.
After the discussions, I might also need to go back to the PeriodicEvents as I can see it is not clearly understandable and does not really cover this case.

What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also understand if you want to release this and will go back to it afterwards if you are confident about the current solution's behaviour.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also understand if you want to release this and will go back to it afterwards if you are confident about the current solution's behaviour.

Yes, that would be the best for me now:) and after the form gets closed, we can open a new issue for it. I think I can work on this more on July.

Thank you 😊

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I advise against deploying changes in the codebase that are not sure to be correct. I also have a problem on an operational standpoint as in June there will not be enough human resources to restore a backup if that is needed due to a mistake presented in the newly deployed code. But I will deploy the changes if someone takes the responsibility even though I would not recommend it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay; I think I've played with it long enough to say it's going to be alright. So I'll take the blame if something happens.

@viktorcsimma
Copy link
Contributor Author

Okay; it seems to work now. (For some reason, it was only stable if I used the DB facade directly instead of Eloquent operations. I still don't know what happened, but I'm glad I could find a workaround:D)

if you want, I can take a look tomorrow

Thank you:) but it's not important for now; the priority would be to deploy this as soon as possible.

@horcsinbalint
Copy link
Member

Thank you:) but it's not important for now; the priority would be to deploy this as soon as possible.

Is this test finished on the staging system? #532 (comment)

@viktorcsimma
Copy link
Contributor Author

Thank you:) but it's not important for now; the priority would be to deploy this as soon as possible.

Is this test finished on the staging system? #532 (comment)

Yes; it was quite a long saga, but in the end, it got merged to development. I think you have also tested it; see #547.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Outside diff range and nitpick comments (1)
app/Utils/HasPeriodicEvent.php (1)

Line range hint 35-62: The methods periodicEvent and periodicEventForSemester seem well-implemented. However, consider adding error handling or logging to manage cases where the database queries fail or return unexpected results.

+ try {
+     // Existing code
+ } catch (\Exception $e) {
+     \Log::error("Failed to retrieve periodic event: " . $e->getMessage());
+     return null;
+ }

@horcsinbalint
Copy link
Member

Thank you:) but it's not important for now; the priority would be to deploy this as soon as possible.

Is this test finished on the staging system? #532 (comment)

Yes; it was quite a long saga, but in the end, it got merged to development. I think you have also tested it; see #547.

It was requested from me to deploy it to staging #532 (comment) :

@horcsinbalint please let me know when can I test it on the test server, if that's available

I have deployed the changes to the staging server and sent credentials privately. #543 and #548 are quite big and I have not received confirmation whether it works with live data and if it is safe to deploy on the live environment.

@horcsinbalint
Copy link
Member

Or at least I have not tested it (other than logging into it and catching #544). But I have no idea if the code is fit for production.

@kdmnk
Copy link
Contributor

kdmnk commented Jun 14, 2024

@horcsinbalint please keep the chat here only for the PR and code related messages, it is already quite hectic.

@horcsinbalint horcsinbalint dismissed their stale review June 14, 2024 11:20

Does not address recent changes

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Comment on lines +65 to +77
public static function createForUser(User $user, Semester $semester = null): AnswerSheet
{
if (is_null($user)) {
$user = user();
}
if (is_null($semester)) {
$semester = Semester::current();
}

return $semester->answerSheets()->create([
'year_of_acceptance' => $user->educationalInformation->year_of_acceptance
]);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method handles null users and semesters effectively. Consider adding a comment to clarify that a null user defaults to the current authenticated user.

- if (is_null($user)) {
+ // Default to the current authenticated user if none is provided
+ if (is_null($user)) {
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static function createForUser(User $user, Semester $semester = null): AnswerSheet
{
if (is_null($user)) {
$user = user();
}
if (is_null($semester)) {
$semester = Semester::current();
}
return $semester->answerSheets()->create([
'year_of_acceptance' => $user->educationalInformation->year_of_acceptance
]);
}
public static function createForUser(User $user, Semester $semester = null): AnswerSheet
{
// Default to the current authenticated user if none is provided
if (is_null($user)) {
$user = user();
}
if (is_null($semester)) {
$semester = Semester::current();
}
return $semester->answerSheets()->create([
'year_of_acceptance' => $user->educationalInformation->year_of_acceptance
]);
}

@viktorcsimma
Copy link
Contributor Author

Then if you are fine with it; I'll merge this now and then we can reopen discussion in the summer. And I'll take the blame if anything blows up;) Thank you both very much!

@viktorcsimma viktorcsimma merged commit f933a43 into development Jun 15, 2024
6 checks passed
@viktorcsimma viktorcsimma deleted the anonymous-questions branch June 15, 2024 10:35
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.

Add new anonymous questions to the evaluation form
3 participants