Index: tags/extensions/SemanticInternalObjects/REL_0_1/SemanticInternalObjects.php |
— | — | @@ -0,0 +1,54 @@ |
| 2 | +<?php
|
| 3 | +/**
|
| 4 | + * Initialization file for SemanticInternalObjects
|
| 5 | + *
|
| 6 | + * @file
|
| 7 | + * @ingroup SemanticInternalObjects
|
| 8 | + * @author Yaron Koren
|
| 9 | + */
|
| 10 | +
|
| 11 | +if ( !defined( 'MEDIAWIKI' ) ) die();
|
| 12 | +
|
| 13 | +define( 'SIO_VERSION', '0.1' );
|
| 14 | +
|
| 15 | +$wgExtensionCredits['parserhook'][] = array(
|
| 16 | + 'name' => 'Semantic Internal Objects',
|
| 17 | + 'version' => SIO_VERSION,
|
| 18 | + 'author' => 'Yaron Koren',
|
| 19 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:Semantic_Internal_Objects',
|
| 20 | + 'description' => 'Setting of internal objects in Semantic MediaWiki',
|
| 21 | + 'descriptionmsg' => 'semanticinternalobjects-desc',
|
| 22 | +);
|
| 23 | +
|
| 24 | +$wgExtensionFunctions[] = 'siofParserFunctions';
|
| 25 | +$wgHooks['LanguageGetMagic'][] = 'siofLanguageGetMagic';
|
| 26 | +$wgHooks['smwDeleteSemanticData'][] = 'SIOHandler::updateData';
|
| 27 | +
|
| 28 | +$siogIP = $IP . '/extensions/SemanticInternalObjects';
|
| 29 | +$wgExtensionMessagesFiles['SemanticInternalObjects'] = $siogIP . '/SemanticInternalObjects.i18n.php';
|
| 30 | +$wgAutoloadClasses['SIOHandler'] = $siogIP . '/SemanticInternalObjects_body.php';
|
| 31 | +
|
| 32 | +function siofParserFunctions() {
|
| 33 | + global $wgHooks, $wgParser;
|
| 34 | + if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) {
|
| 35 | + $wgHooks['ParserFirstCallInit'][] = 'siofRegisterParserFunctions';
|
| 36 | + } else {
|
| 37 | + if ( class_exists( 'StubObject' ) && !StubObject::isRealObject( $wgParser ) ) {
|
| 38 | + $wgParser->_unstub();
|
| 39 | + }
|
| 40 | + siofRegisterParserFunctions( $wgParser );
|
| 41 | + }
|
| 42 | +}
|
| 43 | +
|
| 44 | +function siofRegisterParserFunctions( &$parser ) {
|
| 45 | + $parser->setFunctionHook( 'set_internal', array( 'SIOHandler', 'doSetInternal' ) );
|
| 46 | + return true; // always return true, in order not to stop MW's hook processing!
|
| 47 | +}
|
| 48 | +
|
| 49 | +function siofLanguageGetMagic( &$magicWords, $langCode = "en" ) {
|
| 50 | + switch ( $langCode ) {
|
| 51 | + default:
|
| 52 | + $magicWords['set_internal'] = array ( 0, 'set_internal' );
|
| 53 | + }
|
| 54 | + return true;
|
| 55 | +}
|
Index: tags/extensions/SemanticInternalObjects/REL_0_1/README |
— | — | @@ -0,0 +1,85 @@ |
| 2 | +Semantic Internal Objects Extension |
| 3 | + |
| 4 | + Version 0.1 |
| 5 | + Yaron Koren |
| 6 | + |
| 7 | +This is free software licensed under the GNU General Public License. Please |
| 8 | +see http://www.gnu.org/copyleft/gpl.html for further details, including the |
| 9 | +full text and terms of the license. |
| 10 | + |
| 11 | +== Overview == |
| 12 | + |
| 13 | +Semantic Internal Objects is an extension to MediaWiki that defines a |
| 14 | +parser function, '#set_internal', that is used to define "internal objects" |
| 15 | +within the Semantic MediaWiki system. There are complex types of |
| 16 | +information sometimes known as 'n-ary relations' that involve more than one |
| 17 | +data value associated together. A simple example is in a cooking recipe; a |
| 18 | +recipe may call for 1 cup of flour, and the values "1", "cup" and "flour" |
| 19 | +must be encoded together; by themselves, the values are not meaningful (the |
| 20 | +third value has meaning, though not all of the meaning it could have). Such |
| 21 | +information can be stored already in SMW using multi-valued properties, |
| 22 | +though this approach is not flexible and currently leads to querying problems. |
| 23 | +Instead, #set_internal can be used to define "internal objects" within a page, |
| 24 | +which can then be queried as normal SMW pages would; a row of a recipe would |
| 25 | +be a good example of data that could be defined using #set_internal. |
| 26 | + |
| 27 | +The syntax of #set_internal is as follows: |
| 28 | + |
| 29 | +{{#set_internal:object_to_page_property |
| 30 | +|property1=value1 |
| 31 | +|property2=value2 |
| 32 | +... |
| 33 | +}} |
| 34 | + |
| 35 | +A sample call to #set_internal would be: |
| 36 | + |
| 37 | +{{#set_internal:Has recipe |
| 38 | +|Has quantity=1 |
| 39 | +|Has unit=cup |
| 40 | +|Has ingredient=flour |
| 41 | +}} |
| 42 | + |
| 43 | +This call would be placed in a page for a recipe, and it would define an object |
| 44 | +that had an automatically-generated name; if it were in a page called "Carrot |
| 45 | +cake", for instance, the object would be called "Carrot cake#1". If that page |
| 46 | +had subsequent calls to #set_internal, the objects that those calls generated |
| 47 | +would be called "Carrot cake#2", "Carrot cake#3", etc. |
| 48 | + |
| 49 | +It should be noted that #set_internal does not display anything to the screen; |
| 50 | +display of the values has to be handled separately (this can be done easily |
| 51 | +if the function is called from a template). |
| 52 | + |
| 53 | +Internal objects, once stored, can be queried as if they were wiki pages. So |
| 54 | +the following query would show a table of all the recipes that contain more |
| 55 | +than 1/2 a cup of flour, and the number of cups they contain: |
| 56 | + |
| 57 | +{{#ask:[[Has recipe::+]][[Has ingredient::flour]][[Has unit::cup]][[Has quantity::>.5]] |
| 58 | +|mainlabel=- |
| 59 | +|? Has recipe |
| 60 | +|? Has quantity |
| 61 | +}} |
| 62 | + |
| 63 | +Note the "mainlabel=-" parameter in the query: that hides the names of the |
| 64 | +internal objects from users, since those names are meaningless. |
| 65 | + |
| 66 | +For more information, see the extension homepage at: |
| 67 | +http://www.mediawiki.org/wiki/Extension:Semantic_Internal_Objects |
| 68 | + |
| 69 | +== Requirements == |
| 70 | + |
| 71 | +This version of the Semantic Internal Objects extension requires MediaWiki 1.8 |
| 72 | +or higher and Semantic MediaWiki 1.4 or higher. |
| 73 | + |
| 74 | +== Installation == |
| 75 | + |
| 76 | +To install the extension, place the entire 'SemanticInternalObjects' directory |
| 77 | +within your MediaWiki 'extensions' directory, then add the following |
| 78 | +line to your 'LocalSettings.php' file: |
| 79 | + |
| 80 | + require_once( "$IP/extensions/SemanticInternalObjects/SemanticInternalObjects.php" ); |
| 81 | + |
| 82 | +== Contact == |
| 83 | + |
| 84 | +Comments, questions, suggestions and bug reports are welcome, and can |
| 85 | +be placed on the Talk page for the extension, or sent to Yaron at |
| 86 | +yaron57@gmail.com. |
Index: tags/extensions/SemanticInternalObjects/REL_0_1/SemanticInternalObjects.i18n.magic.php |
— | — | @@ -0,0 +1,7 @@ |
| 2 | +<?php
|
| 3 | +
|
| 4 | +$magicWords = array();
|
| 5 | +
|
| 6 | +$magicWords['en'] = array(
|
| 7 | + 'set_internal' => array( 0, 'set_internal' ),
|
| 8 | +);
|
Index: tags/extensions/SemanticInternalObjects/REL_0_1/SemanticInternalObjects_body.php |
— | — | @@ -0,0 +1,155 @@ |
| 2 | +<?php
|
| 3 | +/**
|
| 4 | + * @author Yaron Koren
|
| 5 | + */
|
| 6 | +
|
| 7 | +if ( !defined( 'MEDIAWIKI' ) ) die();
|
| 8 | +
|
| 9 | +/**
|
| 10 | + * Class that holds information on a single internal object, including all
|
| 11 | + * its properties.
|
| 12 | + */
|
| 13 | +class SIOInternalObject {
|
| 14 | + var $main_title;
|
| 15 | + var $index;
|
| 16 | + var $property_value_pairs;
|
| 17 | +
|
| 18 | + public function SIOInternalObject( $main_title, $index ) {
|
| 19 | + $this->main_title = $main_title;
|
| 20 | + $this->index = $index;
|
| 21 | + $this->property_value_pairs = array();
|
| 22 | + }
|
| 23 | +
|
| 24 | + public function addPropertyAndValue( $prop_name, $value ) {
|
| 25 | + $property = SMWPropertyValue::makeUserProperty( $prop_name );
|
| 26 | + $data_value = SMWDataValueFactory::newPropertyObjectValue( $property, $value );
|
| 27 | + if ( $data_value->isValid() ) {
|
| 28 | + $this->property_value_pairs[] = array( $property, $data_value );
|
| 29 | + } // else - show an error message?
|
| 30 | + }
|
| 31 | +
|
| 32 | + public function getName() {
|
| 33 | + return $this->main_title->getDBkey() . '#' . $this->index;
|
| 34 | + }
|
| 35 | +}
|
| 36 | +
|
| 37 | +/**
|
| 38 | + * Class for all database-related actions.
|
| 39 | + * This class exists mostly because SMWSQLStore2's functions makeSMWPageID()
|
| 40 | + * and makeSMWPropertyID(), which are needed for the DB access, are both
|
| 41 | + * protected, and thus can't be accessed externally.
|
| 42 | + */
|
| 43 | +class SIOSQLStore extends SMWSQLStore2 {
|
| 44 | + function deletePageObjects( $page_name, $namespace ) {
|
| 45 | + $ids = array();
|
| 46 | +
|
| 47 | + $iw = '';
|
| 48 | + $db =& wfGetDB( DB_SLAVE );
|
| 49 | + $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() );
|
| 50 | + while ( $row = $db->fetchObject( $res ) ) {
|
| 51 | + $ids[] = $row->smw_id;
|
| 52 | + }
|
| 53 | + foreach ( $ids as $id ) {
|
| 54 | + $db->delete( 'smw_rels2', array( 's_id' => $id ), 'SIO::updateData::Rels2' );
|
| 55 | + $db->delete( 'smw_rels2', array( 'o_id' => $id ), 'SIO::updateData::Rels2' );
|
| 56 | + $db->delete( 'smw_atts2', array( 's_id' => $id ), 'SMW::deleteSubject::Atts2' );
|
| 57 | + }
|
| 58 | + }
|
| 59 | +
|
| 60 | + function storeAllInfo( $main_page_name, $namespace, $internal_object ) {
|
| 61 | + $main_page_id = $this->makeSMWPageID( $main_page_name, $namespace, '' );
|
| 62 | + $io_id = $this->makeSMWPageID( $internal_object->getName(), $namespace, '' );
|
| 63 | + $up_rels2 = array();
|
| 64 | + $up_atts2 = array();
|
| 65 | + // set all the properties pointing from this internal object
|
| 66 | + foreach ( $internal_object->property_value_pairs as $property_value_pair ) {
|
| 67 | + list( $property, $value ) = $property_value_pair;
|
| 68 | + $mode = SMWSQLStore2::getStorageMode( $property->getPropertyTypeID() );
|
| 69 | + switch ( $mode ) {
|
| 70 | + case SMW_SQL2_RELS2:
|
| 71 | + $up_rels2[] = array(
|
| 72 | + 's_id' => $io_id,
|
| 73 | + 'p_id' => $this->makeSMWPropertyID( $property ),
|
| 74 | + 'o_id' => $this->makeSMWPageID( $value->getDBkey(), $value->getNamespace(), $value->getInterwiki() )
|
| 75 | + );
|
| 76 | + break;
|
| 77 | + case SMW_SQL2_ATTS2:
|
| 78 | + $keys = $value->getDBkeys();
|
| 79 | + $up_atts2[] = array(
|
| 80 | + 's_id' => $io_id,
|
| 81 | + 'p_id' => $this->makeSMWPropertyID( $property ),
|
| 82 | + 'value_unit' => $value->getUnit(),
|
| 83 | + 'value_xsd' => $keys[0],
|
| 84 | + 'value_num' => $value->getNumericValue()
|
| 85 | + );
|
| 86 | + break;
|
| 87 | + }
|
| 88 | + }
|
| 89 | +
|
| 90 | + // now save everything to the database
|
| 91 | + $db =& wfGetDB( DB_MASTER );
|
| 92 | + if ( count( $up_rels2 ) > 0 ) {
|
| 93 | + $db->insert( 'smw_rels2', $up_rels2, 'SMW::updateRel2Data' );
|
| 94 | + }
|
| 95 | + if ( count( $up_atts2 ) > 0 ) {
|
| 96 | + $db->insert( 'smw_atts2', $up_atts2, 'SMW::updateAtt2Data' );
|
| 97 | + }
|
| 98 | + }
|
| 99 | +}
|
| 100 | +
|
| 101 | +/**
|
| 102 | + * Class for hook functions for creating and storing information
|
| 103 | + */
|
| 104 | +class SIOHandler {
|
| 105 | +
|
| 106 | + static $cur_page_name = '';
|
| 107 | + static $cur_page_namespace = 0;
|
| 108 | + static $internal_object_index = 1;
|
| 109 | + static $internal_objects = array();
|
| 110 | +
|
| 111 | + public static function doSetInternal( &$parser ) {
|
| 112 | + $main_page_name = $parser->getTitle()->getDBKey();
|
| 113 | + $main_page_namespace = $parser->getTitle()->getNamespace();
|
| 114 | + if ( $main_page_name == self::$cur_page_name &&
|
| 115 | + $main_page_namespace == self::$cur_page_namespace ) {
|
| 116 | + self::$internal_object_index++;
|
| 117 | + } else {
|
| 118 | + self::$cur_page_name = $main_page_name;
|
| 119 | + self::$cur_page_namespace = $main_page_namespace;
|
| 120 | + self::$internal_object_index = 1;
|
| 121 | + }
|
| 122 | + $cur_object_num = self::$internal_object_index;
|
| 123 | + $params = func_get_args();
|
| 124 | + array_shift( $params ); // we already know the $parser...
|
| 125 | + $internal_object = new SIOInternalObject( $parser->getTitle(), $cur_object_num );
|
| 126 | + $obj_to_page_prop_name = array_shift( $params );
|
| 127 | + $internal_object->addPropertyAndValue( $obj_to_page_prop_name, $parser->getTitle() );
|
| 128 | + foreach ( $params as $param ) {
|
| 129 | + $parts = explode( "=", trim( $param ) );
|
| 130 | + if ( count( $parts ) == 2 ) {
|
| 131 | + $key = $parts[0];
|
| 132 | + $value = $parts[1];
|
| 133 | + $internal_object->addPropertyAndValue( $key, $value );
|
| 134 | + }
|
| 135 | + }
|
| 136 | + self::$internal_objects[] = $internal_object;
|
| 137 | + }
|
| 138 | +
|
| 139 | + public static function updateData( $subject ) {
|
| 140 | + $sio_sql_store = new SIOSQLStore();
|
| 141 | + // Find all "pages" in the SMW IDs table that are internal
|
| 142 | + // objects for this page, and delete their properties from
|
| 143 | + // the SMW tables.
|
| 144 | + // Then save the current contents of the $internal_objects
|
| 145 | + // array.
|
| 146 | + $page_name = $subject->getDBKey();
|
| 147 | + $namespace = $subject->getNamespace();
|
| 148 | + $sio_sql_store->deletePageObjects( $page_name, $namespace );
|
| 149 | + foreach ( self::$internal_objects as $internal_object ) {
|
| 150 | + $sio_sql_store->storeAllInfo( $page_name, $namespace, $internal_object );
|
| 151 | + }
|
| 152 | + self::$internal_objects = array();
|
| 153 | + return true;
|
| 154 | + }
|
| 155 | +
|
| 156 | +}
|
Index: tags/extensions/SemanticInternalObjects/REL_0_1/SemanticInternalObjects.i18n.php |
— | — | @@ -0,0 +1,28 @@ |
| 2 | +<?php
|
| 3 | +/**
|
| 4 | + * Internationalization file for Semantic Internal Objects
|
| 5 | + *
|
| 6 | + * @file
|
| 7 | + * @ingroup Language
|
| 8 | + * @ingroup I18n
|
| 9 | + * @ingroup SemanticInternalObjects
|
| 10 | + */
|
| 11 | +
|
| 12 | +// FIXME: Can be enabled when new style magic words are used (introduced in r52503)
|
| 13 | +// require_once( dirname( __FILE__ ) . '/SemanticInternalObjects.i18n.magic.php' );
|
| 14 | +
|
| 15 | +$messages = array();
|
| 16 | +
|
| 17 | +/** English
|
| 18 | + * @author Yaron Koren
|
| 19 | + */
|
| 20 | +$messages['en'] = array(
|
| 21 | + 'semanticinternalobjects-desc' => 'Setting of internal objects in Semantic MediaWiki',
|
| 22 | +);
|
| 23 | +
|
| 24 | +/** Message documentation (Message documentation)
|
| 25 | + * @author Yaron Koren
|
| 26 | + */
|
| 27 | +$messages['qqq'] = array(
|
| 28 | + 'semanticinternalobjects-desc' => '{{desc}}',
|
| 29 | +);
|