http://www.mediawiki.org/wiki/Special:Code/MediaWiki/55343
Revision: 55343 Author: yaron Date: 2009-08-19 19:45:28 +0000 (Wed, 19 Aug 2009) Log Message: ----------- New extension Added Paths: ----------- trunk/extensions/SemanticInternalObjects/ trunk/extensions/SemanticInternalObjects/README trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.i18n.magic.php trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.i18n.php trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.php trunk/extensions/SemanticInternalObjects/SemanticInternalObjects_body.php Added: trunk/extensions/SemanticInternalObjects/README =================================================================== --- trunk/extensions/SemanticInternalObjects/README (rev 0) +++ trunk/extensions/SemanticInternalObjects/README 2009-08-19 19:45:28 UTC (rev 55343) @@ -0,0 +1,85 @@ +Semantic Internal Objects Extension + + Version 0.1 + Yaron Koren + +This is free software licensed under the GNU General Public License. Please +see http://www.gnu.org/copyleft/gpl.html for further details, including the +full text and terms of the license. + +== Overview == + +Semantic Internal Objects is an extension to MediaWiki that defines a +parser function, '#set_internal', that is used to define "internal objects" +within the Semantic MediaWiki system. There are complex types of +information sometimes known as 'n-ary relations' that involve more than one +data value associated together. A simple example is in a cooking recipe; a +recipe may call for 1 cup of flour, and the values "1", "cup" and "flour" +must be encoded together; by themselves, the values are not meaningful (the +third value has meaning, though not all of the meaning it could have). Such +information can be stored already in SMW using multi-valued properties, +though this approach is not flexible and currently leads to querying problems. +Instead, #set_internal can be used to define "internal objects" within a page, +which can then be queried as normal SMW pages would; a row of a recipe would +be a good example of data that could be defined using #set_internal. + +The syntax of #set_internal is as follows: + +{{#set_internal:object_to_page_property +|property1=value1 +|property2=value2 +... +}} + +A sample call to #set_internal would be: + +{{#set_internal:Has recipe +|Has quantity=1 +|Has unit=cup +|Has ingredient=flour +}} + +This call would be placed in a page for a recipe, and it would define an object +that had an automatically-generated name; if it were in a page called "Carrot +cake", for instance, the object would be called "Carrot cake#1". If that page +had subsequent calls to #set_internal, the objects that those calls generated +would be called "Carrot cake#2", "Carrot cake#3", etc. + +It should be noted that #set_internal does not display anything to the screen; +display of the values has to be handled separately (this can be done easily +if the function is called from a template). + +Internal objects, once stored, can be queried as if they were wiki pages. So +the following query would show a table of all the recipes that contain more +than 1/2 a cup of flour, and the number of cups they contain: + +{{#ask:[[Has recipe::+]][[Has ingredient::flour]][[Has unit::cup]][[Has quantity::>.5]] +|mainlabel=- +|? Has recipe +|? Has quantity +}} + +Note the "mainlabel=-" parameter in the query: that hides the names of the +internal objects from users, since those names are meaningless. + +For more information, see the extension homepage at: +http://www.mediawiki.org/wiki/Extension:Semantic_Internal_Objects + +== Requirements == + +This version of the Semantic Internal Objects extension requires MediaWiki 1.8 +or higher and Semantic MediaWiki 1.4 or higher. + +== Installation == + +To install the extension, place the entire 'SemanticInternalObjects' directory +within your MediaWiki 'extensions' directory, then add the following +line to your 'LocalSettings.php' file: + + require_once( "$IP/extensions/SemanticInternalObjects/SemanticInternalObjects.php" ); + +== Contact == + +Comments, questions, suggestions and bug reports are welcome, and can +be placed on the Talk page for the extension, or sent to Yaron at +yaro...@gmail.com. Added: trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.i18n.magic.php =================================================================== --- trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.i18n.magic.php (rev 0) +++ trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.i18n.magic.php 2009-08-19 19:45:28 UTC (rev 55343) @@ -0,0 +1,7 @@ +<?php + +$magicWords = array(); + +$magicWords['en'] = array( + 'set_internal' => array( 0, 'set_internal' ), +); Added: trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.i18n.php =================================================================== --- trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.i18n.php (rev 0) +++ trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.i18n.php 2009-08-19 19:45:28 UTC (rev 55343) @@ -0,0 +1,28 @@ +<?php +/** + * Internationalization file for Semantic Internal Objects + * + * @file + * @ingroup Language + * @ingroup I18n + * @ingroup SemanticInternalObjects + */ + +// FIXME: Can be enabled when new style magic words are used (introduced in r52503) +// require_once( dirname( __FILE__ ) . '/SemanticInternalObjects.i18n.magic.php' ); + +$messages = array(); + +/** English + * @author Yaron Koren + */ +$messages['en'] = array( + 'semanticinternalobjects-desc' => 'Setting of internal objects in Semantic MediaWiki', +); + +/** Message documentation (Message documentation) + * @author Yaron Koren + */ +$messages['qqq'] = array( + 'semanticinternalobjects-desc' => '{{desc}}', +); Added: trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.php =================================================================== --- trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.php (rev 0) +++ trunk/extensions/SemanticInternalObjects/SemanticInternalObjects.php 2009-08-19 19:45:28 UTC (rev 55343) @@ -0,0 +1,54 @@ +<?php +/** + * Initialization file for SemanticInternalObjects + * + * @file + * @ingroup SemanticInternalObjects + * @author Yaron Koren + */ + +if (!defined('MEDIAWIKI')) die(); + +define('SIO_VERSION', '0.1'); + +$wgExtensionCredits['parserhook'][]= array( + 'name' => 'Semantic Internal Objects', + 'version' => SIO_VERSION, + 'author' => 'Yaron Koren', + 'url' => 'http://www.mediawiki.org/wiki/Extension:Semantic_Internal_Objects', + 'description' => 'Setting of internal objects in Semantic MediaWiki', + 'descriptionmsg' => 'semanticinternalobjects-desc', +); + +$wgExtensionFunctions[] = 'siofParserFunctions'; +$wgHooks['LanguageGetMagic'][] = 'siofLanguageGetMagic'; +$wgHooks['smwDeleteSemanticData'][] = 'SIOHandler::updateData'; + +$siogIP = $IP . '/extensions/SemanticInternalObjects'; +$wgExtensionMessagesFiles['SemanticInternalObjects'] = $siogIP . '/SemanticInternalObjects.i18n.php'; +$wgAutoloadClasses['SIOHandler'] = $siogIP . '/SemanticInternalObjects_body.php'; + +function siofParserFunctions() { + global $wgHooks, $wgParser; + if( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) { + $wgHooks['ParserFirstCallInit'][] = 'siofRegisterParserFunctions'; + } else { + if ( class_exists( 'StubObject' ) && !StubObject::isRealObject( $wgParser ) ) { + $wgParser->_unstub(); + } + siofRegisterParserFunctions( $wgParser ); + } +} + +function siofRegisterParserFunctions(&$parser) { + $parser->setFunctionHook( 'set_internal', array('SIOHandler','doSetInternal') ); + return true; // always return true, in order not to stop MW's hook processing! +} + +function siofLanguageGetMagic( &$magicWords, $langCode = "en" ) { + switch ( $langCode ) { + default: + $magicWords['set_internal'] = array ( 0, 'set_internal' ); + } + return true; +} Added: trunk/extensions/SemanticInternalObjects/SemanticInternalObjects_body.php =================================================================== --- trunk/extensions/SemanticInternalObjects/SemanticInternalObjects_body.php (rev 0) +++ trunk/extensions/SemanticInternalObjects/SemanticInternalObjects_body.php 2009-08-19 19:45:28 UTC (rev 55343) @@ -0,0 +1,155 @@ +<?php +/** + * @author Yaron Koren + */ + +if (!defined('MEDIAWIKI')) die(); + +/** + * Class that holds information on a single internal object, including all + * its properties. + */ +class SIOInternalObject { + var $main_title; + var $index; + var $property_value_pairs; + + public function SIOInternalObject($main_title, $index) { + $this->main_title = $main_title; + $this->index = $index; + $this->property_value_pairs = array(); + } + + public function addPropertyAndValue($prop_name, $value) { + $property = SMWPropertyValue::makeUserProperty($prop_name); + $data_value = SMWDataValueFactory::newPropertyObjectValue($property, $value); + if ($data_value->isValid()) { + $this->property_value_pairs[] = array($property, $data_value); + } // else - show an error message? + } + + public function getName() { + return $this->main_title->getDBkey() . '#' . $this->index; + } +} + +/** + * Class for all database-related actions. + * This class exists mostly because SMWSQLStore2's functions makeSMWPageID() + * and makeSMWPropertyID(), which are needed for the DB access, are both + * protected, and thus can't be accessed externally. + */ +class SIOSQLStore extends SMWSQLStore2 { + function deletePageObjects($page_name, $namespace) { + $ids = array(); + + $iw = ''; + $db =& wfGetDB( DB_SLAVE ); + $res = $db->select('smw_ids', array('smw_id'), 'smw_title LIKE ' . $db->addQuotes($page_name . '#%') . ' AND ' . 'smw_namespace=' . $db->addQuotes($namespace) . ' AND smw_iw=' . $db->addQuotes($iw), 'SIO::getSMWPageObjectIDs', array()); + while ($row = $db->fetchObject($res)) { + $ids[] = $row->smw_id; + } + foreach ($ids as $id) { + $db->delete('smw_rels2', array('s_id' => $id), 'SIO::updateData::Rels2'); + $db->delete('smw_rels2', array('o_id' => $id), 'SIO::updateData::Rels2'); + $db->delete('smw_atts2', array('s_id' => $id), 'SMW::deleteSubject::Atts2'); + } + } + + function storeAllInfo($main_page_name, $namespace, $internal_object) { + $main_page_id = $this->makeSMWPageID($main_page_name, $namespace, ''); + $io_id = $this->makeSMWPageID($internal_object->getName(), $namespace, ''); + $up_rels2 = array(); + $up_atts2 = array(); + // set all the properties pointing from this internal object + foreach ($internal_object->property_value_pairs as $property_value_pair) { + list($property, $value) = $property_value_pair; + $mode = SMWSQLStore2::getStorageMode($property->getPropertyTypeID()); + switch ($mode) { + case SMW_SQL2_RELS2: + $up_rels2[] = array( + 's_id' => $io_id, + 'p_id' => $this->makeSMWPropertyID($property), + 'o_id' => $this->makeSMWPageID($value->getDBkey(), $value->getNamespace(), $value->getInterwiki()) + ); + break; + case SMW_SQL2_ATTS2: + $keys = $value->getDBkeys(); + $up_atts2[] = array( + 's_id' => $io_id, + 'p_id' => $this->makeSMWPropertyID($property), + 'value_unit' => $value->getUnit(), + 'value_xsd' => $keys[0], + 'value_num' => $value->getNumericValue() + ); + break; + } + } + + // now save everything to the database + $db =& wfGetDB( DB_MASTER ); + if (count($up_rels2) > 0) { + $db->insert( 'smw_rels2', $up_rels2, 'SMW::updateRel2Data'); + } + if (count($up_atts2) > 0) { + $db->insert( 'smw_atts2', $up_atts2, 'SMW::updateAtt2Data'); + } + } +} + +/** + * Class for hook functions for creating and storing information + */ +class SIOHandler { + + static $cur_page_name = ''; + static $cur_page_namespace = 0; + static $internal_object_index = 1; + static $internal_objects = array(); + + public static function doSetInternal(&$parser) { + $main_page_name = $parser->getTitle()->getDBKey(); + $main_page_namespace = $parser->getTitle()->getNamespace(); + if ($main_page_name == self::$cur_page_name && + $main_page_namespace == self::$cur_page_namespace) { + self::$internal_object_index++; + } else { + self::$cur_page_name = $main_page_name; + self::$cur_page_namespace = $main_page_namespace; + self::$internal_object_index = 1; + } + $cur_object_num = self::$internal_object_index; + $params = func_get_args(); + array_shift( $params ); // we already know the $parser... + $internal_object = new SIOInternalObject($parser->getTitle(), $cur_object_num); + $obj_to_page_prop_name = array_shift( $params ); + $internal_object->addPropertyAndValue($obj_to_page_prop_name, $parser->getTitle()); + foreach ( $params as $param ) { + $parts = explode("=", trim($param)); + if (count($parts)==2) { + $key = $parts[0]; + $value = $parts[1]; + $internal_object->addPropertyAndValue($key, $value); + } + } + self::$internal_objects[] = $internal_object; + } + + public static function updateData($subject) { + $sio_sql_store = new SIOSQLStore(); + // Find all "pages" in the SMW IDs table that are internal + // objects for this page, and delete their properties from + // the SMW tables. + // Then save the current contents of the $internal_objects + // array. + $page_name = $subject->getDBKey(); + $namespace = $subject->getNamespace(); + $sio_sql_store->deletePageObjects($page_name, $namespace); + foreach (self::$internal_objects as $internal_object) { + $sio_sql_store->storeAllInfo($page_name, $namespace, $internal_object); + } + self::$internal_objects = array(); + return true; + } + +} _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs