Creating a simple ticketing system with Semantic MediaWiki

Good, easy to use, ticketing systems are few and far between. Most cost a lot of money; others are free, but lack features; some are free but have way too many features that are all poorly implemented. This article will explain how to create a simple ticketing system with supporters, supporter groups, customizable fields, and emailing capability.

Notice that this ticketing system’s functionality will mostly be based on the functionality of OneOrZero Helpdesk (now AIMS). This isn’t a endorsement of the OOZ software. In fact, I went through the trouble of implementing a system like this specifically to move away from OOZ. OOZ is quasi-open source, and is switching to a CMS model, which defeats the purpose of its simple helpdesk nature.

[toc title=”Table of Contents”]

Get the software

The following software and extensions will be used for this:

  1. MediaWiki
    1. ParserFunctions
    2. LiquidThreads
    3. DynamicSidebar
    4. Semantic MediaWiki (SMW)
      1. Semantic Forms (SF)
      2. Semantic Result Formats (SRF)
      3. Semantic Tasks (ST)
    5. Replace Text

Follow the installation instructions provided by MediaWiki and each extension.

Create the structure

Note that before we get too deep into this, that I have an implementation of this already ready to test, and easily export. So, if you don’t want to go through the pain of creating all of the properties, templates, and forms, just get them from my prototype wiki. I’ll have instructions to do so at the end of this article.

Create properties

This will define the basics of your ticket. What information do you want to gather from the end-user? Use Special:CreateProperty for this (“Create a property” on Special:SpecialPages). Here’s a quick list to start you off:

  • Supporter group – String
  • Supporter – Page
  • Priority – String; add a list of priorities here, I recommend:
    • Critical
    • High
    • Medium
    • Low
  • Status – String; add a list of statuses here, I recommend:
    • Unassigned
    • Open
    • In progress
    • Waiting for response
    • Closed
  • First name – String
  • Last name – String
  • Username – String
  • Building – String
  • Room – String
  • Phone number – String
  • Short description – String
  • Long description – Text
  • Attachment – Page

Adding more properties, and modifying them later isn’t difficult, so don’t worry too much if you don’t get everything you need at first.

Create templates

Now that you have properties defined, you’ll want a way to programatically fill them with values, and to display them. Semantic Forms has a special page to create a template from a list of properties. We should use this to create the templates. Go to Special:CreateTemplate, which can be found in special pages as “Create a template”.

