Fz-29 has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/359793 )

Change subject: Add Hierarchy Structure Table creation for hierarchy field
......................................................................

Add Hierarchy Structure Table creation for hierarchy field

This commit adds the functionality to create hierarchy structure table with 
columns (_value, _left, _right) and also populated from the hierarchical 
enumeration provided using "*".

Change-Id: Idad419eb4dc78c70eb2efc69cccc77a1f3a5ba4b
---
M Cargo.php
M CargoFieldDescription.php
A CargoHierarchy.php
M CargoUtils.php
M extension.json
M parserfunctions/CargoDeclare.php
6 files changed, 147 insertions(+), 28 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Cargo 
refs/changes/93/359793/1

diff --git a/Cargo.php b/Cargo.php
index 02249f3..301ae1b 100644
--- a/Cargo.php
+++ b/Cargo.php
@@ -82,6 +82,7 @@
 $wgAutoloadClasses['CargoUtils'] = $dir . '/CargoUtils.php';
 $wgAutoloadClasses['CargoFieldDescription'] = $dir . 
'/CargoFieldDescription.php';
 $wgAutoloadClasses['CargoTableSchema'] = $dir . '/CargoTableSchema.php';
+$wgAutoloadClasses['CargoHierarchy'] = $dir . '/CargoHierarchy.php';
 $wgAutoloadClasses['CargoDeclare'] = $dir . 
'/parserfunctions/CargoDeclare.php';
 $wgAutoloadClasses['CargoAttach'] = $dir . '/parserfunctions/CargoAttach.php';
 $wgAutoloadClasses['CargoStore'] = $dir . '/parserfunctions/CargoStore.php';
