Completed
Pull Request — develop (#1444)
by Zack
14:05 queued 04:01
created

Entry_Collection   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 368
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 78.49%

Importance

Changes 0
Metric Value
dl 0
loc 368
ccs 73
cts 93
cp 0.7849
rs 9.68
c 0
b 0
f 0
wmc 34
lcom 1
cbo 5

17 Methods

Rating   Name   Duplication   Size   Complexity  
A add() 0 9 2
A get() 0 8 3
A total() 0 18 4
A all() 0 6 3
A limit() 0 6 1
A last() 0 6 3
A first() 0 6 3
A filter() 0 8 1
A sort() 0 8 1
A offset() 0 6 1
A page() 0 6 1
A add_fetch_callback() 0 3 1
A add_count_callback() 0 3 1
A add_callback() 0 7 2
A clear() 0 4 1
A fetch() 0 25 4
A pluck() 0 10 2
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 23
	public function add( $entry ) {
65 23
		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 23
		parent::add( $entry );
71 23
		$this->fetched = max( 1, $this->fetched + 1 );
72 23
	}
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 41
	public function total() {
103 41
		$total = 0;
104
105
		/** Call all lazy callbacks. */
106 41
		foreach ( $this->callbacks as $callback ) {
107 28
			if ( $callback[0] != 'count' ) {
108 1
				continue;
109
			}
110
111 28
			$total += $callback[1]( $this->filters );
112
		}
113
114 41
		if ( ! $total ) {
115 39
			$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 41
		return $total - $this->offset;
119
	}
120
121
	/**
122
	 * Get the entries as an array.
123
	 *
124
	 * @api
125
	 * @since 2.0
126
	 *
127
	 * @return \GV\Entry[] The entries as an array.
128
	 */
129 62
	public function all() {
130 62
		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...
131 62
			return parent::all();
132
		}
133 48
		return $this->fetch()->all();
134
	}
135
136
	/**
137
	 * Pluck by key.
138
	 *
139
	 * @api
140
	 * @since develop
141
	 *
142
	 * @param string $key The key to pluck by.
143
	 *
144
	 * @return array The plucked values.
145
	 */
146 1
	public function pluck( $key ) {
147 1
		$result = array();
148
149 1
		foreach ( $this->all() as $entry ) {
150
			$entry = $entry->as_entry();
151
			$result[] = Utils::get( $entry, $key, null );
152
		}
153
154 1
		return $result;
155
	}
156
157
	/**
158
	 * Get the last \GV\Entry in this collection.
159
	 *
160
	 * @api
161
	 * @since 2.0
162
	 *
163
	 * @return \GV\Entry|null The last entry or null.
164
	 */
165
	public function last() {
166
		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...
167
			return parent::last();
168
		}
169
		return $this->fetch()->last();
170
	}
171
172
	/**
173
	 * Get the first \GV\Entry in this collection.
174
	 *
175
	 * @api
176
	 * @since 2.0
177
	 *
178
	 * @return \GV\Entry|null The first entry or null.
179
	 */
180 3
	public function first() {
181 3
		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...
182 3
			return parent::first();
183
		}
184 3
		return $this->fetch()->first();
185
	}
186
187
	/**
188
	 * Hydrate this collection now.
189
	 *
190
	 * @api
191
	 * @since 2.0
192
	 *
193
	 * @return \GV\Entry_Collection This collection, now hydrated.
194
	 */
195 56
	public function fetch() {
196 56
		if ( $this->fetched >= 0 ) {
197
			return $this;
198
		}
199
200 56
		$this->clear();
201
202
		/** Calculate the offsets. */
203 56
		$offset = new \GV\Entry_Offset();
204 56
		$offset->limit = $this->limit;
205 56
		$offset->offset = ( $this->limit * ( $this->current_page - 1 ) ) + $this->offset;
206
207
		/** Call all lazy callbacks. */
208 56
		foreach ( $this->callbacks as $i => $callback ) {
209 54
			if ( $callback[0] != 'fetch' ) {
210 54
				continue;
211
			}
212
213
			$this->merge( $callback[1]( $this->filters, $this->sorts, $offset ) );
214
		}
215
216 56
		$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...
217
218 56
		return $this;
219
	}
220
221
	/**
222
	 * Apply a filter to the current collection.
223
	 *
224
	 * This operation is non-destructive as a copy of the collection is returned.
225
	 *
226
	 * @param \GV\Entry_Filter $filter The filter to be applied.
227
	 *
228
	 * @api
229
	 * @since 2.0
230
	 *
231
	 * @return \GV\Entry_Collection A copy of the this collection with the filter applied.
232
	 */
