Version: current

      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      * Most of the code below was copied from ManyManyComplexTableField.
     18      * Painful, but necessary, until PHP supports multiple inheritance.
     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                     // @modification http://open.silverstripe.org/ticket/5194
     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             // Add more selected fields if they are from joined table.
    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 ExtraData() {
    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. -