Completed
Push — master ( 578283...5ad19b )
by Zack
15s
created

Entry_Collection::total()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
nc 6
nop 0
dl 0
loc 18
ccs 9
cts 9
cp 1
crap 4
rs 9.6666
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 12 and the first side effect is on line 6.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

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