Version: current

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

[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. -