233 1
	public function filter( \GV\Entry_Filter $filter ) {
234 1
		$collection = clone $this;
235 1
		$collection->clear();
236
237 1
		array_push( $collection->filters, $filter );
238
239 1
		return $collection;
240
	}
241
242
	/**
243
	 * Sort.
244
	 *
245
	 * @param \GV\Entry_Sort $sort The sort to apply to this collection.
246
	 *
247
	 * @api
248
	 * @since 2.0
249
	 *
250
	 * @return \GV\Entry_Collection A copy of the this collection with the sort applied.
251
	 */
252 1
	public function sort( $sort ) {
253 1
		$collection = clone $this;
254 1
		$collection->clear();
255
256 1
		array_push( $collection->sorts, $sort );
257
258 1
		return $collection;
259
	}
260
261
	/**
262
	 * Limit the fetch to a specified window.
263
	 *
264
	 * @param int $limit The limit.
265
	 *
266
	 * @api
267
	 * @since 2.0
268
	 *
269
	 * @return \GV\Entry_Collection A copy of the this collection with the limit applied.
270
	 */
271 1
	public function limit( $limit ) {
272 1
		$collection = clone $this;
273 1
		$collection->clear();
274 1
		$collection->limit = $limit;
275 1
		return $collection;
276
	}
277
278
	/**
279
	 * Add an $offset to these entries.
280
	 *
281
	 * Useful, you know, for pagination and stuff. Not too useful directly.
282
	 *
283
	 * @see \GV\Entry_Collection::page()
284
	 *
285
	 * @param int $offset The number of entries to skip in the database.
286
	 *
287
	 * @api
288
	 * @since 2.0
289
	 *
290
	 * @return \GV\Entry_Collection A copy of the this collection with the offset applied.
291
	 */
292 1
	public function offset( $offset ) {
293 1
		$collection = clone $this;
294 1
		$collection->clear();
295 1
		$collection->offset = $offset;
296 1
		return $collection;
297
	}
298
299
	/**
300
	 * Set the current page.
301
	 *
302
	 * @param int $page Set the current page to this page. Ends up agumenting the $offset in \GV\Entry_Offset
303
	 *
304
	 * @return \GV\Entry_Collection A copy of the this collection with the offset applied.
305
	 */
306 1
	public function page( $page ) {
307 1
		$collection = clone $this;
308 1
		$collection->clear();
309 1
		$collection->current_page = $page;
310 1
		return $collection;
311
	}
312
313
	/**
314
	 * Defer fetching of data to the provided callable.
315
	 *
316
	 * The callback signature should be as follows:
317
	 *  \GV\Entry_Collection callback( \GV\Entry_Filter $filter, \GV\Entry_Sort $sort, \GV\Entry_Offset $offset );
318
	 *
319
	 * The methods that trigger the callback are:
320
	 * - \GV\Entry_Collection::fetch
321
	 *
322
	 * ::fetch is triggered via:
323
	 * - \GV\Entry_Collection::all
324
	 * - \GV\Entry_Collection::last
325
	 *
326
	 * @param callable $callback The callback to call when needed.
327
	 *
328
	 * @internal
329
	 * @since 2.0
330
	 *
331
	 * @return void
332
	 */
333
	public function add_fetch_callback( $callback ) {
334
		$this->add_callback( 'fetch', $callback );
335
	}
336
337
	/**
338
	 * Defer counting of data to the provided callable.
339
	 *
340
	 * The callback signature should be as follows:
341
	 *  int callback( \GV\Entry_Filter $filter );
342
	 *
343
	 * The methods that trigger the callback are:
344
	 * - \GV\Entry_Collection::count
345
	 *
346
	 * @param callable $callback The callback to call when needed.
347
	 *
348
	 * @internal
349
	 * @since 2.0
350
	 *
351
	 * @return void
352
	 */
353 67
	public function add_count_callback( $callback ) {
354 67
		$this->add_callback( 'count', $callback );
355 67
	}
356
357
	/**
358
	 * Add a callback for lazy loading/counting.
359
	 *
360
	 * @param callable $callback The callback to call when needed.
361
	 *
362
	 * @return void
363
	 */
364 67
	private function add_callback( $type, $callback ) {
365 67
		if ( ! is_callable( $callback ) ) {
366
			return;
367
		}
368
369 67
		$this->callbacks []= array( $type, $callback );
370 67
	}
371
372
	/**
373
	 * @inheritdoc
374
	 */
375 56
	public function clear() {
376 56
		$this->fetched = -1;
377 56
		parent::clear();
378 56
	}
379
}
380