Create the Ticket template

  1. Enter “Ticket” for the template name (without the quotes)
  2. Enter “Tickets” for the category name (without the quotes)
  3. Add your fields from the properties previously created
    1. I recommend making the “Field name” and the “Display name” of each property the same as the property itself. So, for “First name”, “Field name” would be “First name”, and “Display name” would also be “First name”. Make sure to select “This field can hold a list of values, separated by commas” for fields that should be allowed to have multiple values. In this example, we are going to ensure “Supporter group”, “Supporter”, and “Username” allow multiple values, at minimum
  4. Use “Standard” as the output format, and click “Save”; you can tweak the output format heavily later
  5. Edit the template, and change the following portions, to add ST support:
    1. Change the “Supporter group” arraymap to: {{#arraymap:{{{Supporter group|}}}|,|x|[[Supporter group::x]] [[Assigned to group::x| ]]}}
    2. Change the “Supporter” arraymap to: {{#arraymap:{{{Supporter|}}}|,|x|[[Supporter::User:x|x]] [[Assigned to::User:x| ]]}} {{#if:{{{Supporter|}}}|([[Special:EmailUser/{{{Supporter|}}}|email]])|}}
    3. Change the “Username” arraymap to: {{#arraymap:{{{User name|}}}|,|x|[[Username::User:x|x]] {{#if:x|([[Special:EmailUser/x|email]])|}} [[Carbon copy::User:x| ]]}}

Create the User template

In this helpdesk system, we want users to be able to mark themselves as supporters, and provide some information about themselves. Since this is a wiki, we are assuming it is fairly open. If you want this to be locked down, you’ll have to find another method to go about this; notice, that this is possible, I just won’t go into it.

  1. Enter “User” for the template name (without the quotes)
  2. Leave the category name blank
  3. Add fields for first name, last name, phone number, building, and room
  4. Use “Standard” as the output format, and click “Save”; you can tweak the output format later (I like using actual infoboxes here)
  5. Edit the template; at the end of your template, add: {{#ifeq:{{{Supporter|}}}|Yes|[[Category:Supporters]]|}}
    1. This will allow us to conditionally add people to the Supporters category

Create the Supporter group template

Unfortunately, SMW doesn’t allow you to query user pages based on MediaWiki user groups. So, we’ll make supporter groups based on SMW properties. We’ll want to have support groups that can hold a list of supporters.

  1. Enter “Supporter group” for the template name (without the quotes)
  2. Enter “Supporter groups” for the category name (without the quotes)
  3. Add the Supporter property; make sure to select “This field can hold a list of values, separated by commas”, as groups should be allowed to have multiple supporters
  4. Use “Standard” as the output format, and click “Save”. It really doesn’t matter what these look like; this is only used to add/remove supporters to/from groups

Create forms

Now that we have a way to programatically fill SMW values, and display them, we’ll want to make something for users to easily enter tickets. SF has a special page to create forms, based off of templates. To create the Ticket form, visit Special:CreateForm, which can be found in special pages as “Create a template”.

Create the Ticket form

  1. Type “Ticket” for the Form name (without the quotes)
  2. Select “Ticket” from the Add template drop down; click “Add”
  3. Select Mandatory for whichever fields should be mandatory, and click “Save page”

Create the User form

  1. Type “User” for the Form name (without the quotes)
  2. Select “User” from the Add template drop down; click “Add”
  3. Select Mandatory for whichever fields should be mandatory, and click “Save page”
  4. Make sure the Input type for the Supporter field is set as checkbox; we aren’t setting a supporter here, but instead a true/false value that will decide if they are in the supporters category or not

Create the Supporter group form

  1. Type “Supporter group” for the Form name (without the quotes)
  2. Select “Supporter group” from the Add template drop down; click “Add”
  3. Select Mandatory for the Supporter field, and click “Save page”
  4. Edit the form, and change the supporter field to: {{{field|Supporter|input type=checkboxes|values from category=Supporters}}}

Create the Supporter groups

Creating supporter groups allows you to send ticket creation emails to entire groups of users, and allows users to get a view of only the tickets that pertain to their role. To create a supporter group:

  1. Visit Form:Supporter group
  2. Type the name of the group you wish to add into the inputbox, and click “Create or edit”
  3. Select the users you wish to add, and click “Save page”

Create your navigation

Obviously, to test any navigation, you’ll want to add some test tickets first. So, do that before starting this.

Create basic sidebar navigation

For the basic sidebar navigation, you’ll want anonymous users to be able to view all open tickets, and all recently closed tickets. To add the basic navigation do the following:

  1. Visit Special:Ask
    1. Create your query using your own username in the query, and test it
    2. Hide the query
    3. Copy the URL
  2. Add the link to MediaWiki:Sidebar

Create sidebar navigation based on groups

Logged-in users need to be able to create tickets, view/edit their open tickets, and view/edit their recently closed tickets. It is easy enough to query per user for tickets in Special:Ask; the problem is that MediaWiki has no way, except via Javascript, to have content display differently per user. To add the group based navigation do the following:

  1. Visit Special:Ask
    1. Create your query using your own username in the query, and test it
    2. Hide the query
    3. Copy the URL
  2. Add the link to MediaWiki:Sidebar/Group:user. Make sure you add a new section, and add the link under that section. Also, make sure that “user” in “Group:user” is lowercase. “User” won’t work.
  3. Modify the link to change your username to USERNAME
  4. Add Javascript to MediaWiki:Common.js to change USERNAME to wgUsername

Create sidebar navigation based on categories

Users who add themselves to the supporters category, and support groups, will need to be able to view/edit their groups’ open and recently closed tickets. Like the user group sidebar, we’ll also need to change USERNAME to wgUsername, but the already created Javascript should handle that. Something extra we’ll need in this query, is a list of supporter groups to which the user belongs. We’ll need to use this list inside of our query. Thankfully, since we added supporter group pages, that have supporters as properties, we can get this list using a subquery. To add the category based navigation, do the following:

  1. Visit Special:Ask
    1. Create your query using your own username in the query, and test it
      1. Your query should look somewhat like this: [[Category:Tickets]][[Supporter group::<q>[[Supporter::Ryan Lane]][[Category::Supporter groups]]</q>]][[Status::!Closed]]
    2. Hide the query
    3. Copy the URL
  2. Add the link to MediaWiki:Sidebar/Category:Supporters; make sure you add a new section, and add the link under that section
  3. Modify the link to change your username to USERNAME

Add statistics

I won’t go into too much detail here, since everyone has their own idea of what their statistics need to be. I have an example stats page to check out. You can use this as a base to get started. Notice that the example statistics page would be very inefficient for a large amount of tickets. I’ve tested it with 35,000 tickets, and it took nearly a minute and a half to load. I recommend breaking the page up, and possibly doing it more efficiently than I am.

Statistics look better with charts. I don’t have plotting support added in this prototype, yet; however, I plan on using my Plotters extension to take care of that. If you’d like to help out with the Plotters extension with Javascript, or PHP coding, I’d be more than appreciative.

Optional configuration

Optionally, you can move tickets into their own namespace, if you want them to be separate from the rest of your content. This is likely a good idea if you use your wiki as a documentation system. Remember, though, if you do this, to add the namespace to $smwgNamespacesWithSemanticLinks.

Missing features

  • No supporter only comments.
  • No separate forms for supporters and end-users; though, with a little extra effort, this is doable with some Javascript and/or multiple ticket forms.
  • The long description field is not searchable via the advanced search form, or via ask queries, as text properties can’t be searched via ask.

Gotchas and workarounds

  • Fields accept wiki text, and not all wiki-text will work in your fields. In fact, some of it will cause that field not to display, and will cause it to be ignored by SMW.
    • A workaround is to add the text to the page twice; once as a pre tag, that displays the text, and another, adds the property via a {{#set:<property>=<value>}} call. For example: {{#set:Long description={{{Long description|}}}}} {{#tag:pre|{{{Long description|}}}|style=”white-space: pre-wrap; white-space: -moz-pre-wrap; word-wrap: break-word; border-style: none; background-color: white; padding: 0px; white-space: normal;”}}
    • This workaround doesn’t solve the problem for SMW. Some tickets simply won’t have values for bad text.
  • Ask queries are case sensitive. For properties that have a list of values, this isn’t too much of an issue, but for fields like “Short description”, this makes searches difficult.
    • A workaround for this is to lowercase values in properties, like: [[Short description::{{lc:{{{Short description|}}}}}]]
  • Semantic Forms currently has a bug (verified in 1.9 and below) that will not read text that has been entered, and will cause properties to appear empty. Known problematic characters are {, | and }
    • A workaround for this is to add Javascript that will encode {, | and } characters on form save, and decode them on form load – this will cause problems inside of pre blocks.
    • The Semantic Forms author is aware of the bug. We’ve discussed possible solutions, but no code changes have occurred.

Exporting the system from my prototype

As mentioned at the beginning of this article, you can export the system I already have implemented, to save some work. Export the following categories and pages to get the system:

  • Category:Ticket properties
  • Category:Helpdesk interface
  • MediaWiki:Sidebar
  • MediaWiki:Sidebar/Category:Supporters
  • MediaWiki:Sidebar/Group:user
  • Template:Infobox

You will also want to manually copy the Javascript I’m using from MediaWiki:Common.js, and add it to your Javascript in MediaWiki:Common.js. Notice that you don’t necessarily want to export the category pages, but instead you want to export the pages in the categories. Special:Export has a field to do this. Also, my prototype wiki has tickets kept in a separate namespace. You’ll need to make some minor changes to the exported pages after importing them, if you don’t want tickets in a separate namespace. When exporting, ensure you have “” checked.

TODO

This is mostly a first-take at a system like this; the following things could be done to improve it:

  1. Auto-populate the fields in the ticket with information from the user’s properties when creating tickets
  2. Make the sidebar Javascript more generic
  3. Update ST to have email templates, so that users don’t have to see confusing wiki-text in task assigned/created and diff emails
  4. Update SMW to add properties to user pages for MediaWiki groups
  5. Update SMW to allow Text fields to be searchable via ask
  6. Update SMW to allow case insensitive searches in ask
  7. Update LiquidThreads to allow transcludable discussions, so that they can be shown below ticket information on the ticket page

If you’d like to help, I’ll give you access to modify the prototype wiki. Coordination on changes ahead of time is preferred.

  • Pingback: Tweets that mention Creating a simple ticketing system with Semantic MediaWiki | Ryan Lane's Blog -- Topsy.com()

  • Hi Ryan,

    Thank you very much for all the magic, it was very interesting…

    Actually I logged in in your protowiki, my username is Andreslucena. I really liked the ticket system, tough I missed that you can’t add comments to the ticket. I worked as a technician for a few years and I think its pretty important to be possible to add some (like when you fix a Software related incident, its good for you and your coworkers to document the fix); though I think that you should supposed to add them in the Long description, but I think that comments its very easy to implement using the “multiple” option in Semantic Forms.

    I also liked the hardware inventory listing, as I’m doing something very similar for my work. But I’m also using the multiple option for some things (like Usernames, so you could add the user, pass and comment). For inserting that kind of data I’m using Semantic Internal Objects (SIO).

    Finally and returning to the ticketing system, in my website (sharewiki.locolandia.net SPAM :P) I’ve implemented it, so THANK YOU very much !! For the comments stuff I’m using the Discussion extension, though I think that finally I’ll be using the multiple option of Semantic Forms.

    Bye,
    Anders

    • @Anders

      Well, you can leave comments on the discussion page via liquid threads, or you can add a “Resolution” field. I try to avoid using the “multiple” templates option since it is confusing for users, and have avoided using SIO, since it really should be a built in feature of SMW, and may disappear at some point. The really nice thing about the system is that it is really easy to modify. My implementation is really just a proof of concept.

      For the hardware system, you can add multiple users and admins by separating them with commas. If the user/admin has a user page, their information will also show on the hardware page, since it is being pulled via an ask query.

      I’m glad to see this has been useful for you. I was hoping someone would get some use out of my proof of concepts :).

      • Hey Ryan,

        Yeah, I noticed the liquid threads stuff, but I think that only wikiadmins/gardners are the one that notice the discussion tab :)

        Though as you say in you comment, there would be nice to have that feature in the Ticket page, I don’t know if as a hack you could use the Labeled Section Transclusion extension; have a look at it.

        About SIO, well, yeah, probably they will integrate it; for the moment you can do almost the same thing with the Record property type.

        Bye,
        Anders

        • I’m nearly positive liquid threads can’t be transcluded. I remember asking the developer about this a while ago, and at that time it wasn’t really on his priority list.

          As for SIO/Records. I’m waiting for them to settle on one or the other so I don’t have to change anything in the future.

  • Anonymous

    E-mail notifications don’t seem to be working. Could this be an issue with my setup or the Semantic Tasks extension? I noticed a fatal error when attempting to run ST_CheckForReminders.php.

    • Unfortunately, I haven’t gotten a chance to fix the reminders code yet. I’ll hopefully get a chance to work on this soon.

      • enterprise_user

        Okay, but e-mail notification on ticket submission/change should work, right? I’m finding that after tickets are submitted, no notification e-mail is sent out. Normal “Send E-mail to User” through MediaWiki works fine. The “Assigned to”, “Assigned to group”, “Carbon Copy”, “Email address”, “Username”, and “Has assigneee” properties are all populated correctly.

        • Yeah, notification emails should definitely be sent.

          The “Assigned to” property has usernames and not email addresses in it, correct? The users have their email addresses set in their preferences, and the address confirmed as well?

          • enterprise_user

            Yes the “Assigned to” property has usernames, not email addressess, in it. Also, the users have their email addresses set in their preferences, and they’ve been confirmed.

            I’ve checked the Ticket template, and the #arraymap for Supporter group and Supporter seem fine. Is there a variable in one of the SemanticTasks scripts that I need to set to enable e-mail?

          • enterprise_user

            Okay, on a blank page, inserting [[Assigned to::Somebody]] assigns the page to the user, and they get e-mail notifications fine. The problem seems centered around Ticket generation. It either doesn’t assign to a user, or something isn’t being read in the #arraymap.

          • This is sounding insanely familiar. It sounds like a bug I fixed a while back. Now the question is, did I commit that fix? /me goes to look

          • Well, this is embarassing. Seems I fixed this problem months ago, and forgot to check it into Wikimedia’s SVN. I’ll check this in tonight. Here’s a patch for the time being.

          • enterprise_user

            Works perfectly! SemanticTasks v1.4 corrects the non-main namespace notification bug.

  • enterprise_user

    After implementing the ticket system, conducting a Special:Ask query with [[Ticket:+]] produces a list of all submitted tickets. Adding the “Additional printouts”:

    ?Supporter
    ?Short description
    ?Username
    ?Creation date
    ?Priority
    ?Status

    produces column headings which successfully link to the properties, but no ticket data is listed in any column. Do you have any idea what might be causing this? My tickets are generated in a seperate namespace (Ticket); could that have something to do with the problem?

    • enterprise_user

      Further investigation shows the Special:Browse/Ticket: page for any ticket lists no properties:

      =========================
      Ticket:1
      This page has no properties.

      No properties link to this page.
      =========================

      The ticket generates fine in the Ticket namespace, but no properties seem to link to it.

      • Do you have that namespace added to $smwgNamespacesWithSemanticLinks? If you don’t, add it, and run extensions/SemanticMediaWiki/maintenance/SMW_refreshData.php.

        That should populate your properties.

        • enterprise_user

          Well, that somewhat resolved the problem. I did have the namespace added to $smwgNamespacesWithSemanticLinks, but running the SMW_refreshData.php script the first time revealed that the NS_TICKET and NS_TICKET_TALK namespace defines were not properly placed in the LocalSettings.php script, causing the namespace to appear undefined.

          After correcting that, and rerunning the SMW_refreshData.php script, the Ticket properties are populated and appear when using Special:Ask. My only concern now is that while the SMW_refreshData.php script is running verbosely, the following is produced:

          Processing all IDs from 1 to last ID …
          (0) Processing ID 1 …
          .
          .
          .
          (18) Processing ID 19 …
          PHP Fatal error: Call to a member function getNamespace() on a non-object in /var/lib/mediawiki/extensions/SemanticForms/includes/SF_LinkUtils.php on line 169

          Nothing seems broken, but that doesn’t appear to be desired behavior for the script.

          • That looks like it could be a bug. You can get around this by disabling semantic forms, running the script, and re-enabling it.

          • enterprise_user

            Performing the following resulted in a purge of any User property data (Assigned to, Lab manager, Phone num, etc.) on my tickets:

            1. disabling SemanticForms by commenting out the include_once in LocalSettings.php

            2. executing export MW_INSTALL_PATH=”/var/lib/mediawiki” && php SMW_refreshData.php -v

            3. renabling SemanticForms by uncommenting its include_once in LocalSettings.php

            The ticket data itself was still sound. I was able to reverse the unwanted result by resaving my tickets.

          • That’s strange. I don’t know why that would be the case. The data itself is stored in templates, so SMW_refreshData.php should find the properties without issues. I’ll try to replicate this to see where the bug is.

  • enterprise_user

    Should Ticket editing default to formedit as opposed to source editing, or is this something specific to MediaWiki v1.17?

    Currently running MediaWiki v1.15.1.

  • That bug is now fixed in SVN. I’ve upped the version number to 1.4. Download via SVN or the extension distributor.

  • enterprise_user

    Closing a ticket fails to assign a “Closed date” to the ticket. Similar behavior is seen on your prototype Wiki (see Ticket #3).

    Wiki syntax appears fine as far as I can tell. Perhaps the issue originates from Common.js.

    • Ah, yeah. I know. I need to update this when I get a chance. I have Javascript that does that (which is unfortunately the only way to have closed dates). I haven’t added this Javascript to my prototype yet, as I added this fairly recently.

  • enterprise_user

    When adding either of the following lines to MediaWiki:Sidebar,

    GROUP-SIDEBAR
    CATEGORY-SIDEBAR
    USER-SIDEBAR

    The Wiki in its entirety fails to work, providing only blank pages. The following error is in the apache log:

    PHP Fatal error: Call to undefined method SkinMonoBook::addToSidebar() in /var/lib/mediawiki/extensions/DynamicSidebar/DynamicSidebar.body.php on line 35

    The same problem is found when incorporating the patch suggested on the DynamicSidebar extension page. The only way to reverse the total failure is to go back in one’s browser history and re-save MediaWiki:Sidebar without the GROUP/CATEGORY/USER-SIDEBAR calls. Alternatively, one could disable DynamicSidebar altogether.

    MediaWiki 1.15.1
    PHP 5.3.2-1ubuntu4 (apache2handler)
    MySQL 5.1.41-3ubuntu12.3

  • Anon

    Ticket system in Mediawiki seem really interesting, and I’ve tried to visit your Prototype wiki to check it out and export it, but are only receiving 404 error. Is this temporary, or could you redirect me to another demo site of this ticket system implementation?

    • Sorry, I took the wiki down quite a while ago. There’s no demo around. The ticketing system was really a proof of concept. In reality it doesn’t scale terribly well.