Completed
Push — master ( af77e8...7d9d07 )
by Zack
11s
created

Entry_Collection::get()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 2
dl 0
loc 8
ccs 0
cts 5
cp 0
crap 12
rs 9.4285
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
	private $filters = array();
29
30
	/**
31
	 * @var \GV\Entry_Sort[] Sorting criteria.
32
	 */
33
	private $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
	 * @throws \InvalidArgumentException if $field is not of type \GV\Entry.
61
	 *
62
	 * @api
63
	 * @since future
64
	 * @return void
65
	 */
66
	public function add( $entry ) {
67
		if ( ! $entry instanceof Entry ) {
68
			throw new \InvalidArgumentException( 'Entry_Collections can only contain objects of type \GV\Entry.' );
69
		}
70
		parent::add( $entry );
71
	}
72
73
	/**
74
	 * Get a \GV\Entry from this list.
75
	 *
76
	 * @param int $entry_id The ID of the entry to get.
77
	 * @param string $backend The form backend identifier, allows for multiple form backends in the future. Unused until then.
78
	 *
79
	 * @api
80
	 * @since future
81
	 *
82
	 * @return \GV\Entry|null The \GV\entry with the $entry_id as the ID, or null if not found.
83
	 */
84
	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...
85
		foreach ( $this->all() as $entry ) {
86
			if ( $entry->ID == $entry_id ) {
87
				return $entry;
88
			}
89
		}
90
		return null;
91
	}
92
93
	/**
94
	 * Count the total number of \GV\Entry objects that are possible to get.
95
	 *
96
	 * @api
97
	 * @since future
98
	 *
99
	 * @return int The total number of entries that are fetchable.
100
	 */
101 1
	public function total() {
102 1
		$total = 0;
103
104
		/** Call all lazy callbacks. */
105 1
		foreach ( $this->callbacks as $callback ) {
106 1
			if ( $callback[0] != 'count' ) {
0 ignored issues
show
introduced by
Found "!= '". Use Yoda Condition checks, you must
Loading history...
107 1
				continue;
108
			}
109
110 1
			$total += $callback[1]( $this->filters );
111
		}
112
113 1
		return $total - $this->offset;
114
	}
115
116
	/**
117
	 * Get the entries as an array.
118
	 *
119
	 * @api
120
	 * @since future
121
	 *
122
	 * @return \GV\Entry[] The entries as an array.
123
	 */
124
	public function all() {
125
		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...
126
			return parent::all();
127
		}
128
		return $this->fetch()->all();
129
	}
130
131
	/**
132
	 * Get the last \GV\Entry in this collection.
133
	 *
134
	 * @api
135
	 * @since future
136
	 *
137
	 * @return \GV\Entry|null The last entry or null.
138
	 */
139
	public function last() {
140
		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...
141
			return parent::last();
142
		}
143
		return $this->fetch()->last();
144
	}
145
146
	/**
147
	 * Hydrate this collection now.
148
	 *
149
	 * @api
150
	 * @since future
151
	 *
152
	 * @return \GV\Entry_Collection This collection, now hydrated.
153
	 */
154
	public function fetch() {
155
		$this->clear();
156
157
		/** Calculate the offsets. */
158
		$offset = new \GV\Entry_Offset();
159
		$offset->limit = $this->limit;
160
		$offset->offset = ( $this->limit * ( $this->current_page - 1 ) ) + $this->offset;
161
162
		/** Call all lazy callbacks. */
163
		foreach ( $this->callbacks as $i => $callback ) {
164
			if ( $callback[0] != 'fetch' ) {
0 ignored issues
show
introduced by
Found "!= '". Use Yoda Condition checks, you must
Loading history...
165
				continue;
166
			}
167
168
			$this->merge( $callback[1]( $this->filters, $this->sorts, $offset ) );
169
		}
170
171
		$this->fetched = $this->count();
172
173
		return $this;
174
	}
175
176
	/**
177
	 * Apply a filter to the current collection.
178
	 *
179
	 * This operation is non-destructive as a copy of the collection is returned.
180
	 *
181
	 * @param \GV\Entry_Filter $filter The filter to be applied.
182
	 *
183
	 * @api
184
	 * @since future
185
	 *
186
	 * @return \GV\Entry_Collection A copy of the this collection with the filter applied.
187
	 */
188 1
	public function filter( \GV\Entry_Filter $filter ) {
189 1
		$collection = clone( $this );
190 1
		$collection->clear();
191
192 1
		array_push( $collection->filters, $filter );
193
194 1
		return $collection;
195
	}
