1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Created by Vitaly Iegorov <[email protected]> |
4
|
|
|
* on 07.08.14 at 17:11 |
5
|
|
|
*/ |
6
|
|
|
namespace samsoncms\api; |
7
|
|
|
|
8
|
|
|
use samson\activerecord\dbQuery; |
9
|
|
|
use \samsonframework\orm\Condition; |
10
|
|
|
use samsonframework\orm\Query; |
11
|
|
|
use \samsonframework\orm\QueryInterface; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* SamsonCMS Material database record object. |
15
|
|
|
* This class extends default ActiveRecord material table record functionality. |
16
|
|
|
* @package samson\cms |
17
|
|
|
* @author Vitaly Egorov <[email protected]> |
18
|
|
|
*/ |
19
|
|
|
class Material extends \samson\activerecord\material |
20
|
|
|
{ |
21
|
|
|
/** Override table attributes for late static binding */ |
22
|
|
|
public static $_attributes = array(); |
23
|
|
|
public static $_sql_select = array(); |
24
|
|
|
public static $_sql_from = array(); |
25
|
|
|
public static $_own_group = array(); |
26
|
|
|
public static $_map = array(); |
27
|
|
|
|
28
|
|
|
/** @var integer Primary field */ |
29
|
|
|
public $MaterialID; |
30
|
|
|
|
31
|
|
|
/** @var string Unique identifier */ |
32
|
|
|
public $Url; |
33
|
|
|
|
34
|
|
|
/** @var bool Internal existence flag */ |
35
|
|
|
public $Active; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Get material entity by URL(s). |
39
|
|
|
* |
40
|
|
|
* @param QueryInterface $query Object for performing database queries |
41
|
|
|
* @param array|string $url Material URL or collection of material URLs |
42
|
|
|
* @param self|array|null $return Variable where request result would be returned |
43
|
|
|
* @return bool|self True if material entities has been found |
44
|
|
|
*/ |
45
|
|
|
public static function byUrl(QueryInterface $query, $url, & $return = array()) |
46
|
|
|
{ |
47
|
|
|
// Get entities by filtered identifiers |
48
|
|
|
$return = $query->entity(get_called_class()) |
49
|
|
|
->where('Url', $url) |
|
|
|
|
50
|
|
|
->where('Active', 1) |
51
|
|
|
->first(); |
52
|
|
|
|
53
|
|
|
// If only one argument is passed - return null, otherwise bool |
54
|
|
|
return func_num_args() > 2 ? $return !== null : $return; |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Set additional material field value by field identifier |
59
|
|
|
* @param string $fieldID Field identifier |
60
|
|
|
* @param string $value Value to be stored |
61
|
|
|
* @param string $locale Locale identifier |
62
|
|
|
*/ |
63
|
|
|
public function setFieldByID($fieldID, $value, $locale = DEFAULT_LOCALE) |
64
|
|
|
{ |
65
|
|
|
// TODO: This should be removed |
66
|
|
|
/** @var QueryInterface $query This should be removed to use $this->database*/ |
67
|
|
|
$query = dbQuery(); |
|
|
|
|
68
|
|
|
|
69
|
|
|
/** @var Field $fieldRecord Try to find this additional field */ |
70
|
|
|
$fieldRecord = null; |
71
|
|
|
if (Field::byID($query, $fieldID, $fieldRecord)) { |
|
|
|
|
72
|
|
|
/** @var MaterialField[] $materialFieldRecord Try to find additional field value */ |
73
|
|
|
$materialFieldRecord = null; |
74
|
|
|
if (!MaterialField::byFieldIDAndMaterialID($query, $this->id, $fieldRecord->id, $materialFieldRecord)) { |
75
|
|
|
// Create new additional field value record if it does not exists |
76
|
|
|
$materialFieldRecord = new MaterialField(); |
77
|
|
|
$materialFieldRecord->FieldID = $fieldRecord->id; |
78
|
|
|
$materialFieldRecord->MaterialID = $this->id; |
79
|
|
|
$materialFieldRecord->Active = 1; |
|
|
|
|
80
|
|
|
$materialFieldRecord->locale = $locale; |
81
|
|
|
} else { // Get first record(actually it should be only one) |
82
|
|
|
$materialFieldRecord = array_shift($materialFieldRecord); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
// At this point we already have database record instance |
86
|
|
|
$valueFieldName = $fieldRecord->valueFieldName(); |
87
|
|
|
$materialFieldRecord->$valueFieldName = $value; |
88
|
|
|
$materialFieldRecord->save(); |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Get select additional field text value. |
94
|
|
|
* |
95
|
|
|
* @param string $fieldID Field identifier |
96
|
|
|
* @return string Select field text |
97
|
|
|
*/ |
98
|
|
|
public function selectText($fieldID) |
99
|
|
|
{ |
100
|
|
|
/** @var Field $field */ |
101
|
|
|
$field = null; |
102
|
|
|
if (Field::byID(new Query('\samsoncms\api\Field', $this->database), $fieldID, $fieldID)) { |
|
|
|
|
103
|
|
|
// If this entity has this field set |
104
|
|
|
if (isset($this[$field->Name]{0})) { |
105
|
|
|
return $field->options($this[$field->Name]); |
106
|
|
|
} |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
// Value not set |
110
|
|
|
return ''; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Get collection of images for material by gallery additional field selector. If none is passed |
115
|
|
|
* all images from gallery table would be returned for this material entity. |
116
|
|
|
* |
117
|
|
|
* @param string|null $fieldSelector Additional field selector value |
118
|
|
|
* @param string $selector Additional field field name to search for |
119
|
|
|
* @return \samsonframework\orm\RecordInterface[] Collection of images in this gallery additional field for material |
120
|
|
|
*/ |
121
|
|
|
public function &gallery($fieldSelector = null, $selector = 'FieldID') |
122
|
|
|
{ |
123
|
|
|
/** @var \samsonframework\orm\RecordInterface[] $images Get material images for this gallery */ |
124
|
|
|
$images = array(); |
125
|
|
|
|
126
|
|
|
// Create query |
127
|
|
|
$query = new dbQuery(); |
128
|
|
|
|
129
|
|
|
$query->entity(CMS::MATERIAL_FIELD_RELATION_ENTITY); |
130
|
|
|
|
131
|
|
|
/* @var Field Get field object if we need to search it by other fields */ |
132
|
|
|
$field = null; |
133
|
|
|
if ($selector != 'FieldID' && Field::oneByColumn($query, $selector, $fieldSelector)) { |
134
|
|
|
$fieldSelector = $field->id; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
// Add field filter if present |
138
|
|
|
if (isset($fieldSelector)) { |
139
|
|
|
$query->where("FieldID", $fieldSelector); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** @var \samson\activerecord\materialfield $dbMaterialField Find material field gallery record */ |
143
|
|
|
$dbMaterialField = null; |
144
|
|
|
if ($query->where('MaterialID', $this->id)->first($dbMaterialField)) { |
145
|
|
|
// Get material images for this materialfield |
146
|
|
|
$images = $query->entity(CMS::MATERIAL_IMAGES_RELATION_ENTITY) |
147
|
|
|
->where('materialFieldId', $dbMaterialField->id) |
148
|
|
|
->exec(); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
return $images; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* Copy this material related entities. |
156
|
|
|
* |
157
|
|
|
* @param QueryInterface $query Database query instance |
158
|
|
|
* @param string $entity Entity identifier |
159
|
|
|
* @param string $newIdentifier Copied material idetifier |
160
|
|
|
* @param array $excludedIDs Collection of related entity identifier to exclude from copying |
161
|
|
|
*/ |
162
|
|
|
protected function copyRelatedEntity(QueryInterface $query, $entity, $newIdentifier, $excludedIDs = array()) |
163
|
|
|
{ |
164
|
|
|
// Copy additional fields |
165
|
|
|
foreach ($query->entity($entity) |
|
|
|
|
166
|
|
|
->where('MaterialID', $this->MaterialID) |
167
|
|
|
->exec() as $copiedEntity) { |
168
|
|
|
// Check if field is NOT excluded from copying |
169
|
|
|
if (!in_array($copiedEntity->id, $excludedIDs)) { |
170
|
|
|
/** @var MaterialField $copy Copy instance */ |
171
|
|
|
$copy = $copiedEntity->copy(); |
172
|
|
|
$copy->MaterialID = $newIdentifier; |
|
|
|
|
173
|
|
|
$copy->save(); |
174
|
|
|
} |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Create copy of current object. |
180
|
|
|
* |
181
|
|
|
* @param mixed $clone Material for cloning |
182
|
|
|
* @param array $excludedFields Additional fields identifiers not copied |
183
|
|
|
* @returns self New copied instance |
184
|
|
|
*/ |
185
|
|
|
public function ©(&$clone = null, $excludedFields = array()) |
186
|
|
|
{ |
187
|
|
|
/** @var Material $clone Create new instance by copying */ |
188
|
|
|
$clone = parent::copy($clone); |
189
|
|
|
|
190
|
|
|
// Create query |
191
|
|
|
$query = new dbQuery(); |
192
|
|
|
|
193
|
|
|
$this->copyRelatedEntity($query, CMS::MATERIAL_NAVIGATION_RELATION_ENTITY, $clone->id); |
194
|
|
|
$this->copyRelatedEntity($query, CMS::MATERIAL_FIELD_RELATION_ENTITY, $clone->id, $excludedFields); |
195
|
|
|
$this->copyRelatedEntity($query, CMS::MATERIAL_IMAGES_RELATION_ENTITY, $clone->id); |
196
|
|
|
|
197
|
|
|
return $clone; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
public function nestedIDs($navigationID = null, &$return = array()) |
201
|
|
|
{ |
202
|
|
|
// Create query |
203
|
|
|
$query = new dbQuery(); |
204
|
|
|
|
205
|
|
|
/** @var array $nestedIDs Get collection of materials by navigation */ |
206
|
|
|
$nestedIDs = null; |
207
|
|
|
if (static::idsByNavigationID($query, $navigationID, $nestedIDs)) { |
|
|
|
|
208
|
|
|
// Get collection of nested materials |
209
|
|
|
$return = $query->entity(get_class($this)) |
210
|
|
|
->where('MaterialID', $nestedIDs) |
|
|
|
|
211
|
|
|
->where('Active', 1) |
212
|
|
|
->where('parent_id', $this->id) |
213
|
|
|
->orderBy('priority') |
214
|
|
|
->fields('MaterialID'); |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
return $return; |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* Get material additional fields table. |
222
|
|
|
* |
223
|
|
|
* @param string $navigationID Navigation table identifier |
224
|
|
|
* @param array $tableColumns Columns names list |
225
|
|
|
* @param string $externalHandler External handler to perform some extra code |
|
|
|
|
226
|
|
|
* @param array $params External handler params |
|
|
|
|
227
|
|
|
* @return array Collection of collections of table cells, represented as materialfield objects |
228
|
|
|
*/ |
229
|
|
|
public function table($navigationID, &$tableColumns = null) { |
230
|
|
|
// Create query |
231
|
|
|
$query = new dbQuery(); |
232
|
|
|
|
233
|
|
|
/** @var array $resultTable Collection of collections of field cells */ |
234
|
|
|
$resultTable = array(); |
235
|
|
|
|
236
|
|
|
/** @var array $dbTableFieldsIds Array of table structure column identifiers */ |
237
|
|
|
$dbTableFieldsIds = array(); |
238
|
|
|
if (Field::byNavigationID($query, $navigationID, $dbTableFieldsIds)) { |
239
|
|
|
// Get localized and not localized fields |
240
|
|
|
$localizedFields = array(); |
241
|
|
|
$unlocalizedFields = array(); |
242
|
|
|
|
243
|
|
|
/** @var Field $field Table column */ |
244
|
|
|
foreach ($dbTableFieldsIds as $field) { |
|
|
|
|
245
|
|
|
/** Add table columns names */ |
246
|
|
|
$tableColumns[] = $field->Name; |
247
|
|
View Code Duplication |
if ($field->local == 1) { |
|
|
|
|
248
|
|
|
$localizedFields[] = $field->id; |
249
|
|
|
} else { |
250
|
|
|
$unlocalizedFields[] = $field->id; |
251
|
|
|
} |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
// Get table row materials |
255
|
|
|
$tableRowsIDs = array(); |
256
|
|
|
if ($this->nestedIDs($navigationID, $tableRowsIDs)) { |
257
|
|
|
// Create field condition |
258
|
|
|
$localizationFieldCond = new Condition('or'); |
259
|
|
|
|
260
|
|
|
// Create localized condition |
261
|
|
|
if (sizeof($localizedFields)) { |
262
|
|
|
$localizedFieldCond = new Condition('and'); |
263
|
|
|
$localizedFieldCond->add('FieldID', $localizedFields) |
264
|
|
|
->add('locale', locale()); |
265
|
|
|
// Add this condition to condition group |
266
|
|
|
$localizationFieldCond->add($localizedFieldCond); |
|
|
|
|
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
// Create not localized condition |
270
|
|
|
if (sizeof($unlocalizedFields)) { |
271
|
|
|
$localizationFieldCond->add('FieldID', $unlocalizedFields); |
272
|
|
|
}// Create db query |
273
|
|
|
; |
274
|
|
|
|
275
|
|
|
// Flip field identifiers as keys |
276
|
|
|
$tableColumnIds = array_flip($dbTableFieldsIds); |
277
|
|
|
$resultTable = array_flip($tableRowsIDs); |
278
|
|
|
|
279
|
|
|
/** @var \samson\activerecord\material $dbTableRow Material object (table row) */ |
280
|
|
|
foreach ($query->entity(CMS::MATERIAL_FIELD_RELATION_ENTITY) |
281
|
|
|
->where('MaterialID', $tableRowsIDs) |
|
|
|
|
282
|
|
|
->whereCondition($localizationFieldCond)->exec() as $mf) { |
283
|
|
View Code Duplication |
if (!is_array($resultTable[$mf['MaterialID']])) { |
|
|
|
|
284
|
|
|
$resultTable[$mf['MaterialID']] = array(); |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
$resultTable[$mf['MaterialID']][$tableColumnIds[$mf->FieldID]] = |
288
|
|
|
!empty($mf->Value) ? $mf->Value : (!empty($mf->numeric_value) ? $mf->numeric_value : $mf->key_value); |
289
|
|
|
} |
290
|
|
|
} |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
return array_values($resultTable); |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* Function to retrieve this material table by specified field |
298
|
|
|
* @param string $tableSelector Selector to identify table structure |
299
|
|
|
* @param string $selector Database field by which search is performed |
300
|
|
|
* @param array $tableColumns Columns names list |
301
|
|
|
* @param string $externalHandler External handler to perform some extra code |
302
|
|
|
* @param array $params External handler params |
303
|
|
|
* @return array Collection of collections of table cells, represented as materialfield objects |
304
|
|
|
* @deprecated Use table() |
305
|
|
|
*/ |
306
|
|
|
public function getTable( |
307
|
|
|
$tableSelector, |
308
|
|
|
$selector = 'StructureID', |
309
|
|
|
&$tableColumns = null, |
310
|
|
|
$externalHandler = null, |
311
|
|
|
$params = array() |
312
|
|
|
) { |
313
|
|
|
// Create query |
314
|
|
|
$query = new dbQuery(); |
|
|
|
|
315
|
|
|
|
316
|
|
|
/** @var array $resultTable Collection of collections of field cells */ |
317
|
|
|
$resultTable = array(); |
318
|
|
|
/** @var array $dbTableFieldsIds Array of table structure column identifiers */ |
319
|
|
|
$dbTableFieldsIds = array(); |
320
|
|
|
|
321
|
|
|
// Get structure object if we need to search it by other fields |
322
|
|
|
if ($selector != 'StructureID') { |
323
|
|
|
$structure = dbQuery('structure')->cond($selector, $tableSelector)->first(); |
|
|
|
|
324
|
|
|
$tableSelector = $structure->id; |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
/** If this table has columns */ |
328
|
|
|
if (dbQuery('structurefield') |
|
|
|
|
329
|
|
|
->cond("StructureID", $tableSelector) |
330
|
|
|
->fields('FieldID', $dbTableFieldsIds) |
|
|
|
|
331
|
|
|
) { |
332
|
|
|
// Get localized and not localized fields |
333
|
|
|
$localizedFields = array(); |
334
|
|
|
$unlocalizedFields = array(); |
335
|
|
|
/** @var \samson\cms\CMSField $dbTableField Table column */ |
336
|
|
|
foreach (dbQuery('field')->order_by('priority')->cond('FieldID', $dbTableFieldsIds)->exec() as $field) { |
|
|
|
|
337
|
|
|
/** Add table columns names */ |
338
|
|
|
$tableColumns[] = $field->Name; |
339
|
|
View Code Duplication |
if ($field->local == 1) { |
|
|
|
|
340
|
|
|
$localizedFields[] = $field->id; |
341
|
|
|
} else { |
342
|
|
|
$unlocalizedFields[] = $field->id; |
343
|
|
|
} |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
// Query to get table rows(table materials) |
347
|
|
|
$tableQuery = dbQuery('material') |
|
|
|
|
348
|
|
|
->cond('parent_id', $this->MaterialID) |
349
|
|
|
->cond('Active', '1') |
350
|
|
|
->join('structurematerial') |
351
|
|
|
->cond('structurematerial_StructureID', $tableSelector) |
352
|
|
|
->order_by('priority'); |
353
|
|
|
|
354
|
|
|
// Call user function if exists |
355
|
|
|
if (is_callable($externalHandler)) { |
356
|
|
|
// Give it query as parameter |
357
|
|
|
call_user_func_array($externalHandler, array_merge(array(&$tableQuery), $params)); |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
// Get table row materials |
361
|
|
|
$tableMaterialIds = array(); |
362
|
|
|
if ($tableQuery->fields('MaterialID', $tableMaterialIds)) { |
363
|
|
|
// Create field condition |
364
|
|
|
$localizationFieldCond = new Condition('or'); |
365
|
|
|
|
366
|
|
|
// Create localized condition |
367
|
|
|
if (sizeof($localizedFields)) { |
368
|
|
|
$localizedFieldCond = new Condition('and'); |
369
|
|
|
$localizedFieldCond->add('materialfield_FieldID', $localizedFields) |
370
|
|
|
->add('materialfield_locale', locale()); |
371
|
|
|
// Add this condition to condition group |
372
|
|
|
$localizationFieldCond->add($localizedFieldCond); |
|
|
|
|
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
// Create not localized condition |
376
|
|
|
if (sizeof($unlocalizedFields)) { |
377
|
|
|
$localizationFieldCond->add('materialfield_FieldID', $unlocalizedFields); |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
// Create db query |
381
|
|
|
$materialFieldQuery = dbQuery('materialfield') |
|
|
|
|
382
|
|
|
->cond('MaterialID', $tableMaterialIds) |
|
|
|
|
383
|
|
|
->cond($localizationFieldCond); |
|
|
|
|
384
|
|
|
|
385
|
|
|
// Flip field identifiers as keys |
386
|
|
|
$tableColumnIds = array_flip($dbTableFieldsIds); |
387
|
|
|
$resultTable = array_flip($tableMaterialIds); |
388
|
|
|
|
389
|
|
|
/** @var \samson\activerecord\material $dbTableRow Material object (table row) */ |
390
|
|
|
foreach ($materialFieldQuery->exec() as $mf) { |
391
|
|
View Code Duplication |
if (!is_array($resultTable[$mf['MaterialID']])) { |
|
|
|
|
392
|
|
|
$resultTable[$mf['MaterialID']] = array(); |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
$resultTable[$mf['MaterialID']][$tableColumnIds[$mf->FieldID]] = |
396
|
|
|
!empty($mf->Value) ? $mf->Value : (!empty($mf->numeric_value) ? $mf->numeric_value : $mf->key_value); |
397
|
|
|
} |
398
|
|
|
} |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
return array_values($resultTable); |
402
|
|
|
} |
403
|
|
|
} |
404
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.