private function run()
 {
     global $wgServerName, $wgScriptPath;
     $params = $this->extractRequestParams();
     wfDebugLog('p2p', ' - ApiQueryPatchPushed params ' . $params['pushName']);
     $publishedInPush = getPublishedPatches($params['pushName']);
     $published = null;
     // filtered on published patch on page title
     if (isset($params['pageName'])) {
         foreach ($publishedInPush as $patch) {
             $patches = array();
             $res = utils::getSemanticQuery('[[Patch:+]][[patchID::' . $patch . ']][[onPage::' . $params['pageName'] . ']]');
             $count = $res->getCount();
             for ($i = 0; $i < $count; $i++) {
                 $row = $res->getNext();
                 if ($row === false) {
                     break;
                 }
                 $row = $row[0];
                 $col = $row->getContent();
                 // SMWResultArray object
                 foreach ($col as $object) {
                     // SMWDataValue object
                     $wikiValue = $object->getWikiValue();
                     $patches[] = $wikiValue;
                 }
             }
             if (count($patches)) {
                 $published[] = $patch;
             }
         }
         wfDebugLog('p2p', '  -> isset($params[pageName]');
     } else {
         $published = $publishedInPush;
         wfDebugLog('p2p', '  -> not isset($params[pageName]');
     }
     $result = $this->getResult();
     if (!is_null($published)) {
         $result->setIndexedTagName($published, 'patch');
         $result->addValue('query', $this->getModuleName(), $published);
         $result->addValue(array('query', $this->getModuleName()), 'pushFeed', $params['pushName']);
     }
 }
 /**
  * MW Hook used to redirect to page creation (pushfeed, pullfeed, changeset),
  * to forms or to push/pull action testing the action param
  *
  * @since 1.1
  *
  * @param string $action
  * @param Article $article
  *
  * @return true
  */
 public function onUnknownAction($action, Article $article)
 {
     global $wgOut, $wgServerName, $wgScriptPath, $wgUser, $wgScriptExtension, $wgDSMWIP;
     $urlServer = 'http://' . $wgServerName . $wgScriptPath . "/index{$wgScriptExtension}";
     $urlAjax = 'http://' . $wgServerName . $wgScriptPath;
     ///////// / pull form page////////
     if (isset($_GET['action']) && $_GET['action'] == 'addpullpage') {
         wfDebugLog('p2p', 'addPullPage ');
         $newtext = "Add a new site:\n\t<div id='dsmw' style=\"color:green;\"></div>\n\n\t{{#form:action=" . $urlServer . "?action=pullpage|method=POST|\n\t\tPushFeed Url: {{#input:type=button|value=Url test|onClick=\n\t\tvar url = document.getElementsByName('url')[0].value;\n\t\tif(url.indexOf('PushFeed')==-1){\n\t\t\talert('No valid PushFeed syntax, see example.');\n\t\t}else{\n\t\t\tvar urlTmp = url.substring( 0, url.indexOf( 'PushFeed' ) );\n\t\t\t//alert(urlTmp);\n\n\t\t\tvar pos1 = urlTmp.indexOf( 'index.php' );\n\t\t\t//alert( pos1 );\n\t\t\tvar pushUrl='';\n\t\t\tif( pos1 != -1 ){\n\t\t\t\tpushUrl = urlTmp.substring(0,pos1);\n\t\t\t\t//alert('if');\n\t\t\t} else {\n\t\t\t\tpushUrl = urlTmp;\n\t\t\t\t//alert('else');\n\t\t\t}\n\t\t\t//alert(pushUrl);\n\n\t\t\t//alert(pushUrl+'api.php?action=query&meta=patch&papatchId=1&format=xml');\n\t\t\tvar xhr_object = null;\n\n\t\t\tif( window.XMLHttpRequest ) { // Firefox\n\t\t\t\txhr_object = new XMLHttpRequest();\n\t\t\t}else if( window.ActiveXObject ) { // Internet Explorer\n\t\t\t\txhr_object = new ActiveXObject('Microsoft.XMLHTTP');\n\t\t\t} else {\n\t\t\t\talert('Votre navigateur ne supporte pas les objets XMLHTTPRequest...');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\txhr_object.open('GET', '" . $urlAjax . "/extensions/DSMW/files/ajax.php?url='+escape(pushUrl+'api.php?action=query&meta=patch&papatchId=1&format=xml'), true);\n\t\t\t} catch( e ) {\n\t\t\t\t//alert('There is no DSMW Server responding at this URL');\n\t\t\t\tdocument.getElementById('dsmw').innerHTML = 'There is no DSMW Server responding at this URL!';\n\t\t\t\tdocument.getElementById('dsmw').style.color = 'red';\n\t\t\t}\n\t\t\txhr_object.onreadystatechange = function() {\n\n\t\t\tif( xhr_object.readyState == 4 ) {\n\t\t\t\tif( xhr_object.statusText=='OK' ){\n\t\t\t\t\tif( xhr_object.responseText == 'true' ){\n\t\t\t\t\t\t//alert('URL valid, there is a DSMW Server responding');\n\t\t\t\t\t\tdocument.getElementById('dsmw').innerHTML = 'URL valid, there is a DSMW Server responding!';\n\t\t\t\t\t\tdocument.getElementById('dsmw').style.color = 'green';\n\t\t\t\t\t} else{ //alert('There is no DSMW Server responding at this URL');\n\t\t\t\t\t\tdocument.getElementById('dsmw').innerHTML = 'There is no DSMW Server responding at this URL!';\n\t\t\t\t\t\tdocument.getElementById('dsmw').style.color = 'red';\n\t\t\t\t\t}\n\t\t\t\t} else{\n\t\t\t\t\t//alert('There is no DSMW Server responding at this URL');\n\t\t\t\t\tdocument.getElementById('dsmw').innerHTML = 'There is no DSMW Server responding at this URL!';\n\t\t\t\t\tdocument.getElementById('dsmw').style.color = 'red';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\txhr_object.send(null);\n\t}\n\t}}<br>        {{#input:type=text|name=url|size=50}} <b>e.g. http://server/path/index.php?title=PushFeed:PushName</b><br>\n\tPullFeed Name:   <br>    {{#input:type=text|name=pullname}}<br>\n\t{{#input:type=submit|value=ADD}}\n\t}}";
         $article->doEdit($newtext, $summary = "");
         $wgOut->redirect($article->getTitle()->getFullURL());
         return false;
     } elseif (isset($_GET['action']) && $_GET['action'] == 'addpushpage') {
         wfDebugLog('p2p', 'addPushPage');
         $specialAsk = $urlServer . '?title=Special:Ask';
         $newtext = "Add a new pushfeed:\n\n\t{{#form:action=" . $urlServer . "?action=pushpage|method=POST|\n\tPushFeed Name:   <br>    {{#input:class=test|name=name|type=text|onKeyUp=test('{$urlServer}');}}<div style=\"display:inline; \" id=\"state\" ></div><br />\n\tRequest: {{#input:type=button|value=Test your query|title=click here to test your query results|onClick=\n\tvar query = document.getElementsByName('keyword')[0].value;\n\tvar query1 = encodeURI(query);\n\twindow.open('" . $specialAsk . "&q='+query1+'&eq=yes&p%5Bformat%5D=broadtable','querywindow','menubar=no, status=no, scrollbars=yes, menubar=no, width=1000, height=900');}}\n\t  <br>{{#input:type=textarea|cols=30 | style=width:auto |rows=2|name=keyword}} <b>e.g. [[Category:city]][[locatedIn::France]]</b><br>\n\t{{#input:type=submit|value=ADD}}\n\t}}";
         $article->doEdit($newtext, $summary = "");
         $wgOut->redirect($article->getTitle()->getFullURL());
         return false;
     } elseif (isset($_GET['action']) && $_GET['action'] == 'pushpage') {
         // $url = $_POST['url'];//pas url mais changesetId
         wfDebugLog('p2p', 'Create new push ' . $_POST['name'] . ' with ' . $_POST['keyword']);
         $name = $_POST['name'];
         $request = $_POST['keyword'];
         $stringReq = utils::encodeRequest($request);
         // avoid "semantic injection" :))
         // addPushSite($url, $name, $request);
         $newtext = "\n[[Special:ArticleAdminPage|DSMW Admin functions]]\n\n==Features==\n[[name::PushFeed:" . $name . "| ]]\n'''Semantic query:''' [[hasSemanticQuery::" . $stringReq . "| ]]<nowiki>" . $request . "</nowiki>\n\n'''Pages concerned:'''\n{{#ask: " . $request . "}}\n[[deleted::false| ]]\n\n==Actions==\n\n{{#input:type=ajax|value=PUSH|onClick=pushpull('" . $urlServer . "','PushFeed:" . $name . "', 'onpush');}}\nThe \"PUSH\" action publishes the (unpublished) modifications of the articles listed above.\n\n== PUSH Progress : ==\n<div id=\"state\" ></div><br />\n";
         wfDebugLog('p2p', '  -> push page contains : ' . $newtext);
         $title = Title::newFromText($_POST['name'], PUSHFEED);
         $article = new Article($title);
         $edit = $article->doEdit($newtext, $summary = "");
         $wgOut->redirect($title->getFullURL());
         return false;
     } elseif (isset($_POST['action']) && $_POST['action'] == 'onpush') {
         /* In case we push directly from an article page */
         if (isset($_POST['page']) && isset($_POST['request'])) {
             $articlename = Title::newFromText($_POST['name']);
             if (!$articlename->exists()) {
                 $result = utils::createPushFeed($_POST['name'], $_POST['request']);
                 utils::writeAndFlush("Create push <A HREF=" . 'http://' . $wgServerName . $wgScriptPath . "/index.php?title=" . $_POST['name'] . ">" . $_POST['name'] . "</a>");
                 if ($result == false) {
                     throw new MWException(__METHOD__ . ': no Pushfeed created in utils:: createPushFeed: ' . 'name: ' . $_POST['name'] . ' request' . $_POST['request']);
                 }
             }
         }
         wfDebugLog('p2p', 'push on ');
         $patches = array();
         $tmpPatches = array();
         if (isset($_POST['name'])) {
             $name1 = $_POST['name'];
             if (!is_array($name1)) {
                 $name1 = array($name1);
             }
             foreach ($name1 as $push) {
                 wfDebugLog('p2p', ' - ' . $push);
             }
         } else {
             $name1 = '';
         }
         if ($name1 == '') {
             utils::writeAndFlush('<p><b>No pushfeed selected!</b></p>');
             $title = Title::newFromText('Special:ArticleAdminPage');
             $wgOut->redirect($title->getFullURL());
             return false;
         }
         // $name = $name1[0];
         utils::writeAndFlush('<p><b>Start push </b></p>');
         foreach ($name1 as $name) {
             utils::writeAndFlush("<span style=\"margin-left:30px;\">begin push: <A HREF=" . 'http://' . $wgServerName . $wgScriptPath . "/index.php?title={$name}>" . $name . "</a></span> <br/>");
             $patches = array();
             // / / for each pushfeed name==> push
             wfDebugLog('p2p', '  -> pushname ' . $name);
             // $name = $_GET['name'];//PushFeed name
             $request = getPushFeedRequest($name);
             // $previousCSID = getPreviousCSID($name);
             $previousCSID = getHasPushHead($name);
             if ($previousCSID == false) {
                 $previousCSID = "none";
                 // $CSID = $name."_0";
             }
             // else{
             //	$count = explode(" ", $previousCSID);
             //	$cnt = $count[1] + 1;
             //	$CSID = $name."_".$cnt;
             // }
             wfDebugLog('p2p', '  ->pushrequest ' . $request);
             wfDebugLog('p2p', '  ->pushHead : ' . $previousCSID);
             $CSID = utils::generateID();
             // changesetID
             if ($request == false) {
                 $outtext = '<p><b>No semantic request found!</b></p> <a href="' . $_SERVER['HTTP_REFERER'] . '">back</a>';
                 $wgOut->addHTML($outtext);
                 return false;
             }
             $pages = getRequestedPages($request);
             // ce sont des pages et non des patches
             foreach ($pages as $page) {
                 wfDebugLog('p2p', '  ->requested page ' . $page);
                 $page = str_replace('"', '', $page);
                 $request1 = '[[Patch:+]][[onPage::' . $page . ']]';
                 $tmpPatches = utils::orderPatchByPrevious($page);
                 if (!is_array($tmpPatches)) {
                     throw new MWException(__METHOD__ . ': $tmpPatches is not an array');
                 }
                 $patches = array_merge($patches, $tmpPatches);
                 wfDebugLog('p2p', '  -> ' . count($tmpPatches) . 'patchs were found for the page ' . $page);
             }
             wfDebugLog('p2p', '  -> ' . count($patches) . ' patchs were found for the pushfeed ' . $name);
             $published = getPublishedPatches($name);
             $unpublished = array_diff($patches, $published);
             /* unpublished = patches-published */
             wfDebugLog('p2p', '  -> ' . count($published) . ' patchs were published for the pushfeed ' . $name . ' and ' . count($unpublished) . ' unpublished patchs');
             if (empty($unpublished)) {
                 wfDebugLog('p2p', '  -> no unpublished patch');
                 utils::writeAndFlush("<span style=\"margin-left:60px;\">no unpublished patch</span><br/>");
                 // return false; //If there is no unpublished patch
             } else {
                 utils::writeAndFlush("<span style=\"margin-left:60px;\">" . count($unpublished) . " unpublished patch</span><br/>");
                 $pos = strrpos($CSID, ":");
                 // NS removing
                 if ($pos === false) {
                     // not found...
                     $articleName = $CSID;
                     $CSID = "ChangeSet:" . $articleName;
                 } else {
                     $articleName = substr($CSID, 0, $pos + 1);
                     $CSID = "ChangeSet:" . $articleName;
                 }
                 $newtext = "\n[[Special:ArticleAdminPage|DSMW Admin functions]]\n\n==Features==\n[[changeSetID::" . $CSID . "| ]]\n\n'''Date:''' " . date(DATE_RFC822) . "\n\n'''User:''' " . $wgUser->getName() . "\n\nThis ChangeSet is in : [[inPushFeed::" . $name . "]]<br>\n==Published patches==\n\n{| class=\"wikitable\" border=\"1\" style=\"text-align:left; width:30%;\"\n|-\n!bgcolor=#c0e8f0 scope=col | Patch\n|-\n";
                 // wfDebugLog('p2p','  -> count unpublished patch '.count($unpublished));
                 foreach ($unpublished as $patch) {
                     wfDebugLog('p2p', '  -> unpublished patch ' . $patch);
                     $newtext .= "|[[hasPatch::" . $patch . "]]\n\t|-\n\t";
                 }
                 $newtext .= "\n\t|}";
                 $newtext .= "\n==Previous ChangeSet==\n[[previousChangeSet::" . $previousCSID . "]]\n";
                 $update = updatePushFeed($name, $CSID);
                 if ($update == true) {
                     // update the "hasPushHead" value successful
                     $title = Title::newFromText($articleName, CHANGESET);
                     $article = new Article($title);
                     $article->doEdit($newtext, $summary = "");
                 } else {
                     $outtext = '<p><b>PushFeed has not been updated!</b></p>';
                     $wgOut->addHTML($outtext);
                 }
             }
         }
         // end foreach pushfeed list
         utils::writeAndFlush('<p><b>End push</b></p>');
         $title = Title::newFromText('Special:ArticleAdminPage');
         $wgOut->redirect($title->getFullURL());
         return false;
     } elseif (isset($_GET['action']) && $_GET['action'] == 'pullpage') {
         // wfDebugLog('p2p','Create pull '.$_POST['pullname'].' with pushName '.$_POST['pushname'].' on '.$_POST['url']);
         // $url = rtrim($_POST['url'], "/"); //removes the final "/" if there is one
         $urlTmp = $_POST['url'];
         if (utils::isValidURL($urlTmp) == false) {
             // throws an exception if $url is invalid
             throw new MWException(__METHOD__ . ': ' . $urlTmp . ' seems not to be an url');
         }
         $res = utils::parsePushURL($urlTmp);
         if ($res === false || empty($res)) {
             throw new MWException(__METHOD__ . ': URL format problem');
         }
         $pushname = $res[0];
         $url = $res[1];
         // $pushname = $_POST['pushname'];
         $pullname = $_POST['pullname'];
         $newtext = "\n[[Special:ArticleAdminPage|DSMW Admin functions]]\n\n==Features==\n\n[[name::PullFeed:" . $pullname . "| ]]\n'''URL of the DSMW PushServer:''' [[pushFeedServer::" . $url . "]]<br>\n'''PushFeed name:''' [[pushFeedName::PushFeed:" . $pushname . "]]\n[[deleted::false| ]]\n\n==Actions==\n\n{{#input:type=ajax|value=PULL|onClick=pushpull('" . $urlServer . "','PullFeed:" . $pullname . "','onpull');}}\n\nThe \"PULL\" action gets the modifications published in the PushFeed of the PushFeedServer above.\n\n== PULL Progress : ==\n<div id=\"state\" ></div><br />\n";
         $title = Title::newFromText($pullname, PULLFEED);
         $article = new Article($title);
         $article->doEdit($newtext, $summary = "");
         $wgOut->redirect($title->getFullURL());
         return false;
     } elseif (isset($_POST['action']) && $_POST['action'] == 'onpull') {
         if (isset($_POST['name'])) {
             $name1 = $_POST['name'];
             wfDebugLog('p2p', 'pull on ');
             if (!is_array($name1)) {
                 $name1 = array($name1);
             }
         } else {
             $name1 = '';
         }
         if ($name1 == '') {
             utils::writeAndFlush('<p><b>No pullfeed selected!</b></p> ');
             $title = Title::newFromText('Special:ArticleAdminPage');
             $article = new Article($title);
             $article->doEdit('', $summary = "");
             $wgOut->redirect($title->getFullURL());
             return false;
         }
         // $name = $name1[0];//with NS
         utils::writeAndFlush('<p><b>Start pull</b></p>');
         foreach ($name1 as $name) {
             // for each pullfeed name==> pull
             utils::writeAndFlush("<span style=\"margin-left:30px;\">begin pull: <A HREF=" . 'http://' . $wgServerName . $wgScriptPath . "/index.php?title={$name}>" . $name . "</a></span> <br/>");
             wfDebugLog('p2p', '      -> pull : ' . $name);
             // $previousCSID = getPreviousPulledCSID($name);
             // if($previousCSID==false) {
             //	$previousCSID = "none";
             // }
             $previousCSID = getHasPullHead($name);
             if ($previousCSID == false) {
                 $previousCSID = "none";
             }
             wfDebugLog('p2p', '      -> pullHead : ' . $previousCSID);
             $relatedPushServer = getPushURL($name);
             if (is_null($relatedPushServer)) {
                 throw new MWException(__METHOD__ . ': no relatedPushServer url');
             }
             $namePush = getPushName($name);
             $namePush = str_replace(' ', '_', $namePush);
             wfDebugLog('p2p', '      -> pushServer : ' . $relatedPushServer);
             wfDebugLog('p2p', '      -> pushName : ' . $namePush);
             if (is_null($namePush)) {
                 throw new MWException(__METHOD__ . ': no PushName');
             }
             // split NS and name
             preg_match("/^(.+?)_*:_*(.*)\$/S", $namePush, $m);
             $nameWithoutNS = $m[2];
             // $url = $relatedPushServer.'/api.php?action=query&meta=changeSet&cspushName='.$nameWithoutNS.'&cschangeSet='.$previousCSID.'&format=xml';
             // $url = $relatedPushServer."/api{$wgScriptExtension}?action=query&meta=changeSet&cspushName=".$nameWithoutNS.'&cschangeSet='.$previousCSID.'&format=xml';
             wfDebugLog('testlog', '      -> request ChangeSet : ' . $relatedPushServer . '/api.php?action=query&meta=changeSet&cspushName=' . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml');
             $cs = utils::file_get_contents_curl(utils::lcfirst($relatedPushServer) . "/api.php?action=query&meta=changeSet&cspushName=" . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml');
             /* test if it is a xml file. If not, the server is not reachable via the url
              * Then we try to reach it with the .php5 extension
              */
             if (strpos($cs, "<?xml version=\"1.0\"?>") === false) {
                 $cs = utils::file_get_contents_curl(utils::lcfirst($relatedPushServer) . "/api.php5?action=query&meta=changeSet&cspushName=" . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml');
             }
             if (strpos($cs, "<?xml version=\"1.0\"?>") === false) {
                 $cs = false;
             }
             if ($cs === false) {
                 throw new MWException(__METHOD__ . ': Cannot connect to Push Server (ChangeSet API)');
             }
             $cs = trim($cs);
             $dom = new DOMDocument();
             $dom->loadXML($cs);
             $changeSet = $dom->getElementsByTagName('changeSet');
             $CSID = null;
             foreach ($changeSet as $cs) {
                 if ($cs->hasAttribute("id")) {
                     $CSID = $cs->getAttribute('id');
                     $csName = $CSID;
                 }
             }
             wfDebugLog('p2p', '     -> changeSet found ' . $CSID);
             while ($CSID != null) {
                 // if(!utils::pageExist($CSID)) {
                 $listPatch = null;
                 $patchs = $dom->getElementsByTagName('patch');
                 foreach ($patchs as $p) {
                     wfDebugLog('p2p', '          -> patch ' . $p->firstChild->nodeValue);
                     $listPatch[] = $p->firstChild->nodeValue;
                 }
                 // $CSID = substr($CSID,strlen('changeSet:'));
                 utils::createChangeSetPull($CSID, $name, $previousCSID, $listPatch);
                 integrate($CSID, $listPatch, $relatedPushServer, $csName);
                 updatePullFeed($name, $CSID);
                 // }
                 $previousCSID = $CSID;
                 wfDebugLog('p2p', '     -> request ChangeSet : ' . $relatedPushServer . '/api.php?action=query&meta=changeSet&cspushName=' . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml');
                 $cs = utils::file_get_contents_curl(utils::lcfirst($relatedPushServer) . "/api.php?action=query&meta=changeSet&cspushName=" . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml');
                 /* test if it is a xml file. If not, the server is not reachable via the url
                  * Then we try to reach it with the .php5 extension
                  */
                 if (strpos($cs, "<?xml version=\"1.0\"?>") === false) {
                     $cs = utils::file_get_contents_curl(utils::lcfirst($relatedPushServer) . "/api.php5?action=query&meta=changeSet&cspushName=" . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml');
                 }
                 if (strpos($cs, "<?xml version=\"1.0\"?>") === false) {
                     $cs = false;
                 }
                 if ($cs === false) {
                     throw new MWException(__METHOD__ . ': Cannot connect to Push Server (ChangeSet API)');
                 }
                 $cs = trim($cs);
                 $dom = new DOMDocument();
                 $dom->loadXML($cs);
                 $changeSet = $dom->getElementsByTagName('changeSet');
                 $CSID = null;
                 foreach ($changeSet as $cs) {
                     if ($cs->hasAttribute("id")) {
                         $CSID = $cs->getAttribute('id');
                     }
                 }
                 wfDebugLog('p2p', '     -> changeSet found ' . $CSID);
             }
             if (is_null($csName)) {
                 wfDebugLog('p2p', '  - redirect to Special:ArticleAdminPage');
                 utils::writeAndFlush("<span style=\"margin-left:60px;\">no new patch</span><br/>");
             } else {
                 wfDebugLog('p2p', '  - redirect to ChangeSet:' . $csName);
             }
         }
         // end foreach list pullfeed
         utils::writeAndFlush('<p><b>End pull</b></p>');
         $title = Title::newFromText('Special:ArticleAdminPage');
         $wgOut->redirect($title->getFullURL());
         return false;
     } else {
         return true;
     }
 }