Ok, here's what I did, and it seems to work:
Created QQAncestorNode.class.php in includes/qcodo/qform:
<?php
class QQAncestorNode extends QQBaseNode {
public function __construct($objParentNode) {
$this->objParentNode = $objParentNode;
if ($objParentNode) {
if (version_compare(phpversion(), '5.1.0') == -1)
$this->strRootTableName = $objParentNode->__get('_RootTableName');
else
$this->strRootTableName = $objParentNode->_RootTableName;
} else
$this->strRootTableName = $strName;
}
public function GetColumnAliasHelper(QQueryBuilder $objBuilder, $strBegin, $strEnd, $blnExpandSelection) {
// Are we at the Parent Node?
if (is_null($this->objParentNode))
// Yep -- Simply return the Parent Node Name
return $this->strName;
else {
// No -- First get the Parent Alias
$strParentAlias = $this->objParentNode->GetColumnAliasHelper($objBuilder, $strBegin, $strEnd, $blnExpandSelection);
// Next, Join the Appropriate Table
$objBuilder->AddJoinItem(sprintf('LEFT JOIN %s%s%s AS %s%s___ancestors_%s%s ON %s%s%s.%slft%s BETWEEN %s%s___ancestors_%s%s.%slft%s AND %s%s___ancestors_%s%s.%srgt%s',
$strBegin, $this->strTableName, $strEnd,
$strBegin, $strParentAlias, $this->strName, $strEnd,
$strBegin, $strParentAlias, $strEnd,
$strBegin, $strEnd,
$strBegin, $strParentAlias, $this->strName, $strEnd,
$strBegin, $strEnd,
$strBegin, $strParentAlias, $this->strName, $strEnd,
$strBegin, $strEnd));
// Next, Expand the Selection Fields for this Table (if applicable)
// TODO: If/when we add assn-based attributes, possibly add selectionfields addition here?
// if ($blnExpandSelection) {
// call_user_func(array($this->strClassName, 'GetSelectFields'), $objBuilder, $strParentAlias . '__' . $this->strName);
// }
// Return our Alias
return $strParentAlias . '___ancestors_' . $this->strName;
}
}
}
?>
Made sure that file was loaded, by adding this to prepend.inc.php:
<?php
QApplicationBase::$PreloadedClassFile['QQAncestorNode'] = __QCODO__ . '/qform/QQAncestorNode.class.php';
?>
Added a QQNodeGroupAncestors class in Group.class.php
<?php
class QQNodeGroupAncestors extends QQAncestorNode {
protected $strType = 'association';
protected $strName = 'groupancestors';
protected $strTableName = 'groups';
protected $strPrimaryKey = 'id';
protected $strClassName = 'Group';
public function __get($strName) {
switch ($strName) {
case 'Id':
return new QQNode('id', 'integer', $this);
case 'Name':
return new QQNode('name', 'string', $this);
case 'Lft':
return new QQNode('lft', 'integer', $this);
case 'Rgt':
return new QQNode('rgt', 'integer', $this);
case 'Level':
return new QQNode('level', 'integer', $this);
case 'UsersForGroupMember':
return new QQNodeGroupUsersForGroupMember($this);
case 'Ancestors':
return new QQNodeGroupAncestors($this);
case '_PrimaryKeyNode':
return new QQNode('id', 'integer', $this);
default:
try {
return parent::__get($strName);
} catch (QCallerException $objExc) {
$objExc->IncrementOffset();
throw $objExc;
}
}
}
}
?>
And finally, the annoying part, hacked GroupGen.class.php to include the Ancestor case in QQNodeGroup::__get
<?php
case 'Ancestors':
return new QQNodeGroupAncestors($this);
?>
What's annoying about that? It's overwritten on every codegen.
So now instead of the SQL I used in the first thread, I use:
QQ::Equal(QQN::User()->Group->Ancestors->Id, 1)
So, did I miss something, is there a way to clean that up, or did I stumble upon an acceptable way to add “ancestor” Nested Set support?
If so, I'll be going ahead and adding QQDescendantsNode, QQParentNode, and QQChildrenNode, as well as updating my templates to make “the codegen'd class be QQNodeGroupBase with QQNodeGroup defined in Group.class.php instead”.