Hello. I'm developing a Semantic MediaWiki extension to partition an ask query 
based upon the first character of one of the queried properties so that the 
user can page through partitions of what would otherwise be a very large query 
result. For example, I'd like to query all pages in Category:Author in my wiki, 
but there are almost 4,000 of those, so I want to partition the results 
dynamically by the first character of the author's last name. I have a working 
version, but I'm in the process of enhancing it to use Ajax so that it only 
needs to refresh the <div> with the new query results rather than the entire 
page as well as retaining previous partitions in hidden <div>'s so previous 
queries don't need to be repeated. (I may need to figure out a way to purge 
some of those <div>'s if performance becomes a problem after wandering through 
the partitions, but that's a problem for another day.) I'm having two parsing 
issues in the Ajax callback. I do not believe that they are related to Ajax per 
se. The second issue may be caused by my inexpert fix to the first issue, 
although I ran across the same second issue previously in a different context. 
I have reproduced both issues in a vastly simplified, minimal test program that 
I will discuss below.

I'm using MediaWiki 1.16.0 and SemanticMediaWiki 1.5.2.

The first issue is that I need access to the parser in the Ajax callback so I 
can call recursiveTagParse on the results for the query. I tried using 
$wgParser, but it does not appear to be in a good state in the callback. I had 
a series of errors where the parser was calling functions on non-objects. I 
played around with it a bit and was able to get past all of these errors with 
this rather ugly code:

    global $wgParser;
    $wgParser->mOptions = new ParserOptions;
    $wgParser->initialiseVariables();
    $wgParser->clearState();
    $wgParser->setTitle(new Title($title));

where $title is the title retrieved using getTitle on the original (pre-Ajax) 
working parser and sent as a parameter to JavaScript and back. These calls 
allow me to get a parser that does not give me run-time errors, but I'm not at 
all confident that this is the correct approach.

The second issue I'm having is that when I call recursiveTagParse on the data 
returned from the query in the Ajax callback, some of the data is "disappears". 
I should note that I'm invoking the same query and parsing code in both the 
initial display of the page and in the Ajax callback. It works initially but 
does not work in the callback using the questionable parser instance described 
above. However, I had also seen the same blanking behavior in a previous task 
where I did not have the first contributing issue. In that case, I changed my 
approach completely to avoid the recursiveTagParse, but I don't believe I have 
the option of doing that here, unless there is some option in the SMW query 
code that will return the results already parsed.

I'm reproducing my simplified test case below. You can run it by placing the 
following wikitext on a page:

{{#testQuery:[[Category:Author]]
|limit=5
|searchlabel=
|format=table
}}

replacing [[Category:Author]] with the query term of your choice. When you 
install the PHP extension code below, you'll see a page with a button and a 
table containing up to 5 query results. When you press the button, the same 
query is invoked, but the table is empty. If you comment out the line that 
contains the call to recursiveTagParse in the PHP code below, you'll see that 
the query results are indeed being returned in both cases, but they are getting 
obliterated in the Ajax callback by recursiveTagParse.

It may very well be that solving the first issue will solve the second one, but 
since I saw the second issue in another context previously, I wonder if they 
really are two separate issues.

Thank you very much for any assistance in working through these issues!

Cindy

PHP extension code:

<?php

/**
* To activate the functionality of this extension include the following
* in your LocalSettings.php file:
* include_once("$IP/extensions/TestQuery/TestQuery.php");
*/

