Completed
Push — master ( 971f99...10707b )
by Peter
07:20 queued 02:39
created

DataProvider::setCriteria()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 2
Bugs 0 Features 0
Metric Value
dl 0
loc 15
ccs 0
cts 8
cp 0
rs 9.2
c 2
b 0
f 0
cc 4
eloc 7
nc 6
nop 1
crap 20
1
<?php
2
3
/**
4
 * This software package is licensed under AGPL or Commercial license.
5
 *
6
 * @package maslosoft/mangan
7
 * @licence AGPL or Commercial
8
 * @copyright Copyright (c) Piotr Masełkowski <[email protected]>
9
 * @copyright Copyright (c) Maslosoft
10
 * @copyright Copyright (c) Others as mentioned in code
11
 * @link http://maslosoft.com/mangan/
12
 */
13
14
namespace Maslosoft\Mangan;
15
16
use Maslosoft\Addendum\Interfaces\AnnotatedInterface;
17
use Maslosoft\Mangan\Exceptions\ManganException;
18
use Maslosoft\Mangan\Interfaces\Criteria\DecoratableInterface;
19
use Maslosoft\Mangan\Interfaces\Criteria\LimitableInterface;
20
use Maslosoft\Mangan\Interfaces\CriteriaInterface;
21
use Maslosoft\Mangan\Interfaces\DataProviderInterface;
22
use Maslosoft\Mangan\Interfaces\FinderInterface;
23
use Maslosoft\Mangan\Interfaces\PaginationInterface;
24
use Maslosoft\Mangan\Interfaces\SortInterface;
25
use Maslosoft\Mangan\Interfaces\WithCriteriaInterface;
26
use Maslosoft\Mangan\Meta\ManganMeta;
27
28
/**
29
 * Mongo document data provider
30
 *
31
 * Implements a data provider based on Document.
32
 *
33
 * DataProvider provides data in terms of Document objects which are
34
 * of class {@link modelClass}. It uses the AR {@link EntityManager::findAll} method
35
 * to retrieve the data from database. The {@link query} property can be used to
36
 * specify various query options, such as conditions, sorting, pagination, etc.
37
 *
38
 * @author Ianaré Sévi
39
 * @author Dariusz Górecki <[email protected]>
40
 * @author Invenzzia Group, open-source division of CleverIT company http://www.invenzzia.org
41
 * @copyright 2011 CleverIT http://www.cleverit.com.pl
42
 * @since v1.0
43
 */
