Completed
Push — master ( 869a2b...d02afe )
by Zack
11:33 queued 03:17
created

Entry_Collection::add_count_callback()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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