User facing application for the Wikimedia Deutschland fundraising.
The easiest way to get a working installation of the application is to use Vagrant.
Just get a clone of our git repository and run vagrant up
in it. Then vagrant ssh
into it and go to /vagrant
, where you will be able to run the full test suite. (Excluding a handful of payment provider system tests).
Get a copy of the code and make sure you have Vagrant installed.
Inside the root directory of the project, execute
vagrant up
vagrant ssh
Once you're ssh'd into the VM, you can find the application installed in /vagrant
.
At this point you will be able to run nearly all of the tests (those that you cannot run will be
skipped automatically). To run the system tests and get the app to fully show in your browser,
you will need to do additional configuration, as per the configuration section.
System dependencies:
- PHP >= 7.1 with the following extensions:
- curl
- intl
- kontocheck (only needed when you want to use or test direct debit)
- mbstring
- sqlite3
- xml
- Node.js and npm (only needed in development for compiling the JavaScript and running the JavaScript tests)
Get a clone of our git repository and then run these commands in it:
composer install
npm install
npm run build-js
For the database connection you need to create the file app/config/config.prod.json
and enter your database
connection data. If you're using MySQL, it's important to add the encoding to the driverOptions
key.
"db": {
"driver": "pdo_mysql",
"user": "donations_user",
"password": "s00pa_s33cr1t",
"dbname": "all_donations",
"host": "localhost",
"charset": "utf8",
"driverOptions": {
"1002": "SET NAMES utf8"
}
}
For a fully working instance with all payment types and working templates you need to fill out the following configuration data:
- `bank-data-file`
- `operator-email`
- `operator-displayname-organization`
- `operator-displayname-suborganization`
- `paypal-donation`
- `paypal-membership`
- `creditcard`
The application needs a copy of the content repository at https://github.com/wmde/fundraising-frontend-content to work properly. On development machines, the content repository is in the composer dev-dependencies. If you put the content repository in another place, you need to configure the paths to it. The following example shows the configuration when the content repository is at the same level as the application directory:
"twig": {
"loaders": {
"filesystem": {
"template-dir": [
"../fundraising-frontend-content/ab_test/a/templates",
"../fundraising-frontend-content/ab_test/b/templates",
"../fundraising-frontend-content/templates",
"../fundraising-frontend-content/i18n/%_locale_%/pages"
]
}
}
},
"i18n-base-path": "../fundraising-frontend-content/i18n"
For development
cd web
php -S 0:8000
The "add donation" form can then be found at http://localhost:8000/index.php
Full CI run
composer ci
For tests only
composer test ; npm run test
For style checks only
composer cs ; npm run cs
PHP
For tests only
composer test
For x (unit/integration/edgetoedge) tests only
vendor/bin/phpunit --testsuite=x
For one context only
vendor/bin/phpunit contexts/DonationContext/
JS
For a full JS CI run
npm run ci
If JavaScript files where changed, you will first need to run
npm run build-js
If you are working on the JavaScript files and need automatic recompilation when a files changes, then run
npm run watch-js
If you want to debug problems in the Redux data flow, set the following variable in the shell environment:
export REDUX_LOG=on
Actions and their resulting state will be logged.
For an in-depth documentation how deployment on a server is done, see the deployment documentation.
When accessing the API via web/index.dev.php
, profiling information will be generated and in
app/cache/profiler
. You can access the profiler UI via index.dev.php/_profiler
.
This codebase follows a modified version of The Clean Architecture, combined with a partial application of Domain Driven Design. The high level structure is represented by this diagram.
src/
: framework agnostic code not belonging to any Bounded ContextFactories/
: application factories used by the framework, including top level factoryFFFactory
Presentation/
: presentation code, including thePresenters/
Validation/
: validation code
contexts/$ContextName/src/
framework agnostic code belonging to a specific Bounded ContextDomain/
: domain model and domain servicesUseCases/
: one directory per use caseDataAccess/
: implementations of services that binds to database, network, etcInfrastructure/
: implementations of services binding to cross cutting concerns, ie logging
web/
: web accessible codeindex.php
: production entry point
app/
: contains configuration and all framework (Silex) dependent codebootstrap.php
: framework application bootstrap (used by System tests)routes.php
: defines the routes and their handlersRouteHandlers/
: route handlers that get benefit from having their own class are placed hereconfig/
: configuration filesconfig.dist.json
: default configurationconfig.test.json
: configuration used by integration and system tests (gets merged into default config)config.test.local.json
: instance specific (gitignored) test config (gets merged into config.test.json)config.prod.json
: instance specific (gitignored) production configuration (gets merged into default config)
js/lib
: Javascript modules, will be compiled into one file for the frontend.js/test
: Unit tests for the JavaScript modules
var/
: Ephemeral application datalog/
: Log files (in debug mode, every request creates a log file)cache/
: Cache directory for Twig templates
The test directory structure (and namespace structure) mirrors the production code. Tests for code
in src/
can be found in tests/
. Tests for code in contexts/$ContextName/src/
can be found in
contexts/$ContextName/tests/
.
Tests are categorized by their type. To run only tests of a given type, you can use one of the
testsuites defined in phpunit.xml.dist
.
Unit/
: small isolated tests (one class or a small number of related classes)Integration/
: tests combining several unitsEdgeToEdge/
: edge-to-edge tests (fake HTTP requests to the framework)System/
: tests involving outside systems (ie, beyond our PHP app and database)Fixtures/
: test doubles (stubs, spies and mocks)
If you need access to the application in your non-unit tests, for instance to interact with
persistence, you should use TestEnvironment
defined in tests/TestEnvironment.php
.
Database (in memory) | Top level factory | Framework (Silex) | Network & Disk | |
---|---|---|---|---|
Unit | No | No | No | No |
Integration | If needed | Discouraged | No | Read only |
EdgeToEdge | Yes | Yes | Yes | Read only |
System | Yes | Yes | Yes | Yes |
deployment/
: Ansible scripts and configuration for deploying the application
- Rewriting the Wikimedia Deutschland fundraising - blog post on why we created this codebase
- Implementing the Clean Architecture - blog post on the architecture of this application