Passed
Push — master ( 23d0a5...26f6d6 )
by Aimeos
05:18
created

mshoplib/src/MShop/Common/Manager/Lists/Base.php (1 issue)

Labels
Severity
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2011
6
 * @copyright Aimeos (aimeos.org), 2015-2018
7
 * @package MShop
8
 * @subpackage Common
9
 */
10
11
12
namespace Aimeos\MShop\Common\Manager\Lists;
13
14
15
/**
16
 * Abstract list manager implementation
17
 *
18
 * @package MShop
19
 * @subpackage Common
20
 */
21
abstract class Base
22
	extends \Aimeos\MShop\Common\Manager\Base
23
{
24
	private $date;
25
	private $prefix;
26
	private $searchConfig;
27
28
29
	/**
30
	 * Creates the common list manager using the given context object.
31
	 *
32
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object with required objects
33
	 *
34
	 * @throws \Aimeos\MShop\Exception if no configuration is available
35
	 */
36
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context )
37
	{
38
		$this->date = $context->getDateTime();
39
		$this->searchConfig = $this->getSearchConfig();
40
41
		if( ( $entry = reset( $this->searchConfig ) ) === false ) {
42
			throw new \Aimeos\MShop\Exception( sprintf( 'Search configuration not available' ) );
43
		}
44
45
		if( ( $pos = strrpos( $entry['code'], '.' ) ) === false ) {
46
			throw new \Aimeos\MShop\Exception( sprintf( 'Search configuration for "%1$s" not available', $entry['code'] ) );
47
		}
48
49
		if( ( $this->prefix = substr( $entry['code'], 0, $pos + 1 ) ) === false ) {
50
			throw new \Aimeos\MShop\Exception( sprintf( 'Search configuration for "%1$s" not available', $entry['code'] ) );
51
		}
52
53
		parent::__construct( $context );
54
	}
55
56
57
	/**
58
	 * Counts the number items that are available for the values of the given key.
59
	 *
60
	 * @param \Aimeos\MW\Criteria\Iface $search Search criteria
61
	 * @param string $key Search key to aggregate items for
62
	 * @return integer[] List of the search keys as key and the number of counted items as value
63
	 */
64
	public function aggregate( \Aimeos\MW\Criteria\Iface $search, $key )
65
	{
66
		$required = array( trim( $this->prefix, '.' ) );
67
		return $this->aggregateBase( $search, $key, $this->getConfigPath() . 'aggregate', $required );
68
	}
69
70
71
	/**
72
	 * Creates a new empty item instance
73
	 *
74
	 * @param array $values Values the item should be initialized with
75
	 * @return \Aimeos\MShop\Common\Item\Lists\Iface New list item object
76
	 */
77
	public function createItem( array $values = [] )
78
	{
79
		$values[$this->prefix . 'siteid'] = $this->getContext()->getLocale()->getSiteId();
80
		return $this->createItemBase( $values );
81
	}
82
83
84
	/**
85
	 * Updates or adds a common list item object.
86
	 *
87
	 * @param \Aimeos\MShop\Common\Item\Lists\Iface $item List item object which should be saved
88
	 * @param boolean $fetch True if the new ID should be returned in the item
89
	 * @return \Aimeos\MShop\Common\Item\Iface $item Updated item including the generated ID
90
	 */
91
	public function saveItem( \Aimeos\MShop\Common\Item\Iface $item, $fetch = true )