if( !defined( 'MEDIAWIKI' ) ) die( "This is an extension to the MediaWiki
  package and cannot be run standalone." );

# credits
$wgExtensionCredits['parserhook'][] = array (
  'name' => 'TestQuery',
  'version' => '1.0',
  'author' => "Cindy Cicalese",
  'description' => "Bug test"
);

$wgUseAjax = true;
$wgAjaxExportList[] = 'testQueryPopulateDiv';

$wgHooks['LanguageGetMagic'][] = 'wfExtensionTestQuery_Magic';
$wgHooks['ParserFirstCallInit'][] = 'efTestQueryParserFunction_Setup';

function efTestQueryParserFunction_Setup (& $parser) {
  $parser->setFunctionHook('testQuery', 'testQuery');
  return true;
}

function wfExtensionTestQuery_Magic(& $magicWords, $langCode) {
  $magicWords['testQuery'] = array (0, 'testQuery');
  return true;
}

function testQuery($parser, $query) {
  $params = func_get_args();
  array_shift($params); // first is $parser; strip it
  array_shift($params); // second is query string; strip it
  $testQuery = new TestQuery();
  $output = $testQuery->firstVisit($parser, $query, $params);
  $parser->disableCache();
  return array($parser->insertStripItem($output, $parser->mStripState),
    'noparse' => false);
}

function testQueryPopulateDiv($query, $paramString, $title) {
  $params = explode("|", $paramString);
  $testQuery = new TestQuery();
  $output = $testQuery->populateDiv($query, $params, $title);
  return $output;
}

class TestQuery {

  private $template = false;

  function firstVisit($parser, $query, $params) {
    $js = <<<EOT
<script type="text/javascript">
function buttonClicked() {
  var query = document.forms['TestQuery'].Query.value;
  var params = document.forms['TestQuery'].Params.value;
  var title = document.forms['TestQuery'].Title.value;
  var div = document.getElementById('TestDiv');
  sajax_do_call('testQueryPopulateDiv', [query, params, title], div);
}
</script>
EOT;
    $parser->mOutput->addHeadItem($js);
    $this->parseParameters($params);
    $output = $this->buildForm($query, $params, $parser->getTitle());
    $result = $this->getData($parser, $query, $params);
    $output .= $this->buildDiv($result);
    return $output;
  }

  function populateDiv($query, $params, $title) {
    global $wgParser;
    $wgParser->mOptions = new ParserOptions;
    $wgParser->initialiseVariables();
    $wgParser->clearState();
    $wgParser->setTitle(new Title($title));
    $this->parseParameters($params);
    $currentPartitionData = $this->getData($wgParser, $query, $params);
    return $currentPartitionData;
  }

  private function parseParameters($params) {
    foreach ($params as $param) {
      if (preg_match("/^ *format *= *template *$/", $param) === 1) {
        $this->template = true;
      }
    }
  }

  private function buildForm($query, $params, $title) {
    $paramString = implode("|", $params);
    $out = <<<EOT
<center>
<button type='button' id='TestButton' onClick="buttonClicked()">Test 
Button</button>
<form id='TestQuery' method='post' action=''>
<input type='hidden' name='Query' value='$query'>
<input type='hidden' name='Params' value='$paramString'>
<input type='hidden' name='Title' value='$title'>
</form>
</center><br>
EOT;
    return $out;
  }

  private function getData($parser, $query, $params) {
    $result = $this->doSMWAsk($parser, $query, $params);
    $result = $parser->recursiveTagParse($result);
    return $result;
  }

  private function doSMWAsk($parser, $query, $rawParams) {
    SMWQueryProcessor::processFunctionParams($rawParams, $qs, $params,
      $printouts);
    $output = SMWQueryProcessor::getResultFromQueryString($query, $params,
      $printouts, SMW_OUTPUT_WIKI);
    return $output;
  }

  private function buildDiv($result) {
    $output = "<div id='TestDiv' display='block'>";
    $output .= $result;
    $output .= "</div>";
    return $output;
  }
}

--
Dr. Cynthia Cicalese
Lead Software Systems Engineer
The MITRE Corporation
------------------------------------------------------------------------------
Centralized Desktop Delivery: Dell and VMware Reference Architecture
Simplifying enterprise desktop deployment and management using
Dell EqualLogic storage and VMware View: A highly scalable, end-to-end
client virtualization framework. Read more!
http://p.sf.net/sfu/dell-eql-dev2dev
_______________________________________________
Semediawiki-devel mailing list
Semediawiki-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/semediawiki-devel

Reply via email to