1 <?php
2
3 class ManyManyDataObjectManager extends HasManyDataObjectManager {
4
5 protected static $only_related;
6 private $manyManyParentClass;
7 public $RelationType = "ManyMany";
8 public $itemClass = 'ManyManyDataObjectManager_Item';
9 protected $OnlyRelated = false;
10 protected $sortableOwner;
11
12 public static function set_only_related($bool) {
13 self::$only_related = $bool;
14 }
15
16 17 18 19
20 function __construct($controller, $name, $sourceClass, $fieldList = null, $detailFormFields = null, $sourceFilter = "", $sourceSort = "Created DESC", $sourceJoin = "") {
21
22 parent::__construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin);
23 $manyManyTable = false;
24 $classes = array_reverse(ClassInfo::ancestry($this->controllerClass()));
25 foreach($classes as $class) {
26 if($class != "Object") {
27 $singleton = singleton($class);
28 $manyManyRelations = $singleton->uninherited('many_many', true);
29 if(isset($manyManyRelations) && array_key_exists($this->name, $manyManyRelations)) {
30 $this->manyManyParentClass = $class;
31 $manyManyTable = $class . '_' . $this->name;
32 break;
33 }
34
35 $belongsManyManyRelations = $singleton->uninherited( 'belongs_many_many', true );
36 if( isset( $belongsManyManyRelations ) && array_key_exists( $this->name, $belongsManyManyRelations ) ) {
37 $this->manyManyParentClass = $class;
38
39
40 $manyManyClass = $belongsManyManyRelations[$this->name];
41 $manyManyRelations = singleton($manyManyClass)->uninherited('many_many', true);
42 foreach($manyManyRelations as $manyManyRelationship => $manyManyChildClass)
43 if ($manyManyChildClass == $class)
44 break;
45
46 $manyManyTable = $manyManyClass . '_' . $manyManyRelationship;
47 break;
48 }
49 }
50 }
51 if(!$manyManyTable) user_error("I could not find the relation $this->name in " . $this->controllerClass() . " or any of its ancestors.",E_USER_WARNING);
52 $tableClasses = ClassInfo::dataClassesFor($this->sourceClass);
53 $source = array_shift($tableClasses);
54 $sourceField = $this->sourceClass;
55 if($this->manyManyParentClass == $sourceField)
56 $sourceField = 'Child';
57 $parentID = $this->controller->ID;
58
59 $this->sourceJoin .= " LEFT JOIN `$manyManyTable` ON (`$source`.`ID` = `{$manyManyTable}`.`{$sourceField}ID` AND `{$manyManyTable}`.`{$this->manyManyParentClass}ID` = '$parentID')";
60
61 $this->joinField = 'Checked';
62 if(isset($_REQUEST['ctf'][$this->Name()]['only_related']))
63 $this->OnlyRelated = $_REQUEST['ctf'][$this->Name()]['only_related'];
64
65 $this->addPermission('only_related');
66
67 if($this->ShowAll() && SortableDataObject::is_sortable_many_many($this->sourceClass()))
68 $this->OnlyRelated = '1';
69
70 }
71
72 public function setParentClass($class) {
73 parent::setParentClass($class);
74 $this->joinField = "Checked";
75 }
76
77
78 protected function loadSort() {
79
80 if($this->ShowAll())
81 $this->setPageSize(999);
82
83 if(SortableDataObject::is_sortable_many_many($this->sourceClass(), $this->manyManyParentClass)) {
84 list($parentClass, $componentClass, $parentField, $componentField, $table) = singleton($this->controllerClass())->many_many($this->Name());
85 $sort_column = "`$table`.SortOrder";
86 if(!isset($_REQUEST['ctf'][$this->Name()]['sort']) || $_REQUEST['ctf'][$this->Name()]['sort'] == $sort_column) {
87 $this->sort = $sort_column;
88 $this->sourceSort = "$sort_column " . SortableDataObject::$sort_dir;
89 }
90 }
91 elseif($this->Sortable() && (!isset($_REQUEST['ctf'][$this->Name()]['sort']) || $_REQUEST['ctf'][$this->Name()]['sort'] == "SortOrder")) {
92 $this->sort = "SortOrder";
93 $this->sourceSort = "SortOrder " . SortableDataObject::$sort_dir;
94 }
95
96 elseif(isset($_REQUEST['ctf'][$this->Name()]['sort']))
97 $this->sourceSort = $_REQUEST['ctf'][$this->Name()]['sort'] . " " . $this->sort_dir;
98
99 }
100
101
102 public function setOnlyRelated($bool) {
103 if(!isset($_REQUEST['ctf'][$this->Name()]['only_related']))
104 $this->OnlyRelated = $bool;
105 }
106
107 public function OnlyRelated() {
108 return self::$only_related !== null ? self::$only_related : $this->OnlyRelated;
109 }
110
111 public function getQueryString($params = array()) {
112 $only_related = isset($params['only_related'])? $params['only_related'] : $this->OnlyRelated();
113 return parent::getQueryString($params)."&ctf[{$this->Name()}][only_related]={$only_related}";
114 }
115
116 public function OnlyRelatedLink() {
117 return $this->RelativeLink(array('only_related' => '1'));
118 }
119
120 public function AllRecordsLink() {
121 return $this->RelativeLink(array('only_related' => '0'));
122 }
123
124
125 function getQuery($limitClause = null) {
126 if($this->customQuery) {
127 $query = $this->customQuery;
128 $query->select[] = "{$this->sourceClass}.ID AS ID";
129 $query->select[] = "{$this->sourceClass}.ClassName AS ClassName";
130 $query->select[] = "{$this->sourceClass}.ClassName AS RecordClassName";
131 }
132 else {
133 $query = singleton($this->sourceClass)->extendedSQL($this->sourceFilter, $this->sourceSort, $limitClause, $this->sourceJoin);
134
135
136
137 $SNG = singleton($this->sourceClass);
138 foreach($this->FieldList() as $k => $title) {
139 if(! $SNG->hasField($k) && ! $SNG->hasMethod('get' . $k))
140 $query->select[] = $k;
141 }
142 $parent = $this->controllerClass();
143 $if_clause = "IF(`{$this->manyManyParentClass}ID` IS NULL, '0', '1')";
144 $query->select[] = "$if_clause AS Checked";
145
146 if($this->OnlyRelated())
147 $query->where[] = $if_clause;
148 }
149 return clone $query;
150 }
151
152 function getParentIdName($parentClass, $childClass) {
153 return $this->getParentIdNameRelation($parentClass, $childClass, 'many_many');
154 }
155
156 function () {
157 $items = array();
158 foreach($this->unpagedSourceItems as $item) {
159 if($item->{$this->joinField})
160 $items[] = $item->ID;
161 }
162 $list = implode(',', $items);
163 $value = ",";
164 $value .= !empty($list) ? $list."," : "";
165 $inputId = $this->id() . '_' . $this->htmlListEndName;
166 $controllerID = $this->controller->ID;
167 return <<<HTML
168 <input name="controllerID" type="hidden" value="$controllerID" />
169 <input id="$inputId" name="{$this->name}[{$this->htmlListField}]" type="hidden" value="$value"/>
170 HTML;
171 }
172
173
174 public function Sortable() {
175 return (SortableDataObject::is_sortable_many_many($this->sourceClass())) || (SortableDataObject::is_sortable_class($this->sourceClass()));
176 }
177
178 public function SortableClass() {
179 return $this->manyManyParentClass."-".$this->sourceClass();
180 }
181
182
183 }
184
185 class ManyManyDataObjectManager_Item extends DataObjectManager_Item {
186
187 function MarkingCheckbox() {
188 $name = $this->parent->Name() . '[]';
189 $disabled = $this->parent->hasMarkingPermission() ? "" : "disabled='disabled'";
190
191 if($this->parent->IsReadOnly)
192 return "<input class=\"checkbox\" type=\"checkbox\" name=\"$name\" value=\"{$this->item->ID}\" disabled=\"disabled\"/>";
193 else if($this->item->{$this->parent->joinField})
194 return "<input class=\"checkbox\" type=\"checkbox\" name=\"$name\" value=\"{$this->item->ID}\" checked=\"checked\" $disabled />";
195 else
196 return "<input class=\"checkbox\" type=\"checkbox\" name=\"$name\" value=\"{$this->item->ID}\" $disabled />";
197 }
198 }
199
200
201
202
203 ?>
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-