/** * Overloaded getter. * * @param $limit string SQL * @param $offset int * @param $filter string SQL * @param $sort string SQL * @param $join string SQL * @return ComponentSet */ public function Members($limit = "", $offset = "", $filter = "", $sort = "", $join = "") { $table = "Group_Members"; if ($filter) { $filter = is_array($filter) ? $filter : array($filter); } if (is_numeric($limit)) { if (is_numeric($offset)) { $limit = "{$offset}, {$limit}"; } else { $limit = "0, {$limit}"; } } else { $limit = ""; } // Get all of groups that this group contains $groupFamily = implode(", ", $this->collateFamilyIDs()); $filter[] = "`{$table}`.GroupID IN ({$groupFamily})"; $join .= " INNER JOIN `{$table}` ON `{$table}`.MemberID = `Member`.ID" . Convert::raw2sql($join); $result = singleton("Member")->instance_get($filter, $sort, $join, $limit, "ComponentSet"); if (!$result) { $result = new ComponentSet(); } $result->setComponentInfo("many-to-many", $this, "Group", $table, "Member"); foreach ($result as $item) { $item->GroupID = $this->ID; } return $result; }
/** * @todo Test removeMany() and addMany() on $many_many relationships */ function testManyManyRelationships() { $player1 = $this->objFromFixture('DataObjectTest_Player', 'player1'); $player2 = $this->objFromFixture('DataObjectTest_Player', 'player2'); $team1 = $this->objFromFixture('DataObjectTest_Team', 'team1'); $team2 = $this->objFromFixture('DataObjectTest_Team', 'team2'); // Test adding single DataObject by reference $player1->Teams()->add($team1); $player1->flushCache(); $compareTeams = new ComponentSet($team1); $this->assertEquals($player1->Teams()->column('ID'), $compareTeams->column('ID'), "Adding single record as DataObject to many_many"); // test removing single DataObject by reference $player1->Teams()->remove($team1); $player1->flushCache(); $compareTeams = new ComponentSet(); $this->assertEquals($player1->Teams()->column('ID'), $compareTeams->column('ID'), "Removing single record as DataObject from many_many"); // test adding single DataObject by ID $player1->Teams()->add($team1->ID); $player1->flushCache(); $compareTeams = new ComponentSet($team1); $this->assertEquals($player1->Teams()->column('ID'), $compareTeams->column('ID'), "Adding single record as ID to many_many"); // test removing single DataObject by ID $player1->Teams()->remove($team1->ID); $player1->flushCache(); $compareTeams = new ComponentSet(); $this->assertEquals($player1->Teams()->column('ID'), $compareTeams->column('ID'), "Removing single record as ID from many_many"); }
/** * Get a "many-to-many" map that holds for all members their group * memberships * * @return Member_GroupSet Returns a map holding for all members their * group memberships. */ public function Groups() { $groups = $this->getManyManyComponents("Groups"); $groupIDs = $groups->column(); $collatedGroups = array(); if ($groups) { foreach ($groups as $group) { $collatedGroups = array_merge((array) $collatedGroups, $group->collateAncestorIDs()); } } $table = "Group_Members"; if (count($collatedGroups) > 0) { $collatedGroups = implode(", ", array_unique($collatedGroups)); $unfilteredGroups = singleton('Group')->instance_get("\"Group\".\"ID\" IN ({$collatedGroups})", "\"Group\".\"ID\"", "", "", "Member_GroupSet"); $result = new ComponentSet(); // Only include groups where allowedIPAddress() returns true $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null; foreach ($unfilteredGroups as $group) { if ($group->allowedIPAddress($ip)) { $result->push($group); } } } else { $result = new Member_GroupSet(); } $result->setComponentInfo("many-to-many", $this, "Member", $table, "Group"); return $result; }
/** * Returns a many-to-many component, as a ComponentSet. * @param string $componentName Name of the many-many component * @return ComponentSet The set of components * * @todo Implement query-params */ public function getManyManyComponents($componentName, $filter = "", $sort = "", $join = "", $limit = "") { $sum = md5("{$filter}_{$sort}_{$join}_{$limit}"); if(isset($this->componentCache[$componentName . '_' . $sum]) && false != $this->componentCache[$componentName . '_' . $sum]) { return $this->componentCache[$componentName . '_' . $sum]; } list($parentClass, $componentClass, $parentField, $componentField, $table) = $this->many_many($componentName); // Join expression is done on SiteTree.ID even if we link to Page; it helps work around // database inconsistencies $componentBaseClass = ClassInfo::baseDataClass($componentClass); if($this->ID && is_numeric($this->ID)) { if($componentClass) { $query = $this->getManyManyComponentsQuery($componentName, $filter, $sort, $join, $limit); $records = $query->execute(); $result = $this->buildDataObjectSet($records, "ComponentSet", $query, $componentBaseClass); if($result) $result->parseQueryLimit($query); // for pagination support if(!$result) { $result = new ComponentSet(); } } } else { $result = new ComponentSet(); } $result->setComponentInfo("many-to-many", $this, $parentClass, $table, $componentClass); // If this record isn't in the database, then we want to hold onto this specific ComponentSet, // because it's the only copy of the data that we have. if(!$this->isInDB()) { $this->setComponent($componentName . '_' . $sum, $result); } return $result; }
/** * Returns a many-to-many component, as a ComponentSet. * @param string $componentName Name of the many-many component * @return ComponentSet The set of components * * @todo Implement query-params */ public function getManyManyComponents($componentName, $filter = "", $sort = "", $join = "", $limit = "") { $sum = md5("{$filter}_{$sort}_{$join}_{$limit}"); if (isset($this->componentCache[$componentName . '_' . $sum]) && false != $this->componentCache[$componentName . '_' . $sum]) { return $this->componentCache[$componentName . '_' . $sum]; } list($parentClass, $componentClass, $parentField, $componentField, $table) = $this->many_many($componentName); if ($this->ID && is_numeric($this->ID)) { if ($componentClass) { $componentObj = singleton($componentClass); // Join expression is done on SiteTree.ID even if we link to Page; it helps work around // database inconsistencies $componentBaseClass = ClassInfo::baseDataClass($componentClass); $query = $componentObj->extendedSQL("`{$table}`.{$parentField} = {$this->ID}", $sort, $limit, "INNER JOIN `{$table}` ON `{$table}`.{$componentField} = `{$componentBaseClass}`.ID"); array_unshift($query->select, "`{$table}`.*"); if ($filter) { $query->where[] = $filter; } if ($join) { $query->from[] = $join; } $records = $query->execute(); $result = $this->buildDataObjectSet($records, "ComponentSet", $query, $componentBaseClass); if (!$result) { $result = new ComponentSet(); } } } else { $result = new ComponentSet(); } $result->setComponentInfo("many-to-many", $this, $parentClass, $table, $componentClass); // If this record isn't in the database, then we want to hold onto this specific ComponentSet, // because it's the only copy of the data that we have. if (!$this->isInDB()) { $this->setComponent($componentName . '_' . $sum, $result); } return $result; }