92
	{
93
		self::checkClass( \Aimeos\MShop\Common\Item\Lists\Iface::class, $item );
94
95
		if( !$item->isModified() ) {
96
			return $item;
97
		}
98
99
		$context = $this->getContext();
100
101
		$dbm = $context->getDatabaseManager();
102
		$dbname = $this->getResourceName();
103
		$conn = $dbm->acquire( $dbname );
104
105
		try
106
		{
107
			$id = $item->getId();
108
			$date = date( 'Y-m-d H:i:s' );
109
			$path = $this->getConfigPath();
110
			$columns = $this->getObject()->getSaveAttributes();
1 ignored issue
show
The method getSaveAttributes() does not exist on Aimeos\MShop\Common\Manager\Iface. Did you maybe mean getSearchAttributes()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

110
			$columns = $this->getObject()->/** @scrutinizer ignore-call */ getSaveAttributes();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
111
112
			if( $id === null ) {
113
				$sql = $this->addSqlColumns( array_keys( $columns ), $this->getSqlConfig( $path .= 'insert' ) );
114
			} else {
115
				$sql = $this->addSqlColumns( array_keys( $columns ), $this->getSqlConfig( $path .= 'update' ), false );
116
			}
117
118
			$idx = 1;
119
			$stmt = $this->getCachedStatement( $conn, $path, $sql );
120
121
			foreach( $columns as $name => $entry ) {
122
				$stmt->bind( $idx++, $item->get( $name ), $entry->getInternalType() );
123
			}
124
125
			$stmt->bind( $idx++, $item->getParentId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
126
			$stmt->bind( $idx++, $item->getKey() );
127
			$stmt->bind( $idx++, $item->getType() );
128
			$stmt->bind( $idx++, $item->getDomain() );
129
			$stmt->bind( $idx++, $item->getRefId() );
130
			$stmt->bind( $idx++, $item->getDateStart() );
131
			$stmt->bind( $idx++, $item->getDateEnd() );
132
			$stmt->bind( $idx++, json_encode( $item->getConfig() ) );
133
			$stmt->bind( $idx++, $item->getPosition(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
134
			$stmt->bind( $idx++, $item->getStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
135
			$stmt->bind( $idx++, $date ); //mtime
136
			$stmt->bind( $idx++, $this->getContext()->getEditor() );
137
			$stmt->bind( $idx++, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
138
139
140
			if( $id !== null ) {
141
				$stmt->bind( 14, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
142
			} else {
143
				$stmt->bind( 14, $date ); //ctime
144
			}
145
146
			$stmt->execute()->finish();
147
148
			if( $fetch === true )
149
			{
150
				if( $id === null ) {
151
					$item->setId( $this->newId( $conn, $this->getConfigPath() . 'newid' ) );
152
				} else {
153
					$item->setId( $id ); // modified false
154
				}
155
			}
156
157
			$dbm->release( $conn, $dbname );
158
		}
159
		catch( \Exception $e )
160
		{
161
			$dbm->release( $conn, $dbname );
162
			throw $e;
163
		}
164
165
		return $item;
166
	}
167
168
169
	/**
170
	 * Removes multiple items specified by ids in the array.
171
	 *
172
	 * @param string[] $ids List of IDs
173
	 * @return \Aimeos\MShop\Common\Manager\Lists\Iface Manager object for chaining method calls
174
	 */
175
	public function deleteItems( array $ids )
176
	{
177
		return $this->deleteItemsBase( $ids, $this->getConfigPath() . 'delete' );
178
	}
179
180
181
	/**
182
	 * Creates common list item object for the given common list item id.
183
	 *
184
	 * @param string $id Id of common list item object
185
	 * @param string[] $ref List of domains to fetch list items and referenced items for
186
	 * @param boolean $default Add default criteria
187
	 * @return \Aimeos\MShop\Common\Item\Lists\Iface Returns common list item object of the given id
188
	 * @throws \Aimeos\MShop\Exception If item couldn't be found
189
	 */
190
	public function getItem( $id, array $ref = [], $default = false )
191
	{
192
		if( ( $conf = reset( $this->searchConfig ) ) === false || !isset( $conf['code'] ) ) {
193
			throw new \Aimeos\MShop\Exception( sprintf( 'Search configuration not available' ) );
194
		}
195
196
		$criteria = $this->getObject()->createSearch( $default );
197
		$expr = [
198
			$criteria->compare( '==', $conf['code'], $id ),
199
			$criteria->getConditions()
200
		];
201
		$criteria->setConditions( $criteria->combine( '&&', $expr ) );
202
		$items = $this->getObject()->searchItems( $criteria, $ref );
203
204
		if( ( $item = reset( $items ) ) === false )
205
		{
206
			$msg = sprintf( 'List item with ID "%2$s" in "%1$s" not found', $conf['code'], $id );
207
			throw new \Aimeos\MShop\Exception( $msg );
208
		}
209
210
		return $item;
211
	}
212
213
214
	/**
215
	 * Search for all list items based on the given critera.
216
	 *
217
	 * @param \Aimeos\MW\Criteria\Iface $search Search criteria object
218
	 * @param string[] $ref List of domains to fetch list items and referenced items for
219
	 * @param integer|null &$total Number of items that are available in total
220
	 * @return array List of list items implementing \Aimeos\MShop\Common\Item\Lists\Iface
221
	 */
222
	public function searchItems( \Aimeos\MW\Criteria\Iface $search, array $ref = [], &$total = null )
223
	{
224
		$items = [];
225
226
		$dbm = $this->getContext()->getDatabaseManager();
227
		$dbname = $this->getResourceName();
228
		$conn = $dbm->acquire( $dbname );
229
230
		try
231
		{
232
			$level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
233
			$cfgPathSearch = $this->getConfigPath() . 'search';
234
			$cfgPathCount = $this->getConfigPath() . 'count';
235
236
			$name = trim( $this->prefix, '.' );
237
			$required = array( $name );
238
239
			$results = $this->searchItemsBase( $conn, $search, $cfgPathSearch, $cfgPathCount, $required, $total, $level );
240
241
			while( ( $row = $results->fetch() ) !== false )
242
			{
243
				if( ( $row[$this->prefix . 'config'] = json_decode( $config = $row[$this->prefix . 'config'], true ) ) === null )
244
				{
245
					$msg = sprintf( 'Invalid JSON as result of search for ID "%2$s" in "%1$s": %3$s', $this->prefix . 'list.config', $row['id'], $config );
246
					$this->getContext()->getLogger()->log( $msg, \Aimeos\MW\Logger\Base::WARN );
247
				}
248
249
				$items[(string) $row[$this->prefix . 'id']] = $this->createItemBase( $row );
250
			}
251
252
			$dbm->release( $conn, $dbname );
253
		}
254
		catch( \Exception $e )
255
		{
256
			$dbm->release( $conn, $dbname );
257
			throw $e;
258
		}
259
260
		return $items;
261
	}
262
263
264
	/**
265
	 * Creates a search object including the base criteria (optional)
266
	 *
267
	 * @param boolean $default Include default criteria
268
	 * @return \Aimeos\MW\Criteria\Iface Search critera object
269
	 */
270
	public function createSearch( $default = false )
271
	{
272
		if( $default === true )
273
		{
274
			$prefix = rtrim( $this->getPrefix(), '.' );
275
			$object = $this->createSearchBase( $prefix );
276
277
			$expr = [$object->getConditions()];
278
279
			$exprTwo = [];
280
			$exprTwo[] = $object->compare( '<=', $prefix . '.datestart', $this->date );
281
			$exprTwo[] = $object->compare( '==', $prefix . '.datestart', null );
282
			$expr[] = $object->combine( '||', $exprTwo );
283
284
			$exprTwo = [];
285
			$exprTwo[] = $object->compare( '>=', $prefix . '.dateend', $this->date );
286
			$exprTwo[] = $object->compare( '==', $prefix . '.dateend', null );
287
			$expr[] = $object->combine( '||', $exprTwo );
288
289
			$object->setConditions( $object->combine( '&&', $expr ) );
290
291
			return $object;
292
		}
293
294
		return parent::createSearch();
295
	}
296
297
298
	/**
299
	 * Creates a new manager for list extensions.
300
	 *
301
	 * @param string $manager Name of the sub manager type in lower case
302
	 * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
303
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager for different extensions, e.g type, etc.
304
	 */
305
	public function getSubManager( $manager, $name = null )
306
	{
307
		return $this->getSubManagerBase( 'common', 'lists/' . $manager, $name );
308
	}
309
310
311
	/**
312
	 * Returns the config path for retrieving the configuration values.
313
	 *
314
	 * @return string Configuration path
315
	 */
316
	abstract protected function getConfigPath();
317
318
319
	/**
320
	 * Returns the search configuration for searching items.
321
	 *
322
	 * @return array Associative list of search keys and search definitions
323
	 */
324
	abstract protected function getSearchConfig();
325
326
327
	/**
328
	 * Creates new common list item object.
329
	 *
330
	 * @see \Aimeos\MShop\Common\Item\Lists\Standard Default list item
331
	 * @param array $values Possible optional array keys can be given: id, parentid, refid, domain, pos, start, end
332
	 * @return \Aimeos\MShop\Common\Item\Lists\Standard New common list item object
333
	 */
334
	protected function createItemBase( array $values = [] )
335
	{
336
		$values['.date'] = $this->date;
337
338
		return new \Aimeos\MShop\Common\Item\Lists\Standard( $this->prefix, $values );
339
	}
340
341
342
	/**
343
	 * Returns the domain prefix.
344
	 *
345
	 * @return string Domain prefix with sub-domains separated by "."
346
	 */
347
	protected function getPrefix()
348
	{
349
		return $this->prefix;
350
	}
351
}
352