This post may be fairly technical, but considering the main target of a bug tracking and project management software suite, I think you will all do just fine.
The Bug Genie is an “old” project – when it comes to code, some of the concepts used and when it comes to people. By people I mean old people, like your eccentric grandmother who only brushes her teeth on Wednesdays and smells like rosemary. In a good way of course, The Bug Genie is like that. The codebase for the current release version of The Bug Genie was started at a time before there were established PHP coding standards and best practices. Before Github, Composer and many other frameworks were even available, before PHP 5.3 was released there was The Bug Genie.
What am I getting at? Read on for more details.
This isn’t to brag about the age, it’s a background story for the current state of The Bug Genie codebase. Some of the concepts doesn’t really play along nicely with the way we write PHP code nowadays. With the introduction of PSR-0 + PSR-1 and even more so PSR-2 + PSR-4, there are now well established naming conventions and best practices for writing and structuring PHP code. All the work done by the people behind these PSR definitions have made life a whole lot easier and more pleasant for all PHP developers.
As a result of this work, we now have software like Composer and Packagist, which provides a one-stop shop for packaging up and providing PHP software and libraries to both end users and developers. The Bug Genie already uses and ships with several libraries also available in the Packagist repositories.
Rewrite, rewrite, rewrite
It is becoming painfully obvious that the inner workings of The Bug Genie is in need for an update and upgrade. We’ve already had several commits and pull requests to help The Bug Genie 3.3 work better with composer, as well as pulling in some of the required libraries via composer, instead of distributing them via The Bug Genie packages. However, for a full Composer and PSR-* compliant experience, some of the internal structure had to change – and this wasn’t for anyone to just rip out the pieces and put them back in a new, “correct” order.
There’s already been done a whole lot of refactoring, optimization and standardisation in the 3.3 codebase by several contributors. The final step, however, completely breaks backwards compatibility in a variety of ways. Explanations below.
All configuration files are now located in core/config, using a standard YAML format.
The first file you’ll find in here is the database configuration file. Previously, this file was auto-generated by the database layer and structured such that it needed to be included inside the database layer (using calls such as self::setDSN()). The new configuration file simply lists the database configuration in YAML format, making changing or replacing this file much easier.
Routes have previously been loaded via two files, “load_routes.inc.php” and “load_routes_postmodules.inc.php”. However, the routes in this file did not really give much information, and were a bit messy to maintain. This has been merged into one routes.yml file (core/config/routes.yml), and modules wishing to provide new routes (pages, basically) will use the same mechanism inside their modules folder (modules\publish\config\routes.yml as an example). This makes route caching a lot easier, and maintaining routes is now much less painful.
In addition to these configuration files, there is also a settings.yml for non-essential configurable settings such as turning debug mode or caching on or off. This file does not exist to provide functionality settings – it is solely for framework or core settings which does not make sense to expose via an interface.
The core classes (TBGContext, TBGProject, TBGIssue, etc) have not been touched. They still live in core\classes and core\classes\B2DB and are autoloaded from here.
All modules have up until now resided in the modules/ folder. This made sense to begin with, but then we also put external modules in the same folder, and there hasn’t really been any way to distinguish between “internal” and “external” modules – they’ve behaved very similar, and at the same time they haven’t. This has changed. All internal modules are now in the core/modules folder, and are namespaced as \thebuggenie\core\modules\* – for example, the previous “mainActions” class (which provided actions for the main “module”) is now \thebuggenie\core\modules\main\Actions, and “mainComponents” is now \thebuggenie\core\modules\main\Components, and the same goes for all other internal modules. These modules are not meant to be touched, extended or replaced.
External modules now lives in the modules/ folder. Any module in this folder can be safely removed (and new modules are added here), and these modules have to be namespaced as \thebuggenie\modules\*, with the main module class named as ucfirst(module_name). All modules are also expected to namespace any provided classes and constants, including database classes. The Bug Genie ships with four optional modules by default: LDAP authentication, Mailing, Wiki and VCS integration, and all these modules are now namespaced by their module names. An example is the wiki module (previously called TBGPublish) which is now \thebuggenie\modules\publish\Publish. Its namespaced database classes were TBGWikiArticles and TBGArticlesTable, which are now \thebuggenie\modules\publish\entities\Article and \thebuggenie\modules\publish\entities\b2db\Articles.
As you can understand, implementing and changing all this has not come easy, and if you are not used to namespacing in PHP, this may all sound like a lot of mumbo jumbo – but it has some real nice benefits.
Standardising class names, module names and namespace rules helps the autoloader find classes. It also provides a basic structure around the class hierarchy and file locations, which helps anyone looking at your (and our) code for whatever reason they’re looking at it. With the changes above, there is no longer a need for TBG to have its own autoloading mechanism, and instead fall back on a standardised solution. Such as?
Composer and Packagist
If you don’t know what Composer is or does, go ahead and read about it. If you don’t know what Packagist is either, you should have a look at that, too. Explained *very* briefly, it provides and apt-get + repository-like software and structure for PHP applications and libraries (that’s not all, but it’s what most people will use it for, and it does that job in an excellent way). If you don’t know what apt-get is then go read a book instead, I recommend “The call of the wild”.
At the core of any Composer-compatible software and library lives the composer.json file, which provides information about the software itself, required software (such as PHP >= 5.3), class naming (autoloading), required libraries (including versions) and more. If any of these libraries are on Packagist, Composer is able to download and install these for you, and it also provides a standard autoloader for classes following either PSR-0 or PSR-4 (and some fallback mechanisms). The Bug Genie now includes its own composer.json file to handle all the different libraries and dependencies used by The Bug Genie (and there are quite a few), including our own database layer b2db, which is also made available on Packagist.
All the effort put into this has been to make The Bug Genie more standards compliant, easy to work with and efficient. It gives us much less headache when switching between different libraries and helps people contributing to work better with The Bug Genie. In the end, The Bug Genie will also be published on Packagist – as version 4.0.
More on that in a new blog post.