PageRenderTime 90ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/extensions/Wikidata/OmegaWiki/SpecialDatasearch.php

https://github.com/ChuguluGames/mediawiki-svn
PHP | 359 lines | 268 code | 88 blank | 3 comment | 37 complexity | dea6b2e56f8381350db2027a76ad3748 MD5 | raw file
  1. <?php
  2. if ( !defined( 'MEDIAWIKI' ) ) die();
  3. require_once( "Wikidata.php" );
  4. require_once( "WikiDataGlobals.php" );
  5. class SpecialDatasearch extends SpecialPage {
  6. protected $externalIdentifierAttribute;
  7. protected $collectionAttribute;
  8. protected $collectionMemberAttribute;
  9. protected $externalIdentifierMatchStructure;
  10. protected $spellingAttribute;
  11. protected $languageAttribute;
  12. protected $expressionStructure;
  13. protected $expressionAttribute;
  14. protected $definedMeaningAttribute;
  15. protected $definitionAttribute;
  16. protected $meaningStructure;
  17. protected $meaningAttribute;
  18. function SpecialDatasearch() {
  19. parent::__construct( 'DataSearch' );
  20. }
  21. function execute( $parameter ) {
  22. global $wgOut;
  23. initializeOmegaWikiAttributes( new ViewInformation() );
  24. global
  25. $definedMeaningReferenceType,
  26. $wgDefinedMeaning;
  27. require_once( "WikiDataGlobals.php" );
  28. require_once( "forms.php" );
  29. require_once( "type.php" );
  30. require_once( "ViewInformation.php" );
  31. require_once( "WikiDataAPI.php" );
  32. require_once( "OmegaWikiAttributes.php" );
  33. require_once( "OmegaWikiRecordSets.php" );
  34. require_once( "OmegaWikiEditors.php" );
  35. $wgOut->setPageTitle( wfMsg( 'search' ) );
  36. $this->spellingAttribute = new Attribute( "found-word", wfMsg( 'datasearch_found_word' ), "short-text" );
  37. $this->languageAttribute = new Attribute( "language", wfMsg( 'ow_Language' ), "language" );
  38. $this->expressionStructure = new Structure( $this->spellingAttribute, $this->languageAttribute );
  39. $this->expressionAttribute = new Attribute( "expression", wfMsg( 'ow_Expression' ), $this->expressionStructure );
  40. $this->definedMeaningAttribute = new Attribute( $wgDefinedMeaning, wfMsg( 'ow_DefinedMeaning' ), $definedMeaningReferenceType );
  41. $this->definitionAttribute = new Attribute( "definition", wfMsg( 'ow_Definition' ), "definition" );
  42. $this->meaningStructure = new Structure( $this->definedMeaningAttribute, $this->definitionAttribute );
  43. $this->meaningAttribute = new Attribute( "meaning", wfMsg( 'datasearch_meaning' ), $this->meaningStructure );
  44. $this->externalIdentifierAttribute = new Attribute( "external-identifier", wfMsg( 'datasearch_ext_identifier' ), "short-text" );
  45. $this->collectionAttribute = new Attribute( "collection", wfMsg( 'ow_Collection' ), $definedMeaningReferenceType );
  46. $this->collectionMemberAttribute = new Attribute( "collection-member", wfMsg( 'ow_CollectionMember' ), $definedMeaningReferenceType );
  47. $this->externalIdentifierMatchStructure = new Structure(
  48. $this->externalIdentifierAttribute,
  49. $this->collectionAttribute,
  50. $this->collectionMemberAttribute
  51. );
  52. if ( array_key_exists( 'search-text', $_GET ) ) {
  53. $searchText = ltrim( $_GET['search-text'] );
  54. } else {
  55. $searchText = null;
  56. }
  57. if ( isset( $_GET['go'] ) )
  58. $this->go( $searchText );
  59. else
  60. $this->search( $searchText );
  61. }
  62. function go( $searchText ) {
  63. global
  64. $wgScript, $wgOut;
  65. $expressionMeaningIds = getExpressionMeaningIds( $searchText );
  66. if ( count( $expressionMeaningIds ) > 0 ) {
  67. if ( count( $expressionMeaningIds ) == 1 )
  68. $wgOut->redirect( definedMeaningIdAsURL( $expressionMeaningIds[0] ) );
  69. else
  70. $wgOut->redirect( spellingAsURL( $searchText ) );
  71. }
  72. else {
  73. $collectionMemberId = getAnyDefinedMeaningWithSourceIdentifier( $searchText );
  74. if ( $collectionMemberId != 0 )
  75. $wgOut->redirect( definedMeaningIdAsURL( $collectionMemberId ) );
  76. else
  77. $wgOut->redirect( spellingAsURL( $searchText ) );
  78. }
  79. }
  80. function search( $searchText ) {
  81. global
  82. $wgOut, $wgRequest, $wgFilterLanguageId,
  83. $wgSearchWithinWordsDefaultValue, $wgSearchWithinExternalIdentifiersDefaultValue,
  84. $wgShowSearchWithinExternalIdentifiersOption, $wgShowSearchWithinWordsOption;
  85. $collectionId = $wgRequest->getInt( "collection" );
  86. $languageId = $wgRequest->getInt( "language" );
  87. $withinWords = $wgRequest->getBool( "within-words" );
  88. $withinExternalIdentifiers = $wgRequest->getBool( "within-external-identifiers" );
  89. if ( !$withinWords && !$withinExternalIdentifiers ) {
  90. $withinWords = $wgSearchWithinWordsDefaultValue;
  91. $withinExternalIdentifiers = $wgSearchWithinExternalIdentifiersDefaultValue;
  92. }
  93. $languageName = languageIdAsText( $languageId );
  94. $options = array();
  95. $options[wfMsg( 'datasearch_search_text' )] = getTextBox( 'search-text', $searchText );
  96. if ( $wgFilterLanguageId == 0 )
  97. $options[wfMsg( 'datasearch_language' )] = getSuggest( 'language', "language", array(), $languageId, $languageName );
  98. else
  99. $languageId = $wgFilterLanguageId;
  100. $options[wfMsg( 'ow_Collection_colon' )] = getSuggest( 'collection', 'collection', array(), $collectionId, collectionIdAsText( $collectionId ) );
  101. if ( $wgShowSearchWithinWordsOption )
  102. $options[wfMsg( 'datasearch_within_words' )] = getCheckBox( 'within-words', $withinWords );
  103. else
  104. $withinWords = $wgSearchWithinWordsDefaultValue;
  105. if ( $wgShowSearchWithinExternalIdentifiersOption )
  106. $options[wfMsg( 'datasearch_within_ext_ids' )] = getCheckBox( 'within-external-identifiers', $withinExternalIdentifiers );
  107. else
  108. $withinExternalIdentifiers = $wgSearchWithinExternalIdentifiersDefaultValue;
  109. $wgOut->addHTML( getOptionPanel( $options ) );
  110. if ( $withinWords ) {
  111. if ( $languageId != 0 && $languageName != "" )
  112. $wgOut->addHTML( '<h1>' . wfMsg( 'datasearch_match_words_lang', $languageName, $searchText ) . '</h1>' );
  113. else
  114. $wgOut->addHTML( '<h1>' . wfMsg( 'datasearch_match_words', $searchText ) . '</h1>' );
  115. $resultCount = $this->searchWordsCount( $searchText, $collectionId, $languageId ) ;
  116. $wgOut->addHTML( '<p>' . wfMsgExt( 'datasearch_showing_only', 'parsemag', 100 , $resultCount ) . '</p>' );
  117. $wgOut->addHTML( $this->searchWords( $searchText, $collectionId, $languageId ) );
  118. }
  119. if ( $withinExternalIdentifiers ) {
  120. $wgOut->addHTML( '<h1>' . wfMsg( 'datasearch_match_ext_ids', $searchText ) . '</i></h1>' );
  121. $wgOut->addHTML( '<p>' . wfMsgExt( 'datasearch_showing_only', 'parsemag', 100 ) . '</p>' );
  122. $wgOut->addHTML( $this->searchExternalIdentifiers( $searchText, $collectionId ) );
  123. }
  124. }
  125. function getSpellingRestriction( $spelling, $tableColumn ) {
  126. $dbr = wfGetDB( DB_SLAVE );
  127. if ( trim( $spelling ) != '' )
  128. return " AND " . $tableColumn . " LIKE " . $dbr->addQuotes( "%$spelling%" );
  129. else
  130. return "";
  131. }
  132. function getSpellingOrderBy( $spelling ) {
  133. if ( trim( $spelling ) != '' )
  134. return "position ASC, ";
  135. else
  136. return "";
  137. }
  138. function getPositionSelectColumn( $spelling, $tableColumn ) {
  139. $dbr = wfGetDB( DB_SLAVE );
  140. if ( trim( $spelling ) != '' )
  141. return "INSTR(LCASE(" . $tableColumn . "), LCASE(" . $dbr->addQuotes( "$spelling" ) . ")) as position, ";
  142. else
  143. return "";
  144. }
  145. function searchWords( $text, $collectionId, $languageId ) {
  146. $dc = wdGetDataSetContext();
  147. $dbr = wfGetDB( DB_SLAVE );
  148. $sql =
  149. "SELECT " . $this->getPositionSelectColumn( $text, "{$dc}_expression.spelling" ) . " {$dc}_syntrans.defined_meaning_id AS defined_meaning_id, {$dc}_expression.spelling AS spelling, {$dc}_expression.language_id AS language_id " .
  150. "FROM {$dc}_expression, {$dc}_syntrans ";
  151. if ( $collectionId > 0 )
  152. $sql .= ", {$dc}_collection_contents ";
  153. $sql .=
  154. "WHERE {$dc}_expression.expression_id={$dc}_syntrans.expression_id AND {$dc}_syntrans.identical_meaning=1 " .
  155. " AND " . getLatestTransactionRestriction( "{$dc}_syntrans" ) .
  156. " AND " . getLatestTransactionRestriction( "{$dc}_expression" ) .
  157. $this->getSpellingRestriction( $text, 'spelling' );
  158. if ( $collectionId > 0 )
  159. $sql .=
  160. " AND {$dc}_collection_contents.member_mid={$dc}_syntrans.defined_meaning_id " .
  161. " AND {$dc}_collection_contents.collection_id=" . $collectionId .
  162. " AND " . getLatestTransactionRestriction( "{$dc}_collection_contents" );
  163. if ( $languageId > 0 )
  164. $sql .=
  165. " AND {$dc}_expression.language_id=$languageId";
  166. $sql .=
  167. " ORDER BY " . $this->getSpellingOrderBy( $text ) . "{$dc}_expression.spelling ASC limit 100";
  168. $queryResult = $dbr->query( $sql );
  169. $recordSet = $this->getWordsSearchResultAsRecordSet( $queryResult );
  170. $editor = $this->getWordsSearchResultEditor();
  171. return $editor->view( new IdStack( "words" ), $recordSet );
  172. }
  173. /**
  174. * Gives the exact number of results (not limited to 100)
  175. */
  176. function searchWordsCount( $text, $collectionId, $languageId ) {
  177. $dc = wdGetDataSetContext();
  178. $dbr = wfGetDB( DB_SLAVE );
  179. $sql =
  180. "SELECT COUNT(*) " .
  181. "FROM {$dc}_expression, {$dc}_syntrans ";
  182. if ( $collectionId > 0 )
  183. $sql .= ", {$dc}_collection_contents ";
  184. $sql .=
  185. "WHERE {$dc}_expression.expression_id={$dc}_syntrans.expression_id AND {$dc}_syntrans.identical_meaning=1 " .
  186. " AND " . getLatestTransactionRestriction( "{$dc}_syntrans" ) .
  187. " AND " . getLatestTransactionRestriction( "{$dc}_expression" ) .
  188. $this->getSpellingRestriction( $text, 'spelling' );
  189. if ( $collectionId > 0 )
  190. $sql .=
  191. " AND {$dc}_collection_contents.member_mid={$dc}_syntrans.defined_meaning_id " .
  192. " AND {$dc}_collection_contents.collection_id=" . $collectionId .
  193. " AND " . getLatestTransactionRestriction( "{$dc}_collection_contents" );
  194. if ( $languageId > 0 )
  195. $sql .=
  196. " AND {$dc}_expression.language_id=$languageId";
  197. $queryResult_r = mysql_query( $sql );
  198. $queryResult_a = mysql_fetch_row( $queryResult_r );
  199. $queryResultCount = $queryResult_a[0];
  200. return $queryResultCount ;
  201. }
  202. function getWordsSearchResultAsRecordSet( $queryResult ) {
  203. $o = OmegaWikiAttributes::getInstance();
  204. $dbr = wfGetDB( DB_SLAVE );
  205. $recordSet = new ArrayRecordSet( new Structure( $o->definedMeaningId, $this->expressionAttribute, $this->meaningAttribute ), new Structure( $o->definedMeaningId ) );
  206. while ( $row = $dbr->fetchObject( $queryResult ) ) {
  207. $expressionRecord = new ArrayRecord( $this->expressionStructure );
  208. $expressionRecord->setAttributeValue( $this->spellingAttribute, $row->spelling );
  209. $expressionRecord->setAttributeValue( $this->languageAttribute, $row->language_id );
  210. $meaningRecord = new ArrayRecord( $this->meaningStructure );
  211. $meaningRecord->setAttributeValue( $this->definedMeaningAttribute, getDefinedMeaningReferenceRecord( $row->defined_meaning_id ) );
  212. $meaningRecord->setAttributeValue( $this->definitionAttribute, getDefinedMeaningDefinition( $row->defined_meaning_id ) );
  213. $recordSet->addRecord( array( $row->defined_meaning_id, $expressionRecord, $meaningRecord ) );
  214. }
  215. return $recordSet;
  216. }
  217. function getWordsSearchResultEditor() {
  218. $expressionEditor = new RecordTableCellEditor( $this->expressionAttribute );
  219. $expressionEditor->addEditor( new SpellingEditor( $this->spellingAttribute, new SimplePermissionController( false ), false ) );
  220. $expressionEditor->addEditor( new LanguageEditor( $this->languageAttribute, new SimplePermissionController( false ), false ) );
  221. $meaningEditor = new RecordTableCellEditor( $this->meaningAttribute );
  222. $meaningEditor->addEditor( new DefinedMeaningReferenceEditor( $this->definedMeaningAttribute, new SimplePermissionController( false ), false ) );
  223. $meaningEditor->addEditor( new TextEditor( $this->definitionAttribute, new SimplePermissionController( false ), false, true, 75 ) );
  224. $editor = createTableViewer( null );
  225. $editor->addEditor( $expressionEditor );
  226. $editor->addEditor( $meaningEditor );
  227. return $editor;
  228. }
  229. function searchExternalIdentifiers( $text, $collectionId ) {
  230. $dc = wdGetDataSetContext();
  231. $dbr = wfGetDB( DB_SLAVE );
  232. $sql =
  233. "SELECT " . $this->getPositionSelectColumn( $text, "{$dc}_collection_contents.internal_member_id" ) . " {$dc}_collection_contents.member_mid AS member_mid, {$dc}_collection_contents.internal_member_id AS external_identifier, {$dc}_collection.collection_mid AS collection_mid " .
  234. "FROM {$dc}_collection_contents, {$dc}_collection ";
  235. $sql .=
  236. "WHERE {$dc}_collection.collection_id={$dc}_collection_contents.collection_id " .
  237. " AND " . getLatestTransactionRestriction( "{$dc}_collection" ) .
  238. " AND " . getLatestTransactionRestriction( "{$dc}_collection_contents" ) .
  239. $this->getSpellingRestriction( $text, "{$dc}_collection_contents.internal_member_id" );
  240. if ( $collectionId > 0 )
  241. $sql .=
  242. " AND {$dc}_collection.collection_id=$collectionId ";
  243. $sql .=
  244. " ORDER BY " . $this->getSpellingOrderBy( $text ) . "{$dc}_collection_contents.internal_member_id ASC limit 100";
  245. $queryResult = $dbr->query( $sql );
  246. $recordSet = $this->getExternalIdentifiersSearchResultAsRecordSet( $queryResult );
  247. $editor = $this->getExternalIdentifiersSearchResultEditor();
  248. return $editor->view( new IdStack( "external-identifiers" ), $recordSet );
  249. }
  250. function getExternalIdentifiersSearchResultAsRecordSet( $queryResult ) {
  251. $dbr = wfGetDB( DB_SLAVE );
  252. $externalIdentifierMatchStructure = new Structure( $this->externalIdentifierAttribute, $this->collectionAttribute, $this->collectionMemberAttribute );
  253. $recordSet = new ArrayRecordSet( $externalIdentifierMatchStructure, new Structure( $this->externalIdentifierAttribute ) );
  254. while ( $row = $dbr->fetchObject( $queryResult ) ) {
  255. $record = new ArrayRecord( $this->externalIdentifierMatchStructure );
  256. $record->setAttributeValue( $this->externalIdentifierAttribute, $row->external_identifier );
  257. $record->setAttributeValue( $this->collectionAttribute, $row->collection_mid );
  258. $record->setAttributeValue( $this->collectionMemberAttribute, $row->member_mid );
  259. $recordSet->add( $record );
  260. }
  261. expandDefinedMeaningReferencesInRecordSet( $recordSet, array( $this->collectionAttribute, $this->collectionMemberAttribute ) );
  262. return $recordSet;
  263. }
  264. function getExternalIdentifiersSearchResultEditor() {
  265. $editor = createTableViewer( null );
  266. $editor->addEditor( createShortTextViewer( $this->externalIdentifierAttribute ) );
  267. $editor->addEditor( createDefinedMeaningReferenceViewer( $this->collectionMemberAttribute ) );
  268. $editor->addEditor( createDefinedMeaningReferenceViewer( $this->collectionAttribute ) );
  269. return $editor;
  270. }
  271. }