diff --git a/CargoFieldDescription.php b/CargoFieldDescription.php
index 2cc3202..727136c 100644
--- a/CargoFieldDescription.php
+++ b/CargoFieldDescription.php
@@ -50,7 +50,7 @@
                                if ( count( $extraParamParts ) == 1 ) {
                                        $paramKey = trim( $extraParamParts[0] );
                                        if ( $paramKey == 'hierarchy' ) {
-                                               $mIsHierarchy = true;
+                                               $fieldDescription->mIsHierarchy 
= true;
                                        }
                                        
$fieldDescription->mOtherParams[$paramKey] = true;
                                } else {
diff --git a/CargoHierarchy.php b/CargoHierarchy.php
new file mode 100644
index 0000000..9b23bcf
--- /dev/null
+++ b/CargoHierarchy.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * CargoHierarchy - holds the tree for hierarchy inorder to implement Nested 
Set model for
+ * efficient storage and query of hierarchy fields.
+ *
+ * @author Feroz Ahmad
+ * @ingroup Cargo
+ */
+
+class CargoHierarchy {
+    public $mTitle;
+    public $mChildren;
+    public $mLeft = 0;
+    public $mRight = 0;
+
+       function __construct( $curTitle ) {
+               $this->mTitle = $curTitle;
+               $this->mChildren = array();
+       }
+
+       function addChild( $child ) {
+               $this->mChildren[] = $child;
+       }
+
+       /**
+        * Turn a manually-created "structure", defined as a bulleted list
+        * in wikitext, into a tree. This code has been borrowed from PFTree 
class
+     * of PageForms Extension
+        */
+       public static function newFromWikiText( $wikitext ) {
+        // __psuedo_root__ node is added so that multiple nodes can be added 
in the first level
+        $fullTree = new CargoHierarchy( '__psuedo_root__' );
+               $lines = explode( "\n", $wikitext );
+               foreach ( $lines as $line ) {
+                       $numBullets = 0;
+                       for ( $i = 0; $i < strlen( $line ) && $line[$i] == '*'; 
$i++ ) {
+                               $numBullets++;
+                       }
+                       if ( $numBullets == 0 ) continue;
+                       $lineText = trim( substr( $line, $numBullets ) );
+                       $curParentNode = $fullTree->getLastNodeForLevel( 
$numBullets );
+                       $curParentNode->addChild( new CargoHierarchy( $lineText 
) );
+               }
+               return $fullTree;
+       }
+
+       function getLastNodeForLevel( $level ) {
+               if ( $level <= 1 || count( $this->mChildren ) == 0 ) {
+                       return $this;
+               }
+               $lastNodeOnCurLevel = end( $this->mChildren );
+               return $lastNodeOnCurLevel->getLastNodeForLevel( $level - 1 );
+       }
+
+    function generateHierarchyStructureTableData() {
+        $tableData = array();
+        $this->computeLeftRight();
+        //Preorder traversal using Stack data structure
+        $stack = new SplStack();
+        $stack->push( $this );
+        while( !$stack->isEmpty() ) {
+            $node = $stack->pop();
+            $row = array();
+            $row['_value'] = $node->mTitle;
+            $row['_left'] = $node->mLeft;
+            $row['_right'] = $node->mRight; 
+            $tableData[] = $row;
+            foreach( array_reverse( $node->mChildren ) as $child ) {
+                $stack->push( $child );
+            }            
+        }
+        return $tableData;   
+    }
+
+    private function __computeLeftRight( &$counter ) {
+        $this->mLeft = $counter;
+        $counter += 1;
+        //visit mChildren
+        foreach( $this->mChildren as $child ) {
+            $child->__computeLeftRight( $counter );
+        }
+        $this->mRight = $counter;
+        $counter += 1;
+    }
+
+    function computeLeftRight() {
+        $counter = 1;
+        $this->__computeLeftRight( $counter );
+    }
+}
\ No newline at end of file
diff --git a/CargoUtils.php b/CargoUtils.php
index 438e3a6..ece6c06 100644
--- a/CargoUtils.php
+++ b/CargoUtils.php
@@ -686,34 +686,58 @@
                // if there are any.
                $fieldTableNames = array();
                foreach ( $tableSchema->mFieldDescriptions as $fieldName => 
$fieldDescription ) {
-                       if ( !$fieldDescription->mIsList ) {
-                               continue;
+                       if ( $fieldDescription->mIsList ) {
+                               // The double underscore in this table name 
should
+                               // prevent anyone from giving this name to a 
"real"
+                               // table.
+                               $fieldTableName = $tableName . '__' . 
$fieldName;
+                               $cdb->dropTable( $fieldTableName );
+                               $fieldType = $fieldDescription->mType;
+                               $createSQL = "CREATE TABLE " .
+                                       $cdb->tableName( $fieldTableName ) . ' 
( ' .
+                                       $cdb->addIdentifierQuotes( '_rowID' ) . 
" $intTypeString, ";
+                               if ( $fieldType == 'Coordinates' ) {
+                                       $floatTypeString = 
self::fieldTypeToSQLType( 'Float', $dbType );
+                                       $createSQL .= 
$cdb->addIdentifierQuotes( '_value' ) . " $floatTypeString, ";
+                                       $createSQL .= 
$cdb->addIdentifierQuotes( '_lat' ) . " $floatTypeString, ";
+                                       $createSQL .= 
$cdb->addIdentifierQuotes( '_lon' ) . " $floatTypeString";
+                               } else {
+                                       $createSQL .= 
$cdb->addIdentifierQuotes( '_value' ) . ' ' . self::fieldTypeToSQLType( 
$fieldType, $dbType, $size );
+                               }
+                               $createSQL .= ' )';
+                               $cdb->query( $createSQL );
+                               $createIndexSQL = 'CREATE INDEX ' .
+                                       $cdb->addIdentifierQuotes( 
"row_id_$fieldTableName" ) . ' ON ' .
+                                       $cdb->tableName( $fieldTableName ) .
+                                       ' (' . $cdb->addIdentifierQuotes( 
'_rowID' ) . ')';
+                               $cdb->query( $createIndexSQL );
+                               $fieldTableNames[] = $tableName . '__' . 
$fieldName;
                        }
-                       // The double underscore in this table name should
-                       // prevent anyone from giving this name to a "real"
-                       // table.
-                       $fieldTableName = $tableName . '__' . $fieldName;
-                       $cdb->dropTable( $fieldTableName );
-                       $fieldType = $fieldDescription->mType;
-                       $createSQL = "CREATE TABLE " .
-                               $cdb->tableName( $fieldTableName ) . ' ( ' .
-                               $cdb->addIdentifierQuotes( '_rowID' ) . " 
$intTypeString, ";
-                       if ( $fieldType == 'Coordinates' ) {
-                               $floatTypeString = self::fieldTypeToSQLType( 
'Float', $dbType );
-                               $createSQL .= $cdb->addIdentifierQuotes( 
'_value' ) . " $floatTypeString, ";
-                               $createSQL .= $cdb->addIdentifierQuotes( '_lat' 
) . " $floatTypeString, ";
-                               $createSQL .= $cdb->addIdentifierQuotes( '_lon' 
) . " $floatTypeString";
-                       } else {
-                               $createSQL .= $cdb->addIdentifierQuotes( 
'_value' ) . ' ' . self::fieldTypeToSQLType( $fieldType, $dbType, $size );
+                       if ( $fieldDescription->mIsHierarchy ) {
+                               $fieldTableName = $tableName . '__' . 
$fieldName . '__hierarchy';
+                               $cdb->dropTable( $fieldTableName );
+                               $fieldType = $fieldDescription->mType;
+                               $createSQL = "CREATE TABLE " . $cdb->tableName( 
$fieldTableName ) . ' ( ' ;
+                               $createSQL .= $cdb->addIdentifierQuotes( 
'_value' ) . ' ' . self::fieldTypeToSQLType( $fieldType, $dbType, $size ) . ", 
";
+                               $createSQL .= $cdb->addIdentifierQuotes( 
'_left' ) . " $intTypeString, ";
+                               $createSQL .= $cdb->addIdentifierQuotes( 
'_right' ) . " $intTypeString ";
+                               $createSQL .= ' )';
+                               $cdb->query( $createSQL );
+                               $createIndexSQL = 'CREATE INDEX ' . 
$cdb->addIdentifierQuotes( "nested_set_$fieldTableName" ) . ' ON ' ;
+                               $createIndexSQL .= $cdb->tableName( 
$fieldTableName ) . ' (' ; 
+                               $createIndexSQL .= $cdb->addIdentifierQuotes( 
'_value' ) . ', ';
+                               $createIndexSQL .= $cdb->addIdentifierQuotes( 
'_left' ) . ', ';
+                               $createIndexSQL .= $cdb->addIdentifierQuotes( 
'_right' ) . ')';
+                               $cdb->query( $createIndexSQL );
+                               $fieldTableNames[] = $fieldTableName;
+                               //Insert Hierarchy Structure
+                               $allowedValuesWikitext = 
$fieldDescription->mAllowedValues[0];
+                               $hierarchyTree = 
CargoHierarchy::newFromWikiText( $allowedValuesWikitext );
+                               $hierarchyStructureData = 
$hierarchyTree->generateHierarchyStructureTableData();
+                               foreach( $hierarchyStructureData as $entry ) {
+                                       $cdb->insert( $fieldTableName, $entry );
+                               }
                        }
-                       $createSQL .= ' )';
-                       $cdb->query( $createSQL );
-                       $createIndexSQL = 'CREATE INDEX ' .
-                               $cdb->addIdentifierQuotes( 
'row_id_$fieldTableName' ) . ' ON ' .
-                               $cdb->tableName( $fieldTableName ) .
-                               ' (' . $cdb->addIdentifierQuotes( '_rowID' ) . 
')';
-                       $cdb->query( $createIndexSQL );
-                       $fieldTableNames[] = $tableName . '__' . $fieldName;
                }
 
                // And create a helper table holding all the files stored in
@@ -741,7 +765,7 @@
                        'main_table' => $tableName,
                        'field_tables' => serialize( $fieldTableNames ),
                        'table_schema' => $tableSchemaString
-               ) );
+               ) );    
        }
 
        public static function fullTextMatchSQL( $cdb, $tableName, $fieldName, 
$searchTerm ) {
diff --git a/extension.json b/extension.json
index 2d3240a..bb9ec75 100755
--- a/extension.json
+++ b/extension.json
@@ -45,6 +45,7 @@
                "CargoUtils": "CargoUtils.php",
                "CargoFieldDescription": "CargoFieldDescription.php",
                "CargoTableSchema": "CargoTableSchema.php",
+               "CargoHierarchy": "CargoHierarchy.php",
                "CargoDeclare": "parserfunctions/CargoDeclare.php",
                "CargoAttach": "parserfunctions/CargoAttach.php",
                "CargoStore": "parserfunctions/CargoStore.php",
diff --git a/parserfunctions/CargoDeclare.php b/parserfunctions/CargoDeclare.php
index ecbcb30..9f3eea5 100644
--- a/parserfunctions/CargoDeclare.php
+++ b/parserfunctions/CargoDeclare.php
@@ -73,6 +73,9 @@
                                if ( $fieldDescription == null ) {
                                        return CargoUtils::formatError( "Error: 
could not parse type for field \"$fieldName\"." );
                                }
+                               if ( $fieldDescription->mIsHierarchy == true && 
$fieldDescription->mType == 'Coordinates' ) {
+                                       return CargoUtils::formatError( "Error: 
Hierarchy enumeration field cannot be created for $fieldDescription->mType 
type." );
+                               }
                                $tableSchema->mFieldDescriptions[$fieldName] = 
$fieldDescription;
                        }
                }

-- 
To view, visit https://gerrit.wikimedia.org/r/359793
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Idad419eb4dc78c70eb2efc69cccc77a1f3a5ba4b
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Cargo
Gerrit-Branch: master
Gerrit-Owner: Fz-29 <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to