function run($dbi, $argstr, &$request, $basepage) { global $WikiTheme; $this->_supported_operators = array(':=', '<', '<=', '>', '>=', '!=', '==', '=~'); $this->_text_operators = array(':=', '==', '=~', '!='); $args = $this->getArgs($argstr, $request); if (empty($args['page'])) { $args['page'] = "*"; } if (!isset($args['s'])) { // it might be (integer) 0 $args['s'] = "*"; } $posted = $request->getArg("semsearch"); $form = $this->showForm($dbi, $request, $args); if (isset($this->_norelations_warning)) { $form->pushContent(HTML::div(array('class' => 'warning'), _("Warning:"), HTML::br(), _("No relations nor attributes in the whole wikidb defined!"), "\n", fmt("See %s", WikiLink(_("Help:SemanticRelations"))))); } extract($args); // for convenience and harmony we allow GET requests also. if (!$request->isPost()) { if ($relation or $attribute) { // check for good GET request } else { return $form; } // nobody called us, so just display our supadupa form } $pagequery = $this->regex_query($page, $args['case_exact'], $args['regex']); // we might want to check for semsearch['relations'] and semsearch['attributes'] also if (empty($relation) and empty($attribute)) { // so we just clicked without selecting any relation. // hmm. check which button we clicked, before we do the massive alltogether search. if (isset($posted['relations']) and $posted['relations']) { $relation = '*'; } elseif (isset($posted['attributes']) and $posted['attributes']) { $attribute = '*'; // here we have to check for invalid text operators. ignore it then if (!in_array($attr_op, $this->_text_operators)) { $attribute = ''; } } } $searchtype = "Text"; if (!empty($relation)) { $querydesc = $relation . "::" . $s; $linkquery = $this->regex_query($s, $args['case_exact'], $args['regex']); $relquery = $this->regex_query($relation, $args['case_exact'], $args['regex']); $links = $dbi->linkSearch($pagequery, $linkquery, 'relation', $relquery); $pagelist = new PageList($info, $exclude, $args); $pagelist->_links = array(); while ($link = $links->next()) { $pagelist->addPage($link['pagename']); $pagelist->_links[] = $link; } // default (=empty info) wants all three. but we want to be able to override this. // $pagelist->_columns_seen is the exploded info if (!$info or $info and isset($pagelist->_columns_seen['relation'])) { $pagelist->addColumnObject(new _PageList_Column_SemanticSearch_relation('relation', _("Relation"), $pagelist)); } if (!$args['info'] or $args['info'] and isset($pagelist->_columns_seen['linkto'])) { $pagelist->addColumnObject(new _PageList_Column_SemanticSearch_link('linkto', _("Link"), $pagelist)); } } // can we merge two different pagelist? if (!empty($attribute)) { $relquery = $this->regex_query($attribute, $args['case_exact'], $args['regex']); if (!in_array($attr_op, $this->_supported_operators)) { return HTML($form, $this->error(fmt("Illegal operator: %s", HTML::tt($attr_op)))); } $s_base = preg_replace("/,/", "", $s); $units = new Units(); if (!is_numeric($s_base)) { $s_base = $units->basevalue($s_base); $is_numeric = is_numeric($s_base); } else { $is_numeric = true; } // check which type to search with: // at first check if forced text matcher if ($attr_op == '=~') { if ($s == '*') { $s = '.*'; } // help the poor user. we need pcre syntax. $linkquery = new TextSearchQuery("{$s}", $args['case_exact'], 'pcre'); $querydesc = "{$attribute} {$attr_op} {$s}"; } elseif ($is_numeric) { // do comparison with numbers /* We want to search for multiple attributes also. linkSearch can do this. * But we have to construct the query somehow. (that's why we try the AND OR dhtml) * population < 1 million AND area > 50 km2 * Here we check only for one attribute per page. * See SemanticSearchAdvanced for the full expression. */ // it might not be the best idea to use '*' as variable to expand. hmm. if ($attribute == '*') { $attribute = '_star_'; } $searchtype = "Numeric"; $query = $attribute . " " . $attr_op . " " . $s_base; $linkquery = new SemanticAttributeSearchQuery($query, $attribute, $units->baseunit($s)); if ($attribute == '_star_') { $attribute = '*'; } $querydesc = $attribute . " " . $attr_op . " " . $s; // no number or unit: check other text matchers or '*' MATCH_ALL } elseif (in_array($attr_op, $this->_text_operators)) { if ($attr_op == '=~') { if ($s == '*') { $s = '.*'; } // help the poor user. we need pcre syntax. $linkquery = new TextSearchQuery("{$s}", $args['case_exact'], 'pcre'); } else { $linkquery = $this->regex_query($s, $args['case_exact'], $args['regex']); } $querydesc = "{$attribute} {$attr_op} {$s}"; // should we fail or skip when the user clicks on Relations? } elseif (isset($posted['relations']) and $posted['relations']) { $linkquery = false; // skip } else { $querydesc = $attribute . " " . $attr_op . " " . $s; return HTML($form, $this->error(fmt("Only text operators can be used with strings: %s", HTML::tt($querydesc)))); } if ($linkquery) { $links = $dbi->linkSearch($pagequery, $linkquery, 'attribute', $relquery); if (empty($relation)) { $pagelist = new PageList($args['info'], $args['exclude'], $args); $pagelist->_links = array(); } while ($link = $links->next()) { $pagelist->addPage($link['pagename']); $pagelist->_links[] = $link; } // default (=empty info) wants all three. but we want to override this. if (!$args['info'] or $args['info'] and isset($pagelist->_columns_seen['attribute'])) { $pagelist->addColumnObject(new _PageList_Column_SemanticSearch_relation('attribute', _("Attribute"), $pagelist)); } if (!$args['info'] or $args['info'] and isset($pagelist->_columns_seen['value'])) { $pagelist->addColumnObject(new _PageList_Column_SemanticSearch_link('value', _("Value"), $pagelist)); } } } if (!isset($pagelist)) { $querydesc = _("<empty>"); $pagelist = new PageList(); } if (!$noheader) { // We put the form into the caption just to be able to return one pagelist object, // and to still have the convenience form at the top. we could workaround this by // putting the form as WikiFormRich into the actionpage. but thid doesnt look as // nice as this here. $pagelist->setCaption(HTML($noform ? '' : HTML($form, HTML::hr()), fmt("Semantic %s Search Result for \"%s\" in pages \"%s\"", $searchtype, $querydesc, $page))); } return $pagelist; }
function _expandurl($url) { $m = array(); if (!preg_match('/^ ([^:]+) (:[:=]) (.+) $/x', $url, $m)) { return HTML::span(array('class' => 'error'), _("BAD semantic relation link")); } $this->_relation = urldecode($m[1]); $is_attribute = $m[2] == ':='; if ($is_attribute) { $this->_attribute = urldecode($m[3]); // since this stored in the markup cache, we are extra sensible // not to store false empty stuff. $units = new Units(); if (!DISABLE_UNITS and !$units->errcode) { $this->_attribute_base = $units->Definition($this->_attribute); $this->_unit = $units->baseunit($this->_attribute); } } else { $this->_page = urldecode($m[3]); } return $m; }