Skip to content
Richard Thomson edited this page Oct 9, 2019 · 2 revisions

Prerequisites

Manx assumes PHP 5.5 and a MySQL database. The unit tests assume PHPUnit 6.

Directory Structure

The source directories for manx are organized as follows:

  • the main directory contains the user browsable applciation pages, e.g. search.php
  • assets: CSS and JavaScript files for use in rendering pages
  • cron: PHP source files for periodic tasks
  • pages: PHP source files for classes and interfaces that make up the application
  • schema: SQL source files that evolve the schema
  • test: PHP source files for the unit tests

Deployment

Database

Create a blank MySQL database and a set of database credentials for the database. Evaluate the SQL files in the schema directory in numerical order. This builds the initial database schema and evolves it to match the current implementation.

Files

The following repository files need to be deployed on the web server:

  • main directory *.php
  • assets directory
  • cron directory if you want to run periodic tasks
  • pages directory

Create a file called pages/Config.php that calles define to create a value for PRIVATE_DIR that is a path (relative or absolute) from the application directory to the location of config.txt. Usually PRIVATE_DIR is defined to a location that can't be served by URL browsing. This prevents the SQL database connection information from being accessible to web clients.

Create a file called config.txt in PRIVATE_DIR that contains the connection string for your database, e.g. mysql:host=localhost:dbname=manx foo bar for a local host MySQL database named manx, user foo and password bar.

Layered Architecture

To facilitate unit testing of all the functionality, manx is organized into a small set of layers. The bottom most layer is IDatabase that provides a small basic operations on a database via SQL queries, e.g. INSERT, SELECT, UPDATE, DELETE, etc. At this layer, IDatabase looks like a PDO database in PHP.

The next layer is IManxDatabase that exposes the database in terms of application domain objects: companies, publications, etc. Pages that create, read, update or delete information in the database use IManxDatabase to perform the necessary operations. If transactions are necessary in order to ensure consistency across multiple SQL statements, this is handled by IManxDatabase and to the caller, the updates appear atomic.

Each different page in the application is represented by the instance of a corresponding class object for that page. The main directory PHP file, e.g. search.php, is responsible for instantiating the class for the page and invoking the renderPage method to produce the page output. The main directory PHP files consist only of PHP and no HTML output so that the PHP code for the page can control the contents of the headers for the response to the HTTP request that caused the page to be rendered. This enables redirects, among other things.

All simple page classes derive from PageBase in pages/PageBase.php. PageBase takes care of consistent styling across pages by referencing the main CSS file in the head of the HTML for the page and rendering the top banner and the menu items underneath the top banner. Each page class responds to any input parameters and renders the necessary HTML for the page to the standard output.

Administrative pages derive from AdminPageBase in pages/AdminPageBase.php, which in turn derives from PageBase. AdminPageBase takes care of rendering the administrative menu and ensures that all administrative tasks are only performed by logged in users. An attempt to load the administrative page without being logged in results in a redirect to the login page using HTTPS and a redirect back to the requested page after a successful login.

Most pages don't use any JavaScript, but the UrlWizardPage for adding documents via a URL makes extensive use of AJAX calls back to manx to assist in filling out database information. The AJAX calls are serviced by url-wizard-service.php in the main directory. The UrlWizardService class in pages/UrlWizardService.php responds to the AJAX requests with JSON responses. UrlWizardService derives from ServicePageBase that contains common elements for AJAX service endpoints. The UrlWizard JavaScript is written using jQuery and a minified version of jQuery is in the assets folder.

Unit Testing

All unit tests are written assuming PHP 5.5 and PHPUnit 6. The composer.json file can be used to get a local installation of PHPUnit to run the tests. Run composer install to download and install PHPUnit 6 in the vendor directory. To run the tests execute the command vendor/bin/phpunit test/AllTests.php.

To assist in unit testing, all concrete classes collaborate with other classes through interfaces, e.g. "details depend on abstractions". The interfaces are defined in the pages/I*.php files. Collaborators with a class can be supplied as optional constructor arguments for the class. If those optional arguments are missing, the class instantiates the production implementation of the collaborator. Most simple pages depend only on IManx from which they can get IManxDatabase for application level operations.

In unit tests, dependencies are created with PHPUnit mocks and injected into the class under test as arguments to the constructor. Each test sets expectations on the collaborators which are automatically validated at the end of the test by the PHPUnit mocks.

Each set of related tests is grouped by a PHPUnit test fixture and each test PHP source file is considered to be a test suite. The PHP file test/AllTests.php loads all the other PHP test files and adds them as test suites in PHPUnit.