196
197
	/**
198
	 * Sort.
199
	 *
200
	 * @param \GV\Entry_Sort $sort The sort to apply to this collection.
201
	 *
202
	 * @api
203
	 * @since future
204
	 *
205
	 * @return \GV\Entry_Collection A copy of the this collection with the sort applied.
206
	 */
207 1
	public function sort( $sort ) {
208 1
		$collection = clone( $this );
209 1
		$collection->clear();
210
211 1
		array_push( $collection->sorts, $sort );
212
213 1
		return $collection;
214
	}
215
216
	/**
217
	 * Limit the fetch to a specified window.
218
	 *
219
	 * @param int $limit The limit.
220
	 *
221
	 * @api
222
	 * @since future
223
	 *
224
	 * @return \GV\Entry_Collection A copy of the this collection with the limit applied.
225
	 */
226 1
	public function limit( $limit ) {
227 1
		$collection = clone( $this );
228 1
		$collection->clear();
229 1
		$collection->limit = $limit;
230 1
		return $collection;
231
	}
232
233
	/**
234
	 * Add an $offset to these entries.
235
	 *
236
	 * Useful, you know, for pagination and stuff. Not too useful directly.
237
	 *
238
	 * @see \GV\Entry_Collection::page()
239
	 *
240
	 * @param int $offset The number of entries to skip in the database.
241
	 *
242
	 * @api
243
	 * @since future
244
	 *
245
	 * @return \GV\Entry_Collection A copy of the this collection with the offset applied.
246
	 */
247 1
	public function offset( $offset ) {
248 1
		$collection = clone( $this );
249 1
		$collection->clear();
250 1
		$collection->offset = $offset;
251 1
		return $collection;
252
	}
253
254
	/**
255
	 * Set the current page.
256
	 *
257
	 * @param int $page Set the current page to this page. Ends up agumenting the $offset in \GV\Entry_Offset
258
	 *
259
	 * @return \GV\Entry_Collection A copy of the this collection with the offset applied.
260
	 */
261 1
	public function page( $page ) {
262 1
		$collection = clone( $this );
263 1
		$collection->clear();
264 1
		$collection->current_page = $page;
265 1
		return $collection;
266
	}
267
268
	/**
269
	 * Defer fetching of data to the provided callable.
270
	 *
271
	 * The callback signature should be as follows:
272
	 *  \GV\Entry_Collection callback( \GV\Entry_Filter $filter, \GV\Entry_Sort $sort, \GV\Entry_Offset $offset );
273
	 *
274
	 * The methods that trigger the callback are:
275
	 * - \GV\Entry_Collection::fetch
276
	 *
277
	 * ::fetch is triggered via:
278
	 * - \GV\Entry_Collection::all
279
	 * - \GV\Entry_Collection::last
280
	 *
281
	 * @param callable $callback The callback to call when needed.
282
	 *
283
	 * @internal
284
	 * @since future
285
	 *
286
	 * @return void
287
	 */
288
	public function add_fetch_callback( $callback ) {
289
		$this->add_callback( 'fetch', $callback );
290
	}
291
292
	/**
293
	 * Defer counting of data to the provided callable.
294
	 *
295
	 * The callback signature should be as follows:
296
	 *  int callback( \GV\Entry_Filter $filter );
297
	 *
298
	 * The methods that trigger the callback are:
299
	 * - \GV\Entry_Collection::count
300
	 *
301
	 * @param callable $callback The callback to call when needed.
302
	 *
303
	 * @internal
304
	 * @since future
305
	 *
306
	 * @return void
307
	 */
308
	public function add_count_callback( $callback ) {
309
		$this->add_callback( 'count', $callback );
310
	}
311
312
	/**
313
	 * Add a callback for lazy loading/counting.
314
	 *
315
	 * @param callable $callback The callback to call when needed.
316
	 *
317
	 * @return void
318
	 */
319
	private function add_callback( $type, $callback ) {
320
		if ( ! is_callable( $callback ) ) {
321
			return;
322
		}
323
324
		$this->callbacks []= array( $type, $callback );
0 ignored issues
show
introduced by
Expected 1 space before "="; 0 found
Loading history...
325
	}
326
327
	/**
328
	 * @inheritdoc
329
	 */
330
	public function clear() {
331
		$this->fetched = -1;
332
		parent::clear();
333
	}
334
}
335