Passed
Push — pulls/manymanylist-add-callbac... ( e094c2...9c86cd )
by Ingo
08:27
created

HasManyList::remove()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 14
c 0
b 0
f 0
nc 5
nop 1
dl 0
loc 25
rs 8.8333
1
<?php
2
3
namespace SilverStripe\ORM;
4
5
use InvalidArgumentException;
6
7
/**
8
 * Subclass of {@link DataList} representing a has_many relation.
9
 */
10
class HasManyList extends RelationList
11
{
12
13
    /**
14
     * @var string
15
     */
16
    protected $foreignKey;
17
18
    /**
19
     * Create a new HasManyList object.
20
     * Generation of the appropriate record set is left up to the caller, using the normal
21
     * {@link DataList} methods.  Addition arguments are used to support {@@link add()}
22
     * and {@link remove()} methods.
23
     *
24
     * @param string $dataClass The class of the DataObjects that this will list.
25
     * @param string $foreignKey The name of the foreign key field to set the ID filter against.
26
     */
27
    public function __construct($dataClass, $foreignKey)
28
    {
29
        parent::__construct($dataClass);
30
31
        $this->foreignKey = $foreignKey;
32
    }
33
34
    /**
35
     * Gets the field name which holds the related object ID.
36
     *
37
     * @return string
38
     */
39
    public function getForeignKey()
40
    {
41
        return $this->foreignKey;
42
    }
43
44
    /**
45
     * @param null|int|array|string $id
46
     * @return array
47
     */
48
    protected function foreignIDFilter($id = null)
49
    {
50
        if ($id === null) {
51
            $id = $this->getForeignID();
52
        }
53
54
        // Apply relation filter
55
        $key = DataObject::getSchema()->sqlColumnForField($this->dataClass(), $this->getForeignKey());
56
        if (is_array($id)) {
57
            return ["$key IN (" . DB::placeholders($id) . ")"  => $id];
58
        }
59
        if ($id !== null) {
60
            return [$key => $id];
61
        }
62
        return null;
63
    }
64
65
    /**
66
     * Adds the item to this relation.
67
     *
68
     * It does so by setting the relationFilters.
69
     *
70
     * @param DataObject|int $item The DataObject to be added, or its ID
71
     */
72
    public function add($item)
73
    {
74
        if (is_numeric($item)) {
75
            $item = DataObject::get_by_id($this->dataClass, $item);
76
        } elseif (!($item instanceof $this->dataClass)) {
77
            user_error("HasManyList::add() expecting a $this->dataClass object, or ID value", E_USER_ERROR);
78
        }
79
80
        $foreignID = $this->getForeignID();
81
82
        // Validate foreignID
83
        if (!$foreignID) {
84
            user_error("HasManyList::add() can't be called until a foreign ID is set", E_USER_WARNING);
85
            return;
86
        }
87
        if (is_array($foreignID)) {
0 ignored issues
show
introduced by
The condition is_array($foreignID) is always false.
Loading history...
88
            user_error("HasManyList::add() can't be called on a list linked to mulitple foreign IDs", E_USER_WARNING);
89
            return;
90
        }
91
92
        $foreignKey = $this->foreignKey;
93
        $item->$foreignKey = $foreignID;
94
95
        $item->write();
96
97
        // Call addCallback, if applicable
98
        if ($this->addCallback) {
99
            $callback = $this->addCallback;
100
            $callback($this, $item, []);
101
        }
102
    }
103
104
    /**
105
     * Remove an item from this relation.
106
     *
107
     * Doesn't actually remove the item, it just clears the foreign key value.
108
     *
109
     * @param int $itemID The ID of the item to be removed.
110
     */
111
    public function removeByID($itemID)
112
    {
113
        $item = $this->byID($itemID);
114
115
        return $this->remove($item);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->remove($item) targeting SilverStripe\ORM\HasManyList::remove() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
116
    }
117
118
    /**
119
     * Remove an item from this relation.
120
     * Doesn't actually remove the item, it just clears the foreign key value.
121
     *
122
     * @param DataObject $item The DataObject to be removed
123
     * @todo Maybe we should delete the object instead?
124
     */
125
    public function remove($item)
126
    {
127
        if (!($item instanceof $this->dataClass)) {
128
            throw new InvalidArgumentException(
129
                "HasManyList::remove() expecting a $this->dataClass object, or ID",
130
                E_USER_ERROR
131
            );
132
        }
133
134
        // Don't remove item which doesn't belong to this list
135
        $foreignID = $this->getForeignID();
136
        $foreignKey = $this->getForeignKey();
137
138
        if (empty($foreignID)
139
            || (is_array($foreignID) && in_array($item->$foreignKey, $foreignID))
140
            || $foreignID == $item->$foreignKey
141
        ) {
142
            $item->$foreignKey = null;
143
            $item->write();
144
        }
145
146
        // Call removeCallback, if applicable
147
        if ($this->removeCallback) {
148
            $callback = $this->removeCallback;
149
            $callback($this, [$item->ID]);
150
        }
151
    }
152
}
153