Here is a small set of examples that may help anyone who is interested in internal classes of SMW. Many thanks to my student, Rinat Fayzrahmanov for his research.
If you want to develop extensions for SMW, first of all you should read Manual:Extension for MediaWiki.
For good introduction to SMW-classes we recommend to read Architecture guide. However there is no single big book called "Programmer's manual on SMW" and unfortunately you will need to review the code of existing Semantic MediaWiki extensions. Programmer's guide can also help.
If you want to see the Doxygen documentation for the classes we use in these examples, there is a API Documentation doxygen website.
Contents
- 1 How to actually create Ask queries programmatically
- 2 SMW Classes
- 3 Defining and registering our extension
- 4 Ask-queries
- 4.1 All pages with the property
- 4.2 All pages with a certain property value
- 4.3 Ask for several properties
- 4.4 Ask for particular property of the pages
- 4.5 Category queries, limits and offsets
- 4.6 Complex query with sorting
- 4.7 Custom decoration of the query results
- 4.8 Template as a result format
- 4.9 Map as a result format
- 4.10 #Show function
- 4.11 Asking hashes (SHA1)
- 4.12 Asking boolean values
How to actually create Ask queries programmatically[edit]
In the next chapter I will operate with a low-level SMW objects. If you just want to execute an ask-query and see its result, you can do so easily:
// {{#ask: [[Pagename]] | ?ExampleProperty=| mainlabel=-}}| ;
$params = array ("[[Pagename]]", "?ExampleProperty=", "mainlabel=-");
$result = SMWQueryProcessor::getResultFromFunctionParams( $params, SMW_OUTPUT_WIKI );
That's it!
SMW Classes[edit]
This toy extension just creates a tab where several SMW-queries are represented. The point is to show how those queries look like from inside and how to use some of SMW datatype classes.
Defining and registering our extension[edit]
<?php
ini_set('display_errors', 'on');
error_reporting(E_ALL);
$wgExtensionCredits['other'][] = array(
'name' => 'testExtension',
'version' => '0.0.1',
'author' => 'Rinat Fayzrahmanov',
'url' => '',
'description' => 'Test Extension',
);
$extension = new TestExtension; //test;
Here is the definition of a new tab:
$wgHooks['SkinTemplateContentActions'][] = array($extension, 'tab');
$wgHooks['UnknownAction'][] = array($extension, 'action');
class TestExtension {
const TAB = 'test';
static $namespace = NS_MAIN;
protected function checkNamespace() {
global $wgTitle;
if (static::$namespace == $wgTitle->getNamespace())
return true;
else
return false;
}
public function tab(&$content_actions) {
if ($this->checkNamespace()) {
global $wgRequest;
$class = $wgRequest->getText( 'action' ) == static::TAB ? 'selected' : null;
$href = $wgRequest->appendQueryValue( 'action', static::TAB);
$content_actions[static::TAB] = Array('class' => $class,
'text' => static::TAB,
'href' => $href);
}
return true;
}
When tab is pressed the function called action will run. In this function we will run all our ASk-queries:
public function action( $action, $article ) {
if ( static::TAB != $action && static::checkNamespace())
return true;
global $wgOut;
$this->wgOut = $wgOut;
$this->store = smwfGetStore();
$wgOut->setPageTitle('Toying with SMW data');
$wgOut->addHTML('Some tests<br />');
$this->askTestPlus();
$this->askAge24();
$this->askAge24Female();
$this->askJob();
$this->askScientists();
$this->askScientists2();
$this->askScientists3();
$this->askScientists4();
$this->askScientists5();
$this->showAge();
$this->askSHAString();
$this->askBoolTrue();
return false;
}
And here will be a function for print results:
protected function printResult(array $wikiPages) {
foreach ($wikiPages as $wikiPage) {
$this->wgOut->addHTML($wikiPage->getText() . ' ');
$this->wgOut->addHTML($wikiPage->getShortWikiText(true) . '<br />');
}
}
Ask-queries[edit]
There are many types of queries in SMW. We'll try to show how each of them can be coded in php.
All pages with the property[edit]
Let us start from the most general one: show me all pages that hava the property called test.
//{{#ask:[[test:+]]}}
protected function askTestPlus() {
$this->wgOut->addHTML('<h2>#ask:[[test:+]]</h2>');
$propertyValue = SMWPropertyValue::makeProperty('Test');
$property = new SMWSomeProperty($propertyValue, new SMWThingDescription);
$query = new SMWQuery($property);
$result = $this->store->getQueryResult($query);
$this->printResult($result->getResults());
}
All pages with a certain property value[edit]
This is the query that asks for all the pages with a property age and the value 24.
//{{#ask: [[age::24]]}}
protected function askAge24() {
$this->wgOut->addHTML('<h2>#ask:[[age::24]]</h2>');
$numberValue = new SMWNumberValue('number');
$numberValue->setUserValue('24');
$description = new SMWValueDescription($numberValue);
$property = SMWPropertyValue::makeProperty('Age');
$queryDescription = new SMWSomeProperty($property, $description);
$query = new SMWQuery($queryDescription);
$result = $this->store->getQueryResult($query);
$this->printResult($result->getResults());
}
Ask for several properties[edit]
//{{#ask: [[age::24]][[sex::female]] }}
protected function askAge24Female() {
$this->wgOut->addHTML('<h2>#ask:[[age::24]][[sex::female]]</h2>');
$numberValue = new SMWNumberValue('number');
$numberValue->setUserValue('24');
$description = new SMWValueDescription($numberValue);
$property = SMWPropertyValue::makeProperty('Age');
$ageDescription = new SMWSomeProperty($property, $description);
$wikiPage = SMWWikiPageValue::makePage('Female', NS_MAIN);
$description = new SMWValueDescription($wikiPage);
$property = SMWPropertyValue::makeProperty('Sex');
$sexDescription = new SMWSomeProperty($property, $description);
$queryDescription = new SMWConjunction(array($ageDescription, $sexDescription));
$query = new SMWQuery($queryDescription);
$result = $this->store->getQueryResult($query);
$this->printResult($result->getResults());
}
Ask for particular property of the pages[edit]
//{{#ask: [[job::Manager]]| ?Salary| format=broadtable}}
protected function askJob() {
$this->wgOut->addHTML('<h2>#ask:[[job::Manager]]|?Salary|format=broadtable</h2>');
$wikiPage = SMWWikiPageValue::makePage('Manager', NS_MAIN);
$description = new SMWValueDescription($wikiPage);
$property = SMWPropertyValue::makeProperty('Job');
$jobDescription = new SMWSomeProperty($property, $description);
$jobDescription->prependPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, ''));
$query = new SMWQuery($jobDescription);
$salary = SMWPropertyValue::makeProperty('Salary');
$printRequest = new SMWPrintRequest(SMWPrintRequest::PRINT_PROP, 'Salary', $salary);
$query->setExtraPrintouts(array($printRequest));
$printer = new SMWTableResultPrinter('broadtable', SMWQueryProcessor::INLINE_QUERY);
$result = $printer->getResult($this->store->getQueryResult($query), array(), null);
$this->wgOut->addHTML($result);
}
Category queries, limits and offsets[edit]
//{{#ask: [[Category:Scientist]]|limit=40|offset=3
//|default="there are no scientists here!"|searchlabel="go to the next page!"}}
protected function askScientists() {
$this->wgOut->addHTML('<h2>#ask:[[Category:Scientist]]|limit=40|offset=3
|default="there are no scientists here!"
|searchlabel="go to the next page!</h2>');
$title = Title::newFromText('Scientist',NS_CATEGORY);
$description = new SMWClassDescription($title);
$description->prependPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, ''));
$query = new SMWQuery($description);
$query->setOffset(3);
$query->setLimit(40);
$printer = new SMWAutoResultPrinter('', SMWQueryProcessor::INLINE_QUERY);
$params = array('default' => 'there are no scientists here!',
'searchlabel' => 'go to the next page!');
$result = $printer->getResult($this->store->getQueryResult($query), $params, null);
$this->wgOut->addWikiText($result);
}
Complex query with sorting[edit]
//{{#ask: [[Category:Scientist]] [[age::24]]| ?Salary| ?Sex| sort=Salary| order=descending}}
protected function askScientists2() {
$this->wgOut->addHTML('<h2>#ask:[[Category:Scientist]] [[age::24]]
|?Salary| ?Sex| sort=Salary| order=descending</h2>');
$numberValue = new SMWNumberValue('number');
$numberValue->setUserValue('24');
$description = new SMWValueDescription($numberValue);
$property = SMWPropertyValue::makeProperty('Age');
$ageDescription = new SMWSomeProperty($property, $description);
$title = Title::newFromText('Scientist',NS_CATEGORY);
$scientistsDescription = new SMWClassDescription($title);
$scientistsDescription->prependPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, ''));
$queryDescription = new SMWConjunction(array($ageDescription, $scientistsDescription));
$queryDescription->prependPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, ''));
$query = new SMWQuery($queryDescription);
$salary = SMWPropertyValue::makeProperty('Salary');
$printRequest = new SMWPrintRequest(SMWPrintRequest::PRINT_PROP, 'Salary', $salary);
$query->setExtraPrintouts(array($printRequest));
$sex = SMWPropertyValue::makeProperty('Sex');
$printRequest = new SMWPrintRequest(SMWPrintRequest::PRINT_PROP, 'Sex', $sex);
$query->setExtraPrintouts(array($printRequest));
$query->sort = true;
$query->sortkeys = array('Salary' => 'DESC');
$printer = new SMWAutoResultPrinter('', SMWQueryProcessor::INLINE_QUERY);
$result = $printer->getResult($this->store->getQueryResult($query), array(), null);
$this->wgOut->addHTML($result);
}
Custom decoration of the query results[edit]
//{{#ask:[[Category:Scientist]][[age::24]]|mainlabel=Scientist|?Sex=Male or female}}
protected function askScientists3() {
$this->wgOut->addHTML('<h2>#ask:[[Category:Scientist]][[age::24]]
|mainlabel=Scientist|?Sex=Male or female</h2>');
$numberValue = new SMWNumberValue('number');
$numberValue->setUserValue('24');
$description = new SMWValueDescription($numberValue);
$property = SMWPropertyValue::makeProperty('Age');
$ageDescription = new SMWSomeProperty($property, $description);
$title = Title::newFromText('Scientist',NS_CATEGORY);
$scientistsDescription = new SMWClassDescription($title);
$scientistsDescription->prependPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, ''));
$queryDescription = new SMWConjunction(array($ageDescription, $scientistsDescription));
$queryDescription->prependPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, 'Scientist'));
$sex = SMWPropertyValue:: makeUserProperty('Sex');
$printRequest = new SMWPrintRequest(SMWPrintRequest::PRINT_PROP, 'Male or female', $sex);
$queryDescription->addPrintRequest($printRequest);
$query = new SMWQuery($queryDescription);
$printer = new SMWAutoResultPrinter('', SMWQueryProcessor::INLINE_QUERY);
$result = $printer->getResult($this->store->getQueryResult($query), array(), null);
$this->wgOut->addHTML($result);
}
Template as a result format[edit]
//{{#ask: [[Category:Scientist]]| ?Age| ?Sex| ?Salary|template = scientists template demo}}
protected function askScientists4() {
$this->wgOut->addHTML('<h2>#ask: [[Category:Scientist]]
|?Age|?Sex|?Salary|template = scientists template demo</h2>');
$title = Title::newFromText('Scientist',NS_CATEGORY);
$description = new SMWClassDescription($title);
$description->addPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, null));
$age = SMWPropertyValue::makeUserProperty('Age');
$printRequest = new SMWPrintRequest(SMWPrintRequest::PRINT_PROP, 'Age', $age);
$description->addPrintRequest($printRequest);
$sex = SMWPropertyValue::makeUserProperty('Sex');
$printRequest = new SMWPrintRequest(SMWPrintRequest::PRINT_PROP, 'Sex', $sex);
$description->addPrintRequest($printRequest);
$salary = SMWPropertyValue::makeUserProperty('Salary');
$printRequest = new SMWPrintRequest(SMWPrintRequest::PRINT_PROP, 'Salary', $salary);
$description->addPrintRequest($printRequest);
$query = new SMWQuery($description);
$printer = new SMWAutoResultPrinter('', SMWQueryProcessor::INLINE_QUERY);
$params = array('template' => 'scientists template demo');
$result = $printer->getResult($this->store->getQueryResult($query), $params, null);
$this->wgOut->addHTML($result);
}
Map as a result format[edit]
//{{#ask [[Category:Scientist]]| ?Geocoordinates| format=map}}
protected function askScientists5() {
$this->wgOut->addHTML('<h2>#ask [[Category:Scientist]]| ?Geocoordinates| format=map</h2>');
$title = Title::newFromText('Scientist', NS_CATEGORY);
$description = new SMWClassDescription($title);
$description->prependPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, ''));
$geo = SMWPropertyValue::makeUserProperty('Geocoordinates');
$printRequest = new SMWPrintRequest(SMWPrintRequest::PRINT_PROP, 'Geocoordinates', $geo);
$description->addPrintRequest($printRequest);
$query = new SMWQuery($description);
$printer = new SMWAutoResultPrinter('map', SMWQueryProcessor::INLINE_QUERY);
$result = $printer->getResult($this->store->getQueryResult($query), array(), null);
$this->wgOut->addHtml($result[0]);
}
#Show function[edit]
//{{#show [[Katkov]] | ?age}}
protected function showAge() {
$this->wgOut->addHTML('<h2>#show: Katkov | ?age</h2>');
$wikiPage = SMWWikiPageValue::makePage('Katkov', NS_MAIN);
$description = new SMWValueDescription($wikiPage);
$age = SMWPropertyValue::makeUserProperty('Age');
$printRequest = new SMWPrintRequest(SMWPrintRequest::PRINT_PROP, null, $age);
$description->addPrintRequest($printRequest);
$query = new SMWQuery($description);
$printer = new SMWAutoResultPrinter(null, SMWQueryProcessor::INLINE_QUERY);
$result = $printer->getResult($this->store->getQueryResult($query), array(), null);
$this->wgOut->addHtml($result);
}
Asking hashes (SHA1)[edit]
//{{#ask: [[SHA1::a813998c607222af902c3e058457ebb2bdc4ac1d]] }}
protected function askSHAString() {
$this->wgOut->addHTML('<h2>#ask:[[SHA1::a813998c607222af902c3e058457ebb2bdc4ac1d]]</h2>');
$stringValue = new SMWStringValue ('string');
$stringValue->setUserValue ('a813998c607222af902c3e058457ebb2bdc4ac1d');
$propertyDescription = new SMWValueDescription($stringValue);
$propertyValue = SMWPropertyValue::makeProperty('SHA1');
$property = new SMWSomeProperty($propertyValue, $propertyDescription);
$query = new SMWQuery($property);
$result = $this->store->getQueryResult($query);
$this->printResult($result->getResults());
}
Asking boolean values[edit]
//{{#ask: [[IDnotInDB::true]] }}
protected function askBoolTrue() {
$this->wgOut->addHTML('<h2>#ask:[[IDnotInDB::true]]</h2>');
$boolValue = new SMWBoolValue ('boolean');
$boolValue->setUserValue ('true');
$propertyDescription = new SMWValueDescription($boolValue);
$propertyValue = SMWPropertyValue::makeProperty('IDnotInDB');
$property = new SMWSomeProperty($propertyValue, $propertyDescription);
$query = new SMWQuery($property);
$result = $this->store->getQueryResult($query);
$this->printResult($result->getResults());
}
}//class TestExtension