44
class DataProvider implements DataProviderInterface
45
{
46
47
	/**
48
	 * Instance of model
49
	 * @var Document
50
	 * @since v1.0
51
	 */
52
	public $model;
53
54
	/**
55
	 * Finder instance
56
	 * @var FinderInterface
57
	 */
58
	private $finder = null;
59
60
	/**
61
	 * @var CriteriaInterface
62
	 */
63
	private $criteria;
64
65
	/**
66
	 * @var SortInterface
67
	 */
68
	private $sort;
69
	private $data = null;
70
	private $totalItemCount = null;
71
72
	/**
73
	 * Pagination instance
74
	 * @var PaginationInterface
75
	 */
76
	private $pagination = null;
77
78
	/**
79
	 * Constructor.
80
	 * @param mixed $modelClass the model class (e.g. 'Post') or the model finder instance
81
	 * (e.g. <code>Post::model()</code>, <code>Post::model()->published()</code>).
82
	 * @param array $config configuration (name=>value) to be applied as the initial property values of this class.
83
	 * @since v1.0
84
	 */
85 1
	public function __construct($modelClass, $config = [])
86
	{
87 1
		if (is_string($modelClass))
88
		{
89
			$this->model = new $modelClass;
90
		}
91 1
		elseif (is_object($modelClass))
92
		{
93 1
			$this->model = $modelClass;
94
		}
95
		else
96
		{
97
			throw new ManganException('Invalid model type for ' . __CLASS__);
98
		}
99
100 1
		$this->finder = Finder::create($this->model);
101 1
		if ($this->model instanceof WithCriteriaInterface)
102
		{
103
			$this->criteria = $this->model->getDbCriteria();
104
		}
105
		else
106
		{
107 1
			$this->criteria = new Criteria();
108
		}
109
110
		// Merge criteria from configuration
111 1
		if (isset($config['criteria']))
112
		{
113
			$this->criteria->mergeWith($config['criteria']);
114
			unset($config['criteria']);
115
		}
116
117
		// Merge limit from configuration
118 1
		if (isset($config['limit']) && $config['limit'] > 0)
119
		{
120
			$this->criteria->setLimit($config['limit']);
121
			unset($config['limit']);
122
		}
123
124
		// Merge sorting from configuration
125 1
		if (isset($config['sort']))
126
		{
127
			// Apply default sorting if criteria does not have sort configured
128
			if (isset($config['sort']['defaultOrder']) && empty($this->criteria->getSort()))
129
			{
130
				$this->criteria->setSort($config['sort']['defaultOrder']);
131
			}
132
			unset($config['sort']);
133
		}
134
135 1
		if (!$this->criteria->getSelect())
136
		{
137 1
			$fields = array_keys(ManganMeta::create($this->model)->fields());
138 1
			$fields = array_fill_keys($fields, true);
139 1
			$this->criteria->setSelect($fields);
140
		}
141
142 1
		foreach ($config as $key => $value)
143
		{
144
			$this->$key = $value;
145
		}
146 1
	}
147
148
	/**
149
	 * Get model used by this dataprovider
150
	 * @return AnnotatedInterface
151
	 */
152
	public function getModel()
153
	{
154
		return $this->model;
155
	}
156
157
	/**
158
	 * Returns the criteria.
159
	 * @return Criteria the query criteria
160
	 * @since v1.0
161
	 */
162
	public function getCriteria()
163
	{
164
		// Initialise empty criteria, so it's always available via this method call.
165
		if (empty($this->criteria))
166
		{
167
			$this->criteria = new Criteria;
168
		}
169
		return $this->criteria;
170
	}
171
172
	/**
173
	 * Sets the query criteria.
174
	 * @param CriteriaInterface|array $criteria the query criteria. Array representing the MongoDB query criteria.
175
	 * @since v1.0
176
	 */
177
	public function setCriteria($criteria)
178
	{
179
		if (is_array($criteria))
180
		{
181
			$this->criteria = new Criteria($criteria);
182
		}
183
		elseif ($criteria instanceof CriteriaInterface)
184
		{
185
			$this->criteria = $criteria;
186
		}
187
		if ($this->criteria instanceof DecoratableInterface)
188
		{
189
			$this->criteria->decorateWith($this->getModel());
190
		}
191
	}
192
193
	/**
194
	 * Returns the sort object.
195
	 * @return Sort the sorting object. If this is false, it means the sorting is disabled.
196
	 */
197 1
	public function getSort()
198
	{
199 1
		if ($this->sort === null)
200
		{
201 1
			$this->sort = new Sort;
202 1
			$this->sort->setModel($this->model);
203
		}
204 1
		return $this->sort;
205
	}
206
207
	/**
208
	 * Set sort
209
	 * @param SortInterface $sort
210
	 * @return DataProvider
211
	 */
212
	public function setSort(SortInterface $sort)
213
	{
214
		$this->sort = $sort;
215
		$this->sort->setModel($this->model);
216
		return $this;
217
	}
218
219
	/**
220
	 * Returns the pagination object.
221
	 * @param string $className the pagination object class name, use this param to override default pagination class.
222
	 * @return Pagination|false the pagination object. If this is false, it means the pagination is disabled.
223
	 */
224 1
	public function getPagination($className = Pagination::class)
225
	{
226 1
		if ($this->pagination === false)
227
		{
228
			return false;
229
		}
230 1
		if ($this->pagination === null)
231
		{
232 1
			$this->pagination = new $className;
233
		}
234 1
		return $this->pagination;
235
	}
236
237
	/**
238
	 * Returns the number of data items in the current page.
239
	 * This is equivalent to <code>count($provider->getData())</code>.
240
	 * When {@link pagination} is set false, this returns the same value as {@link totalItemCount}.
241
	 * @param boolean $refresh whether the number of data items should be re-calculated.
242
	 * @return integer the number of data items in the current page.
243
	 */
244
	public function getItemCount($refresh = false)
245
	{
246
		return count($this->getData($refresh));
247
	}
248
249
	/**
250
	 * Returns the total number of data items.
251
	 * When {@link pagination} is set false, this returns the same value as {@link itemCount}.
252
	 * @return integer total number of possible data items.
253
	 */
254 1
	public function getTotalItemCount()
255
	{
256 1
		if ($this->totalItemCount === null)
257
		{
258 1
			$this->totalItemCount = $this->finder->count($this->criteria);
259
		}
260 1
		return $this->totalItemCount;
261
	}
262
263
	/**
264
	 * Fetches the data from the persistent data storage.
265
	 * @return Document[]|Cursor list of data items
266
	 * @since v1.0
267
	 */
268 1
	protected function fetchData()
269
	{
270 1
		$pagination = $this->getPagination();
271 1
		if ($pagination !== false && $this->criteria instanceof LimitableInterface)
272
		{
273 1
			$pagination->setCount($this->getTotalItemCount());
274 1
			$pagination->apply($this->criteria);
275
		}
276
277 1
		$sort = $this->getSort();
278 1
		if ($sort->isSorted())
279
		{
280
			$this->criteria->setSort($sort);
281
		}
282
283 1
		return $this->finder->findAll($this->criteria);
284
	}
285
286
	/**
287
	 * Returns the data items currently available, ensures that result is at leas empty array
288
	 * @param boolean $refresh whether the data should be re-fetched from persistent storage.
289
	 * @return array the list of data items currently available in this data provider.
290
	 */
291 1
	public function getData($refresh = false)
292
	{
293 1
		if ($this->data === null || $refresh)
294
		{
295 1
			$this->data = $this->fetchData();
296
		}
297 1
		if ($this->data === null)
298
		{
299
			return [];
300
		}
301 1
		return $this->data;
302
	}
303
304
}
305