Improvements for channel counter
[friendica.git/.git] / src / BaseCollection.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2024, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica;
23
24 /**
25  * The Collection classes inheriting from this class are meant to represent a list of structured objects of a single type.
26  *
27  * Collections can be used with foreach(), accessed like an array and counted.
28  */
29 class BaseCollection extends \ArrayIterator
30 {
31         /**
32          * This property is used with paginated results to hold the total number of items satisfying the paginated request.
33          * @var int
34          */
35         protected $totalCount = 0;
36
37         /**
38          * @param BaseEntity[] $entities
39          * @param int|null     $totalCount
40          */
41         public function __construct(array $entities = [], int $totalCount = null)
42         {
43                 parent::__construct($entities);
44
45                 $this->totalCount = $totalCount ?? count($entities);
46         }
47
48         /**
49          * @inheritDoc
50          */
51         #[\ReturnTypeWillChange]
52         public function offsetSet($key, $value): void
53         {
54                 if (is_null($key)) {
55                         $this->totalCount++;
56                 }
57
58                 parent::offsetSet($key, $value);
59         }
60
61         /**
62          * @inheritDoc
63          */
64         #[\ReturnTypeWillChange]
65         public function offsetUnset($key): void
66         {
67                 if ($this->offsetExists($key)) {
68                         $this->totalCount--;
69                 }
70
71                 parent::offsetUnset($key);
72         }
73
74         /**
75          * Getter for total count
76          *
77          * @return int Total count
78          */
79         public function getTotalCount(): int
80         {
81                 return $this->totalCount;
82         }
83
84         /**
85          * Return the values from a single field in the collection
86          *
87          * @param string   $column
88          * @param int|null $index_key
89          * @return array
90          * @see array_column()
91          */
92         public function column(string $column, $index_key = null): array
93         {
94                 return array_column($this->getArrayCopy(true), $column, $index_key);
95         }
96
97         /**
98          * Apply a callback function on all elements in the collection and returns a new collection with the updated elements
99          *
100          * @param callable $callback
101          * @return BaseCollection
102          * @see array_map()
103          */
104         public function map(callable $callback): BaseCollection
105         {
106                 return new static(array_map($callback, $this->getArrayCopy()), $this->getTotalCount());
107         }
108
109         /**
110          * Filters the collection based on a callback that returns a boolean whether the current item should be kept.
111          *
112          * @param callable|null $callback
113          * @param int           $flag
114          * @return BaseCollection
115          * @see array_filter()
116          */
117         public function filter(callable $callback = null, int $flag = 0): BaseCollection
118         {
119                 return new static(array_filter($this->getArrayCopy(), $callback, $flag));
120         }
121
122         /**
123          * Reverse the orders of the elements in the collection
124          *
125          * @return $this
126          */
127         public function reverse(): BaseCollection
128         {
129                 return new static(array_reverse($this->getArrayCopy()), $this->getTotalCount());
130         }
131
132         /**
133          * Split the collection in smaller collections no bigger than the provided length
134          *
135          * @param int $length
136          * @return static[]
137          */
138         public function chunk(int $length): array
139         {
140                 if ($length < 1) {
141                         throw new \RangeException('BaseCollection->chunk(): Size parameter expected to be greater than 0');
142                 }
143
144                 return array_map(function ($array) {
145                         return new static($array);
146                 }, array_chunk($this->getArrayCopy(), $length));
147         }
148
149
150         /**
151          * @inheritDoc
152          *
153          * includes recursion for entity::toArray() function
154          * @see BaseEntity::toArray()
155          */
156         public function getArrayCopy(bool $recursive = false): array
157         {
158                 if (!$recursive) {
159                         return parent::getArrayCopy();
160                 }
161
162                 return array_map(function ($item) {
163                         return is_object($item) ? $item->toArray() : $item;
164                 }, parent::getArrayCopy());
165         }
166 }