diff options
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/src/SQLStore/Lookup/UsageStatisticsListLookup.php')
-rw-r--r-- | www/wiki/extensions/SemanticMediaWiki/src/SQLStore/Lookup/UsageStatisticsListLookup.php | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/src/SQLStore/Lookup/UsageStatisticsListLookup.php b/www/wiki/extensions/SemanticMediaWiki/src/SQLStore/Lookup/UsageStatisticsListLookup.php new file mode 100644 index 00000000..34529efb --- /dev/null +++ b/www/wiki/extensions/SemanticMediaWiki/src/SQLStore/Lookup/UsageStatisticsListLookup.php @@ -0,0 +1,352 @@ +<?php + +namespace SMW\SQLStore\Lookup; + +use RuntimeException; +use SMW\DIProperty; +use SMW\SQLStore\PropertyStatisticsStore; +use SMW\SQLStore\SQLStore; +use SMW\Store; + +/** + * @license GNU GPL v2+ + * @since 2.2 + * + * @author mwjames + */ +class UsageStatisticsListLookup implements ListLookup { + + /** + * @var Store + */ + private $store; + + /** + * @var PropertyStatisticsStore + */ + private $propertyStatisticsStore; + + /** + * @since 2.2 + * + * @param Store $store + * @param PropertyStatisticsStore $propertyStatisticsStore + */ + public function __construct( Store $store, PropertyStatisticsStore $propertyStatisticsStore ) { + $this->store = $store; + $this->propertyStatisticsStore = $propertyStatisticsStore; + } + + /** + * Returns a list with statistical information where keys are matched to: + * + * - 'PROPUSES': Number of property instances (value assignments) in the connection + * - 'USEDPROPS': Number of properties that are used with at least one value + * - 'DECLPROPS': Number of properties that have been declared (i.e. assigned a type) + * - 'OWNPAGE': Number of properties with their own page + * - 'QUERY': Number of inline queries + * - 'QUERYSIZE': Represents collective query size + * - 'CONCEPTS': Number of declared concepts + * - 'SUBOBJECTS': Number of declared subobjects + * - 'QUERYFORMATS': Array of used formats and its usage count + * - 'TOTALPROPS': Total number of registered properties + * - 'ERRORUSES': Number of annotations with an error + * - 'DELETECOUNT': Number of "marked for deletion" + * + * @since 2.2 + * + * @return array + */ + public function fetchList() { + return [ + 'OWNPAGE' => $this->getPropertyPageCount(), + 'QUERY' => $this->getQueryCount(), + 'QUERYSIZE' => $this->getQuerySize(), + 'QUERYFORMATS' => $this->getQueryFormatsCount(), + 'CONCEPTS' => $this->getConceptCount(), + 'SUBOBJECTS' => $this->getSubobjectCount(), + 'DECLPROPS' => $this->getDeclaredPropertiesCount(), + 'PROPUSES' => $this->getPropertyUsageCount(), + 'USEDPROPS' => $this->getUsedPropertiesCount(), + 'TOTALPROPS' => $this->getTotalPropertiesCount(), + 'ERRORUSES' => $this->getImproperValueForCount(), + 'DELETECOUNT' => $this->getDeleteCount() + ]; + } + + /** + * @since 2.2 + * + * @return boolean + */ + public function isFromCache() { + return false; + } + + /** + * @since 2.2 + * + * @return integer + */ + public function getTimestamp() { + return wfTimestamp( TS_UNIX ); + } + + /** + * @since 2.2 + * + * @return string + */ + public function getHash() { + return 'statistics-lookup'; + } + + /** + * @since 2.2 + * + * @return number + */ + public function getImproperValueForCount() { + return $this->propertyStatisticsStore->getUsageCount( + $this->store->getObjectIds()->getSMWPropertyID( new DIProperty( '_ERRP' ) ) + ); + } + + /** + * @since 1.9 + * + * @return number + */ + public function getQueryCount() { + return $this->count( '_ASK' ); + } + + /** + * @since 1.9 + * + * @return number + */ + public function getQuerySize() { + return $this->count( '_ASKSI' ); + } + + /** + * @since 1.9 + * + * @return number + */ + public function getConceptCount() { + return $this->count( '_CONC' ); + } + + /** + * @since 1.9 + * + * @return number + */ + public function getSubobjectCount() { + return $this->count( DIProperty::TYPE_SUBOBJECT ); + } + + /** + * @since 1.9 + * + * @return number + */ + public function getDeclaredPropertiesCount() { + return $this->count( DIProperty::TYPE_HAS_TYPE ); + } + + /** + * @since 1.9 + * + * @return int[] + */ + public function getQueryFormatsCount() { + $count = []; + + $res = $this->store->getConnection()->select( + $this->findPropertyTableByType( '_ASKFO' )->getName(), + 'o_hash, COUNT(s_id) AS count', + [], + __METHOD__, + [ + 'ORDER BY' => 'count DESC', + 'GROUP BY' => 'o_hash' + ] + ); + + foreach ( $res as $row ) { + $count[$row->o_hash] = (int)$row->count; + } + + return $count; + } + + /** + * @since 1.9 + * + * @return number + */ + public function getPropertyPageCount() { + + $options = []; + + // Only match entities that have a NOT null smw_proptable_hash entry + // which indicates that it is not a object but a subject value (has + // annotations such as `has type` == page was created with ... etc.) + $conditions = [ + 'smw_namespace' => SMW_NS_PROPERTY, + 'smw_iw' => '', + 'smw_subobject' => '', + 'smw_proptable_hash IS NOT NULL' + ]; + + $db = $this->store->getConnection( 'mw.db' ); + + // Select object ID's against known property ID's that match the conditions + $res = $db->select( + [ $db->tableName( SQLStore::ID_TABLE ), $db->tableName( SQLStore::PROPERTY_STATISTICS_TABLE ) ], + 'smw_id', + $conditions, + __METHOD__, + $options, + [ $db->tableName( SQLStore::ID_TABLE ) => [ 'INNER JOIN', [ 'smw_id=p_id' ] ] ] + ); + + return $res->numRows(); + } + + /** + * Count property uses by summing up property statistics table + * + * @note subproperties that are part of container values are counted + * individually and it does not seem to be important to filter them by + * adding more conditions. + * + * @since 1.9 + * + * @return number + */ + public function getPropertyUsageCount() { + $count = 0; + + $row = $this->store->getConnection()->selectRow( + [ $this->store->getStatisticsTable() ], + 'SUM( usage_count ) AS count', + [], + __METHOD__ + ); + + $count = $row ? $row->count : $count; + + return (int)$count; + } + + /** + * @since 2.5 + * + * @return number + */ + public function getTotalPropertiesCount() { + + $count = 0; + + $conditions = [ + 'smw_namespace' => SMW_NS_PROPERTY, + 'smw_iw' => '', + 'smw_subobject' => '' + ]; + + $row = $this->store->getConnection()->selectRow( + SQLStore::ID_TABLE, + 'Count( * ) AS count', + $conditions, + __METHOD__ + ); + + $count = $row ? $row->count : $count; + + return (int)$count; + } + + /** + * @since 1.9 + * + * @return number + */ + public function getUsedPropertiesCount() { + + $options = []; + + $conditions = [ + 'smw_namespace' => SMW_NS_PROPERTY, + 'smw_iw' => '', + 'smw_subobject' => '', + 'usage_count > 0' + ]; + + $db = $this->store->getConnection( 'mw.db' ); + + // Select object ID's against known property ID's that match the conditions + $res = $db->select( + [ $db->tableName( SQLStore::ID_TABLE ), $db->tableName( SQLStore::PROPERTY_STATISTICS_TABLE ) ], + 'smw_id', + $conditions, + __METHOD__, + $options, + [ + $db->tableName( SQLStore::ID_TABLE ) => [ 'INNER JOIN', [ 'smw_id=p_id' ] ] + ] + ); + + return $res->numRows(); + } + + /** + * @since 2.4 + * + * @return number + */ + public function getDeleteCount() { + $count = 0; + + $row = $this->store->getConnection()->selectRow( + SQLStore::ID_TABLE, + 'Count( * ) AS count', + [ 'smw_iw' => ':smw-delete' ], + __METHOD__ + ); + + $count = $row ? $row->count : $count; + + return (int)$count; + } + + private function count( $type ) { + + $res = $this->store->getConnection()->select( + $this->findPropertyTableByType( $type )->getName(), + 'COUNT(s_id) AS count', + [], + __METHOD__ + ); + + $row = $this->store->getConnection()->fetchObject( $res ); + + return isset( $row->count ) ? (int)$row->count : 0; + } + + private function findPropertyTableByType( $type ) { + $propertyTables = $this->store->getPropertyTables(); + + $tableIdForType = $this->store->findPropertyTableID( new DIProperty( $type ) ); + + if ( isset( $propertyTables[$tableIdForType] ) ) { + return $propertyTables[$tableIdForType]; + } + + throw new RuntimeException( "Tried to access a table that doesn't exist for {$tableIdForType}." ); + } + +} |