InterpretersOffice: court interpreter management system (Laminas MVC, Doctrine ORM)

Ladies and gentlemen: I am pleased to introduce the finest court interpreter management system the world has ever known.

I have been working on this project basically for 20 years. You could say I’m a programmer with a one-project career (so far). The story is that when I started my employment as a federal staff court interpreter in the 1990s, we were running our office with pen and paper, and it was not scaling well. But we could find no software product, commercial or otherwise, that was remotely adequate to our peculiar requirements. Even today there really is nothing else out there, to the best of my knowledge. Anyway: I set about creating our own solution for us with MySQL and PHP. Been working on it – single-handedly – ever since, updating it to keep up with the times (and changing requirements, and lessons learned, and my improving skills). The latest and greatest iteration has a name: InterpretersOffice.

The github repo: https://github.com/davidmintz/court-interpreters-office

The project website (don’t laugh, I know it’s crude): https://interpretersoffice.org.

The app requires authentication in order to do anything interesting, so I can’t really point to a public production website. We do have a demo of sorts: https://demo.interpretersoffice.org.

One more thing: I am soon to retire from my federal court gig, leaving this beast behind. No one in the organization has a clue about this except me. Some hapless IT dudes plan to assume partial responsibility for maintenance, and have encouraged me to create prose documentation. So, I have written a lot of words for https://interpretersoffice.org/documentation, sort of a cross between documentation of the app and a tutorial on Laminas MVC. It is asking way too much to ask you guys to review it – too long, too boring. But if you should happen to skim it and something jumps out at you that you want to comment on, by all means.

Thanks!

2 Likes

I find this work fascinating. I too have a 20+ year project.

You have a well coded project with some ragged edges. You need

  • Docker
  • Doctrine Fixtures
  • Entity Relationship Diagram
  • Migrations
  • Change entities from annotations to XML metadata
  • Documentation to .rst
  • Remove all .sql files in ~/bin

Look for a Docker PR soon.

Hey, thank you for looking at this and commenting. Your feedback has stimulated a number of thoughts and questions in return – I hope you don’t end up regretting opening the door! :grinning:

It’s interesting to work on a problem for 20 years. There are pros and cons, right? (I sometimes joke to myself, yo, I have been writing Javascript since 1998. But that is not necessarily an advantage! I sometimes wonder if I’d have been better off if I never heard of it till about five years ago and then jumped in with both feet.)

  • Docker. Yes. I probably shouldn’t undermine my brand by publicly confessing my ignorance, because I might want to go out and sell my services as a freelancer, but… Docker is something I have played around with, but have yet to learn and understand well. I didn’t even fully grasp the advantage of it until I had kind of a duh! moment while thinking about the possibility of others actually adopting my app, thinking, gee, it’s best if their environment is x, y, z… wouldn’t it be nice if I could provide some kind a self-contained unit including everything they need… hey wait… So, were I to dockerize this, should it be a monolithic docker image with the OS, webserver, php, etc rolled into one? Or a whatever… I have to go do more homework to learn the terminology. And I eagerly look forward to your PR.

  • Doctrine fixtures? I have some of those, or at least I think that’s what they are :slight_smile: Another confession: I’m no phpunit guru and my automated tests are not the state of the art. They’re better than nothing, no doubt.

  • Entity Relationship Diagram. Back when the ZendDeveloperToolbar thing used to work with Doctrine, there was a thing that would generate a PNG but that all broke down with the Laminas migration. Then I discovered https://dbdiagram.io/ and created https://dbdiagram.io/d/5ed5abe839d18f5553001627 It’s a little horrifying how complex it is, and it doesn’t even represent the whole thing. But: does that qualify as an ER Diagram?

  • Migrations. Another thing that I have read a little about but haven’t mastered or become convinced that I needed it. I have had a couple situations where I’ve changed a table’s structure after the app was in production in multiple locations and it was a bit of a pain, going around manually running ALTER TABLE… So I’ve been checking out Doctrine Migrations. Would that be a good choice?

  • Annotations vs XML. Sometimes I do find the annotation syntax cumbersome as hell, but other than that, why do you think XML is a better choice? Just for the sake of separating it from the model’s source code?

  • Documentation to .rst – my prose documentation is markdown (e.g. https://github.com/davidmintz/court-interpreters-office/tree/master/docs/documentation), which appears to me similar to RST and a reasonable choice. Plus, I thought I was hip and with-it because I’m using Jekyll to generate the project website. But seriously – what’s the advantage of RST over markdown?

  • Remove all .sql files in ~/bin. Yeah I have wondered about that. Some of what’s in my bin/sql is crap I no longer need but some of it is required to set up the application. Where would you have me put it?

Another question. Do you think I should create a package on Packagist for this? It seems like people usually publish libraries, components, tools, rather than entire applications. But I’ve also been told there’s no rule against publishing entire applications on Packagist. Anyway it seems that would make it possible to simplify installation enormously.

What you’re calling fixtures are actually faker data. However faker data can be inserted using fixtures.
The way I was using the term is to replace this: https://github.com/davidmintz/court-interpreters-office/blob/master/bin/sql/initial-data.sql with an actual fixture: see (a)

ERD: See https://skipper18.com I am sponsored by this product/company and have been using it since 2011. It will create your XML metadata too.

Migrations: are you using the ORM schema tool to create your database? No? Then you need migrations.

.rst is professional documentation. You can research the Sphinx engine to learn more.

.sql: You should never have .sql files in any database project.

(a)

<?php

namespace Ebay\Fixture;

use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Ebay\Entity\Role;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;

class RoleFixture implements
    FixtureInterface
{
    const GUEST_ID = 1;
    const USER_ID = 2;
    const ADMIN_ID = 3;

    const GUEST = 'guest';
    const USER = 'user';
    const ADMIN = 'admin';

    public function load(ObjectManager $objectManager)
    {
        $hydrator = new DoctrineHydrator($objectManager, false);

        $data = [
            [
                'id' => self::GUEST_ID,
                'roleId' => self::GUEST,
                'parent' => null,
            ],
            [
                'id' => self::USER_ID,
                'roleId' => self::USER,
                'parent' => self::GUEST_ID,
            ],
            [
                'id' => self::ADMIN_ID,
                'roleId' => self::ADMIN,
                'parent' => self::USER_ID,
            ],
        ];

        foreach ($data as $row) {
            $entity = $objectManager
                ->getRepository(Role::class)
                ->find($row['id']);

            if (! $entity) {
                $entity = new Role();
            }

            if ($row['parent']) {
                $row['parent'] = $objectManager
                    ->getRepository(Role::class)
                    ->find($row['parent']);
            }

            $hydrator->hydrate($row, $entity);
            $objectManager->persist($entity);

            $objectManager->flush();
        }
    }
}