📜 ⬆️ ⬇️

Information system based on Semantic MediaWiki

Foreword


It’s fortunate that a few days ago there appeared a good article about Semantic MediaWiki . Without claiming the same deep presentation of the material, pick up the baton and describe my practical experience of using MediaWiki with almost zero initial knowledge. I apologize to the author of the first article, ganqqwerty, for running ahead and telling you about the Semantic Forms.

Start


At the beginning of the year I volunteered to solve a non-core task - to create an information system for our organization. Now the decision has more or less taken shape, I will try to share my experience.

Our employees annually report on their achievements. Based on this information, quantitative indicators are calculated. Also all sorts of pivot tables are interesting. In general, there is enough really useful information there, it makes sense to make it convenient to mine.
')
Previously, everything was designed as an Excel table of a certain structure. Each employee filled out his sheet, the indicators were considered according to the specified formulas. On this, in general, the information ended its way - if it was used somewhere else, it had to be extracted again.

As it always happens, I didn’t come up with this idea at all - I wanted, roughly speaking, to make my contact person to improve the awareness of each other. The idea in the minds of the authorities was transformed and shot me with this project - they say, great, we will definitely do it, but we have annual reports on the nose, can this information be hammered into such a system? I make a kind of " dashing and silly ", I answer in the affirmative and go to study the material part.

Task


So, it is required to make a site very, very quickly, where each user can easily and simply place information of a certain structure. And so that this information could be easily processed - read all indicators, build lists. The search, of course, is needed, and not just a text one, but taking into account the structure of this very information.

Mediawiki


There was almost no time to study implementation options, I had to rely on intuition. I decided that if MediaWiki is successfully used in large projects, first of all by Wikipedia , then we should be. They don't write everything there with their hands, there should be automation tools that I need.
As befits a serious system, MediaWiki has an extension mechanism and this gives hope that everything you need is already written.

Installation and initial setup of MediaWiki was in full compliance with the instructions. A sign of the maturity of the product - Redmine had to mess around much longer.

I had to suffer a little longer with setting up LDAP authentication due to some kind of deep error, but everything also worked out and the employees were able to use the system with their credentials. Anonymous access was completely denied.

Facilitate input - forms


The first task is to save users from wiki markup. This barrier is too high, at best I’m overwhelmed with questions, at worst - no one will use the system. I am looking for an extension that allows you to use forms to enter information. After a couple of simple long abandoned extensions, I find what I need: Semantic Forms .

This extension allows you to create form descriptions that are placed on pages in the Form namespace.
For example, the description of the form for filling out employee information is on the Form: page Form: and, as a first approximation, looks like this:

 <noinclude>      .     .       includeonly.</noinclude> <includeonly> {{{for template|}}} : {{{field|}}} : {{{field|}}} {{{end template}}} </includeonly> 


