• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

podio-community / podio-php / 5155402462

pending completion
5155402462

push

github

daniel-sc
feat: isolated client class to allow for parallel usage + extension + mocking

BREAKING CHANGE: replace static Podio with instantiable PodioClient

648 of 648 new or added lines in 66 files covered. (100.0%)

917 of 2107 relevant lines covered (43.52%)

24.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.21
/lib/PodioCollection.php
1
<?php
2

3
/**
4
 * Provides a very simple iterator and array access interface to a collection
5
 * of PodioObject models.
6
 */
7
class PodioCollection implements IteratorAggregate, ArrayAccess, Countable
8
{
9
    private $__items = array();
10
    private $__idToItems = array();
11
    private $__extToItems = array();
12
    private $__belongs_to;
13

14
    /**
15
     * Constructor. Pass in an array of PodioObject objects.
16
     * @param PodioClient $podio_client not used, but required for compatibility with other Podio collections.
17
     */
18
    public function __construct(PodioClient $podio_client, $items = array())
19
    {
20
        foreach ($items as $item) {
177✔
21
            $this->offsetSet(null, $item);
102✔
22
        }
23
    }
24

25
    /**
26
     * Convert collection to string
27
     */
28
    public function __toString()
29
    {
30
        $items = array();
×
31
        foreach ($this->__items as $item) {
×
32
            $items[] = $item->as_json(false);
×
33
        }
34
        return print_r($items, true);
×
35
    }
36

37
    /**
38
     * Implements Countable
39
     */
40
    public function count(): int
41
    {
42
        return count($this->__items);
102✔
43
    }
44

45
    /**
46
     * Implements IteratorAggregate
47
     */
48
    public function getIterator()
49
    {
50
        return new ArrayIterator($this->__items);
60✔
51
    }
52

53
    /**
54
     * Array access. Set item by offset, automatically adding relationship.
55
     */
56
    public function offsetSet($offset, $value)
57
    {
58
        if (!is_a($value, 'PodioObject')) {
171✔
59
            throw new PodioDataIntegrityError("Objects in PodioCollection must be of class PodioObject");
3✔
60
        }
61

62
        // If the collection has a relationship with a parent, add it to the item as well.
63
        $relationship = $this->relationship();
171✔
64
        if ($relationship) {
171✔
65
            $value->add_relationship($relationship['instance'], $relationship['property']);
×
66
        }
67

68
        if (is_null($offset)) {
171✔
69
            $this->__items[] = $value;
171✔
70
        } else {
71
            if (isset($this->__items[$offset])) {
×
72
                $oldItem = $this->__items[$offset];
×
73
                $this->cleanUpItem($oldItem);
×
74
            }
75
            $this->__items[$offset] = $value;
×
76
        }
77
        if ($value->id) {
171✔
78
            $this->__idToItems[strval($value->id)] = $value;
150✔
79
        }
80
        if ($value->external_id) {
171✔
81
            $this->__extToItems[$value->external_id] = $value;
111✔
82
        }
83
    }
84

85
    /**
86
     * Array access. Check for existence.
87
     */
88
    public function offsetExists($offset)
89
    {
90
        return isset($this->__items[$offset]);
9✔
91
    }
92

93
    /**
94
     * Array access. Unset.
95
     */
96
    public function offsetUnset($offset)
97
    {
98
        if (isset($this->__items[$offset])) {
6✔
99
            $item = $this->__items[$offset];
6✔
100
            $this->cleanUpItem($item);
6✔
101
        }
102
        unset($this->__items[$offset]);
6✔
103
    }
104

105
    /**
106
     * Array access. Get.
107
     */
108
    public function offsetGet($offset)
109
    {
110
        return isset($this->__items[$offset]) ? $this->__items[$offset] : null;
24✔
111
    }
112

113
    /**
114
     * Return the raw array of objects. Internal use only.
115
     */
116
    public function _get_items()
117
    {
118
        return $this->__items;
33✔
119
    }
120

121
    /**
122
     * Set the raw array of objects. Internal use only.
123
     */
124
    public function _set_items($items)
125
    {
126
        $this->__items = $items;
12✔
127
    }
128

129
    /**
130
     * Return any relationship to a parent object.
131
     */
132
    public function relationship()
133
    {
134
        return $this->__belongs_to;
171✔
135
    }
136

137
    /**
138
     * Add a new relationship to a parent object. Will also add relationship
139
     * to all individual objects in the collection.
140
     */
141
    public function add_relationship($instance, $property = 'fields')
142
    {
143
        $this->__belongs_to = array('property' => $property, 'instance' => $instance);
15✔
144

145
        // Add relationship to all individual fields as well.
146
        foreach ($this as $item) {
15✔
147
            if ($item->has_property($property)) {
15✔
148
                $item->add_relationship($instance, $property);
3✔
149
            }
150
        }
151
    }
152

153
    /**
154
     * Get object in the collection by id or external_id.
155
     */
156
    public function get($id_or_external_id)
157
    {
158
        if (is_int($id_or_external_id)) {
30✔
159
            return isset($this->__idToItems[strval($id_or_external_id)]) ? $this->__idToItems[strval($id_or_external_id)] : null;
18✔
160
        } else {
161
            return isset($this->__extToItems[$id_or_external_id]) ? $this->__extToItems[$id_or_external_id] : null;
15✔
162
        }
163
    }
164

165
    /**
166
     * Remove object from collection by id or external_id.
167
     */
168
    public function remove($id_or_external_id)
169
    {
170
        if (count($this) === 0) {
75✔
171
            return true;
69✔
172
        }
173
        $removedObject = null;
69✔
174
        if (is_int($id_or_external_id)) {
69✔
175
            if (isset($this->__idToItems[strval($id_or_external_id)])) {
66✔
176
                $removedObject = $this->__idToItems[strval($id_or_external_id)];
66✔
177
            }
178
        } else {
179
            if (isset($this->__extToItems[$id_or_external_id])) {
6✔
180
                $removedObject = $this->__extToItems[$id_or_external_id];
6✔
181
            }
182
        }
183

184
        // this operation is expensive, hence only do it if necessary:
185
        if ($removedObject) {
69✔
186
            $this->_set_items(array_filter($this->_get_items(), function ($item) use ($id_or_external_id) {
12✔
187
                return !($item->id == $id_or_external_id || $item->external_id == $id_or_external_id);
12✔
188
            }));
12✔
189
            $this->cleanUpItem($removedObject);
12✔
190
        }
191
    }
192

193
    private function cleanUpItem($removedObject)
194
    {
195
        if ($removedObject) {
18✔
196
            if ($removedObject->external_id && isset($this->__extToItems[$removedObject->external_id])) {
18✔
197
                unset($this->__extToItems[$removedObject->external_id]);
18✔
198
            }
199
            if ($removedObject->id && isset($this->__idToItems[strval($removedObject->id)])) {
18✔
200
                unset($this->__idToItems[strval($removedObject->id)]);
18✔
201
            }
202
        }
203
    }
204
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc