This task was done according to challenge_software-engineer_php.md which must be located in the very same directory as this README.md.
Please put your apikey
into config.php
. Script will be working without it only in a textual demo mode; in this case you have to specify it as a command line parameter api_key (see below).
There are two ways to run the demo script: as a command line tool (index.php
) and as a widget (widget.php
).
Example command to output 20 games for today with US-format for the date:
php index.php --date_format="l, m/d/y" --days_future=1 --games_daily=20 vs_separator=' - '
Available options:
date_format
: date format (as in PHP DateTime implementation)time_format
: time format (as in PHP DateTime implementation)days_future
: how many days to fetch games for (1 means today only)games_daily
: how many top games to fetch for each dayvs_separator
: string to concatenate participating teamsteam_name
: what field to use as a name of the team (fullname
,shortname
ormicroname
)competition_name
: what field to use as a name of the competition (name
,shortname
ormicroname
)api_key
: if for any reason you don't want to set your API key inconfig.php
, you can pass it via this option
All parameters are optional as the code contains default values. Also, there's no validation of the parameters since we are not exposing them to the end user.
Simply open widget.php
in your browser (via web-server, of course). It will read the API key from the config.php
and will make one call to the Matches
class with the following options:
['date_format'=>"d.m.Y",'time_format'=>"H:i",'days_future'=>3,'games_daily'=>15]
The widget intentionally has no design (other than default bootstrap styling for tables) and doesn't use any template engines as this is out of the scope of this assignment.
Since I have no documentation for the API but can access the actual data, I've assumed all strings are UTF-8. Also, I've put someone else's implementation of mb_str_pad()
function from github to make command line tool print tidy textual tables (PHP doesn't support multi-byte strings in native str_pad()
function).
Again, I don't have the API documentation, but my testing shows that all the timestamps in the API are GMT. I've assumed that kick-off times and expiration timestamps are GMTs. The application is generating all the output according to local timezone which can be configured in config.php
(currently set to Europe/Vienna
). Also there's a tricky moment with the matchdate_to
parameter - we need to send not GMT midnight, but midnight in our timezone converted to GMT. This way we guarantee that response has no matches starting after the our local midnight on the last day (no need to filter them out).
I've implemented very basic caching to speed up the response time. The caching is based on an URL that we need to fetch. I hash the THE with md5()
and check local storage for that hash. Then I check if the local version of that file has not expired yet. If it's still good, I omit the HTTP request for that particular URL and use locally saved response instead. Cache lifetime is stored as the file modification time (good cache file has its modification time in the future). I'm using expires
field from the response as a cache lifetime.
I'm using local filesystem as a storage, directory can be configured in config.php
; by default it's var/cache
and it must be writeable or caching won't work.
Note: there's no cleaning of the expired cache files (other than during the request). In a production-like environment it should be fixed.
This implementation contains no tests. The code is split into 3 independent classes: Matches
, Client
, and Cache
to comply with the single-responsibility principle and make testing easier: test the Cache
separately (doesn't depend on anything), test the Client
separately (doesn't need to do anything besides fetching data), test the Matches
separately (doesn't need real API responses to do the filtering/sorting according to $options
passed).
- Clean expired cache
- Introduce higher level of caching - besides caching per URL, cache per
Matches::get()
request within the same set of$options
passed. Usemin(expires)
of response pages as a lifetime for this accumulative cache. This cache will reduce number of file reads and further parsing of the JSON data. - Implement tests
- Handle more exceptions
- Validate parameters entered by the user (maximum number of days, maximum number of matches per day etc)
- Follow some code formatting rules
- Write phpdoc-styled comments for methods