Now on any page you need to insert a special function call:

           : {{#forminput:form=}} 


The result will be the entry field for the name of the new / edited page and the button:



As expected, clicking on the button will open a page with the form:


Templates


Next - the most interesting. In what form is saved the data entered into the form and what to do with them next?

Turning to edit the source text of the saved page, you can see the following structure:

 {{ |= |= }} 


This is a call to the Template: with the values ​​of the parameters of the and equal to the and respectively. Templates are defined on pages from the Template namespace and determine what the template call will be replaced with. The values ​​of the template parameters will be substituted for the names of the parameters in triple curly brackets. If you define a pattern like this:

 : {{{}}} : {{{}}} [[Category:]] 


the page of Ivan Ivanov will look like this:



The last line in the template definition indicates that the page belongs to the category. Each category has its own page in the Category namespace (in our case, Category: ), which lists all pages from this category. On the same page, you can set special category properties, for example, the form that will be used to edit category pages:

 [[Has default form::]] 


Semantic MediaWiki and semantic annotations (properties)


Some categories are not enough to structure information. And here comes heavy artillery to the rescue - the expansion of the Semantic Forms brought me to Semantic MediaWiki . This extension allows you to explicitly define semantic annotations . For ease of understanding, programmers may consider wiki pages as objects, and semantic annotations as named properties of these objects. I will also continue to talk about the properties. The syntax for defining properties is similar to the syntax for defining categories (belonging to a category can be considered a property of an object):

 [[::]] 


In our template, Position and Department are natural candidates for the role of properties. Fix it in the template:

 : [[::{{{}}}]] : [[::{{{}}}]] [[Category:]] 


Visually, almost nothing has changed - instead of defining the property, its value is displayed, that is, the value of the template parameter:



By default, the property has a value of the Page type, that is, the name of the wiki page, so the property values ​​turn red — this is how links to nonexistent pages are shown. If the pages existed, the links would be blue. The type of property can be changed. A question for the reader to understand the basic ideas: where and how can the type of property be changed?



 This is a property of type [[Has type::String]]. The allowed values for this property are: * [[Allows value::]] * [[Allows value::]] 


By the way, this change will also affect the form: the field will turn into a drop-down list with the corresponding values.

Note: if the magic does not work, you have to add the property parameter to the definition of the field. The parameter value is the name of the property used by this field:

 {{{field||property=}}} 


Requests


It remains to deal with data processing. Categories and properties can be used in the queries , the results of the queries included in the text of the pages. Instead of Hello, world! we derive a table of employees:

 {{#ask: [[Category:]] |? |? |format=table}} 


First, a couple of words for a general understanding of the syntax: {{#f: ... }} is a function call with the name f. Functions are defined in extensions, I have not tried to define them. Vertical sticks share function parameters. That is, we have a call to the ask function with four parameters.

This query consists of two parts. The first part (the first parameter of the ask function) selects pages that satisfy a certain rule. In this case - belonging to the category . The second part (the remaining parameters) determines the way the results are displayed. In this case, it will be a table with three columns:
  1. The name of the page . The column is mainlabel=- by default, but this can be suppressed if necessary with the parameter mainlabel=- .
  2. Position This we have already asked.
  3. Department And this, too, we.


If necessary, you can add a filter, for example, selecting employees of a specific department (the Department column can be deleted in this case, it is boring):

 {{#ask: [[Category:]] [[::]] |?=      |format=table}} 


The output formats of the ask function can do quite a lot. I, in particular, used format=sum to sum up the values ​​of a given property for the found object pages. For example, if each employee has the Salary property, then in this way you can calculate the total salary by department.

Calculations


For more complex calculations, the ParserFunctions extension offers a set of functions similar to control structures (if and switch) and expressions in programming languages.

Loops are not directly supported, you can instead use recursion on auxiliary templates, but it does not add readability and performance. There is a separate LoopFunctions extension for loops , but I have not tried it.

For my computational problems, ParserFunctions was enough, but as a general solution it would be interesting to find an extension that allows using a scripting language inside the wiki. Possible candidates, if I understood their descriptions correctly, are:
  1. Scribunto - extensions for embedding scripting languages, while only Lua is supported;
  2. Script - calculations on R;
  3. Winter - ( W iki Inter preter) - its own language, reminiscent of PHP and a bit of LISP, as written in the documentation ;
  4. StackFunctions - almost PostScript without graphics.


Choosing an extension for the scripting language, pay attention to security!

Subobjects


Borderless objects whose values ​​are entity lists are too simple a case. In life, everything is much harder and we must be able to cope with it.

Suppose you want to give employees the opportunity to keep records of their travels: departure and return dates and a goal. Simply adding a field for entering arbitrary text is not suitable - the structure of information and the possibility of its analysis are lost.

It would be possible to create a separate page for each trip, and to display the result of a request for his trips on the employee’s page (those who wish can implement the appropriate forms, templates and requests for training). But quite often this approach unnecessarily complicates the input of information. If necessary, everything can fit on one page.

By tradition, let's start with the user interface. If the template parameter is a list of sub-objects, then the form field for this parameter should be associated with the form to define the sub-object.
The SemanticForms extension will automatically generate an interface to manage the list of sub-objects.
It was not easy to formulate, to read, I think, even more difficult, therefore I will give an example.

For the Form field, the must specify the holds template parameter, and below (otherwise it will not work) define another form ( ) and specify multiple parameters in it - can enter several times and embed in field=[] - this form determines the value Form fields:

 {{{for template|}}} ... {{{field||holds template}}} {{{end template}}} {{{for template||label=|multiple |embed in field=[]}}} : {{{field|}}} : {{{field|}}} : {{{field|}}} {{{end template}}} 


Note: The same template ( ) cannot be tied to several fields ( and anything else). You have to create intermediate templates.

The result will be the following interface:


After saving the page, the value of the field will be a list of calls to the template :

 {{ ... |={{ |=2013/04/30 |=2013/05/10 |=   }}{{}} }} 


In the definition of the pattern, the assignment of the parameter will cause a recursive substitution of the pattern, which we define as:

 <includeonly>{{#subobject: |={{{}}} |={{{}}} |={{{}}} }}</includeonly> 


Now not only the employee’s page is an object, on this page a sub-object is defined for each trip. The same query language is used to select sub-objects. By adding the following request to the template definition:

 {{#ask: [[-Has subobject::{{FULLPAGENAME}}]] |? |? |?}} 


we will receive a sign with all employee travel. From the new here, only the use of the Has subobject . This property is automatically defined on all pages and its value is the set of sub-objects defined on this page. A minus at the beginning means that this property should be inverted , that is, use feedback from the sub-object to the page. {{FULLPAGENAME}} is a built-in variable, the value of which is the name of the current page. Thus, we select business trips for the current employee.

The documentation describes this point rather turbidly, some of the information in the discussion , I had to act by trial and error. In the end, the solution and understanding were found, I share.

Access rights


Of course, I agreed at the beginning of the project that it’s bad with the restriction of access rights in MediaWiki and any registered user will be able to see all the information. However, the appetite comes with eating and access restriction did have to be screwed.

Examination of extensions that implement access rights management has shown that IntraACL is the leader . This extension and patch is MediaWiki. There is still no guarantee of complete control, because the extensions have direct access to the database and you need to view and patch them for good. Fortunately, this level of security is all arranged.

Unfortunately, the finished patch was only for MediaWiki 1.18.6, and I already installed 1.20.2 and downloaded decent data. I had to sit and port the patch for several days. According to the law of meanness, the very next day, after everything worked for me, a ready-made patch for MediaWiki 1.20.3 appeared.

When installing, pay attention to the ACL namespace index - it should not conflict with other namespaces. It seems that everything should work, because in the HACL_GlobalFunctions.php file this index is defined in 300:

 if (!isset($haclgNamespaceIndex)) $haclgNamespaceIndex = 300; 


But in HACL_Initialize.php variable is pre-initialized improperly:

 $haclgNamespaceIndex = 102; 


IntraACL allows you to define groups of users and assign rights for specific pages, namespaces and categories to groups and individual users. Group definitions and access rules are stored on pages in the ACL namespace. You can work through a graphical interface or directly edit the sources of wiki-pages.

I came across an annoying feature - if you create a list of access rights before a user is created, then the rights do not work until you save the page with the list of access rights. It brought trouble until I found the maintenance/createAndPromote.php and refined it so that ordinary users could be created without waiting for them to log in. Let me remind you that the list of users is known to me in advance.

Probably, if I immediately knew about the Mediawiki4Intranet assembly, which includes IntraACL, I would use this solution and save myself a few days.

Debugging server code


While IntraACL patch, I figured out the debugging tools . I really liked the debugging console, which allows you to view the log file directly on the page. Turns on like this:

 $wgDebugToolbar = true; 


Conclusion



Semantic MediaWiki as a basis for creating an information system I liked. The tasks are almost solved:


There are disadvantages:


Thanks


I am very grateful:

Source: https://habr.com/ru/post/177615/


All Articles