GravityView  2.17
The best, easiest way to display Gravity Forms entries on your website.
class-gv-collection-entry.php
Go to the documentation of this file.
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  */
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  public function add( $entry ) {
65  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  parent::add( $entry );
71  $this->fetched = max( 1, $this->fetched + 1 );
72  }
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' ) {
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  public function total() {
103  $total = 0;
104 
105  /** Call all lazy callbacks. */
106  foreach ( $this->callbacks as $callback ) {
107  if ( $callback[0] != 'count' ) {
108  continue;
109  }
110 
111  $total += $callback[1]( $this->filters );
112  }
113 
114  if ( ! $total ) {
115  $total = parent::count();
116  }
117 
118  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  public function all() {
130  if ( $this->fetched >= 0 || parent::count() ) {
131  return parent::all();
132  }
133  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  public function pluck( $key ) {
147  $result = array();
148 
149  foreach ( $this->all() as $entry ) {
150  $entry = $entry->as_entry();
151  $result[] = Utils::get( $entry, $key, null );
152  }
153 
154  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() ) {
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  public function first() {
181  if ( $this->fetched >= 0 || parent::count() ) {
182  return parent::first();
183  }
184  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  public function fetch() {
196  if ( $this->fetched >= 0 ) {
197  return $this;
198  }
199 
200  $this->clear();
201 
202  /** Calculate the offsets. */
203  $offset = new \GV\Entry_Offset();
204  $offset->limit = $this->limit;
205  $offset->offset = ( $this->limit * ( $this->current_page - 1 ) ) + $this->offset;
206 
207  /** Call all lazy callbacks. */
208  foreach ( $this->callbacks as $i => $callback ) {
209  if ( $callback[0] != 'fetch' ) {
210  continue;
211  }
212 
213  $this->merge( $callback[1]( $this->filters, $this->sorts, $offset ) );
214  }
215 
216  $this->fetched = parent::count();
217 
218  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  public function filter( \GV\Entry_Filter $filter ) {
234  $collection = clone $this;
235  $collection->clear();
236 
237  array_push( $collection->filters, $filter );
238 
239  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  public function sort( $sort ) {
253  $collection = clone $this;
254  $collection->clear();
255 
256  array_push( $collection->sorts, $sort );
257 
258  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  public function limit( $limit ) {
272  $collection = clone $this;
273  $collection->clear();
274  $collection->limit = $limit;
275  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  public function offset( $offset ) {
293  $collection = clone $this;
294  $collection->clear();
295  $collection->offset = $offset;
296  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  public function page( $page ) {
307  $collection = clone $this;
308  $collection->clear();
309  $collection->current_page = $page;
310  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  public function add_count_callback( $callback ) {
354  $this->add_callback( 'count', $callback );
355  }
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  private function add_callback( $type, $callback ) {
365  if ( ! is_callable( $callback ) ) {
366  return;
367  }
368 
369  $this->callbacks []= array( $type, $callback );
370  }
371 
372  /**
373  * @inheritdoc
374  */
375  public function clear() {
376  $this->fetched = -1;
377  parent::clear();
378  }
379 }
all()
Get the entries as an array.
add_callback( $type, $callback)
Add a callback for lazy loading/counting.
clear()
offset( $offset)
Add an $offset to these entries.
If this file is called directly, abort.
pluck( $key)
Pluck by key.
add( $entry)
Add an to this collection.
last()
Get the last in this collection.
page( $page)
Set the current page.
total()
Count the total number of objects that are possible to get.
filter(\GV\Entry_Filter $filter)
Apply a filter to the current collection.
sort( $sort)
Sort.
If this file is called directly, abort.
If this file is called directly, abort.
gravityview()
The main GravityView wrapper function.
limit( $limit)
Limit the fetch to a specified window.
If this file is called directly, abort.
add_fetch_callback( $callback)
Defer fetching of data to the provided callable.
$entry
Definition: notes.php:27
fetch()
Hydrate this collection now.
first()
Get the first in this collection.
add_count_callback( $callback)
Defer counting of data to the provided callable.