diff options
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/src/MediaWiki/Search/SearchProfileForm.php')
-rw-r--r-- | www/wiki/extensions/SemanticMediaWiki/src/MediaWiki/Search/SearchProfileForm.php | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/src/MediaWiki/Search/SearchProfileForm.php b/www/wiki/extensions/SemanticMediaWiki/src/MediaWiki/Search/SearchProfileForm.php new file mode 100644 index 00000000..1f6ebce9 --- /dev/null +++ b/www/wiki/extensions/SemanticMediaWiki/src/MediaWiki/Search/SearchProfileForm.php @@ -0,0 +1,433 @@ +<?php + +namespace SMW\MediaWiki\Search; + +use Html; +use MWNamespace; +use SMW; +use SMW\MediaWiki\Search\Form\FormsBuilder; +use SMW\MediaWiki\Search\Form\FormsFactory; +use SMW\MediaWiki\Search\Form\FormsFinder; +use SMW\ProcessingErrorMsgHandler; +use SMW\Utils\HtmlModal; +use SMW\Store; +use SMW\Message; +use SpecialSearch; +use Title; +use WikiPage; +use Xml; + +/** + * @license GNU GPL v2+ + * @since 3.0 + * + * @author mwjames + */ +class SearchProfileForm { + + const PROFILE_NAME = 'smw'; + + /** + * Page that hosts the form/forms definition + */ + const SCHEMA_TYPE = 'SEARCH_FORM_SCHEMA'; + + /** + * @var Store + */ + private $store; + + /** + * @var SpecialSearch + */ + private $specialSearch; + + /** + * @var FormsFactory + */ + private $formsFactory; + + /** + * @var [] + */ + private $searchableNamespaces = []; + + /** + * @since 3.0 + * + * @param Store $store + * @param SpecialSearch $specialSearch + */ + public function __construct( Store $store, SpecialSearch $specialSearch ) { + $this->store = $store; + $this->specialSearch = $specialSearch; + $this->formsFactory = new FormsFactory(); + } + + /** + * @since 3.0 + * + * @param string $type + * @param array &$profiles + */ + public static function addProfile( $type, array &$profiles ) { + + if ( $type !== 'SMWSearch' ) { + return; + } + + $profiles[self::PROFILE_NAME] = [ + 'message' => 'smw-search-profile', + 'tooltip' => 'smw-search-profile-tooltip', + 'namespaces' => \SearchEngine::defaultNamespaces() + ]; + } + + /** + * @since 3.0 + * + * @param Store $store + * + * @return array + */ + public static function getFormDefinitions( Store $store ) { + + static $data = null; + + if ( $data !== null ) { + return $data; + } + + $formsFinder = new FormsFinder( $store ); + $data = $formsFinder->getFormDefinitions(); + + return $data; + } + + /** + * @since 3.0 + * + * @param array $searchableNamespaces + */ + public function setSearchableNamespaces( array $searchableNamespaces ) { + $this->searchableNamespaces = $searchableNamespaces; + } + + /** + * @since 3.0 + * + * @param string &$form + * @param array $opts + */ + public function getForm( &$form, array $opts = [] ) { + + $hidden = ''; + $html = ''; + + $context = $this->specialSearch->getContext(); + $request = $context->getRequest(); + + foreach ( $opts as $key => $value ) { + $hidden .= Html::hidden( $key, $value ); + } + + $outputPage = $context->getOutput(); + + $outputPage->addModuleStyles( [ 'smw.ui.styles', 'smw.special.search.styles' ] ); + $outputPage->addModules( + [ + 'smw.ui', + 'smw.special.search', + 'ext.smw.tooltip', + 'ext.smw.autocomplete.property' + ] + ); + + // Set active form + $this->specialSearch->setExtraParam( 'smw-form', $request->getVal( 'smw-form' ) ); + + $searchEngine = $this->specialSearch->getSearchEngine(); + + if ( ( $queryLink = $searchEngine->getQueryLink() ) instanceof \SMWInfolink ) { + $queryLink->setCaption( $this->msg( 'smw-search-profile-link-caption-query', Message::TEXT ) ); + $queryLink->setLinkAttributes( + [ + 'title' => 'Special:Ask' + ] + ); + } + + list( $searchForms, $formList, $termPrefixes, $preselectNamespaces, $hiddenNamespaces ) = $this->buildSearchForms( + $request + ); + + $sortForm = $this->buildSortForm( $request ); + + $namespaceForm = $this->buildNamespaceForm( + $request, + $searchEngine, + $preselectNamespaces, + $hiddenNamespaces, + $hidden + ); + + $options = Html::rawElement( + 'div', + [ + 'class' => 'smw-search-options' + ], + Html::rawElement( + 'div', + [ + 'style' => 'color: #586069;position: relative;display: inline-block; padding-top: 5px; padding-bottom: 2px;' + ], + '' + ) . $sortForm . $formList . HtmlModal::link( + '<span class="smw-icon-info"></span>', + [ + 'data-id' => 'smw-search-profile-extended-cheat-sheet' + ] + ) + ); + + $errors = $this->findErrors( $searchEngine ); + + $modal = HtmlModal::modal( + Message::get( 'smw-cheat-sheet', Message::TEXT, Message::USER_LANGUAGE ), + $this->profile_sheet( $searchEngine->getQueryString(), $queryLink, $termPrefixes ), + [ + 'id' => 'smw-search-profile-extended-cheat-sheet', + 'class' => 'plainlinks', + 'style' => 'display:none;' + ] + ); + + $form .= Html::rawElement( + 'fieldset', + [ + 'id' => 'smw-searchoptions' + ], + $hidden . $errors . $modal . $options . $searchForms + ); + + // Different fieldset therefore it is used as last element + $form .= $namespaceForm; + } + + private function buildNamespaceForm( $request, $searchEngine, $preselectNamespaces, $hiddenNamespaces, &$hidden ) { + + $activeNamespaces = array_merge( $this->specialSearch->getNamespaces(), $preselectNamespaces ); + $default = false; + + $data = $this->getFormDefinitions( $this->store ); + + foreach ( $this->searchableNamespaces as $ns => $name ) { + + if ( $request->getCheck( 'ns' . $ns ) ) { + $activeNamespaces[] = $ns; + $this->specialSearch->setExtraParam( 'ns' . $ns, true ); + } + } + + if ( $searchEngine !== null ) { + $searchEngine->setNamespaces( $activeNamespaces ); + } + + // Contains the copied Advanced namespace form + $namespaceForm = $this->formsFactory->newNamespaceForm(); + + $namespaceForm->setActiveNamespaces( + $activeNamespaces + ); + + $namespaceForm->setHiddenNamespaces( + $hiddenNamespaces + ); + + if ( isset( $data['namespaces']['default_hide'] ) ) { + $default = $data['namespaces']['default_hide']; + } + + $namespaceForm->setHideList( + $request->getVal( 'ns-list', $default ) + ); + + $namespaceForm->setSearchableNamespaces( + $this->searchableNamespaces + ); + + $namespaceForm->checkNamespaceEditToken( + $this->specialSearch + ); + + // Carry over the status (hide/show) of the ns section during a search + // request so we don't have to set a cookie while still being able to + // retain its status on whether the users has the NS hidden or not. + $hidden .= Html::hidden( 'ns-list', $request->getVal( 'ns-list', $default ) ); + + return $namespaceForm->makeFields(); + } + + private function buildSearchForms( $request ) { + + $data = $this->getFormDefinitions( $this->store ); + + if ( $data === [] ) { + return [ '', '', [], [], [] ]; + } + + $formsBuilder = new FormsBuilder( $request, $this->formsFactory ); + + $form = $formsBuilder->buildForm( $data ); + $parameters = $formsBuilder->getParameters(); + + // Set parameters so that any link to a (... 20, 50 ...) list carries + // those parameters, using them as hidden elements is not sufficient + foreach ( $parameters as $key => $value ) { + $this->specialSearch->setExtraParam( $key, $value ); + } + + $formList = $formsBuilder->buildFormList(); + + return [ + $form, + $formList, + $formsBuilder->getTermPrefixes(), + $formsBuilder->getPreselectNsList(), + $formsBuilder->getHiddenNsList() + ]; + } + + private function findErrors( $searchEngine ) { + + if ( ( $errors = $searchEngine->getErrors() ) === [] ) { + return ''; + } + + $divider = "<div class='divider'></div>"; + + $list = ProcessingErrorMsgHandler::normalizeAndDecodeMessages( + $errors + ); + + return Html::rawElement( + 'ul', + [ + 'class' => 'smw-errors', + 'style' => 'color:#b32424;' + ], + '<li>' . implode( '</li><li>', $list ) . '</li>' + ) . $divider; + } + + private function buildSortForm( $request ) { + + $sortForm = $this->formsFactory->newSortForm( $request ); + + // TODO this information should come from the store and not being + // derived from a class! How should such characteristic be represented? + $features = [ + 'best' => is_a( $this->store, "SMWElasticStore" ) + ]; + + $form = $sortForm->makeFields( $features ); + $parameters = $sortForm->getParameters(); + + foreach ( $parameters as $key => $value ) { + $this->specialSearch->setExtraParam( $key, $value ); + } + + return $form; + } + + private function profile_sheet( $query, $queryLink, $termPrefixes ) { + + $text = Message::get( 'smw-search-profile-extended-help-intro', Message::PARSE, Message::USER_LANGUAGE ); + + $link = $queryLink !== null ? $queryLink->getHtml() : ''; + + if ( $link !== '' ) { + $text .= $this->section( 'smw-search-profile-extended-section-query' ); + $text .= $this->msg( [ 'smw-search-profile-extended-help-query', trim( $query ) ] ) . ' '; + $text .= $this->msg( [ 'smw-search-profile-extended-help-query-link', $link ], Message::TEXT ); + } + + $text .= $this->section( 'smw-search-profile-extended-section-search-syntax' ); + $text .= $this->msg( 'smw-search-profile-extended-help-search-syntax', Message::TEXT ); + + $syntax = $this->msg( 'smw-search-profile-extended-help-search-syntax-simplified-in' ); + $syntax .= $this->msg( 'smw-search-profile-extended-help-search-syntax-simplified-phrase' ); + $syntax .= $this->msg( 'smw-search-profile-extended-help-search-syntax-simplified-has' ); + $syntax .= $this->msg( 'smw-search-profile-extended-help-search-syntax-simplified-not' ); + + if ( $termPrefixes !== [] ) { + $prefixes = ''; + + foreach ( array_keys( $termPrefixes ) as $pref ) { + $prefixes .= ( $prefixes === '' ? '' : ', ' ) . "<code>$pref:</code>"; + } + + $syntax .= $this->msg( [ 'smw-search-profile-extended-help-search-syntax-prefix', $prefixes ] ); + } + + $syntax .= $this->msg( [ 'smw-search-profile-extended-help-search-syntax-reserved', "'&&', 'AND', '||', 'OR', '(', ')', '[[', ']]'" ] ); + + $text .= Html::rawElement( 'div', [ 'id' => 'smw-search-synatx-list' ], + $syntax + ); + + $text .= Html::rawElement( 'p', [] , + $this->msg( 'smw-search-profile-extended-help-search-syntax-note' ) + ); + + $text .= $this->section( 'smw-search-profile-extended-section-sort' ); + $text .= $this->msg( 'smw-search-profile-extended-help-sort' ); + $sort = $this->msg( 'smw-search-profile-extended-help-sort-title' ); + $sort .= $this->msg( 'smw-search-profile-extended-help-sort-recent' ); + + if ( is_a( $this->store, "SMWElasticStore" ) ) { + $sort .= $this->msg( 'smw-search-profile-extended-help-sort-best' ); + } + + $text .= Html::rawElement( 'div', [ 'id' => 'smw-search-sort-list' ], + $sort + ); + + $formLink = Html::element( + 'a', + [ + 'href' => Title::newFromText( 'Special:SearchByProperty/Schema type/' . self::SCHEMA_TYPE )->getFullUrl() + ], + $this->msg( 'smw-search-profile-extended-help-find-forms' ) + ); + + $text .= $this->section( 'smw-search-profile-extended-section-form' ); + $text .= $this->msg( [ 'smw-search-profile-extended-help-form', $formLink ], Message::TEXT ); + $text .= $this->section( 'smw-search-profile-extended-section-namespace' ); + $text .= $this->msg( 'smw-search-profile-extended-help-namespace' ); + + return $text; + } + + private function section( $msg, $attributes = [] ) { + return Html::rawElement( + 'div', + [ + 'class' => 'smw-text-strike', + 'style' => 'padding: 5px 0 5px 0;' + ], + Html::rawElement( + 'span', + [ + 'style' => 'font-size: 1.2em; margin-left:0px' + ], + Message::get( $msg, Message::TEXT, Message::USER_LANGUAGE ) + ) + ); + } + + private function msg( $msg, $type = Message::PARSE, $lang = Message::USER_LANGUAGE ) { + return Message::get( $msg, $type, $lang ); + } + +} |