Completed
Pull Request — develop (#1425)
by Gennady
07:04
created

Entry_Collection::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
namespace GV;
3
4
/** If this file is called directly, abort. */
5
if ( ! defined( 'GRAVITYVIEW_DIR' ) ) {
6
	die();
7
}
8
9
/**
10
 * A collection of \GV\Entry objects.
11
 */
12
class Entry_Collection extends Collection {
13
	/**
14
	 * Lazy fetching and counting of data defers
15
	 *  all processing of entries and entry data until
16
	 *  it is really requested.
17
	 *
18
	 * @see \GV\Entry_Collection::add_fetch_callback
19
	 * @see \GV\Entry_Collection::add_count_callback
20
	 *
21
	 * @var array Lazy data loading callbacks.
22
	 */
23
	private $callbacks = array();
24
25
	/**
26
	 * @var \GV\Entry_Filter[] Filtering criteria.
27
	 */
28
	public $filters = array();
29
30
	/**
31
	 * @var \GV\Entry_Sort[] Sorting criteria.
32
	 */
33
	public $sorts = array();
34
35
	/**
36
	 * @var int The offset.
37
	 */
38
	public $offset = 0;
39
40
	/**
41
	 * @var int The limit.
42
	 */
43
	public $limit = 20;
44
45
	/**
46
	 * @var int The current page.
47
	 */
48
	public $current_page = 1;
49
50
	/**
51
	 * @var int The number of entries fetched.
52
	 */
53
	private $fetched = -1;
54
55
	/**
56
	 * Add an \GV\Entry to this collection.
57
	 *
58
	 * @param \GV\Entry $entry The entry to add to the internal array.
59
	 *
60
	 * @api
61
	 * @since 2.0
62
	 * @return void
63
	 */
64 77
	public function add( $entry ) {
65 77
		if ( ! $entry instanceof Entry ) {
66
			$this->fetched = max( 0, $this->fetched );
67
			gravityview()->log->error( 'Entry_Collections can only contain objects of type \GV\Entry.' );
68
			return;
69
		}
70 77
		parent::add( $entry );
71 77
		$this->fetched = max( 1, $this->fetched + 1 );
72 77
	}
73
74
	/**
75
	 * Get a \GV\Entry from this list.
76
	 *
77
	 * @param int $entry_id The ID of the entry to get.
78
	 * @param string $backend The form backend identifier, allows for multiple form backends in the future. Unused until then.
79
	 *
80
	 * @api
81
	 * @since 2.0
82
	 *
83
	 * @return \GV\Entry|null The \GV\entry with the $entry_id as the ID, or null if not found.
84
	 */
85
	public function get( $entry_id, $backend = 'gravityforms' ) {
0 ignored issues
show
Unused Code introduced by
The parameter $backend is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
86
		foreach ( $this->all() as $entry ) {
87
			if ( $entry->ID == $entry_id ) {
88
				return $entry;
89
			}
90
		}
91
		return null;
92
	}
93
94
	/**
95
	 * Count the total number of \GV\Entry objects that are possible to get.
96
	 *
97
	 * @api
98
	 * @since 2.0
99
	 *
100
	 * @return int The total number of entries that are fetchable.
101
	 */
102 49
	public function total() {
103 49
		$total = 0;
104
105
		/** Call all lazy callbacks. */
106 49
		foreach ( $this->callbacks as $callback ) {
107 33
			if ( $callback[0] != 'count' ) {
108 33
				continue;
109
			}
110
111 33
			$total += $callback[1]( $this->filters );
112
		}
113
114 49
		if ( ! $total ) {
115 27
			$total = parent::count();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (count() instead of total()). Are you sure this is correct? If so, you might want to change this to $this->count().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
116
		}
117
118 49
		return $total - $this->offset;
119
	}
120
121
	/**
122
	 * Get the total number of entries that are fetched.
123
	 *
124
	 * @api
125
	 * @since develop
126
	 *
127
	 * @return int The number of entries fetched now.
128
	 */
129 36
	public function count() {
130 36
		return count( $this->fetch()->all() );
131
	}
132
133
	/**
134
	 * Get the entries as an array.
135
	 *
136
	 * @api
137
	 * @since 2.0
138
	 *
139
	 * @return \GV\Entry[] The entries as an array.
140
	 */
141 84
	public function all() {
142 84
		if ( $this->fetched >= 0 || parent::count() ) {
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (count() instead of all()). Are you sure this is correct? If so, you might want to change this to $this->count().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
143 84
			return parent::all();
144
		}
145 64
		return $this->fetch()->all();
146
	}
147
148
	/**
149
	 * Pluck by key.
150
	 *
151
	 * @api
152
	 * @since develop
153
	 *
154
	 * @param string $key The key to pluck by.
155
	 *
156
	 * @return array The plucked values.
157
	 */
158 1
	public function pluck( $key ) {
159 1
		$result = array();
160
161 1
		foreach ( $this->all() as $entry ) {
162 1
			$entry = $entry->as_entry();
163 1
			$result[] = Utils::get( $entry, $key, null );
164
		}
165
166 1
		return $result;
167
	}
168
169
	/**
170
	 * Get the last \GV\Entry in this collection.
171
	 *
172
	 * @api
173
	 * @since 2.0
174
	 *
175
	 * @return \GV\Entry|null The last entry or null.
176
	 */
177
	public function last() {
178
		if ( $this->fetched >= 0 || parent::count() ) {
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (count() instead of last()). Are you sure this is correct? If so, you might want to change this to $this->count().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
179
			return parent::last();
180
		}
181
		return $this->fetch()->last();
182
	}
183
184
	/**
185
	 * Get the first \GV\Entry in this collection.
186
	 *
187
	 * @api
188
	 * @since 2.0
189
	 *
190
	 * @return \GV\Entry|null The first entry or null.
191
	 */
192 4
	public function first() {
193 4
		if ( $this->fetched >= 0 || parent::count() ) {
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (count() instead of first()). Are you sure this is correct? If so, you might want to change this to $this->count().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
194 4
			return parent::first();
195
		}
196 4
		return $this->fetch()->first();
197
	}
198
199
	/**
200
	 * Hydrate this collection now.
201
	 *
202
	 * @api
203
	 * @since 2.0
204
	 *
205
	 * @return \GV\Entry_Collection This collection, now hydrated.
206
	 */
207 74
	public function fetch() {
208 74
		if ( $this->fetched >= 0 ) {
209 27
			return $this;
210
		}
211
212 74
		$this->clear();
213
214
		/** Calculate the offsets. */
215 74
		$offset = new \GV\Entry_Offset();
216 74
		$offset->limit = $this->limit;
217 74
		$offset->offset = ( $this->limit * ( $this->current_page - 1 ) ) + $this->offset;
218
219
		/** Call all lazy callbacks. */
220 74
		foreach ( $this->callbacks as $i => $callback ) {
221 72
			if ( $callback[0] != 'fetch' ) {
222 72
				continue;
223
			}
224
225 72
			$this->merge( $callback[1]( $this->filters, $this->sorts, $offset ) );
226
		}
227
228 74
		$this->fetched = parent::count();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (count() instead of fetch()). Are you sure this is correct? If so, you might want to change this to $this->count().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
229
230 74
		return $this;
231
	}
232
233
	/**
234
	 * Apply a filter to the current collection.
235
	 *
236
	 * This operation is non-destructive as a copy of the collection is returned.
237
	 *
238
	 * @param \GV\Entry_Filter $filter The filter to be applied.
239
	 *
240
	 * @api
241
	 * @since 2.0
242
	 *
243
	 * @return \GV\Entry_Collection A copy of the this collection with the filter applied.
244
	 */
245 73
	public function filter( \GV\Entry_Filter $filter ) {
246 73
		$collection = clone $this;
247 73
		$collection->clear();
248
249 73
		array_push( $collection->filters, $filter );
250
251 73
		return $collection;
252
	}
253
254
	/**
255
	 * Sort.
256
	 *
257
	 * @param \GV\Entry_Sort $sort The sort to apply to this collection.
258
	 *
259
	 * @api
260
	 * @since 2.0
261
	 *
262
	 * @return \GV\Entry_Collection A copy of the this collection with the sort applied.
263
	 */
264 10
	public function sort( $sort ) {
265 10
		$collection = clone $this;
266 10
		$collection->clear();
267
268 10
		array_push( $collection->sorts, $sort );
269
270 10
		return $collection;
271
	}
272
273
	/**
274
	 * Limit the fetch to a specified window.
275
	 *
276
	 * @param int $limit The limit.
277
	 *
278
	 * @api
279
	 * @since 2.0
280
	 *
281
	 * @return \GV\Entry_Collection A copy of the this collection with the limit applied.
282
	 */
283 73
	public function limit( $limit ) {
284 73
		$collection = clone $this;
285 73
		$collection->clear();
286 73
		$collection->limit = $limit;
287 73
		return $collection;
288
	}
289
290
	/**
291
	 * Add an $offset to these entries.
292
	 *
293
	 * Useful, you know, for pagination and stuff. Not too useful directly.
294
	 *
295
	 * @see \GV\Entry_Collection::page()
296
	 *
297
	 * @param int $offset The number of entries to skip in the database.
298
	 *
299
	 * @api
300
	 * @since 2.0
301
	 *
302
	 * @return \GV\Entry_Collection A copy of the this collection with the offset applied.
303
	 */
304 73
	public function offset( $offset ) {
305 73
		$collection = clone $this;
306 73
		$collection->clear();
307 73
		$collection->offset = $offset;
308 73
		return $collection;
309
	}
310
311
	/**
312
	 * Set the current page.
313
	 *
314
	 * @param int $page Set the current page to this page. Ends up agumenting the $offset in \GV\Entry_Offset
315
	 *
316
	 * @return \GV\Entry_Collection A copy of the this collection with the offset applied.
317
	 */
318 73
	public function page( $page ) {
319 73
		$collection = clone $this;
320 73
		$collection->clear();
321 73
		$collection->current_page = $page;
322 73
		return $collection;
323
	}
324
325
	/**
326
	 * Defer fetching of data to the provided callable.
327
	 *
328
	 * The callback signature should be as follows:
329
	 *  \GV\Entry_Collection callback( \GV\Entry_Filter $filter, \GV\Entry_Sort $sort, \GV\Entry_Offset $offset );
330
	 *
331
	 * The methods that trigger the callback are:
332
	 * - \GV\Entry_Collection::fetch
333
	 *
334
	 * ::fetch is triggered via:
335
	 * - \GV\Entry_Collection::all
336
	 * - \GV\Entry_Collection::last
337
	 *
338
	 * @param callable $callback The callback to call when needed.
339
	 *
340
	 * @internal
341
	 * @since 2.0
342
	 *
343
	 * @return void
344
	 */
345 72
	public function add_fetch_callback( $callback ) {
346 72
		$this->add_callback( 'fetch', $callback );
347 72
	}
348
349
	/**
350
	 * Defer counting of data to the provided callable.
351
	 *
352
	 * The callback signature should be as follows:
353
	 *  int callback( \GV\Entry_Filter $filter );
354
	 *
355
	 * The methods that trigger the callback are:
356
	 * - \GV\Entry_Collection::count
357
	 *
358
	 * @param callable $callback The callback to call when needed.
359
	 *
360
	 * @internal
361
	 * @since 2.0
362
	 *
363
	 * @return void
364
	 */
365 72
	public function add_count_callback( $callback ) {
366 72
		$this->add_callback( 'count', $callback );
367 72
	}
368
369
	/**
370
	 * Add a callback for lazy loading/counting.
371
	 *
372
	 * @param callable $callback The callback to call when needed.
373
	 *
374
	 * @return void
375
	 */
376 72
	private function add_callback( $type, $callback ) {
377 72
		if ( ! is_callable( $callback ) ) {
378
			return;
379
		}
380
381 72
		$this->callbacks []= array( $type, $callback );
382 72
	}
383
384
	/**
385
	 * @inheritdoc
386
	 */
387 74
	public function clear() {
388 74
		$this->fetched = -1;
389 74
		parent::clear();
390 74
	}
391
}
392