From 2eef4d2b1340101b3d92b00a761d1c0f88a4c239 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 26 Jan 2024 22:54:00 +0000 Subject: [PATCH] auto fixes + some impl. --- .../QA/Controller/AppController.php | 2 +- Admin/Install/Application/QA/Routes.php | 10 +- .../QA/Themes/Default/tpl/imprint.tpl.php | 4 +- .../QA/Themes/Default/tpl/privacy.tpl.php | 8 +- .../QA/Themes/Default/tpl/terms.tpl.php | 4 +- Admin/Routes/Web/Backend.php | 8 +- CONTRIBUTING.md | 164 ++++++++++++--- Controller/ApiController.php | 43 ++-- Controller/BackendController.php | 2 +- LICENSE.txt | 2 +- Models/QAAnswer.php | 95 ++------- Models/QAAnswerMapper.php | 2 +- Models/QAAnswerVote.php | 12 -- Models/QAApp.php | 12 -- Models/QAHelperMapper.php | 2 +- Models/QAQuestion.php | 196 ++---------------- Models/QAQuestionMapper.php | 2 +- Models/QAQuestionVote.php | 12 -- Theme/Backend/Lang/de.lang.php | 14 +- Theme/Backend/Lang/en.lang.php | 14 +- Theme/Backend/qa-dashboard.tpl.php | 4 +- Theme/Backend/qa-question-create.tpl.php | 9 +- Theme/Backend/qa-question.tpl.php | 15 +- Theme/Backend/qa-tag-list.tpl.php | 4 +- tests/Autoloader.php | 4 +- tests/Bootstrap.php | 71 ++++--- tests/Controller/ApiControllerTest.php | 41 ++-- tests/Models/QAAnswerMapperTest.php | 6 +- tests/Models/QAAnswerTest.php | 45 ++-- tests/Models/QAAppTest.php | 4 +- tests/Models/QAQuestionMapperTest.php | 12 +- tests/Models/QAQuestionTest.php | 97 ++------- 32 files changed, 334 insertions(+), 586 deletions(-) diff --git a/Admin/Install/Application/QA/Controller/AppController.php b/Admin/Install/Application/QA/Controller/AppController.php index b856fe0..6af4045 100755 --- a/Admin/Install/Application/QA/Controller/AppController.php +++ b/Admin/Install/Application/QA/Controller/AppController.php @@ -101,7 +101,7 @@ final class AppController extends ModuleAbstract public function viewProfile(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface { $view = new View($this->app->l11nManager, $request, $response); - $view->setTemplate('/Web/{APPNAME}/tpl/profile'); + $view->setTemplate('/Web/{APPNAME}/tpl/view'); return $view; } diff --git a/Admin/Install/Application/QA/Routes.php b/Admin/Install/Application/QA/Routes.php index 8bfae20..c6174b4 100755 --- a/Admin/Install/Application/QA/Routes.php +++ b/Admin/Install/Application/QA/Routes.php @@ -10,31 +10,31 @@ return [ 'verb' => RouteVerb::GET, ], ], - '^(\/[a-zA-Z]*\/*|\/)/profile(\?.*|$)$' => [ + '^(\/[a-zA-Z]*\/*|\/)/view(\?.*$|$)' => [ [ 'dest' => '\Web\{APPNAME}\Controller\AppController:viewProfile', 'verb' => RouteVerb::GET, ], ], - '^(\/[a-zA-Z]*\/*|\/)/imprint(\?.*|$)$' => [ + '^(\/[a-zA-Z]*\/*|\/)/imprint(\?.*$|$)' => [ [ 'dest' => '\Web\{APPNAME}\Controller\AppController:viewImprint', 'verb' => RouteVerb::GET, ], ], - '^(\/[a-zA-Z]*\/*|\/)/terms(\?.*|$)$' => [ + '^(\/[a-zA-Z]*\/*|\/)/terms(\?.*$|$)' => [ [ 'dest' => '\Web\{APPNAME}\Controller\AppController:viewTerms', 'verb' => RouteVerb::GET, ], ], - '^(\/[a-zA-Z]*\/*|\/)/privacy(\?.*|$)$' => [ + '^(\/[a-zA-Z]*\/*|\/)/privacy(\?.*$|$)' => [ [ 'dest' => '\Web\{APPNAME}\Controller\AppController:viewDataPrivacy', 'verb' => RouteVerb::GET, ], ], - '^(\/[a-zA-Z]*\/*|\/)/question(\?.*|$)$' => [ + '^(\/[a-zA-Z]*\/*|\/)/question(\?.*$|$)' => [ [ 'dest' => '\Web\{APPNAME}\Controller\AppController:viewQuestion', 'verb' => RouteVerb::GET, diff --git a/Admin/Install/Application/QA/Themes/Default/tpl/imprint.tpl.php b/Admin/Install/Application/QA/Themes/Default/tpl/imprint.tpl.php index 26071bf..ae4ce5b 100755 --- a/Admin/Install/Application/QA/Themes/Default/tpl/imprint.tpl.php +++ b/Admin/Install/Application/QA/Themes/Default/tpl/imprint.tpl.php @@ -16,7 +16,7 @@ declare(strict_types=1);

Imprint

-

Karaka

+

Jingga

Vertreten durch

Dennis Eichhorn

@@ -31,7 +31,7 @@ declare(strict_types=1);

Nicht vorhanden

Verantwortlich für den Inhalt nach § 55 Abs. 2 RStV

-

Karaka

+

Jingga

Dennis Eichhorn

Datenschutzbeauftragter

diff --git a/Admin/Install/Application/QA/Themes/Default/tpl/privacy.tpl.php b/Admin/Install/Application/QA/Themes/Default/tpl/privacy.tpl.php index ba7a2d7..131b841 100755 --- a/Admin/Install/Application/QA/Themes/Default/tpl/privacy.tpl.php +++ b/Admin/Install/Application/QA/Themes/Default/tpl/privacy.tpl.php @@ -16,7 +16,7 @@ declare(strict_types=1);

Privacy Policy

-

This privacy policy ("POLICY") will help you understand how [name] ("us", "we", "our") uses and protects the data you provide to us when you visit and use Karaka ("website", "service" and "application").

+

This privacy policy ("POLICY") will help you understand how [name] ("us", "we", "our") uses and protects the data you provide to us when you visit and use Jingga ("website", "service" and "application").

Definitions

For the purposes of these POLICIES:

@@ -24,7 +24,7 @@ declare(strict_types=1);

  • AFFILIATED means an entity that controls, is controlled by or is under common control with a party, where "control" means ownership of 50% or more of the shares, equity interest or other securities entitled to vote for election of directors or other managing authority.
  • COUNTRY refers to Germany
  • -
  • COMPANY (referred to as either "the Company", "We", "Us" or "Our" in this AGREEMENT) refers to Karaka, Kirchstr. 33, 61191 Rosbach.
  • +
  • COMPANY (referred to as either "the Company", "We", "Us" or "Our" in this AGREEMENT) refers to Jingga, Kirchstr. 33, 61191 Rosbach.
  • DEVICE means any device that can access the SERVICE such as a computer, a cellphone or a digital tablet.
  • SERVICE refers to the Website
  • POLICY or AGREEMENT mean these policies that form the entire agreement between You and the COMPANY regarding the use of the SERVICE.
  • @@ -55,7 +55,7 @@ declare(strict_types=1);

Safeguarding and Securing the Data

-

Karaka is committed to securing your data and keeping it confidential. Karaka has done all in its power to prevent data theft, unauthorized access, and disclosure by implementing the latest technologies and software, which help us safeguard all the information we collect online.

+

Jingga is committed to securing your data and keeping it confidential. Jingga has done all in its power to prevent data theft, unauthorized access, and disclosure by implementing the latest technologies and software, which help us safeguard all the information we collect online.

Our Cookie Policy

Once you agree to allow our WEBSITE or APPLICATION to use cookies, you also agree to these POLICIES.

@@ -76,7 +76,7 @@ declare(strict_types=1);
  • If you have already agreed to share your information with us, feel free to contact us via email and we will be more than happy to change this for you.
  • -

    Karaka will not lease, sell or distribute your personal information to any third parties, unless we have your permission. We might do so if the law forces us. Your personal information will be used when we need to send you promotional materials if you agree to this privacy policy.

    +

    Jingga will not lease, sell or distribute your personal information to any third parties, unless we have your permission. We might do so if the law forces us. Your personal information will be used when we need to send you promotional materials if you agree to this privacy policy.

    Governing Law

    The laws of the COUNTRY, excluding its conflicts of law rules, shall govern this POLICY and Your use of the SERVICE. Your use of the APPLICATION may also be subject to other local, state, national, or international laws.

    diff --git a/Admin/Install/Application/QA/Themes/Default/tpl/terms.tpl.php b/Admin/Install/Application/QA/Themes/Default/tpl/terms.tpl.php index c357d83..5ce916b 100755 --- a/Admin/Install/Application/QA/Themes/Default/tpl/terms.tpl.php +++ b/Admin/Install/Application/QA/Themes/Default/tpl/terms.tpl.php @@ -23,7 +23,7 @@ declare(strict_types=1);
    • AFFILIATED means an entity that controls, is controlled by or is under common control with a party, where "control" means ownership of 50% or more of the shares, equity interest or other securities entitled to vote for election of directors or other managing authority.
    • COUNTRY refers to Germany
    • -
    • COMPANY (referred to as either "the Company", "We", "Us" or "Our" in this AGREEMENT) refers to Karaka, Kirchstr. 33, 61191 Rosbach.
    • +
    • COMPANY (referred to as either "the Company", "We", "Us" or "Our" in this AGREEMENT) refers to Jingga, Kirchstr. 33, 61191 Rosbach.
    • DEVICE means any device that can access the Service such as a computer, a cellphone or a digital tablet.
    • SERVICE refers to the Website
    • TERMS or AGREEMENT mean these terms that form the entire agreement between You and the COMPANY regarding the use of the SERVICE.
    • @@ -41,7 +41,7 @@ declare(strict_types=1);

      Your access to and use of the SERVICE is also conditioned on Your acceptance of and compliance with the Privacy Policy of the COMPANY. Our Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your personal information when You use the Application or the WEBSITE and tells You about Your privacy rights and how the law protects You. Please read Our Privacy Policy carefully before using Our SERVICE.

      Copyright

      -

      Unless otherwise noted, all materials including without limitation, logos, brand names, images, designs, photographs, videos, audio, source code and written and other materials that appear as part of our WEBSITE are copyrights, trademarks, service marks, trade dress and/or other intellectual property whether registered or unregistered ("Intellectual Property") owned, controlled or licensed by Karaka. Our WEBSITE as a whole is protected by copyright and trade dress. Nothing on our WEBSITE should be construed as granting, by implication, estoppel or otherwise, any license or right to use any Intellectual Property displayed or used on our WEBSITE, without the prior written permission of the Intellectual Property owner. Karaka aggressively enforces its intellectual property rights to the fullest extent of the law. The names and logos of Karaka, may not be used in any way, including in advertising or publicity pertaining to distribution of materials on our WEBSITE, without prior, written permission from Karaka. Karaka prohibits use of any logo of Karaka or any of its affiliates as part of a link to or from any WEBSITE unless Karaka approves such link in advance and in writing. Fair use of Karaka Intellectual Property requires proper acknowledgment. Other product and company names mentioned in our Website may be the Intellectual Property of their respective owners.

      +

      Unless otherwise noted, all materials including without limitation, logos, brand names, images, designs, photographs, videos, audio, source code and written and other materials that appear as part of our WEBSITE are copyrights, trademarks, service marks, trade dress and/or other intellectual property whether registered or unregistered ("Intellectual Property") owned, controlled or licensed by Jingga. Our WEBSITE as a whole is protected by copyright and trade dress. Nothing on our WEBSITE should be construed as granting, by implication, estoppel or otherwise, any license or right to use any Intellectual Property displayed or used on our WEBSITE, without the prior written permission of the Intellectual Property owner. Jingga aggressively enforces its intellectual property rights to the fullest extent of the law. The names and logos of Jingga, may not be used in any way, including in advertising or publicity pertaining to distribution of materials on our WEBSITE, without prior, written permission from Jingga. Jingga prohibits use of any logo of Jingga or any of its affiliates as part of a link to or from any WEBSITE unless Jingga approves such link in advance and in writing. Fair use of Jingga Intellectual Property requires proper acknowledgment. Other product and company names mentioned in our Website may be the Intellectual Property of their respective owners.

      Links

      Our SERVICE may contain links to third-party web sites or services that are not owned or controlled by the COMPANY.

      diff --git a/Admin/Routes/Web/Backend.php b/Admin/Routes/Web/Backend.php index 33dc475..a3a1659 100755 --- a/Admin/Routes/Web/Backend.php +++ b/Admin/Routes/Web/Backend.php @@ -29,7 +29,7 @@ return [ ], ], ], - '^.*/qa.*$' => [ + '^.*/qa/.*' => [ [ 'dest' => '\Modules\QA\Controller\BackendController:setUpBackend', 'verb' => RouteVerb::GET, @@ -40,7 +40,7 @@ return [ ], ], ], - '^.*/qa/dashboard.*$' => [ + '^.*/qa/dashboard(\?.*$|$)' => [ [ 'dest' => '\Modules\QA\Controller\BackendController:viewQADashboard', 'verb' => RouteVerb::GET, @@ -51,7 +51,7 @@ return [ ], ], ], - '^.*/qa/question(\?.*|$)$' => [ + '^.*/qa/question(\?.*$|$)' => [ [ 'dest' => '\Modules\QA\Controller\BackendController:viewQADoc', 'verb' => RouteVerb::GET, @@ -62,7 +62,7 @@ return [ ], ], ], - '^.*/qa/question/create.*$' => [ + '^.*/qa/question/create(\?.*$|$)' => [ [ 'dest' => '\Modules\QA\Controller\BackendController:viewQAQuestionCreate', 'verb' => RouteVerb::GET, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f4653b..88c5d9c 100755 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,12 +1,16 @@ -# Development - ## Development environment - The setup and configuration of the development environment is in the hands of every developer themselves. However, it is recommended to follow the setup instructions in the [Developer-Guide](https://github.com/Karaka-Management/Developer-Guide/blob/develop/general/setup.md). +The setup and configuration of the development environment is in the hands of every developer themselves. However, it is recommended to follow the setup instructions in the [Developer-Guide](https://github.com/Karaka-Management/Developer-Guide/blob/develop/general/setup.md). ## Code of conduct -Every organization member and contributor to the organization must follow the [code of conduct](../Policies & Guidelines/Code of conduct.md). +Every organization member and contributor to the organization must follow the [Code of Conduct](../Policies%20&%20Guidelines/Code%20of%20Conduct.md). + +## Becoming a contributor + +For public repositories you can immediately start by creating forks and pull requests. For private repositories which are necessary to setup the complete developer environment, feel free to request access. Please not that we may not immediately give you access to private repositories and instead will give you smaller tasks regarding public repositories. Please contact info@jingga.app for more details. (**R1**) + +For all contributions our [Contributor License Agreement "CLA"](https://github.com/Karaka-Management/Organization-Guide/blob/master/Processes/HR/Hiring/Individual%20Contributor%20License%20Agreement.md) comes into effect. (**R2**) ## Code changes @@ -14,58 +18,106 @@ Every organization member and contributor to the organization must follow the [c Generally, the development philosophy is result orientated. This means that anyone can propose tasks, pick up existing tasks or right away implement their code changes. However, implementing code changes without consulting with a senior developer in advance has a much higher risk of code changes not getting admitted. The easiest way to discuss a code change idea in advance are the github [issues](https://github.com/Karaka-Management/Karaka/issues) or [discussions](https://github.com/Karaka-Management/Karaka/discussions). -Developers are encouraged to pick open tasks with high priorities according to their own skill level. Senior developers may directly assign tasks to developers based on their importance. New developers may find it easier to start with a task that has a low priority as they often also have a lower difficulty. +Developers are encouraged to pick open tasks with high priorities according to their own skill level. Senior developers may directly assign tasks to developers based on their importance. New developers may find it easier to start with a task that has a low priority as they often also have a lower difficulty. -Open tasks can be found in the project overview: [PROJECT.md](https://github.com/orgs/Karaka-Management/projects/10) +Open tasks can be found in the project overview: [Todos](https://github.com/orgs/Karaka-Management/projects/10) -Tasks currently in development are prefixed in the priority column with an asterisk `*` and a name tag in the task description of the developer who is working on the task. +Tasks currently in development are prefixed in the priority column with an asterisk `*` and a name tag in the task description of the developer who is working on the task. -The open tasks are reviewed once a month by a senior developer. The senior developer updates the project overview if necessary and requests feedback regarding development status of important tasks under development. During this process important tasks may also get directly assigned to developers. This review is performed on a judgmental bases of the senior basis. +The open tasks are reviewed once a month by a senior developer. The senior developer updates the project overview if necessary and requests feedback regarding development status of important tasks under development. During this process important tasks may also get directly assigned to developers. This review is performed on a judgmental bases of the senior basis. -### Code style +### Quality -Code changes must follow the [style guidelines](https://github.com/Karaka-Management/Developer-Guide/tree/develop/standards). Additionally, the automatic code style inspection tools must return no errors, failures or warnings. Developers should test their changes with inspection tools and configurations mentioned in the [inspection documentation](https://github.com/Karaka-Management/Developer-Guide/blob/develop/quality/inspections.md) in advance before submitting them for review. +#### Code style -In rare cases errors, failures or warnings during the automatic inspection are acceptable. Reasons can be changes in the programming language, special cases which cannot, are difficult or must be individually configured in the inspection settings. If this is the case for a code change and if inspection configuration changes are necessary are decided by the senior developer performing the code review. +Code changes must follow the [style guidelines](https://github.com/Karaka-Management/Developer-Guide/tree/develop/standards) (**R3**). Additionally, the automatic code style inspection tools must return no errors, failures or warnings. Developers should test their changes with inspection tools and configurations mentioned in the [inspection documentation](https://github.com/Karaka-Management/Developer-Guide/blob/develop/quality/inspections.md) in advance before submitting them for review. (**R4**) -Automated checks which are run during the review process: +In rare cases errors, failures or warnings during the automatic inspection are acceptable. Reasons can be for example special cases which are difficult automatize or must be individually configured in the inspection settings. If this is the case for a code change and if inspection configuration changes are necessary are decided by the senior developer performing the code review. (**R5**) + +Automated checks which are run during the review process (**R4**): ```sh -php ./vendor/bin/phpcs --severity=1 ./ --standard="Build/Config/phpcs.xml" +php ./vendor/bin/phpcs ./ --standard="Build/Config/phpcs.xml" +php ./vendor/bin/php-cs-fixer fix ./ --config=Build/Config/.php-cs-fixer.php --allow-risky=yes +php ./vendor/bin/phpcbf --standard=Build/Config/phpcs.xml ./ +php ./vendor/bin/rector process --dry-run --config Build/Config/rector.php ./ npx eslint ./ -c ./Build/Config/.eslintrc.json ``` -### Tests +#### Tests -Code changes must follow the inspection guidelines (i.e. code coverage) mentioned in the [inspection documentation](https://github.com/Karaka-Management/Developer-Guide/blob/develop/quality/inspections.md). Developers should check if the code changes comply with the inspection guidelines before submitting them. +Code changes must follow the inspection guidelines (i.e. code coverage) mentioned in the [inspection documentation](https://github.com/Karaka-Management/Developer-Guide/blob/develop/quality/inspections.md) (**R6**). Developers should test their changes with inspection tools and configurations mentioned in the [inspection documentation](https://github.com/Karaka-Management/Developer-Guide/blob/develop/quality/inspections.md) in advance before submitting them for review. (**R7**) -In rare cases it might be not possible to follow the inspection guidelines. In such cases the senior developer performing the code review may decide if the code change still gets accepted. +In rare cases it might be not possible to follow the inspection guidelines. In such cases the senior developer performing the code review may decide if the code change still gets accepted. (**R8**) -Automated tests which are run during the review process: +Automated tests which are run during the review process (**R7**): ```sh php ./vendor/bin/phpunit -c tests/PHPUnit/phpunit_default.xml -php ./vendor/bin/phpstan analyse --autoload-file=phpOMS/Autoloader.php -l 9 -c Build/Config/phpstan.neon ./ +php ./vendor/bin/phpstan analyse --no-progress -l 9 -c Build/Config/phpstan.neon ./ npx jasmine-node ./ ./cOMS/tests/test.sh ``` -Additional inspections which are run but might be ignored during the review depending on the use case are mentioned in the [inspection documentation](https://github.com/Karaka-Management/Developer-Guide/blob/develop/quality/inspections.md) as other checks. +Additional inspections which are run but might be ignored during the review depending on the use case are mentioned in the [inspection documentation](https://github.com/Karaka-Management/Developer-Guide/blob/develop/quality/inspections.md) as other checks. (**R7**) -### Demo +#### Performance -Some code changes may also require changes or extensions in the demo setup scripts. The demo setup script try to simulate a real world use case by generating and modifying mostly random data. This is also a good way to setup and “manually” test the code changes in a larger picture. The demo setup script can be found in the [demoSetup](https://github.com/Karaka-Management/demoSetup) repository. The demo setup script takes a long time due to the large amount of user input simulated data which is generated. Therefore it is recommended to run this only sporadically. +Developers should occasionaly check performance statistics. At this point no target metrics are defined. -### Code review +Since the primary application is a web based application a similar tool as the Google lighthouse tool can be used to inspect the application for best practicies which can significantly improve the application performance. The sitespeed.io tool shows potential performance improvements and slow pages. With the php trace and profiler enabled in the `php.ini` file the VM automatically generates profiling and trace reports for every web request. These can be found in the webgrind logs directory and inspected in webgrind and dropped into the trace visualizer for a flame chart visualization. With mysqldumpslow you can inspect slow sql queries which may need optimization. + +1. Automatic trace and benchmark generation with every web request in `/var/www/html/webgrind/Logs` +2. Webgrind view `http://vm_ip:82` +3. Trace visualization `http://vm_ip:81` + 1. Download the latest trace from `http://vm_ip:82/Logs` + 2. Drag and drop that downloaded `*.xt` file in the trace visualizer +4. `sitespeed.io ./Build/Helper/Scripts/sitespeedDemoUrls.txt -b chrome --outputFolder /var/www/html/sitespeed` +5. Slow query inspection. + +```sh +mysqldumpslow -t 10 /var/log/mysql/mysql-slow.log +mysqldumpslow -t 10 -s l /var/log/mysql/mysql-slow.log +``` + +#### Code review In addition to the automatic code review performed by the various inspection tools such as (phpcs, phpstan, phpunit, eslint and custom scripts) a senior developer must check the proposed code change before it is merged with the respective `develop` branch. Only upon the approval by the reviewer a code change requests gets merged as no other developers have permission in the software to make such code merges. In case a code change request is not approved the reviewer states the reason for the decision, this may include some tips and requests which will allow the contributor to make improvements so that the code change may get approved. -If the code reviewer only finds minor issues with the proposed code change the reviewer may make small changes to the proposed code change and inform the contributor to speed up the implementation process. Code reviewers are encouraged to do this with new contributors to avoid long iteration processes and to not discourage new developers. However, communication is key and severe issues with code change requests or if the contributor already made multiple code change requests in the past the reviewer should not implement the improvements by himself and rather decline the code change requests with his reasoning. +If the code reviewer only finds minor issues with the proposed code change the reviewer may make small changes to the proposed code change and inform the contributor to speed up the implementation process. Code reviewers are encouraged to do this with new contributors to avoid long iteration processes and to not discourage new developers. However, communication is key and severe issues with code change requests or if the contributor already made multiple code change requests in the past the reviewer should not implement the improvements by himself and rather decline the code change requests with his reasoning. (**R5**+**R8**) + +#### Demo + +Some code changes may also require changes or extensions in the demo setup scripts. The demo setup script try to simulate a real world use case by generating and modifying mostly random data. This is also a good way to setup and “manually” test the code changes in a larger picture. The demo setup script can be found in the [demoSetup](https://github.com/Karaka-Management/demoSetup) repository. The demo setup script takes a long time due to the large amount of user input simulated data which is generated. Therefore it is recommended to run this only sporadically. (**R9**) + +```sh +sudo -u www-data php -dxdebug.remote_enable=1 -dxdebug.start_with_request=yes -dxdebug.mode=coverage,develop,debug demoSetup/setup.php +``` + +#### Documentation + +Occasionally new code or code changes also require new documentation or documentation changes. Developers should make sure that the new code is also reflected in the existing documentation ([Developer-Guide](), [User-Guide]() and/or module documentation) or if additional documentation is necessary. + +#### Improvements, features, bugs + +If a developer (or employee in general) has an idea for an improvement, feature or finds a potential bug it should be reported at https://github.com/Karaka-Management/Karaka/issues. A senior developer has to check these issues and decide how to proceed with them. The decision how to proceed with the issue must be explained by the senior developer as a response in the issue. Possible steps are: + +* Accept the issue and put the task into the [Todos](https://github.com/orgs/Karaka-Management/projects/10) +* Dismiss the issue with an explanation ### Release flow +In case SCSS/CSS or JS files got changed they must get re-built locally before comitting the code change: + +```sh +npx esbuild Web/Backend/js/backend.js --bundle --outfile=Install/Application/Backend/js/backend.min.js --minify +scss cssOMS/styles.scss > cssOMS/styles.css +``` + +For JS you may also use the shorthand command `npm run build`. + Code changes must be performed in a new branch. A new branch can be created with: ```sh @@ -75,8 +127,70 @@ git checkout -b new-branch-name The name of the branch can be chosen freely however it is recommended to follow the following branch naming conventions: * `feature-*` for feature implementations +* `hotfix-*` for security related fixes/improvements * `bug-*` for bug fixes * `security-*` for security related fixes/improvements -* `general-*` for general improvements (i.e. code documentation improvements, code style improvements) +* `general-*` for general improvements (i.e. documentation, code style & performance improvements) -The senior developer who performs the code review merges the change request into the `develop` branch upon approval. \ No newline at end of file +```mermaid +%%{init: { 'gitGraph': {'mainBranchName': 'master'}} }%% + gitGraph + commit + branch hotfix-xxx + commit + checkout master + branch develop + checkout master + merge hotfix-xxx + checkout develop + branch bug-xxx + commit + commit + checkout hotfix-xxx + commit + checkout master + merge hotfix-xxx + checkout develop + merge bug-xxx + commit + checkout develop + branch feature-xxx + commit + commit + commit + checkout develop + merge feature-xxx + checkout master + merge develop + checkout develop + branch general-xxx + commit + checkout develop + merge general-xxx + branch security-xxx + commit + commit + checkout develop + merge security-xxx + checkout master + merge develop + +``` + +The senior developer who performs the code review merges the change request into the `develop` branch after their successful code review. Unsuccessful reviews lead to change requests by the original developer, other developers who can make the requested changes, changes by the senior developer who performed the review, or dismissal of the changed code. (**R10**) + +## Approved dependencies + +### Customer dependencies + +Developers may only rely on the dependencies defined in [Approved Customer Software]() when developing a solution. If new software should be added to this list or a different version is required developers should make a request with their team leader/head of department who forwards this requests if appropriate to the CTO and explain the reasoning for the different dependency needs. The CTO can decide if the dependency will be accepted. (**R11**) + +### Developer dependencies + +Developers may only rely on the dependencies defined in [IT Equipment & Software](). If new software should be added to this list or a different version is required developers should make a request with their team leader/head of department who forwards this requests if appropriate to the CTO and explain the reasoning for the different dependency needs. The CTO can decide if the dependency will be accepted. Changing the package managers such as `composer.json` or `package.json` is not allowed by anyone else than the CTO. (**R12**) + +## Other related documents + +* [Confidentiality Policy](../Policies%20&%20Guidelines/Confidentiality%20Policy.md) +* [Organization Activity Policy](../Policies%20&%20Guidelines/Organization%20Activity%20Policy.md) +* [Tutorials](./Development/Tutorials) \ No newline at end of file diff --git a/Controller/ApiController.php b/Controller/ApiController.php index 9637d6d..054d877 100755 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -32,9 +32,8 @@ use Modules\QA\Models\QAQuestionMapper; use Modules\QA\Models\QAQuestionStatus; use Modules\QA\Models\QAQuestionVote; use Modules\QA\Models\QAQuestionVoteMapper; -use Modules\Tag\Models\NullTag; use phpOMS\Account\PermissionType; -use phpOMS\Message\Http\HttpResponse; +use phpOMS\Localization\ISO639x1Enum; use phpOMS\Message\Http\RequestStatusCode; use phpOMS\Message\RequestAbstract; use phpOMS\Message\ResponseAbstract; @@ -146,30 +145,12 @@ final class ApiController extends Controller $question->questionRaw = (string) $request->getData('plain'); $question->question = Markdown::parse($request->getDataString('plain') ?? ''); $question->app = new NullQAApp($request->getDataInt('app') ?? 1); - $question->setLanguage((string) $request->getData('language')); - $question->setStatus((int) $request->getData('status')); - $question->createdBy = new Profile(new NullAccount($request->header->account)); + $question->language = ISO639x1Enum::tryFromValue($request->getDataString('language')) ?? ISO639x1Enum::_EN; + $question->status = QAQuestionStatus::tryFromValue($request->getDataInt('status')) ?? QAQuestionStatus::ACTIVE; + $question->createdBy = new Profile(new NullAccount($request->header->account)); - if (!empty($tags = $request->getDataJson('tags'))) { - foreach ($tags as $tag) { - if (!isset($tag['id'])) { - $request->setData('title', $tag['title'], true); - $request->setData('color', $tag['color'], true); - $request->setData('icon', $tag['icon'] ?? null, true); - $request->setData('language', $tag['language'], true); - - $internalResponse = new HttpResponse(); - $this->app->moduleManager->get('Tag')->apiTagCreate($request, $internalResponse); - - if (!\is_array($data = $internalResponse->getDataArray($request->uri->__toString()))) { - continue; - } - - $question->addTag($data['response']); - } else { - $question->addTag(new NullTag((int) $tag['id'])); - } - } + if ($request->hasData('tags')) { + $question->tags = $this->app->moduleManager->get('Tag', 'Api')->createTagsFromRequest($request); } if (!empty($uploadedFiles = $request->files)) { @@ -183,13 +164,13 @@ final class ApiController extends Controller ); foreach ($uploaded as $media) { - $question->addMedia($media); + $question->files[] = $media; } } if (!empty($mediaFiles = $request->getDataJson('media'))) { foreach ($mediaFiles as $media) { - $question->addMedia(new NullMedia($media)); + $question->files[] = new NullMedia($media); } } @@ -265,8 +246,8 @@ final class ApiController extends Controller $answer->answer = Markdown::parse($request->getDataString('plain') ?? ''); $answer->question = new NullQAQuestion((int) $request->getData('question')); $answer->isAccepted = false; - $answer->setStatus((int) $request->getData('status')); - $answer->createdBy = new Profile(new NullAccount($request->header->account)); + $answer->status = QAAnswerStatus::tryFromValue($request->getDataInt('status')) ?? QAAnswerStatus::ACTIVE; + $answer->createdBy = new Profile(new NullAccount($request->header->account)); if (!empty($uploadedFiles = $request->files)) { $uploaded = $this->app->moduleManager->get('Media')->uploadFiles( @@ -279,13 +260,13 @@ final class ApiController extends Controller ); foreach ($uploaded as $media) { - $answer->addMedia($media); + $answer->files[] = $media; } } if (!empty($mediaFiles = $request->getDataJson('media'))) { foreach ($mediaFiles as $media) { - $answer->addMedia(new NullMedia($media)); + $answer->files[] = new NullMedia($media); } } diff --git a/Controller/BackendController.php b/Controller/BackendController.php index dd8c3f1..c9a07e0 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -128,7 +128,7 @@ final class BackendController extends Controller ->with('votes') ->with('tags') ->with('tags/title') - ->with('media') + ->with('files') ->where('id', (int) $request->getData('id')) ->where('tags/title/language', $response->header->l11n->language) ->execute(); diff --git a/LICENSE.txt b/LICENSE.txt index 18d430e..4ba0161 100755 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -27,7 +27,7 @@ Version 2.0 Subject to the terms and conditions of this License, each Contributor grants to You after purchase a perpetual, worldwide, non-exclusive, irrevocable copyright license to prepare Derivative Works of, publicly display, publicly perform the Work and such Derivative Works in Source or Object form. You are not allowed to sublicense, reproduce, or distribute the Work and such Derivative Works in Source or Object form. -3. Redistribution. +3. Redistribution You may not reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form. diff --git a/Models/QAAnswer.php b/Models/QAAnswer.php index 730b019..af0dafe 100755 --- a/Models/QAAnswer.php +++ b/Models/QAAnswer.php @@ -14,7 +14,6 @@ declare(strict_types=1); namespace Modules\QA\Models; -use Modules\Media\Models\Media; use Modules\Profile\Models\NullProfile; use Modules\Profile\Models\Profile; @@ -100,14 +99,6 @@ class QAAnswer implements \JsonSerializable */ public array $votes = []; - /** - * Media files - * - * @var array - * @since 1.0.0 - */ - public array $media = []; - /** * Constructor. * @@ -120,44 +111,6 @@ class QAAnswer implements \JsonSerializable $this->question = new NullQAQuestion(); } - /** - * Get id. - * - * @return int Model id - * - * @since 1.0.0 - */ - public function getId() : int - { - return $this->id; - } - - /** - * Get the status - * - * @return int - * - * @since 1.0.0 - */ - public function getStatus() : int - { - return $this->status; - } - - /** - * Set the status - * - * @param int $status Status - * - * @return void - * - * @since 1.0.0 - */ - public function setStatus(int $status) : void - { - $this->status = $status; - } - /** * Get the total vote score * @@ -221,48 +174,22 @@ class QAAnswer implements \JsonSerializable $this->votes[] = $vote; } - /** - * Get all media - * - * @return Media[] - * - * @since 1.0.0 - */ - public function getMedia() : array - { - return $this->media; - } - - /** - * Add media - * - * @param Media $media Media to add - * - * @return void - * - * @since 1.0.0 - */ - public function addMedia(Media $media) : void - { - $this->media[] = $media; - } - /** * {@inheritdoc} */ public function toArray() : array { return [ - 'id' => $this->id, - 'status' => $this->status, - 'answer' => $this->answer, - 'answerRaw' => $this->answerRaw, - 'question' => $this->question, - 'isAccepted' => $this->isAccepted, - 'createdBy' => $this->createdBy, - 'createdAt' => $this->createdAt, - 'votes' => $this->votes, - 'media' => $this->media, + 'id' => $this->id, + 'status' => $this->status, + 'answer' => $this->answer, + 'answerRaw' => $this->answerRaw, + 'question' => $this->question, + 'isAccepted' => $this->isAccepted, + 'createdBy' => $this->createdBy, + 'createdAt' => $this->createdAt, + 'votes' => $this->votes, + 'media' => $this->files, ]; } @@ -273,4 +200,6 @@ class QAAnswer implements \JsonSerializable { return $this->toArray(); } + + use \Modules\Media\Models\MediaListTrait; } diff --git a/Models/QAAnswerMapper.php b/Models/QAAnswerMapper.php index 6574d0b..4617ab7 100755 --- a/Models/QAAnswerMapper.php +++ b/Models/QAAnswerMapper.php @@ -79,7 +79,7 @@ final class QAAnswerMapper extends DataMapperFactory 'self' => 'qa_answer_vote_answer', 'external' => null, ], - 'media' => [ + 'files' => [ 'mapper' => MediaMapper::class, 'table' => 'qa_answer_media', 'external' => 'qa_answer_media_dst', diff --git a/Models/QAAnswerVote.php b/Models/QAAnswerVote.php index ff4801c..d6e9cce 100755 --- a/Models/QAAnswerVote.php +++ b/Models/QAAnswerVote.php @@ -85,16 +85,4 @@ class QAAnswerVote $this->createdBy = new NullAccount(); $this->createdAt = new \DateTimeImmutable(); } - - /** - * Get model id. - * - * @return int - * - * @since 1.0.0 - */ - public function getId() : int - { - return $this->id; - } } diff --git a/Models/QAApp.php b/Models/QAApp.php index 064b1c6..e05730c 100755 --- a/Models/QAApp.php +++ b/Models/QAApp.php @@ -48,18 +48,6 @@ class QAApp implements \JsonSerializable */ public ?int $unit = null; - /** - * Get id. - * - * @return int Model id - * - * @since 1.0.0 - */ - public function getId() : int - { - return $this->id; - } - /** * {@inheritdoc} */ diff --git a/Models/QAHelperMapper.php b/Models/QAHelperMapper.php index 5169669..f33bd4a 100755 --- a/Models/QAHelperMapper.php +++ b/Models/QAHelperMapper.php @@ -73,7 +73,7 @@ final class QAHelperMapper extends DataMapperFactory foreach ($answerScore as $votes) { $scores[(int) $votes['qa_answer_vote_created_for']] ??= 0; - $scores[(int) $votes['qa_answer_vote_created_for']] += (int) $votes['score']; + $scores[(int) $votes['qa_answer_vote_created_for']] += (int) $votes['score']; } return $scores; diff --git a/Models/QAQuestion.php b/Models/QAQuestion.php index de7bfc0..6d2edcc 100755 --- a/Models/QAQuestion.php +++ b/Models/QAQuestion.php @@ -14,10 +14,8 @@ declare(strict_types=1); namespace Modules\QA\Models; -use Modules\Media\Models\Media; use Modules\Profile\Models\NullProfile; use Modules\Profile\Models\Profile; -use Modules\Tag\Models\NullTag; use Modules\Tag\Models\Tag; use phpOMS\Localization\ISO639x1Enum; @@ -125,14 +123,6 @@ class QAQuestion implements \JsonSerializable */ public QAApp $app; - /** - * Media files - * - * @var array - * @since 1.0.0 - */ - public array $media = []; - /** * Constructor. * @@ -145,21 +135,9 @@ class QAQuestion implements \JsonSerializable $this->app = new NullQAApp(1); } - /** - * Get id. - * - * @return int Model id - * - * @since 1.0.0 - */ - public function getId() : int - { - return $this->id; - } - /** * Finds all accounts in the question - * e.g. asked by and all accoounts who answered + * e.g. asked by and all accounts who answered * * @return array */ @@ -193,124 +171,6 @@ class QAQuestion implements \JsonSerializable return false; } - /** - * Get the language - * - * @return string - * - * @since 1.0.0 - */ - public function getLanguage() : string - { - return $this->language; - } - - /** - * Set the language - * - * @param string $language Language - * - * @return void - * - * @since 1.0.0 - */ - public function setLanguage(string $language) : void - { - $this->language = $language; - } - - /** - * Get the status - * - * @return int - * - * @since 1.0.0 - */ - public function getStatus() : int - { - return $this->status; - } - - /** - * Set the status - * - * @param int $status Status - * - * @return void - * - * @since 1.0.0 - */ - public function setStatus(int $status) : void - { - $this->status = $status; - } - - /** - * Adding new tag. - * - * @param Tag $tag Tag - * - * @return int - * - * @since 1.0.0 - */ - public function addTag(Tag $tag) : int - { - $this->tags[] = $tag; - - \end($this->tags); - $key = (int) \key($this->tags); - \reset($this->tags); - - return $key; - } - - /** - * Remove Tag from list. - * - * @param int $id Tag - * - * @return bool - * - * @since 1.0.0 - */ - public function removeTag($id) : bool - { - if (isset($this->tags[$id])) { - unset($this->tags[$id]); - - return true; - } - - return false; - } - - /** - * Get task elements. - * - * @return Tag[] - * - * @since 1.0.0 - */ - public function getTags() : array - { - return $this->tags; - } - - /** - * Get task elements. - * - * @param int $id Element id - * - * @return Tag - * - * @since 1.0.0 - */ - public function getTag(int $id) : Tag - { - return $this->tags[$id] ?? new NullTag(); - } - /** * Count the answers * @@ -440,51 +300,25 @@ class QAQuestion implements \JsonSerializable $this->answers[] = $answer; } - /** - * Get all media - * - * @return Media[] - * - * @since 1.0.0 - */ - public function getMedia() : array - { - return $this->media; - } - - /** - * Add media - * - * @param Media $media Media to add - * - * @return void - * - * @since 1.0.0 - */ - public function addMedia(Media $media) : void - { - $this->media[] = $media; - } - /** * {@inheritdoc} */ public function toArray() : array { return [ - 'id' => $this->id, - 'name' => $this->name, - 'status' => $this->status, - 'question' => $this->question, - 'questionRaw' => $this->questionRaw, - 'language' => $this->language, - 'createdBy' => $this->createdBy, - 'createdAt' => $this->createdAt, - 'app' => $this->app, - 'tags' => $this->tags, - 'answers' => $this->votes, - 'votes' => $this->votes, - 'media' => $this->media, + 'id' => $this->id, + 'name' => $this->name, + 'status' => $this->status, + 'question' => $this->question, + 'questionRaw' => $this->questionRaw, + 'language' => $this->language, + 'createdBy' => $this->createdBy, + 'createdAt' => $this->createdAt, + 'app' => $this->app, + 'tags' => $this->tags, + 'answers' => $this->votes, + 'votes' => $this->votes, + 'media' => $this->files, ]; } @@ -495,4 +329,6 @@ class QAQuestion implements \JsonSerializable { return $this->toArray(); } + + use \Modules\Media\Models\MediaListTrait; } diff --git a/Models/QAQuestionMapper.php b/Models/QAQuestionMapper.php index 2a707a9..104218c 100755 --- a/Models/QAQuestionMapper.php +++ b/Models/QAQuestionMapper.php @@ -75,7 +75,7 @@ final class QAQuestionMapper extends DataMapperFactory 'self' => 'qa_question_vote_question', 'external' => null, ], - 'media' => [ + 'files' => [ 'mapper' => MediaMapper::class, 'table' => 'qa_question_media', 'external' => 'qa_question_media_dst', diff --git a/Models/QAQuestionVote.php b/Models/QAQuestionVote.php index 22ea3b0..6ee7524 100755 --- a/Models/QAQuestionVote.php +++ b/Models/QAQuestionVote.php @@ -85,16 +85,4 @@ class QAQuestionVote $this->createdBy = new NullAccount(); $this->createdAt = new \DateTimeImmutable(); } - - /** - * Get model id. - * - * @return int - * - * @since 1.0.0 - */ - public function getId() : int - { - return $this->id; - } } diff --git a/Theme/Backend/Lang/de.lang.php b/Theme/Backend/Lang/de.lang.php index e570c24..1dfa347 100755 --- a/Theme/Backend/Lang/de.lang.php +++ b/Theme/Backend/Lang/de.lang.php @@ -13,12 +13,12 @@ declare(strict_types=1); return ['QA' => [ - 'All' => 'Alle', - 'Answer' => 'Antwort', - 'Answers' => 'Antworten', - 'Question' => 'Frage', + 'All' => 'Alle', + 'Answer' => 'Antwort', + 'Answers' => 'Antworten', + 'Question' => 'Frage', 'Score' => 'Bewertung', - 'Badges' => 'Abzeichen', - 'Title' => 'Titel', - 'Name' => 'Name', + 'Badges' => 'Abzeichen', + 'Title' => 'Titel', + 'Name' => 'Name', ]]; diff --git a/Theme/Backend/Lang/en.lang.php b/Theme/Backend/Lang/en.lang.php index 1e498a6..b5518e6 100755 --- a/Theme/Backend/Lang/en.lang.php +++ b/Theme/Backend/Lang/en.lang.php @@ -13,12 +13,12 @@ declare(strict_types=1); return ['QA' => [ - 'All' => 'All', - 'Answer' => 'Answer', - 'Answers' => 'Answers', - 'Question' => 'Question', + 'All' => 'All', + 'Answer' => 'Answer', + 'Answers' => 'Answers', + 'Question' => 'Question', 'Score' => 'Score', - 'Badges' => 'Badges', - 'Title' => 'Title', - 'Name' => 'Name', + 'Badges' => 'Badges', + 'Title' => 'Title', + 'Name' => 'Name', ]]; diff --git a/Theme/Backend/qa-dashboard.tpl.php b/Theme/Backend/qa-dashboard.tpl.php index 8e71197..584d44e 100755 --- a/Theme/Backend/qa-dashboard.tpl.php +++ b/Theme/Backend/qa-dashboard.tpl.php @@ -56,14 +56,14 @@ echo $this->data['nav']->render(); ?>
    - getTags(); foreach ($tags as $tag) : + tags as $tag) : if ($tag->id === 0) { continue; } ?> icon) ? '' : ''; ?>printHtml($tag->getL11n()); ?>
    -
    name; ?> + files; foreach ($files as $file) : ?> + name; ?> -
    name; ?> + files; foreach ($files as $file) : ?> + name; ?> - id; ?> diff --git a/tests/Autoloader.php b/tests/Autoloader.php index 9532e73..888a9e8 100755 --- a/tests/Autoloader.php +++ b/tests/Autoloader.php @@ -75,8 +75,8 @@ final class Autoloader */ public static function defaultAutoloader(string $class) : void { - $class = \ltrim($class, '\\'); - $class = \strtr($class, '_\\', '//'); + $class = \ltrim($class, '\\'); + $class = \strtr($class, '_\\', '//'); if (\stripos($class, 'Web/Backend') !== false || \stripos($class, 'Web/Api') !== false) { $class = \is_dir(__DIR__ . '/Web') ? $class : \str_replace('Web/', 'MainRepository/Web/', $class); diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index ddc049d..76c5fae 100755 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -1,4 +1,15 @@ [ + 'db' => [ 'core' => [ 'masters' => [ - 'admin' => [ + 'admin' => [ 'db' => 'mysql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ @@ -80,7 +91,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'insert' => [ + 'insert' => [ 'db' => 'mysql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ @@ -90,7 +101,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'select' => [ + 'select' => [ 'db' => 'mysql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ @@ -100,7 +111,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'update' => [ + 'update' => [ 'db' => 'mysql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ @@ -110,7 +121,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'delete' => [ + 'delete' => [ 'db' => 'mysql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ @@ -120,7 +131,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'schema' => [ + 'schema' => [ 'db' => 'mysql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ @@ -132,7 +143,7 @@ $CONFIG = [ ], ], 'postgresql' => [ - 'admin' => [ + 'admin' => [ 'db' => 'pgsql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '5432', /* db host port */ @@ -142,7 +153,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'insert' => [ + 'insert' => [ 'db' => 'pgsql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '5432', /* db host port */ @@ -152,7 +163,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'select' => [ + 'select' => [ 'db' => 'pgsql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '5432', /* db host port */ @@ -162,7 +173,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'update' => [ + 'update' => [ 'db' => 'pgsql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '5432', /* db host port */ @@ -172,7 +183,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'delete' => [ + 'delete' => [ 'db' => 'pgsql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '5432', /* db host port */ @@ -182,7 +193,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'schema' => [ + 'schema' => [ 'db' => 'pgsql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '5432', /* db host port */ @@ -194,37 +205,37 @@ $CONFIG = [ ], ], 'sqlite' => [ - 'admin' => [ + 'admin' => [ 'db' => 'sqlite', /* db type */ 'database' => __DIR__ . '/../Karaka/phpOMS/Localization/Defaults/localization.sqlite', /* db name */ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'insert' => [ + 'insert' => [ 'db' => 'sqlite', /* db type */ 'database' => __DIR__ . '/../Karaka/phpOMS/Localization/Defaults/localization.sqlite', /* db name */ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'select' => [ + 'select' => [ 'db' => 'sqlite', /* db type */ 'database' => __DIR__ . '/../Karaka/phpOMS/Localization/Defaults/localization.sqlite', /* db name */ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'update' => [ + 'update' => [ 'db' => 'sqlite', /* db type */ 'database' => __DIR__ . '/../Karaka/phpOMS/Localization/Defaults/localization.sqlite', /* db name */ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'delete' => [ + 'delete' => [ 'db' => 'sqlite', /* db type */ 'database' => __DIR__ . '/../Karaka/phpOMS/Localization/Defaults/localization.sqlite', /* db name */ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'schema' => [ + 'schema' => [ 'db' => 'sqlite', /* db type */ 'database' => __DIR__ . '/../Karaka/phpOMS/Localization/Defaults/localization.sqlite', /* db name */ 'weight' => 1000, /* db table prefix */ @@ -232,7 +243,7 @@ $CONFIG = [ ], ], 'mssql' => [ - 'admin' => [ + 'admin' => [ 'db' => 'mssql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '1433', /* db host port */ @@ -242,7 +253,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'insert' => [ + 'insert' => [ 'db' => 'mssql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '1433', /* db host port */ @@ -252,7 +263,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'select' => [ + 'select' => [ 'db' => 'mssql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '1433', /* db host port */ @@ -262,7 +273,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'update' => [ + 'update' => [ 'db' => 'mssql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '1433', /* db host port */ @@ -272,7 +283,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'delete' => [ + 'delete' => [ 'db' => 'mssql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '1433', /* db host port */ @@ -282,7 +293,7 @@ $CONFIG = [ 'weight' => 1000, /* db table prefix */ 'datetimeformat' => 'Y-m-d H:i:s', ], - 'schema' => [ + 'schema' => [ 'db' => 'mssql', /* db type */ 'host' => '127.0.0.1', /* db host address */ 'port' => '1433', /* db host port */ @@ -322,16 +333,16 @@ $CONFIG = [ 'password' => '123456', ], ], - 'log' => [ + 'log' => [ 'file' => [ 'path' => __DIR__ . '/Logs', ], ], - 'page' => [ + 'page' => [ 'root' => '/', 'https' => false, ], - 'app' => [ + 'app' => [ 'path' => __DIR__, 'default' => [ 'app' => 'Backend', @@ -350,7 +361,7 @@ $CONFIG = [ ], ], ], - 'socket' => [ + 'socket' => [ 'master' => [ 'host' => '127.0.0.1', 'limit' => 300, @@ -360,7 +371,7 @@ $CONFIG = [ 'language' => [ 'en', ], - 'apis' => [ + 'apis' => [ ], ]; diff --git a/tests/Controller/ApiControllerTest.php b/tests/Controller/ApiControllerTest.php index e5a7041..1651283 100755 --- a/tests/Controller/ApiControllerTest.php +++ b/tests/Controller/ApiControllerTest.php @@ -34,7 +34,6 @@ use phpOMS\Module\ModuleAbstract; use phpOMS\Module\ModuleManager; use phpOMS\Router\WebRouter; use phpOMS\System\MimeType; -use phpOMS\Uri\HttpUri; use phpOMS\Utils\TestUtils; /** @@ -61,13 +60,13 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase protected string $appName = 'Api'; }; - $this->app->dbPool = $GLOBALS['dbpool']; - $this->app->unitId = 1; - $this->app->accountManager = new AccountManager($GLOBALS['session']); - $this->app->appSettings = new CoreSettings(); - $this->app->moduleManager = new ModuleManager($this->app, __DIR__ . '/../../../../Modules/'); - $this->app->dispatcher = new Dispatcher($this->app); - $this->app->eventManager = new EventManager($this->app->dispatcher); + $this->app->dbPool = $GLOBALS['dbpool']; + $this->app->unitId = 1; + $this->app->accountManager = new AccountManager($GLOBALS['session']); + $this->app->appSettings = new CoreSettings(); + $this->app->moduleManager = new ModuleManager($this->app, __DIR__ . '/../../../../Modules/'); + $this->app->dispatcher = new Dispatcher($this->app); + $this->app->eventManager = new EventManager($this->app->dispatcher); $this->app->eventManager->importFromFile(__DIR__ . '/../../../../Web/Api/Hooks.php'); $this->app->sessionManager = new HttpSession(36000); $this->app->l11nManager = new L11nManager(); @@ -103,7 +102,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase public function testApiQAAppCreate() : void { $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('name', 'TestQAApp'); @@ -119,7 +118,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase public function testApiQAAppCreateInvalidData() : void { $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('invalid', '1'); @@ -135,7 +134,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase public function testApiQAQuestionCreate() : void { $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('title', 'Test Question'); @@ -171,7 +170,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase public function testApiQAQuestionCreateInvalidData() : void { $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('invalid', '1'); @@ -187,7 +186,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase public function testApiQAAnswerCreate() : void { $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('question', '1'); @@ -221,7 +220,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase public function testApiChangeAnsweredStatus() : void { $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('id', '1'); @@ -238,7 +237,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase public function testApiQAAnswerCreateInvalidData() : void { $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('invalid', '1'); @@ -254,7 +253,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase public function testApiChangeQAQuestionVote() : void { $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('id', '1'); @@ -264,7 +263,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase self::assertGreaterThan(0, $response->getDataArray('')['response']->id); $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('id', '1'); @@ -281,7 +280,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase public function testApiChangeQAQuestionVoteInvalidData() : void { $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('invalid', '1'); @@ -297,7 +296,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase public function testApiChangeQAAnswerVote() : void { $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('id', '1'); @@ -307,7 +306,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase self::assertGreaterThan(0, $response->getDataArray('')['response']->id); $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('id', '1'); @@ -324,7 +323,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase public function testApiChangeQAAnswerVoteInvalidData() : void { $response = new HttpResponse(); - $request = new HttpRequest(new HttpUri('')); + $request = new HttpRequest(); $request->header->account = 1; $request->setData('invalid', '1'); diff --git a/tests/Models/QAAnswerMapperTest.php b/tests/Models/QAAnswerMapperTest.php index 7d5b35e..a853288 100755 --- a/tests/Models/QAAnswerMapperTest.php +++ b/tests/Models/QAAnswerMapperTest.php @@ -35,8 +35,8 @@ final class QAAnswerMapperTest extends \PHPUnit\Framework\TestCase { $answer = new QAAnswer(); - $answer->answer = 'Answer content'; - $answer->setStatus(QAAnswerStatus::ACTIVE); + $answer->answer = 'Answer content'; + $answer->status = QAAnswerStatus::ACTIVE; $answer->createdBy = new Profile(new NullAccount(1)); $answer->question = new NullQAQuestion(1); $answer->isAccepted = true; @@ -48,7 +48,7 @@ final class QAAnswerMapperTest extends \PHPUnit\Framework\TestCase $answerR = QAAnswerMapper::get()->with('createdBy')->with('account')->where('id', $answer->id)->execute(); self::assertEquals($answer->answer, $answerR->answer); self::assertEquals($answer->question->id, $answerR->question->id); - self::assertEquals($answer->getStatus(), $answerR->getStatus()); + self::assertEquals($answer->status, $answerR->status); self::assertEquals($answer->isAccepted, $answerR->isAccepted); self::assertEquals($answer->createdBy->account->id, $answerR->createdBy->account->id); } diff --git a/tests/Models/QAAnswerTest.php b/tests/Models/QAAnswerTest.php index 85131bf..02f9ebf 100755 --- a/tests/Models/QAAnswerTest.php +++ b/tests/Models/QAAnswerTest.php @@ -15,7 +15,6 @@ declare(strict_types=1); namespace Modules\QA\tests\Models; use Modules\Admin\Models\NullAccount; -use Modules\Media\Models\Media; use Modules\QA\Models\QAAnswer; use Modules\QA\Models\QAAnswerStatus; use Modules\QA\Models\QAAnswerVote; @@ -45,35 +44,15 @@ final class QAAnswerTest extends \PHPUnit\Framework\TestCase self::assertEquals('', $this->answer->answer); self::assertEquals(0, $this->answer->question->id); self::assertFalse($this->answer->isAccepted); - self::assertEquals(QAAnswerStatus::ACTIVE, $this->answer->getStatus()); + self::assertEquals(QAAnswerStatus::ACTIVE, $this->answer->status); self::assertEquals(0, $this->answer->createdBy->id); self::assertEquals(0, $this->answer->getVoteScore()); self::assertEquals(0, $this->answer->getAccountVoteScore(0)); - self::assertEquals([], $this->answer->getMedia()); + self::assertEquals([], $this->answer->files); self::assertEquals([], $this->answer->getVotes()); self::assertInstanceOf('\DateTimeImmutable', $this->answer->createdAt); } - /** - * @covers Modules\QA\Models\QAAnswer - * @group module - */ - public function testStatusInputOutput() : void - { - $this->answer->setStatus(QAAnswerStatus::ACTIVE); - self::assertEquals(QAAnswerStatus::ACTIVE, $this->answer->getStatus()); - } - - /** - * @covers Modules\QA\Models\QAAnswer - * @group module - */ - public function testMediaInputOutput() : void - { - $this->answer->addMedia(new Media()); - self::assertCount(1, $this->answer->getMedia()); - } - /** * @covers Modules\QA\Models\QAAnswer * @group module @@ -96,9 +75,9 @@ final class QAAnswerTest extends \PHPUnit\Framework\TestCase */ public function testSerialize() : void { - $this->answer->setStatus(QAAnswerStatus::ACTIVE); - $this->answer->answer = 'Answer'; - $this->answer->answerRaw = 'AnswerRaw'; + $this->answer->status = QAAnswerStatus::ACTIVE; + $this->answer->answer = 'Answer'; + $this->answer->answerRaw = 'AnswerRaw'; $serialized = $this->answer->jsonSerialize(); unset($serialized['question']); @@ -107,13 +86,13 @@ final class QAAnswerTest extends \PHPUnit\Framework\TestCase self::assertEquals( [ - 'id' => 0, - 'status' => QAAnswerStatus::ACTIVE, - 'answer' => 'Answer', - 'answerRaw' => 'AnswerRaw', - 'isAccepted' => false, - 'votes' => [], - 'media' => [], + 'id' => 0, + 'status' => QAAnswerStatus::ACTIVE, + 'answer' => 'Answer', + 'answerRaw' => 'AnswerRaw', + 'isAccepted' => false, + 'votes' => [], + 'media' => [], ], $serialized ); diff --git a/tests/Models/QAAppTest.php b/tests/Models/QAAppTest.php index e974a0c..28ce169 100755 --- a/tests/Models/QAAppTest.php +++ b/tests/Models/QAAppTest.php @@ -53,8 +53,8 @@ final class QAAppTest extends \PHPUnit\Framework\TestCase self::assertEquals( [ - 'id' => 0, - 'name' => 'Test Title', + 'id' => 0, + 'name' => 'Test Title', ], $serialized ); diff --git a/tests/Models/QAQuestionMapperTest.php b/tests/Models/QAQuestionMapperTest.php index 3e047bc..94fa9c2 100755 --- a/tests/Models/QAQuestionMapperTest.php +++ b/tests/Models/QAQuestionMapperTest.php @@ -33,11 +33,11 @@ final class QAQuestionMapperTest extends \PHPUnit\Framework\TestCase { $question = new QAQuestion(); - $question->name = 'Question Name'; - $question->question = 'Question content'; - $question->setStatus(QAQuestionStatus::ACTIVE); + $question->name = 'Question Name'; + $question->question = 'Question content'; + $question->status = QAQuestionStatus::ACTIVE; $question->createdBy = new Profile(new NullAccount(1)); - $question->setLanguage('en'); + $question->language = 'en'; $id = QAQuestionMapper::create()->execute($question); self::assertGreaterThan(0, $question->id); @@ -46,8 +46,8 @@ final class QAQuestionMapperTest extends \PHPUnit\Framework\TestCase $questionR = QAQuestionMapper::get()->with('createdBy')->with('createdBy/account')->where('id', $question->id)->execute(); self::assertEquals($question->name, $questionR->name); self::assertEquals($question->question, $questionR->question); - self::assertEquals($question->getStatus(), $questionR->getStatus()); - self::assertEquals($question->getLanguage(), $questionR->getLanguage()); + self::assertEquals($question->status, $questionR->status); + self::assertEquals($question->language, $questionR->language); self::assertEquals($question->createdBy->account->id, $questionR->createdBy->account->id); } } diff --git a/tests/Models/QAQuestionTest.php b/tests/Models/QAQuestionTest.php index d7b2188..d0df74c 100755 --- a/tests/Models/QAQuestionTest.php +++ b/tests/Models/QAQuestionTest.php @@ -15,13 +15,11 @@ declare(strict_types=1); namespace Modules\QA\tests\Models; use Modules\Admin\Models\NullAccount; -use Modules\Media\Models\Media; use Modules\Profile\Models\NullProfile; use Modules\QA\Models\QAAnswer; use Modules\QA\Models\QAQuestion; use Modules\QA\Models\QAQuestionStatus; use Modules\QA\Models\QAQuestionVote; -use Modules\Tag\Models\Tag; use phpOMS\Localization\ISO639x1Enum; /** @@ -49,14 +47,14 @@ final class QAQuestionTest extends \PHPUnit\Framework\TestCase self::assertEquals('', $this->question->name); self::assertEquals('', $this->question->question); self::assertEquals('', $this->question->questionRaw); - self::assertEquals(QAQuestionStatus::ACTIVE, $this->question->getStatus()); - self::assertEquals(ISO639x1Enum::_EN, $this->question->getLanguage()); + self::assertEquals(QAQuestionStatus::ACTIVE, $this->question->status); + self::assertEquals(ISO639x1Enum::_EN, $this->question->language); self::assertEquals(0, $this->question->createdBy->id); self::assertInstanceOf('\DateTimeImmutable', $this->question->createdAt); self::assertFalse($this->question->hasAccepted()); self::assertEquals([0 => 0], $this->question->getAccounts()); // includes createdBy - self::assertEquals([], $this->question->getTags()); - self::assertEquals([], $this->question->getMedia()); + self::assertEquals([], $this->question->tags); + self::assertEquals([], $this->question->files); self::assertEquals([], $this->question->getAnswers()); self::assertEquals([], $this->question->getAnswersByScore()); self::assertEquals(0, $this->question->getVoteScore()); @@ -64,65 +62,6 @@ final class QAQuestionTest extends \PHPUnit\Framework\TestCase self::assertEquals(0, $this->question->getAnswerCount()); } - /** - * @covers Modules\QA\Models\QAQuestion - * @group module - */ - public function testStatusInputOutput() : void - { - $this->question->setStatus(QAQuestionStatus::ACTIVE); - self::assertEquals(QAQuestionStatus::ACTIVE, $this->question->getStatus()); - } - - /** - * @covers Modules\QA\Models\QAQuestion - * @group module - */ - public function testLanguageInputOutput() : void - { - $this->question->setLanguage(ISO639x1Enum::_DE); - self::assertEquals(ISO639x1Enum::_DE, $this->question->getLanguage()); - } - - /** - * @covers Modules\QA\Models\QAQuestion - * @group module - */ - public function testMediaInputOutput() : void - { - $this->question->addMedia(new Media()); - self::assertCount(1, $this->question->getMedia()); - } - - /** - * @covers Modules\QA\Models\QAQuestion - * @group module - */ - public function testTagInputOutput() : void - { - $tag = new Tag(); - $tag->setL11n('Tag'); - - $this->question->addTag($tag); - self::assertEquals($tag, $this->question->getTag(0)); - self::assertCount(1, $this->question->getTags()); - } - - /** - * @covers Modules\QA\Models\QAQuestion - * @group module - */ - public function testTagRemove() : void - { - $tag = new Tag(); - $tag->setL11n('Tag'); - - $this->question->addTag($tag); - self::assertTrue($this->question->removeTag(0)); - self::assertCount(0, $this->question->getTags()); - self::assertFalse($this->question->removeTag(0)); - } - /** * @covers Modules\QA\Models\QAQuestion * @group module @@ -165,10 +104,10 @@ final class QAQuestionTest extends \PHPUnit\Framework\TestCase public function testSerialize() : void { $this->question->name = 'Test Title'; - $this->question->setStatus(QAQuestionStatus::ACTIVE); - $this->question->question = 'Question'; - $this->question->questionRaw = 'QuestionRaw'; - $this->question->setLanguage(ISO639x1Enum::_DE); + $this->question->status = QAQuestionStatus::ACTIVE; + $this->question->question = 'Question'; + $this->question->questionRaw = 'QuestionRaw'; + $this->question->language = ISO639x1Enum::_DE; $serialized = $this->question->jsonSerialize(); unset($serialized['app']); @@ -177,16 +116,16 @@ final class QAQuestionTest extends \PHPUnit\Framework\TestCase self::assertEquals( [ - 'id' => 0, - 'name' => 'Test Title', - 'status' => QAQuestionStatus::ACTIVE, - 'question' => 'Question', - 'questionRaw' => 'QuestionRaw', - 'language' => ISO639x1Enum::_DE, - 'tags' => [], - 'answers' => [], - 'votes' => [], - 'media' => [], + 'id' => 0, + 'name' => 'Test Title', + 'status' => QAQuestionStatus::ACTIVE, + 'question' => 'Question', + 'questionRaw' => 'QuestionRaw', + 'language' => ISO639x1Enum::_DE, + 'tags' => [], + 'answers' => [], + 'votes' => [], + 'media' => [], ], $serialized );