Today, I was cleaning up the code, trying to get the report page work
again. Got it working finally :) The report wizard consists of two
pages, the first one allows to choose the module, and the second is for
entering details. One thing I don't like that much is that I have to
call API::getClass('Bug'); in order to call Bug::createNew(), but I
don't think there is a much cleaner or better solution (moving static
code from the bug class into a bug module would just cause confusion).

Hopefully I'll be able to finish those next week, as I plan to stop
active development on the bugtracker in two weeks. I'll keep on fixing
bugs, but I'm going to focus on my 3D engine.

Bugtracker on SVN

The complete bugtracker source code is now in a dedicated
Subversion repository. Later, I'm gonna
open this repository for a friend so he can keep on maintaining the
bugtracker while I'm working on the 3D engine.

After adding a custom error handler to my bugtracker, the ADOdb library
didn't work properly any longer - debug output caused a script error.
All other functions worked right. This was with ADOdb 4.4x, today, I
upgraded to the latest (4.54) and it stopped working at all.
Fortunately, I found a solution: I include ADOdb before setting up my
error handler. This seems to work fine so far, no errors while including
ADOdb, and yet it does call my custom handler when an error occurs
later.

New editor

I've switched to a new text editor - Programmer's
Notepad. It has a built in file explorer, a
feature I've been missing from
Notepad++. Programmer's Notepad
is comparable fast, and supports even more languages.

API progress

I've modified modules to support a one-time init()-call, which allows
a module to perform static data initialisation. There has been also a
lot of refactoring in the API, a new Utility class encapsulates much of
the framework's static functions. Moreover, a new ErrorHandler class
provides a custom error handler that print backtraces in case of fatal
errors. For some reasons, it does not work together with ADOdb yet, will
have to investigate that further.

Frontend code

Much of the code that has been in the frontend files is now part of the
API, and the remaining code is really just frontend code - data
validation and preparation for the template engine. At the moment, most
of the code is broken, but I'm working on it. I hope the bug report code
will work again this weekend.

Misc changes

Versions and builds can be tagged as "released" now. Only released
versions and builds appear in the report screen, all other are treated
as milestone builds. I've created a JScript based version/build choose
screen, where the user selects the version first and is allowed to
select a valid build or none, in case the exact build is unknown. Looked
quite simple, but the JScript code turned out to be rather ugly (for
example, I'm clearing the build select field using
b_select.innerHTML = '' as there is no clear() function for the
OptionsCollection). I really don't like it, but as it does its job, I'll
keep it in. The alternative would be to add yet another page to the Bug
Report Wizard, but I don't want to expand the current two step wizard
for such a small thing.

Flag system

During the build/version system rewrite, I recognized how important a
flag system is. Previously, I thought it would be easiest to tag bugs
for example with stuff like "blocks version X", but that would be quite
a rigid system with a few, hardcoded flags. I wanted a system where
every project, module or bug could be tagged with an unlimited number of
flags. But this creates some problems:

How to store the flags?

How to allows different flags for different modules?

My first idea was to create a flag table per flag group, with each
column being a flag. Obviously, this system won't scale very well. The
next idea would be to store one entry per flag per bug it concerns. A
quick calculation shows this won't work, at least not the obvious way.
Let's assume there are 5.000 bugs in the database, and we add 3 flags -
makes 15.000 new database entries that would have to performed when you
click the "Add flag" button. The solution is to make 3-state flags:
True, False, Not set. When a bug is show, and a flag has not been found
in the flag table, the status is unknown. This delays the creation of
flag entries until really needed and will become the system I'm gonna
implent once the bug reporting is working again. So much for now!

In case you wonder why I didn't post for some days... On Friday, my
480W PSU arrived, and I got my new comp up & running! Yeah! :) Had to
move my development environment from my old disk to the new one, install
all the tools I'm used to etc. so I didn't have time for updating my
blog. It really rocks, and although it sports 7 fans, it's damn silent
(thanks to temperature control). Really comfortable. After looking at
the Mantis source code, I also started thinking about some API for my
bugtracker. It should allow plugin developers to access core
functionality in a clean, consistent manner, and also separate the core
functions from the processing logic and the display logic.
**Bugtracker API** At the moment, the API does support modules and
classes. The difference between the two is: - A class is - well, a
class, that needs an instance in order to work properly, as it stores
some local data. An example is the Bug class, after a `getData()` call
it stores the results for reuse. Classes can be loaded by the API using
`API::getClass ('className', [... constructor]);`. In order to get
this working, two things have to happen: - A class instance has to be
created. - The constructor needs to be called Unfortunately, I couldn't
find a way to call the class constructor directly, so I use this
workaround: `$instance = @new $class_name (); // Silence the missing
parameters call_user_func_array (array (&$instance, '__construct'),
$args); // Now the real one` This one does work, the warning that
parameters are missing is silenced and everything is fine. - Modules are
basically classes that have only static methods - there is no need to
create a class instance, you can directly call the functions. They're
accessed using `API::getModule ('moduleName');`. I'll move over all
includes I can find to the API and try to clean up the code a bit before
I continue working on the bugtracker. Sty tuned :)

I reached an important milestone - the bugtracker does track its own
bugs now. This means it is already possible to enter new bugs and to
edit the existing ones. Next thing I'll take a look at is the bug
history that should be created every time a bug is updated, and the
comment system. The comments should work (as I entered two into the DB
by hand and those are handled right), but you can't enter new comments,
and that will cause probably some problems. The current plan looks like
this:

Add bug history

Finish comment support

Clean up report/edit page, possibly merge the two into one

Fix some smaller bugs with the output

Add user managment

Add project managment

This is not the full roadmap, but just what I'll do next week when time
allows (and if my new comp does not arrive :) )

Lately, I took a closer look at the bugtracker, and entered some sample
data into the database. Here you can see the current bug detail page:
Detail page, 35kb. Hopefully I'll be
able to create the enter bug page tomorrow. By the way, ordered a new
PSU, hopefully I'll be able to start my new comp next week. Fingers
crossed :) The bugtracker is currently designed with the following
target plattform in mind: Apache 2.0 (maybe
I'll use mod_rewrite to get pretty links like bugtracker/bug/232
instead of bug.php?id=232), PHP5 (as it's quite
object oriented, and I plan to use the XML extensions) and
PostgreSQL (as it has foreign keys, views
and is very reliable). The target browser is
Firefox, as it's my primary browser and I hate
working around IE's CSS quirks and bugs. It's getting on pretty well,
less problems than I expected. There is still a small design problem:
All more or less static data like the various priority levels are also
stored in the DB and read out every time for example the bug page is
called - though they don't change. Their purpose is to serve as foreign
key targets, and I think I'll put all those queries (8 by now) into a
special cache class that is only updated when the data in the database
changes, and otherwise it'll run directly from disk, saving those 8
queries. I'm quite curious to see how much faster it'll get, as the
database is very fast. I think I won't cache the various program
versions. They also don't change often, too, but they aren't needed in
every report page, so it won't be a big deal when they're loaded from
time to time. Something interesting I found out in this context: Let's
assume you have a table with two columns, id and name and you have a
query like that: SELECT * FROM table;. This code does run around half
as fast as this one: SELECT id, name FROM table;. The server load is
higher, anyway, the result set was returned twice as fast (only 7 rows).
This is tested with PostgreSQL 8.0.0 under Windows XP with enough RAM to
hold the whole database. Quite strange, but I use the second style
anyway for the sake of clarity.