From 2acde68bb31f7865998fc3f7d3f241cf6d217076 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Wed, 21 Jun 2023 13:14:32 +0400 Subject: [PATCH 01/24] add missing datatypes --- includes/Filter.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/includes/Filter.php b/includes/Filter.php index ed8764ff..947d738f 100644 --- a/includes/Filter.php +++ b/includes/Filter.php @@ -356,6 +356,30 @@ private function getPropertyType() { $propertyType = 'boolean'; } elseif ( $typeValue == $datatypeLabels['_dat'] ) { $propertyType = 'date'; + } elseif ( $typeValue == $datatypeLabels['_qty'] ) { + $propertyType = 'quantity'; + } elseif ( $typeValue == $datatypeLabels['_keyw'] ) { + $propertyType = 'keyword'; + } elseif ( $typeValue == $datatypeLabels['_geo'] ) { + $propertyType = 'geographic coordinates'; + } elseif ( $typeValue == $datatypeLabels['_tel'] ) { + $propertyType = 'telephone'; + } elseif ( $typeValue == $datatypeLabels['_tem'] ) { + $propertyType = 'temperature'; + } elseif ( $typeValue == $datatypeLabels['_mlt_rec'] ) { + $propertyType = 'monolingual text'; + } elseif ( $typeValue == $datatypeLabels['_rec'] ) { + $propertyType = 'record'; + } elseif ( $typeValue == $datatypeLabels['_ref_rec'] ) { + $propertyType = 'reference'; + } elseif ( $typeValue == $datatypeLabels['_ema'] ) { + $propertyType = 'email'; + } elseif ( $typeValue == $datatypeLabels['_anu'] ) { + $propertyType = 'annotation URI'; + } elseif ( $typeValue == $datatypeLabels['_eid'] ) { + $propertyType = 'external identifier'; + } elseif ( $typeValue == $datatypeLabels['_cod'] ) { + $propertyType = 'code'; } elseif ( $typeValue == $datatypeLabels['_eid'] ) { $propertyType = 'external_id'; } else { From 6531b667b8e3d83a4fb022dd90f40e41cbd1e4cd Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Wed, 21 Jun 2023 13:18:16 +0400 Subject: [PATCH 02/24] add datatypes --- includes/Sql/PropertyTypeDbInfo.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/includes/Sql/PropertyTypeDbInfo.php b/includes/Sql/PropertyTypeDbInfo.php index f34e6523..6f4d600a 100644 --- a/includes/Sql/PropertyTypeDbInfo.php +++ b/includes/Sql/PropertyTypeDbInfo.php @@ -12,6 +12,8 @@ public static function tableName( string $propertyType ): ?string { return 'smw_di_bool'; case 'date': return 'smw_di_time'; + case 'quantity': + case 'temperature': case 'number': return 'smw_di_number'; default: @@ -27,6 +29,8 @@ public static function valueField( string $propertyType ): ?string { case 'boolean': return 'o_value'; case 'date': + case 'quantity': + case 'temperature': case 'number': return 'o_serialized'; default: From 7648b4f6d3d2c51cbc9bc5ab1a7d5f7da1bb8535 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Thu, 29 Jun 2023 02:54:59 +0400 Subject: [PATCH 03/24] support monolingual_text --- includes/Sql/SqlProvider.php | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/includes/Sql/SqlProvider.php b/includes/Sql/SqlProvider.php index 0d13c409..1fb109d0 100644 --- a/includes/Sql/SqlProvider.php +++ b/includes/Sql/SqlProvider.php @@ -97,7 +97,9 @@ public static function getSQLFromClause( string $category, string $subcategory, if ( $includes_none ) { $property_table_name = $dbr->tableName( PropertyTypeDbInfo::tableName( $af->filter->propertyType() ) ); - if ( $af->filter->propertyType() === 'page' ) { + + // @TODO fix me for 'monolingual_text' + if ( $af->filter->propertyType() === 'page' || $af->filter->propertyType() === 'monolingual_text' ) { $property_table_nickname = "nr$i"; $property_field = 'p_id'; } else { @@ -111,11 +113,13 @@ public static function getSQLFromClause( string $category, string $subcategory, // doesn't need to, because of occasional bugs // in SMW where the same page gets two // different SMW IDs. + + $propKey = $af->filter->propKey(); $sql .= "LEFT OUTER JOIN (SELECT s_id FROM $property_table_name - WHERE $property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE smw_title = '$property_value' AND smw_namespace = $prop_ns)) $property_table_nickname + WHERE $property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE ( smw_title = '$property_value' OR smw_title = '$propKey' ) AND smw_namespace = $prop_ns)) $property_table_nickname ON ids.smw_id = $property_table_nickname.s_id "; } } @@ -123,7 +127,8 @@ public static function getSQLFromClause( string $category, string $subcategory, $sql .= "\n "; $property_table_name = $dbr->tableName( PropertyTypeDbInfo::tableName( $af->filter->propertyType() ) ); - if ( $af->filter->propertyType() === 'page' ) { + // @TODO fix me for 'monolingual_text' + if ( $af->filter->propertyType() === 'page' || $af->filter->propertyType() === 'monolingual_text' ) { if ( $includes_none ) { $sql .= "LEFT OUTER "; } @@ -132,7 +137,9 @@ public static function getSQLFromClause( string $category, string $subcategory, $sql .= "LEFT OUTER "; } $sql .= "JOIN $smwIDs o_ids$i ON r$i.o_id = o_ids$i.smw_id "; - } else { + } else if ( $propertyType === 'monolingual_text' ) { + $sql .= "JOIN smw_fpt_text o_ids$i r$i.o_id = o_ids$i.smw_id "; + } else { $sql .= "JOIN $property_table_name a$i ON ids.smw_id = a$i.s_id "; } } @@ -151,11 +158,14 @@ public static function getSQLFromClause( string $category, string $subcategory, } $sql .= ")) "; foreach ( $applied_filters as $i => $af ) { + $propKey = $af->filter->propKey(); $property_value = $af->filter->escapedProperty(); $value_field = PropertyTypeDbInfo::valueField( $af->filter->propertyType() ); - if ( $af->filter->propertyType() === 'page' ) { + + // @TODO fix me for 'monolingual_text' + if ( $af->filter->propertyType() === 'page' || $af->filter->propertyType() === 'monolingual_text' ) { $property_field = "r$i.p_id"; - $sql .= "\n AND ($property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE smw_title = '$property_value' AND smw_namespace = $prop_ns)"; + $sql .= "\n AND ($property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE ( smw_title = '$property_value' OR smw_title = '$propKey' ) AND smw_namespace = $prop_ns)"; if ( $includes_none ) { $sql .= " OR $property_field IS NULL"; } @@ -163,7 +173,7 @@ public static function getSQLFromClause( string $category, string $subcategory, $value_field = "o_ids$i.smw_title"; } else { $property_field = "a$i.p_id"; - $sql .= "\n AND $property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE smw_title = '$property_value' AND smw_namespace = $prop_ns) AND "; + $sql .= "\n AND $property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE ( smw_title = '$property_value' OR smw_title = '$propKey' ) AND smw_namespace = $prop_ns) AND "; if ( strncmp( $value_field, '(IF(o_blob IS NULL', 18 ) === 0 ) { $value_field = str_replace( 'o_', "a$i.o_", $value_field ); } else { From ddaa2b1c7b3294942e81168adaf7fa8e1992dd83 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Thu, 29 Jun 2023 02:56:39 +0400 Subject: [PATCH 04/24] support monolingual_text --- includes/DbService.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/includes/DbService.php b/includes/DbService.php index 22fe4bb7..98dbacea 100644 --- a/includes/DbService.php +++ b/includes/DbService.php @@ -56,7 +56,7 @@ public function createTempTable( $category, $subcategory, $subcategories, $appli * both for speeding up later queries (at least, that's the hope) * and for getting the set of 'None' values. */ - public function createFilterValuesTempTable( $propertyType, $escaped_property ) { + public function createFilterValuesTempTable( $propertyType, $escaped_property, $propKey ) { $smw_ids = $this->dbr->tableName( Utils::getIDsTableName() ); $valuesTable = $this->dbr->tableName( PropertyTypeDbInfo::tableName( $propertyType ) ); @@ -66,7 +66,7 @@ public function createFilterValuesTempTable( $propertyType, $escaped_property ) $sql = <<dbw ); $temporaryTableManager->queryWithAutoCommit( $sql, __METHOD__ ); @@ -97,8 +101,6 @@ public function dropFilterValuesTempTable() { * set of filters and either a new subcategory or a new filter. */ public function getNumResults( $subcategory, $subcategories, $new_filter = null ) { - // Escape the given values to prevent SQL injection - $subcategory = $this->dbr->addQuotes( $subcategory ); foreach ( $subcategories as $key => $value ) { $subcategories[$key] = $this->dbr->addQuotes( $value ); } @@ -146,9 +148,9 @@ public function getCategoryChildren( $category_name, $get_categories, $levels ) foreach ( $res as $row ) { if ( $get_categories ) { $subcategories[] = $row->page_title; - $pages[] = $row->page_namespace; + $pages[] = $row->page_title; } else { - if ( $row->page_title == NS_CATEGORY ) { + if ( $row->page_namespace == NS_CATEGORY ) { $subcategories[] = $row->page_title; } else { $pages[] = $row->page_title; @@ -158,6 +160,7 @@ public function getCategoryChildren( $category_name, $get_categories, $levels ) foreach ( $subcategories as $subcategory ) { $pages = array_merge( $pages, $this->getCategoryChildren( $subcategory, $get_categories, $levels - 1 ) ); } + return $pages; } From 7b475d435d0d48d77a2190122c6e7d23e21064a6 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Thu, 29 Jun 2023 02:58:53 +0400 Subject: [PATCH 05/24] add propKey --- includes/Specials/BrowseData/GetApplicableFilters.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Specials/BrowseData/GetApplicableFilters.php b/includes/Specials/BrowseData/GetApplicableFilters.php index 57168f2b..31181f39 100644 --- a/includes/Specials/BrowseData/GetApplicableFilters.php +++ b/includes/Specials/BrowseData/GetApplicableFilters.php @@ -468,7 +468,7 @@ private function getUnappliedFilterLine( Filter $f ): string { } private function getPossibleValues( Filter $f ): PossibleFilterValues { - $this->db->createFilterValuesTempTable( $f->propertyType(), $f->escapedProperty() ); + $this->db->createFilterValuesTempTable( $f->propertyType(), $f->escapedProperty(), $f->propKey() ); if ( empty( $f->allowedValues() ) ) { $possibleFilterValues = $f->propertyType() == 'date' ? $f->getTimePeriodValues() From 35c34c6c514825f74bdd21c22c0193a35897a1a7 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Thu, 29 Jun 2023 02:59:57 +0400 Subject: [PATCH 06/24] add datavalues --- includes/Sql/PropertyTypeDbInfo.php | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/includes/Sql/PropertyTypeDbInfo.php b/includes/Sql/PropertyTypeDbInfo.php index 6f4d600a..9a75c11d 100644 --- a/includes/Sql/PropertyTypeDbInfo.php +++ b/includes/Sql/PropertyTypeDbInfo.php @@ -7,15 +7,25 @@ class PropertyTypeDbInfo { public static function tableName( string $propertyType ): ?string { switch ( $propertyType ) { case 'page': + case 'monolingual_text': return 'smw_di_wikipage'; case 'boolean': return 'smw_di_bool'; case 'date': return 'smw_di_time'; + case 'telephone_number': + case 'email': + case 'annotation_uri': + case 'URL': + return 'smw_di_uri'; + case 'geographic_coord': + return 'smw_di_coords'; + case 'number': case 'quantity': case 'temperature': - case 'number': return 'smw_di_number'; + // case 'monolingual_text': + // return 'smw_fpt_text'; default: return 'smw_di_blob'; } @@ -32,7 +42,16 @@ public static function valueField( string $propertyType ): ?string { case 'quantity': case 'temperature': case 'number': + case 'telephone_number': + case 'URL': + case 'annotation_uri': + case 'email': + case 'geographic_coord': return 'o_serialized'; + case 'keyword': + return 'o_blob'; + + // case 'monolingual_text': default: // CONVERT() is also supported in PostgreSQL, // but it doesn't seem to work the same way. From deb12ae53f866d8d7af0865aadc9bc7b8caf2129 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Thu, 29 Jun 2023 03:01:02 +0400 Subject: [PATCH 07/24] refactor getPropertyType --- includes/Filter.php | 131 ++++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 59 deletions(-) diff --git a/includes/Filter.php b/includes/Filter.php index 947d738f..c332da3c 100644 --- a/includes/Filter.php +++ b/includes/Filter.php @@ -25,6 +25,7 @@ class Filter { private $allowedValues; public $possible_applied_filters = []; + private $propKey; public function __construct( DbService $db, @@ -89,6 +90,10 @@ public function allowedValues() { public function escapedProperty() { return SqlProvider::escapedProperty( $this->property() ); } + + public function propKey() { + return $this->propKey; + } /** * Gets an array of the possible time period values (e.g., years, @@ -245,11 +250,16 @@ public function getAllValues(): PossibleFilterValues { JOIN $smw_ids o_ids ON p.o_id = o_ids.smw_id LEFT JOIN $revision_table_name ON $revision_table_name.rev_id = o_ids.smw_rev LEFT JOIN $page_props_table_name displaytitle ON $revision_table_name.rev_page = displaytitle.pp_page AND displaytitle.pp_propname = 'displaytitle' +END; + } + if ( $this->propertyType === 'monolingual_text' ) { + $sql .= <<escapedProperty(); $propPage = new SMWDIWikiPage( $escapedProperty, SMW_NS_PROPERTY, '' ); - $types = $store->getPropertyValues( $propPage, new SMWDIProperty( '_TYPE' ) ); $datatypeLabels = Utils::getSMWContLang()->getDatatypeLabels(); - if ( count( $types ) > 0 ) { - if ( $types[0] instanceof SMWDIWikiPage ) { - $typeValue = $types[0]->getDBkey(); - } elseif ( $types[0] instanceof SMWDIURI ) { - // A bit inefficient, but it's the - // simplest approach. - $typeID = $types[0]->getFragment(); - if ( $typeID == '_str' && !array_key_exists( '_str', $datatypeLabels ) ) { - $typeID = '_txt'; + $property = $this->property(); + + // KnownTypeLabels + if ( in_array( $property, $datatypeLabels ) ) { + $typeValue = $property; + } else { + $types = $store->getPropertyValues( $propPage, new SMWDIProperty( '_TYPE' ) ); + + if ( count( $types ) > 0 ) { + if ( $types[0] instanceof SMWDIWikiPage ) { + $typeValue = $types[0]->getDBkey(); + } elseif ( $types[0] instanceof SMWDIURI ) { + // A bit inefficient, but it's the + // simplest approach. + $typeID = $types[0]->getFragment(); + if ( $typeID == '_str' && !array_key_exists( '_str', $datatypeLabels ) ) { + $typeID = '_txt'; + } + $typeValue = $datatypeLabels[$typeID]; + } else { + $typeValue = $types[0]->getWikiValue(); } - $typeValue = $datatypeLabels[$typeID]; - } else { - $typeValue = $types[0]->getWikiValue(); - } - if ( $typeValue == $datatypeLabels['_wpg'] ) { - $propertyType = 'page'; - // _str stopped existing in SMW 1.9 - } elseif ( array_key_exists( '_str', $datatypeLabels ) && $typeValue == $datatypeLabels['_str'] ) { - $propertyType = 'string'; - } elseif ( !array_key_exists( '_str', $datatypeLabels ) && $typeValue == $datatypeLabels['_txt'] ) { - $propertyType = 'string'; - } elseif ( $typeValue == $datatypeLabels['_num'] ) { - $propertyType = 'number'; - } elseif ( $typeValue == $datatypeLabels['_boo'] ) { - $propertyType = 'boolean'; - } elseif ( $typeValue == $datatypeLabels['_dat'] ) { - $propertyType = 'date'; - } elseif ( $typeValue == $datatypeLabels['_qty'] ) { - $propertyType = 'quantity'; - } elseif ( $typeValue == $datatypeLabels['_keyw'] ) { - $propertyType = 'keyword'; - } elseif ( $typeValue == $datatypeLabels['_geo'] ) { - $propertyType = 'geographic coordinates'; - } elseif ( $typeValue == $datatypeLabels['_tel'] ) { - $propertyType = 'telephone'; - } elseif ( $typeValue == $datatypeLabels['_tem'] ) { - $propertyType = 'temperature'; - } elseif ( $typeValue == $datatypeLabels['_mlt_rec'] ) { - $propertyType = 'monolingual text'; - } elseif ( $typeValue == $datatypeLabels['_rec'] ) { - $propertyType = 'record'; - } elseif ( $typeValue == $datatypeLabels['_ref_rec'] ) { - $propertyType = 'reference'; - } elseif ( $typeValue == $datatypeLabels['_ema'] ) { - $propertyType = 'email'; - } elseif ( $typeValue == $datatypeLabels['_anu'] ) { - $propertyType = 'annotation URI'; - } elseif ( $typeValue == $datatypeLabels['_eid'] ) { - $propertyType = 'external identifier'; - } elseif ( $typeValue == $datatypeLabels['_cod'] ) { - $propertyType = 'code'; - } elseif ( $typeValue == $datatypeLabels['_eid'] ) { - $propertyType = 'external_id'; - } else { - // This should hopefully never get called. - print "Error! Unsupported property type ($typeValue) for filter {$this->name}."; - } + } + } + + $propKey = array_search( $typeValue, $datatypeLabels ); + + if ( $propKey === false ) { + // This should hopefully never get called. + print "Error! Unsupported property type ($typeValue) for filter {$this->name}."; + return null; } - return $propertyType; + // normalize as below + $map = [ + '_wpg' => 'page', + '_txt' => 'string', + // _str stopped existing in SMW 1.9 + '_str' => 'string', + '_cod' => 'code', + '_boo' => 'boolean', + '_num' => 'number', + '_geo' => 'geographic_coord', + '_tem' => 'temperature', + '_dat' => 'date', + '_ema' => 'email', + '_uri' => 'URL', + '_anu' => 'annotation_uri', + '_tel' => 'telephone_number', + '_rec' => 'record', + '_qty' => 'quantity', + '_mlt_rec' => 'monolingual_text', + '_eid' => 'external_id', + '_keyw' => 'keyword', + '_ref_rec' => 'reference' + ]; + + // used to retrieve the value of + // properties set with the label of a + // predefined property, e.g. Email::email@test.com + $this->propKey = $propKey; + + // propertyType + return $map[$propKey]; } } From 21cd41f12ecd2c4214db07500a7a4c387a095d25 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Thu, 29 Jun 2023 03:12:52 +0400 Subject: [PATCH 08/24] fix committed tree --- includes/DbService.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/includes/DbService.php b/includes/DbService.php index 98dbacea..281f1077 100644 --- a/includes/DbService.php +++ b/includes/DbService.php @@ -101,10 +101,6 @@ public function dropFilterValuesTempTable() { * set of filters and either a new subcategory or a new filter. */ public function getNumResults( $subcategory, $subcategories, $new_filter = null ) { - foreach ( $subcategories as $key => $value ) { - $subcategories[$key] = $this->dbr->addQuotes( $value ); - } - $sql = "SELECT COUNT(DISTINCT sdv.id) "; if ( $new_filter ) { $sql .= SqlProvider::getSQLFromClauseForField( $new_filter ); From 34e2d906e2817563dda164f6940a1334fd8d793b Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Fri, 30 Jun 2023 11:59:27 +0400 Subject: [PATCH 09/24] fix monolingual_text --- includes/AppliedFilter.php | 6 ++++++ includes/Filter.php | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/includes/AppliedFilter.php b/includes/AppliedFilter.php index 9cacb7a8..4971c713 100644 --- a/includes/AppliedFilter.php +++ b/includes/AppliedFilter.php @@ -234,6 +234,12 @@ public function getAllOrValues( $category ): PossibleFilterValues { JOIN $smw_ids o_ids ON p.o_id = o_ids.smw_id LEFT JOIN $revision_table_name ON $revision_table_name.rev_id = o_ids.smw_rev LEFT JOIN $page_props_table_name displaytitle ON $revision_table_name.rev_page = displaytitle.pp_page AND displaytitle.pp_propname = 'displaytitle' +END; + } + if ( $this->filter->propertyType() === 'monolingual_text' ) { + $sql .= <<tableName( PropertyTypeDbInfo::tableName( $af->filter->propertyType() ) ); - // @TODO fix me for 'monolingual_text' + if ( $af->filter->propertyType() === 'page' || $af->filter->propertyType() === 'monolingual_text' ) { if ( $includes_none ) { $sql .= "LEFT OUTER "; @@ -137,9 +136,12 @@ public static function getSQLFromClause( string $category, string $subcategory, $sql .= "LEFT OUTER "; } $sql .= "JOIN $smwIDs o_ids$i ON r$i.o_id = o_ids$i.smw_id "; - } else if ( $propertyType === 'monolingual_text' ) { - $sql .= "JOIN smw_fpt_text o_ids$i r$i.o_id = o_ids$i.smw_id "; - } else { + + if ( $af->filter->propertyType() === 'monolingual_text' ) { + $sql .= "JOIN smw_fpt_text fpt_text$i ON r$i.o_id = fpt_text$i.s_id "; + } + + } else { $sql .= "JOIN $property_table_name a$i ON ids.smw_id = a$i.s_id "; } } @@ -161,9 +163,8 @@ public static function getSQLFromClause( string $category, string $subcategory, $propKey = $af->filter->propKey(); $property_value = $af->filter->escapedProperty(); $value_field = PropertyTypeDbInfo::valueField( $af->filter->propertyType() ); - - // @TODO fix me for 'monolingual_text' - if ( $af->filter->propertyType() === 'page' || $af->filter->propertyType() === 'monolingual_text' ) { + + if ( $af->filter->propertyType() === 'page' ) { $property_field = "r$i.p_id"; $sql .= "\n AND ($property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE ( smw_title = '$property_value' OR smw_title = '$propKey' ) AND smw_namespace = $prop_ns)"; if ( $includes_none ) { @@ -171,6 +172,10 @@ public static function getSQLFromClause( string $category, string $subcategory, } $sql .= ")\n AND "; $value_field = "o_ids$i.smw_title"; + } else if ( $af->filter->propertyType() === 'monolingual_text' ) { + $property_field = "r$i.p_id"; + $sql .= "\n AND $property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE ( smw_title = '$property_value' OR smw_title = '$propKey' ) AND smw_namespace = $prop_ns) AND "; + } else { $property_field = "a$i.p_id"; $sql .= "\n AND $property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE ( smw_title = '$property_value' OR smw_title = '$propKey' ) AND smw_namespace = $prop_ns) AND "; @@ -182,6 +187,7 @@ public static function getSQLFromClause( string $category, string $subcategory, } $sql .= $af->checkSQL( $value_field ); } + return $sql; } From ae9fcf1ba12add57a5ef5566fd9abe75af30caee Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Fri, 30 Jun 2023 12:19:22 +0400 Subject: [PATCH 11/24] fix monolingual_text --- includes/Sql/SqlProvider.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/includes/Sql/SqlProvider.php b/includes/Sql/SqlProvider.php index c4d1d53c..614cc649 100644 --- a/includes/Sql/SqlProvider.php +++ b/includes/Sql/SqlProvider.php @@ -175,6 +175,11 @@ public static function getSQLFromClause( string $category, string $subcategory, } else if ( $af->filter->propertyType() === 'monolingual_text' ) { $property_field = "r$i.p_id"; $sql .= "\n AND $property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE ( smw_title = '$property_value' OR smw_title = '$propKey' ) AND smw_namespace = $prop_ns) AND "; + if ( strncmp( $value_field, '(IF(o_blob IS NULL', 18 ) === 0 ) { + $value_field = str_replace( 'o_', "fpt_text$i.o_", $value_field ); + } else { + $value_field = "fpt_text$i.$value_field"; + } } else { $property_field = "a$i.p_id"; From 0b32b53e076808672d6c1026c3a0a806f572c8ef Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Fri, 30 Jun 2023 12:49:11 +0400 Subject: [PATCH 12/24] SemanticDrilldown/issues/10 --- includes/Specials/BrowseData/GetCategories.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Specials/BrowseData/GetCategories.php b/includes/Specials/BrowseData/GetCategories.php index 43e25a49..99f7bca2 100644 --- a/includes/Specials/BrowseData/GetCategories.php +++ b/includes/Specials/BrowseData/GetCategories.php @@ -18,7 +18,7 @@ public function __construct( public function __invoke( $selectedCategory ): ?array { if ( $this->urlService->showSingleCat() ) { - return null; + return []; } $toCategoryViewModel = function ( $category ) use ( $selectedCategory ) { From 6fc4f714e6bead6a5f41d98a394423d92b9add82 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Fri, 30 Jun 2023 12:52:13 +0400 Subject: [PATCH 13/24] fix single option error --- includes/Specials/BrowseData/ProcessTemplate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Specials/BrowseData/ProcessTemplate.php b/includes/Specials/BrowseData/ProcessTemplate.php index 4162316a..d3e28239 100644 --- a/includes/Specials/BrowseData/ProcessTemplate.php +++ b/includes/Specials/BrowseData/ProcessTemplate.php @@ -35,7 +35,7 @@ public function __invoke( $template, $vm ) { $msg[ "msg_$message" ] = wfMessage( $message )->text(); } - $html = $templateParser->processTemplate( $template, $vm + $msg ); + $html = $templateParser->processTemplate( $template, (array)$vm + $msg ); // Remove leading whitespace from all lines as the parser will interpret lines containing // text starting with whitespace as preformatted text later; From 5e8ab72d3fbc532abf9dc9c1f438761ab377bd1e Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Fri, 30 Jun 2023 21:38:44 +0400 Subject: [PATCH 14/24] fixes "record", "keyword" and "reference" datatypes --- includes/Filter.php | 107 +++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 72 deletions(-) diff --git a/includes/Filter.php b/includes/Filter.php index ccc5e2ab..ed8764ff 100644 --- a/includes/Filter.php +++ b/includes/Filter.php @@ -25,7 +25,6 @@ class Filter { private $allowedValues; public $possible_applied_filters = []; - private $propKey; public function __construct( DbService $db, @@ -90,10 +89,6 @@ public function allowedValues() { public function escapedProperty() { return SqlProvider::escapedProperty( $this->property() ); } - - public function propKey() { - return $this->propKey; - } /** * Gets an array of the possible time period values (e.g., years, @@ -250,16 +245,11 @@ public function getAllValues(): PossibleFilterValues { JOIN $smw_ids o_ids ON p.o_id = o_ids.smw_id LEFT JOIN $revision_table_name ON $revision_table_name.rev_id = o_ids.smw_rev LEFT JOIN $page_props_table_name displaytitle ON $revision_table_name.rev_page = displaytitle.pp_page AND displaytitle.pp_propname = 'displaytitle' -END; - } - if ( $this->propertyType === 'monolingual_text' ) { - $sql .= <<escapedProperty(); $propPage = new SMWDIWikiPage( $escapedProperty, SMW_NS_PROPERTY, '' ); + $types = $store->getPropertyValues( $propPage, new SMWDIProperty( '_TYPE' ) ); $datatypeLabels = Utils::getSMWContLang()->getDatatypeLabels(); - $property = $this->property(); - - // KnownTypeLabels - if ( in_array( $property, $datatypeLabels ) ) { - $typeValue = $property; - } else { - $types = $store->getPropertyValues( $propPage, new SMWDIProperty( '_TYPE' ) ); - - if ( count( $types ) > 0 ) { - if ( $types[0] instanceof SMWDIWikiPage ) { - $typeValue = $types[0]->getDBkey(); - } elseif ( $types[0] instanceof SMWDIURI ) { - // A bit inefficient, but it's the - // simplest approach. - $typeID = $types[0]->getFragment(); - if ( $typeID == '_str' && !array_key_exists( '_str', $datatypeLabels ) ) { - $typeID = '_txt'; - } - $typeValue = $datatypeLabels[$typeID]; - } else { - $typeValue = $types[0]->getWikiValue(); + if ( count( $types ) > 0 ) { + if ( $types[0] instanceof SMWDIWikiPage ) { + $typeValue = $types[0]->getDBkey(); + } elseif ( $types[0] instanceof SMWDIURI ) { + // A bit inefficient, but it's the + // simplest approach. + $typeID = $types[0]->getFragment(); + if ( $typeID == '_str' && !array_key_exists( '_str', $datatypeLabels ) ) { + $typeID = '_txt'; } - } - } - - $propKey = array_search( $typeValue, $datatypeLabels ); - - if ( $propKey === false ) { - // This should hopefully never get called. - print "Error! Unsupported property type ($typeValue) for filter {$this->name}."; - return null; + $typeValue = $datatypeLabels[$typeID]; + } else { + $typeValue = $types[0]->getWikiValue(); + } + if ( $typeValue == $datatypeLabels['_wpg'] ) { + $propertyType = 'page'; + // _str stopped existing in SMW 1.9 + } elseif ( array_key_exists( '_str', $datatypeLabels ) && $typeValue == $datatypeLabels['_str'] ) { + $propertyType = 'string'; + } elseif ( !array_key_exists( '_str', $datatypeLabels ) && $typeValue == $datatypeLabels['_txt'] ) { + $propertyType = 'string'; + } elseif ( $typeValue == $datatypeLabels['_num'] ) { + $propertyType = 'number'; + } elseif ( $typeValue == $datatypeLabels['_boo'] ) { + $propertyType = 'boolean'; + } elseif ( $typeValue == $datatypeLabels['_dat'] ) { + $propertyType = 'date'; + } elseif ( $typeValue == $datatypeLabels['_eid'] ) { + $propertyType = 'external_id'; + } else { + // This should hopefully never get called. + print "Error! Unsupported property type ($typeValue) for filter {$this->name}."; + } } - // normalize as before - $map = [ - '_wpg' => 'page', - '_txt' => 'string', - // _str stopped existing in SMW 1.9 - '_str' => 'string', - '_cod' => 'code', - '_boo' => 'boolean', - '_num' => 'number', - '_geo' => 'geographic_coord', - '_tem' => 'temperature', - '_dat' => 'date', - '_ema' => 'email', - '_uri' => 'URL', - '_anu' => 'annotation_uri', - '_tel' => 'telephone_number', - '_rec' => 'record', - '_qty' => 'quantity', - '_mlt_rec' => 'monolingual_text', - '_eid' => 'external_id', - '_keyw' => 'keyword', - '_ref_rec' => 'reference' - ]; - - // used to retrieve the value of - // properties set with the label of a - // predefined property, e.g. Email::email@test.com - $this->propKey = $propKey; - - // propertyType - return $map[$propKey]; + return $propertyType; } } From 1a189397fa269baf5c435edc247c2e2d7bb54031 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Fri, 30 Jun 2023 21:41:34 +0400 Subject: [PATCH 15/24] fixes "record", "keyword" and "reference" datatype --- includes/Filter.php | 114 ++++++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 35 deletions(-) diff --git a/includes/Filter.php b/includes/Filter.php index ed8764ff..8a885b62 100644 --- a/includes/Filter.php +++ b/includes/Filter.php @@ -25,6 +25,7 @@ class Filter { private $allowedValues; public $possible_applied_filters = []; + private $propKey; public function __construct( DbService $db, @@ -89,6 +90,10 @@ public function allowedValues() { public function escapedProperty() { return SqlProvider::escapedProperty( $this->property() ); } + + public function propKey() { + return $this->propKey; + } /** * Gets an array of the possible time period values (e.g., years, @@ -245,11 +250,16 @@ public function getAllValues(): PossibleFilterValues { JOIN $smw_ids o_ids ON p.o_id = o_ids.smw_id LEFT JOIN $revision_table_name ON $revision_table_name.rev_id = o_ids.smw_rev LEFT JOIN $page_props_table_name displaytitle ON $revision_table_name.rev_page = displaytitle.pp_page AND displaytitle.pp_propname = 'displaytitle' +END; + } + if ( $this->propertyType === 'monolingual_text' ) { + $sql .= <<escapedProperty(); $propPage = new SMWDIWikiPage( $escapedProperty, SMW_NS_PROPERTY, '' ); - $types = $store->getPropertyValues( $propPage, new SMWDIProperty( '_TYPE' ) ); $datatypeLabels = Utils::getSMWContLang()->getDatatypeLabels(); - if ( count( $types ) > 0 ) { - if ( $types[0] instanceof SMWDIWikiPage ) { - $typeValue = $types[0]->getDBkey(); - } elseif ( $types[0] instanceof SMWDIURI ) { - // A bit inefficient, but it's the - // simplest approach. - $typeID = $types[0]->getFragment(); - if ( $typeID == '_str' && !array_key_exists( '_str', $datatypeLabels ) ) { - $typeID = '_txt'; + $property = $this->property(); + + // KnownTypeLabels + $isKnownLabel = false; + if ( in_array( $property, $datatypeLabels ) ) { + $typeValue = $property; + $isKnownLabel = true; + } else { + $types = $store->getPropertyValues( $propPage, new SMWDIProperty( '_TYPE' ) ); + + if ( count( $types ) > 0 ) { + if ( $types[0] instanceof SMWDIWikiPage ) { + $typeValue = $types[0]->getDBkey(); + } elseif ( $types[0] instanceof SMWDIURI ) { + // A bit inefficient, but it's the + // simplest approach. + $typeID = $types[0]->getFragment(); + if ( $typeID == '_str' && !array_key_exists( '_str', $datatypeLabels ) ) { + $typeID = '_txt'; + } + $typeValue = $datatypeLabels[$typeID]; + } else { + $typeValue = $types[0]->getWikiValue(); } - $typeValue = $datatypeLabels[$typeID]; - } else { - $typeValue = $types[0]->getWikiValue(); - } - if ( $typeValue == $datatypeLabels['_wpg'] ) { - $propertyType = 'page'; - // _str stopped existing in SMW 1.9 - } elseif ( array_key_exists( '_str', $datatypeLabels ) && $typeValue == $datatypeLabels['_str'] ) { - $propertyType = 'string'; - } elseif ( !array_key_exists( '_str', $datatypeLabels ) && $typeValue == $datatypeLabels['_txt'] ) { - $propertyType = 'string'; - } elseif ( $typeValue == $datatypeLabels['_num'] ) { - $propertyType = 'number'; - } elseif ( $typeValue == $datatypeLabels['_boo'] ) { - $propertyType = 'boolean'; - } elseif ( $typeValue == $datatypeLabels['_dat'] ) { - $propertyType = 'date'; - } elseif ( $typeValue == $datatypeLabels['_eid'] ) { - $propertyType = 'external_id'; - } else { - // This should hopefully never get called. - print "Error! Unsupported property type ($typeValue) for filter {$this->name}."; - } + } + } + + $propKey = array_search( $typeValue, $datatypeLabels ); + + if ( $propKey === false ) { + // This should hopefully never get called. + print "Error! Unsupported property type ($typeValue) for filter {$this->name}."; + return $propertyType; + } + + // used to retrieve the value of + // properties set with the label of a + // predefined property, e.g. Email::email@test.com + $this->propKey = $propKey; + + // @see https://github.com/SemanticMediaWiki/SemanticDrilldown/pull/62 + if ( $isKnownLabel && ( $propKey === '_rec' || $propKey === '_keyw' || $propKey === '_ref_rec' ) ) { + return $propertyType; } - return $propertyType; + // normalize as before + $map = [ + '_wpg' => 'page', + '_txt' => 'string', + // _str stopped existing in SMW 1.9 + '_str' => 'string', + '_cod' => 'code', + '_boo' => 'boolean', + '_num' => 'number', + '_geo' => 'geographic_coord', + '_tem' => 'temperature', + '_dat' => 'date', + '_ema' => 'email', + '_uri' => 'URL', + '_anu' => 'annotation_uri', + '_tel' => 'telephone_number', + '_rec' => 'record', + '_qty' => 'quantity', + '_mlt_rec' => 'monolingual_text', + '_eid' => 'external_id', + '_keyw' => 'keyword', + '_ref_rec' => 'reference' + ]; + + // propertyType + return $map[$propKey]; } } From c5564467885a2c6b19636ad5095e8465ba7e299d Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Mon, 3 Jul 2023 14:34:32 +0400 Subject: [PATCH 16/24] fix lint errors --- includes/DbService.php | 2 +- includes/Filter.php | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/includes/DbService.php b/includes/DbService.php index 281f1077..aef14de6 100644 --- a/includes/DbService.php +++ b/includes/DbService.php @@ -78,7 +78,7 @@ public function createFilterValuesTempTable( $propertyType, $escaped_property, $ if ( $propertyType === 'monolingual_text' ) { $sql .= " JOIN smw_fpt_text fpt_text ON $valuesTable.o_id = fpt_text.s_id\n"; } - $sql .= " WHERE ( p_ids.smw_title = '$query_property' OR p_ids.smw_title = '$propKey' )"; + $sql .= " WHERE ( p_ids.smw_title = '$query_property' OR p_ids.smw_title = '$propKey' )"; $temporaryTableManager = new TemporaryTableManager( $this->dbw ); $temporaryTableManager->queryWithAutoCommit( $sql, __METHOD__ ); diff --git a/includes/Filter.php b/includes/Filter.php index 8a885b62..f01fc23c 100644 --- a/includes/Filter.php +++ b/includes/Filter.php @@ -90,7 +90,7 @@ public function allowedValues() { public function escapedProperty() { return SqlProvider::escapedProperty( $this->property() ); } - + public function propKey() { return $this->propKey; } @@ -252,7 +252,7 @@ public function getAllValues(): PossibleFilterValues { LEFT JOIN $page_props_table_name displaytitle ON $revision_table_name.rev_page = displaytitle.pp_page AND displaytitle.pp_propname = 'displaytitle' END; } - if ( $this->propertyType === 'monolingual_text' ) { + if ( $this->propertyType === 'monolingual_text' ) { $sql .= <<getPropertyValues( $propPage, new SMWDIProperty( '_TYPE' ) ); - + if ( count( $types ) > 0 ) { if ( $types[0] instanceof SMWDIWikiPage ) { $typeValue = $types[0]->getDBkey(); @@ -362,14 +362,15 @@ private function getPropertyType() { } else { $typeValue = $types[0]->getWikiValue(); } - } + } } - + $propKey = array_search( $typeValue, $datatypeLabels ); - + if ( $propKey === false ) { // This should hopefully never get called. print "Error! Unsupported property type ($typeValue) for filter {$this->name}."; + $this->propKey = '_wpg'; return $propertyType; } @@ -384,7 +385,7 @@ private function getPropertyType() { } // normalize as before - $map = [ + $map = [ '_wpg' => 'page', '_txt' => 'string', // _str stopped existing in SMW 1.9 From 1fa7fdc884ae6469c4ce0ba984f6bed2d836577a Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Mon, 3 Jul 2023 14:36:21 +0400 Subject: [PATCH 17/24] fix lint --- includes/Sql/PropertyTypeDbInfo.php | 4 ++-- includes/Sql/SqlProvider.php | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/includes/Sql/PropertyTypeDbInfo.php b/includes/Sql/PropertyTypeDbInfo.php index 9a75c11d..b7f84b28 100644 --- a/includes/Sql/PropertyTypeDbInfo.php +++ b/includes/Sql/PropertyTypeDbInfo.php @@ -46,11 +46,11 @@ public static function valueField( string $propertyType ): ?string { case 'URL': case 'annotation_uri': case 'email': - case 'geographic_coord': + case 'geographic_coord': return 'o_serialized'; case 'keyword': return 'o_blob'; - + // case 'monolingual_text': default: // CONVERT() is also supported in PostgreSQL, diff --git a/includes/Sql/SqlProvider.php b/includes/Sql/SqlProvider.php index 614cc649..01715620 100644 --- a/includes/Sql/SqlProvider.php +++ b/includes/Sql/SqlProvider.php @@ -97,7 +97,7 @@ public static function getSQLFromClause( string $category, string $subcategory, if ( $includes_none ) { $property_table_name = $dbr->tableName( PropertyTypeDbInfo::tableName( $af->filter->propertyType() ) ); - + if ( $af->filter->propertyType() === 'page' || $af->filter->propertyType() === 'monolingual_text' ) { $property_table_nickname = "nr$i"; $property_field = 'p_id'; @@ -112,7 +112,7 @@ public static function getSQLFromClause( string $category, string $subcategory, // doesn't need to, because of occasional bugs // in SMW where the same page gets two // different SMW IDs. - + $propKey = $af->filter->propKey(); $sql .= "LEFT OUTER JOIN @@ -126,7 +126,7 @@ public static function getSQLFromClause( string $category, string $subcategory, $sql .= "\n "; $property_table_name = $dbr->tableName( PropertyTypeDbInfo::tableName( $af->filter->propertyType() ) ); - + if ( $af->filter->propertyType() === 'page' || $af->filter->propertyType() === 'monolingual_text' ) { if ( $includes_none ) { $sql .= "LEFT OUTER "; @@ -163,7 +163,7 @@ public static function getSQLFromClause( string $category, string $subcategory, $propKey = $af->filter->propKey(); $property_value = $af->filter->escapedProperty(); $value_field = PropertyTypeDbInfo::valueField( $af->filter->propertyType() ); - + if ( $af->filter->propertyType() === 'page' ) { $property_field = "r$i.p_id"; $sql .= "\n AND ($property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE ( smw_title = '$property_value' OR smw_title = '$propKey' ) AND smw_namespace = $prop_ns)"; @@ -172,7 +172,7 @@ public static function getSQLFromClause( string $category, string $subcategory, } $sql .= ")\n AND "; $value_field = "o_ids$i.smw_title"; - } else if ( $af->filter->propertyType() === 'monolingual_text' ) { + } elseif ( $af->filter->propertyType() === 'monolingual_text' ) { $property_field = "r$i.p_id"; $sql .= "\n AND $property_field = (SELECT MIN(smw_id) FROM $smwIDs WHERE ( smw_title = '$property_value' OR smw_title = '$propKey' ) AND smw_namespace = $prop_ns) AND "; if ( strncmp( $value_field, '(IF(o_blob IS NULL', 18 ) === 0 ) { @@ -192,7 +192,7 @@ public static function getSQLFromClause( string $category, string $subcategory, } $sql .= $af->checkSQL( $value_field ); } - + return $sql; } From 1d3594a88a49c7983ad065620d6af6479d507206 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Mon, 3 Jul 2023 14:42:31 +0400 Subject: [PATCH 18/24] fix lint error --- includes/Filter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/Filter.php b/includes/Filter.php index f01fc23c..5b8aa72e 100644 --- a/includes/Filter.php +++ b/includes/Filter.php @@ -362,7 +362,7 @@ private function getPropertyType() { } else { $typeValue = $types[0]->getWikiValue(); } - } + } } $propKey = array_search( $typeValue, $datatypeLabels ); @@ -373,7 +373,7 @@ private function getPropertyType() { $this->propKey = '_wpg'; return $propertyType; } - + // used to retrieve the value of // properties set with the label of a // predefined property, e.g. Email::email@test.com From 7fc6edd56928c91da5928213c067561d6bb5e3c6 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Mon, 3 Jul 2023 14:43:06 +0400 Subject: [PATCH 19/24] fix lint error --- includes/Sql/PropertyTypeDbInfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Sql/PropertyTypeDbInfo.php b/includes/Sql/PropertyTypeDbInfo.php index b7f84b28..6ac964ef 100644 --- a/includes/Sql/PropertyTypeDbInfo.php +++ b/includes/Sql/PropertyTypeDbInfo.php @@ -46,7 +46,7 @@ public static function valueField( string $propertyType ): ?string { case 'URL': case 'annotation_uri': case 'email': - case 'geographic_coord': + case 'geographic_coord': return 'o_serialized'; case 'keyword': return 'o_blob'; From c964a78d3f9226fa7c49ed15ace5904156217c99 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Mon, 3 Jul 2023 15:18:20 +0400 Subject: [PATCH 20/24] fix phpstan error --- includes/Filter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/includes/Filter.php b/includes/Filter.php index 5b8aa72e..128f3b59 100644 --- a/includes/Filter.php +++ b/includes/Filter.php @@ -342,6 +342,7 @@ private function getPropertyType() { // KnownTypeLabels $isKnownLabel = false; + $typeValue = null; if ( in_array( $property, $datatypeLabels ) ) { $typeValue = $property; $isKnownLabel = true; From 4a4e8390cf5c60e2db96f616ae4550042b5a4e2b Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Wed, 12 Jul 2023 12:47:03 +0400 Subject: [PATCH 21/24] unit test additional datatypes --- .../filters-additional-datatypes.json | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 tests/phpunit/Integration/JSONScript/TestCases/filters-additional-datatypes.json diff --git a/tests/phpunit/Integration/JSONScript/TestCases/filters-additional-datatypes.json b/tests/phpunit/Integration/JSONScript/TestCases/filters-additional-datatypes.json new file mode 100644 index 00000000..0e52b592 --- /dev/null +++ b/tests/phpunit/Integration/JSONScript/TestCases/filters-additional-datatypes.json @@ -0,0 +1,139 @@ +{ + "description": "filters", + "setup": [ + { + "namespace": "SMW_NS_PROPERTY", + "page": "SomeAnnotationUri", + "contents": "[[Has type::Annotation Uri]]" + }, + { + "namespace": "SMW_NS_PROPERTY", + "page": "SomeGeographicCoordinates", + "contents": "[[Has type::Geographic coordinates]]" + }, + { + "namespace": "SMW_NS_PROPERTY", + "page": "SomeKeyword", + "contents": "[[Has type::Keyword]]" + }, + { + "namespace": "SMW_NS_PROPERTY", + "page": "SomeMonolingualText", + "contents": "[[Has type::Monolingual text]]" + }, + { + "namespace": "SMW_NS_PROPERTY", + "page": "SomeTelephoneNumber", + "contents": "[[Has type::Telephone number]]" + }, + { + "namespace": "SMW_NS_PROPERTY", + "page": "SomeTemperature", + "contents": "[[Has type::Temperature]]" + }, + { + "namespace": "SMW_NS_PROPERTY", + "page": "SomeURL", + "contents": "[[Has type::URL]]" + }, + { + "namespace": "SMW_NS_PROPERTY", + "page": "SomeQuantity", + "contents": "[[Has type::Quantity]]" + }, + { + "namespace": "SMW_NS_PROPERTY", + "page": "SomeCode", + "contents": "[[Has type::Code]]" + }, + { + "namespace": "SMW_NS_PROPERTY", + "page": "SomeEmail", + "contents": "[[Has type::Email]]" + }, + { + "namespace": "SMW_NS_PROPERTY", + "page": "Unused", + "contents": "[[Has type::Text]]" + }, + { + "namespace": "NS_CATEGORY", + "page": "Category1", + "contents": "{{#drilldowninfo: filters=AnnotationUri (property=SomeAnnotationUri),GeographicCoordinates (property=SomeGeographicCoordinates),Keyword (property=SomeKeyword),MonolingualText (property=SomeMonolingualText),TelephoneNumber (property=SomeTelephoneNumber),Temperature (property=SomeTemperature),URL (property=SomeURL),Quantity (property=SomeQuantity),Code (property=SomeCode),Email (property=SomeEmail),Unused (property=Unused)|display parameters=format=list}}" + }, + { + "page": "Category2SetA", + "contents": "[[Category:Category2]]{{#set: SomeAnnotationUri=https://example.com/a/b|SomeGeographicCoordinates=55.3781, 3.4360|SomeKeyword=key123|SomeMonolingualText=text@en|SomeTelephoneNumber=+441939550000|SomeTemperature=37|SomeURL=https://example.com|SomeQuantity=34|SomeCode=code123|SomeEmail=test@example.com}}" + }, + { + "page": "Category1SetA", + "contents": "[[Category:Category1]]{{#set: SomeAnnotationUri=https://example.com/a/b|SomeGeographicCoordinates=55.3781, 3.4360|SomeKeyword=key123|SomeMonolingualText=text@en|SomeTelephoneNumber=+441939550000|SomeTemperature=37|SomeURL=https://example.com|SomeQuantity=34|SomeCode=code123|SomeEmail=test@example.com}}" + }, + { + "page": "Category1SetB", + "contents": "[[Category:Category1]]{{#set: SomeAnnotationUri=https://example.com/b/c|SomeGeographicCoordinates=35.3781, 30.4360|SomeKeyword=key456|SomeMonolingualText=text@de|SomeTelephoneNumber=+441939660000|SomeTemperature=36|SomeURL=https://test.com|SomeQuantity=36|SomeCode=code456|SomeEmail=test@test.com}}" + } + ], + "tests": [ + { + "type": "special", + "about": "no filter applied", + "special-page": { + "page": "BrowseData", + "query-parameters": "Category1", + "request-parameters": {} + }, + "assert-output": { + "to-contain": [ + "AnnotationUri:", + "https://example.com/a/b (1)", + "https://example.com/b/c (1)", + + "Keyword:", + "key123 (1)", + "key456 (1)", + + "TelephoneNumber:", + "tel:+441939550000 (1)", + "tel:+441939660000 (1)", + + "Temperature:", + "36 (1)", + "37 (1)", + + "URL:", + "https://example.com (1)", + "https://test.com (1)", + + "Code:", + "code123 (1)", + "code456 (1)", + + "Email:", + "mailto:test@example.com (1)", + "mailto:test@test.com (1)", + + "Unused:", + "(There are no values for this filter)", + + "
", + "Category1SetA", + "Category1SetB" + ], + "not-contain": [ + "Category2SetA", + "Special:BrowseData/Category1?Unused=" + ] + } + } + + ], + "settings": { + "wgLang": "en" + }, + "meta": { + "version": "2", + "is-incomplete": false, + "debug": false + } +} From 8398d99f8256f02960bed0e411b07a385bfdcada Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Sat, 15 Jul 2023 10:54:51 +0400 Subject: [PATCH 22/24] added applied filter --- .../filters-additional-datatypes.json | 69 ++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/Integration/JSONScript/TestCases/filters-additional-datatypes.json b/tests/phpunit/Integration/JSONScript/TestCases/filters-additional-datatypes.json index 0e52b592..a3a887d2 100644 --- a/tests/phpunit/Integration/JSONScript/TestCases/filters-additional-datatypes.json +++ b/tests/phpunit/Integration/JSONScript/TestCases/filters-additional-datatypes.json @@ -39,7 +39,7 @@ { "namespace": "SMW_NS_PROPERTY", "page": "SomeQuantity", - "contents": "[[Has type::Quantity]]" + "contents": "[[Has type::Quantity]][[Corresponds to::1 g]][[Corresponds to::1000 mg]]" }, { "namespace": "SMW_NS_PROPERTY", @@ -61,6 +61,11 @@ "page": "Category1", "contents": "{{#drilldowninfo: filters=AnnotationUri (property=SomeAnnotationUri),GeographicCoordinates (property=SomeGeographicCoordinates),Keyword (property=SomeKeyword),MonolingualText (property=SomeMonolingualText),TelephoneNumber (property=SomeTelephoneNumber),Temperature (property=SomeTemperature),URL (property=SomeURL),Quantity (property=SomeQuantity),Code (property=SomeCode),Email (property=SomeEmail),Unused (property=Unused)|display parameters=format=list}}" }, + { + "namespace": "NS_CATEGORY", + "page": "Category2", + "contents": "{{#drilldowninfo: filters=AnnotationUri (property=SomeAnnotationUri),GeographicCoordinates (property=SomeGeographicCoordinates),Keyword (property=SomeKeyword),MonolingualText (property=SomeMonolingualText),TelephoneNumber (property=SomeTelephoneNumber),Temperature (property=SomeTemperature),URL (property=SomeURL),Quantity (property=SomeQuantity),Code (property=SomeCode),Email (property=SomeEmail),Unused (property=Unused)|display parameters=format=list}}" + }, { "page": "Category2SetA", "contents": "[[Category:Category2]]{{#set: SomeAnnotationUri=https://example.com/a/b|SomeGeographicCoordinates=55.3781, 3.4360|SomeKeyword=key123|SomeMonolingualText=text@en|SomeTelephoneNumber=+441939550000|SomeTemperature=37|SomeURL=https://example.com|SomeQuantity=34|SomeCode=code123|SomeEmail=test@example.com}}" @@ -89,10 +94,13 @@ "https://example.com/a/b (1)", "https://example.com/b/c (1)", + "GeographicCoordinates:", + "(There are no values for this filter)", + "Keyword:", "key123 (1)", "key456 (1)", - + "TelephoneNumber:", "tel:+441939550000 (1)", "tel:+441939660000 (1)", @@ -105,6 +113,10 @@ "https://example.com (1)", "https://test.com (1)", + "Quantity:", + "34 (1)", + "36 (1)", + "Code:", "code123 (1)", "code456 (1)", @@ -125,6 +137,59 @@ "Special:BrowseData/Category1?Unused=" ] } + }, + { + "type": "special", + "about": "keyword filter applied", + "special-page": { + "page": "BrowseData", + "query-parameters": "Category1", + "request-parameters": { + "Keyword": "key123" + } + }, + "assert-output": { + "to-contain": [ + "Category1", + "> Keyword: key123 ", + + "AnnotationUri:", + "https://example.com/a/b (1)", + + "GeographicCoordinates:", + "
(There are no values for this filter)", + + "Keyword:", + "
key123 · key456 · Other · None", + + "TelephoneNumber:", + "tel:+441939550000 (1)", + + "Temperature:", + "37 (1)", + + "URL:", + "https://example.com (1)", + + "Quantity:", + "34 (1)", + + "Code:", + "code123 (1)", + + "Email:", + "mailto:test@example.com (1)", + + "Unused:", + "(There are no values for this filter)", + + "
", + "Category1SetA" + ], + "not-contain": [ + "Category1SetB" + ] + } } ], From d111488f987db89edf43e97ed328593f4c270818 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Fri, 22 Nov 2024 13:09:26 +0400 Subject: [PATCH 23/24] restore original --- includes/AppliedFilter.php | 110 +++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 28 deletions(-) diff --git a/includes/AppliedFilter.php b/includes/AppliedFilter.php index 4971c713..990977b5 100644 --- a/includes/AppliedFilter.php +++ b/includes/AppliedFilter.php @@ -15,12 +15,48 @@ */ class AppliedFilter { + + /** + * filter value + * + * @var Filter + */ public Filter $filter; + /** + * array of values + * + * @var array + */ public $values = []; + /** + * search terms value + * + * @var string + */ public $search_terms; + /** + * lower date value + * + * @var DateTime|null + */ public $lower_date; + /** + * upper date value + * + * @var DateTime|null + */ public $upper_date; + /** + * search terms value + * + * @var string + */ public $lower_date_string; + /** + * search terms value + * + * @var string + */ public $upper_date_string; public static function create( Filter $filter, $values, $search_terms = null, $lower_date = null, $upper_date = null ) { @@ -84,6 +120,8 @@ protected function parseUpperOrLowerDate( $raw_date, $is_upper ) { /** * Convert value of datepicker field (e.g. "1760-11-23") into a human-readable representation * (e.g. "June 15, 2000"). + * + * @return string formatted date */ protected function lowerOrUpperDateToString( $date ) { $ts = sprintf( '%04d%02d%02d000000', $date['year'], $date['month'], $date['day'] ); @@ -93,6 +131,8 @@ protected function lowerOrUpperDateToString( $date ) { /** * Convert value of datepicker field (e.g. "1760-11-23") into value usable in SQL queries. * (e.g. DATE(...)). + * + * @return string formatted date */ protected function lowerOrUpperDateToSql( $date ) { return "DATE('" . $date['year'] . "-" . $date['month'] . "-" . $date['day'] . "')"; @@ -101,6 +141,8 @@ protected function lowerOrUpperDateToSql( $date ) { /** * Returns a string that adds a check for this filter/value * combination to an SQL "WHERE" clause. + * + * @return string */ public function checkSQL( $value_field ) { global $wgDBtype; @@ -168,6 +210,8 @@ public function checkSQL( $value_field ) { $sql .= "$value_field < {$fv->upper_limit} "; } } elseif ( $this->filter->propertyType() == 'date' ) { + // check if the array can be used instead of list + // [ $yearValue, $monthValue, $dayValue ] = SqlProvider::getDateFunctions( $value_field ); list( $yearValue, $monthValue, $dayValue ) = SqlProvider::getDateFunctions( $value_field ); if ( $fv->time_period == 'day' ) { $sql .= "$yearValue = {$fv->year} AND $monthValue = {$fv->month} AND $dayValue = {$fv->day} "; @@ -175,7 +219,8 @@ public function checkSQL( $value_field ) { $sql .= "$yearValue = {$fv->year} AND $monthValue = {$fv->month} "; } elseif ( $fv->time_period == 'year' ) { $sql .= "$yearValue = {$fv->year} "; - } else { // if ( $fv->time_period == 'year range' ) { + } else { + // if ( $fv->time_period == 'year range' ) { $sql .= "$yearValue >= {$fv->year} AND $yearValue <= {$fv->end_year} "; } } else { @@ -206,57 +251,66 @@ public function getAllOrValues( $category ): PossibleFilterValues { $revision_table_name = $dbr->tableName( 'revision' ); $page_props_table_name = $dbr->tableName( 'page_props' ); $category = $dbr->addQuotes( $category ); + if ( $this->filter->propertyType() != 'date' ) { $value_field = PropertyTypeDbInfo::valueField( $this->filter->propertyType() ); } else { - // Is this necessary? $date_field = PropertyTypeDbInfo::dateField( $this->filter->propertyType() ); list( $yearValue, $monthValue, $dayValue ) = SqlProvider::getDateFunctions( $date_field ); + if ( $this->filter->timePeriod() == 'day' ) { $value_field = "$yearValue, $monthValue, $dayValue"; } elseif ( $this->filter->timePeriod() == 'month' ) { $value_field = "$yearValue, $monthValue"; - } elseif ( $this->filter->timePeriod() == 'year' ) { - $value_field = $yearValue; - } else { // if ( $this->filter->timePeriod() == 'year range' ) { + } else { $value_field = $yearValue; } } + $displaytitle = $this->filter->propertyType() === 'page' ? 'displaytitle.pp_value' : 'null'; $smw_ids = $dbr->tableName( Utils::getIDsTableName() ); $smwCategoryInstances = $dbr->tableName( Utils::getCategoryInstancesTableName() ); $cat_ns = NS_CATEGORY; - $sql = "SELECT $value_field as value, $displaytitle as displayTitle - FROM $property_table_name p - JOIN $smw_ids p_ids ON p.p_id = p_ids.smw_id\n"; + + // Construct SQL query + $sql = "SELECT $value_field AS value, $displaytitle AS displayTitle + FROM $property_table_name p + JOIN $smw_ids p_ids ON p.p_id = p_ids.smw_id\n"; + if ( $this->filter->propertyType() === 'page' ) { - $sql .= <<filter->propertyType() === 'monolingual_text' ) { - $sql .= <<query( $sql ); + + $sql .= <<query( $sql, __METHOD__ ); + while ( $row = $res->fetchRow() ) { if ( $this->filter->propertyType() == 'date' && $this->filter->timePeriod() == 'month' ) { $value_string = Utils::monthToString( $row[1] ) . " " . $row['value']; } else { $value_string = str_replace( '_', ' ', $row['value'] ); } - $possible_values[] = new PossibleFilterValue( $value_string, null, htmlspecialchars_decode( $row['displayTitle'] ) ); + + $possible_values[] = new PossibleFilterValue( + $value_string, + null, + htmlspecialchars_decode( $row['displayTitle'] ) + ); } return new PossibleFilterValues( $possible_values ); } From 4499476be223aa7de952db1b3ae274545926f5a2 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Fri, 22 Nov 2024 13:29:43 +0400 Subject: [PATCH 24/24] restore sql monolingual_text --- includes/AppliedFilter.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/includes/AppliedFilter.php b/includes/AppliedFilter.php index 990977b5..5eeae815 100644 --- a/includes/AppliedFilter.php +++ b/includes/AppliedFilter.php @@ -286,6 +286,13 @@ public function getAllOrValues( $category ): PossibleFilterValues { SQL; } + if ( $this->filter->propertyType() === 'monolingual_text' ) { + $sql .= <<