flipboxfactory /
meta
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * @copyright Copyright (c) Flipbox Digital Limited |
||
| 5 | * @license https://flipboxfactory.com/software/meta/license |
||
| 6 | * @link https://www.flipboxfactory.com/software/meta/ |
||
| 7 | */ |
||
| 8 | |||
| 9 | namespace flipbox\meta\services; |
||
| 10 | |||
| 11 | use Craft; |
||
| 12 | use craft\base\Element; |
||
| 13 | use craft\base\ElementInterface; |
||
| 14 | use craft\base\FieldInterface; |
||
| 15 | use craft\elements\db\ElementQueryInterface; |
||
| 16 | use craft\fields\BaseRelationField; |
||
| 17 | use flipbox\craft\sortable\associations\db\SortableAssociationQueryInterface; |
||
| 18 | use flipbox\craft\sortable\associations\records\SortableAssociationInterface; |
||
| 19 | use flipbox\craft\sortable\associations\services\SortableFields; |
||
| 20 | use flipbox\meta\db\MetaQuery; |
||
| 21 | use flipbox\meta\elements\Meta as MetaElement; |
||
| 22 | use flipbox\meta\fields\Meta; |
||
| 23 | use flipbox\meta\fields\Meta as MetaField; |
||
| 24 | use flipbox\meta\Meta as MetaPlugin; |
||
| 25 | use flipbox\meta\records\Meta as MetaRecord; |
||
| 26 | use yii\base\Exception; |
||
| 27 | |||
| 28 | /** |
||
| 29 | * @author Flipbox Factory <[email protected]> |
||
| 30 | * @since 1.0.0 |
||
| 31 | * |
||
| 32 | * @method MetaQuery find() |
||
| 33 | */ |
||
| 34 | class Fields extends SortableFields |
||
| 35 | { |
||
| 36 | /** |
||
| 37 | * @inheritdoc |
||
| 38 | */ |
||
| 39 | const SOURCE_ATTRIBUTE = MetaRecord::SOURCE_ATTRIBUTE; |
||
| 40 | |||
| 41 | /** |
||
| 42 | * @inheritdoc |
||
| 43 | */ |
||
| 44 | const TARGET_ATTRIBUTE = MetaRecord::TARGET_ATTRIBUTE; |
||
| 45 | |||
| 46 | /** |
||
| 47 | * @inheritdoc |
||
| 48 | */ |
||
| 49 | protected static function tableAlias(): string |
||
| 50 | { |
||
| 51 | return MetaRecord::tableAlias(); |
||
| 52 | } |
||
| 53 | |||
| 54 | /** |
||
| 55 | * @param FieldInterface $field |
||
| 56 | * @throws Exception |
||
| 57 | */ |
||
| 58 | private function ensureField(FieldInterface $field) |
||
| 59 | { |
||
| 60 | if (!$field instanceof MetaField) { |
||
| 61 | throw new Exception(sprintf( |
||
| 62 | "The field must be an instance of '%s', '%s' given.", |
||
| 63 | (string)MetaField::class, |
||
| 64 | (string)get_class($field) |
||
| 65 | )); |
||
| 66 | } |
||
| 67 | } |
||
| 68 | |||
| 69 | /** |
||
| 70 | * @inheritdoc |
||
| 71 | */ |
||
| 72 | public function getQuery( |
||
| 73 | FieldInterface $field, |
||
| 74 | ElementInterface $element = null |
||
| 75 | ): SortableAssociationQueryInterface { |
||
| 76 | /** @var MetaField $field */ |
||
| 77 | $this->ensureField($field); |
||
| 78 | |||
| 79 | $query = MetaPlugin::getInstance()->getElements()->getQuery(); |
||
| 80 | |||
| 81 | $query->siteId = $this->targetSiteId($element); |
||
| 82 | $query->fieldId = $field->id; |
||
| 83 | |||
| 84 | return $query; |
||
| 85 | } |
||
| 86 | |||
| 87 | |||
| 88 | /******************************************* |
||
| 89 | * NORMALIZE VALUE |
||
| 90 | *******************************************/ |
||
| 91 | |||
| 92 | /** |
||
| 93 | * @param FieldInterface $field |
||
| 94 | * @param $value |
||
| 95 | * @param ElementInterface|null $element |
||
| 96 | * @return array |
||
| 97 | */ |
||
| 98 | public function serializeValue( |
||
| 99 | FieldInterface $field, |
||
|
0 ignored issues
–
show
|
|||
| 100 | $value, |
||
| 101 | ElementInterface $element = null |
||
|
0 ignored issues
–
show
|
|||
| 102 | ): array { |
||
| 103 | /** @var MetaQuery $value */ |
||
| 104 | $serialized = []; |
||
| 105 | $new = 0; |
||
| 106 | |||
| 107 | foreach ($value->all() as $meta) { |
||
| 108 | $metaId = $meta->id ?? 'new' . ++$new; |
||
| 109 | $serialized[$metaId] = [ |
||
| 110 | 'enabled' => $meta->enabled, |
||
| 111 | 'fields' => $meta->getSerializedFieldValues(), |
||
| 112 | ]; |
||
| 113 | } |
||
| 114 | |||
| 115 | return $serialized; |
||
| 116 | } |
||
| 117 | |||
| 118 | /******************************************* |
||
| 119 | * NORMALIZE VALUE |
||
| 120 | *******************************************/ |
||
| 121 | |||
| 122 | /** |
||
| 123 | * Accepts input data and converts it into an array of associated Meta elements |
||
| 124 | * |
||
| 125 | * @param FieldInterface $field |
||
| 126 | * @param SortableAssociationQueryInterface $query |
||
| 127 | * @param array $value |
||
| 128 | * @param ElementInterface|null $element |
||
| 129 | */ |
||
| 130 | protected function normalizeQueryInputValues( |
||
| 131 | FieldInterface $field, |
||
| 132 | SortableAssociationQueryInterface $query, |
||
| 133 | array $value, |
||
| 134 | ElementInterface $element = null |
||
| 135 | ) { |
||
| 136 | /** @var MetaField $field */ |
||
| 137 | |||
| 138 | $models = []; |
||
| 139 | $sortOrder = 1; |
||
| 140 | $prevElement = null; |
||
| 141 | /** @var MetaElement|null $prevElement */ |
||
| 142 | |||
| 143 | // Get existing values |
||
| 144 | $existingValues = $element === null ? [] : $this->getExistingValues($field, $value, $element); |
||
| 145 | $ownerId = $element->id ?? null; |
||
| 146 | |||
| 147 | foreach ($value as $metaId => $metaData) { |
||
| 148 | // Is this new? (Or has it been deleted?) |
||
| 149 | if (strpos($metaId, 'new') === 0 || !isset($existingValues[$metaId])) { |
||
| 150 | $meta = MetaPlugin::getInstance()->getElements()->create([ |
||
| 151 | 'fieldId' => $field->id, |
||
| 152 | 'ownerId' => $ownerId, |
||
| 153 | 'siteId' => $this->targetSiteId($element) |
||
| 154 | ]); |
||
| 155 | } else { |
||
| 156 | $meta = $existingValues[$metaId]; |
||
| 157 | } |
||
| 158 | |||
| 159 | /** @var MetaElement $meta */ |
||
| 160 | |||
| 161 | $meta->enabled = (bool)$metaData['enabled'] ?? true; |
||
| 162 | $meta->setOwnerId($ownerId); |
||
| 163 | |||
| 164 | // Set the content post location on the element if we can |
||
| 165 | $fieldNamespace = $element->getFieldParamNamespace(); |
||
| 166 | |||
| 167 | if ($fieldNamespace !== null) { |
||
| 168 | $metaFieldNamespace = ($fieldNamespace ? $fieldNamespace . '.' : '') . |
||
| 169 | '.' . $field->handle . |
||
| 170 | '.' . $metaId . |
||
| 171 | '.fields'; |
||
| 172 | $meta->setFieldParamNamespace($metaFieldNamespace); |
||
| 173 | } |
||
| 174 | |||
| 175 | if (isset($metaData['fields'])) { |
||
| 176 | $meta->setFieldValues($metaData['fields']); |
||
| 177 | } |
||
| 178 | |||
| 179 | $sortOrder++; |
||
| 180 | $meta->sortOrder = $sortOrder; |
||
| 181 | |||
| 182 | // Set the prev/next elements |
||
| 183 | if ($prevElement) { |
||
| 184 | $prevElement->setNext($meta); |
||
| 185 | $meta->setPrev($prevElement); |
||
| 186 | } |
||
| 187 | $prevElement = $meta; |
||
| 188 | |||
| 189 | $models[] = $meta; |
||
| 190 | } |
||
| 191 | $query->setCachedResult($models); |
||
| 192 | } |
||
| 193 | |||
| 194 | /** |
||
| 195 | * @param MetaField $field |
||
| 196 | * @param array $values |
||
| 197 | * @param ElementInterface $element |
||
| 198 | * @return array |
||
| 199 | */ |
||
| 200 | protected function getExistingValues(MetaField $field, array $values, ElementInterface $element): array |
||
| 201 | { |
||
| 202 | /** @var Element $element */ |
||
| 203 | if (!empty($element->id)) { |
||
| 204 | $ids = []; |
||
| 205 | |||
| 206 | foreach ($values as $metaId => $meta) { |
||
| 207 | if (is_numeric($metaId) && $metaId !== 0) { |
||
| 208 | $ids[] = $metaId; |
||
| 209 | } |
||
| 210 | } |
||
| 211 | |||
| 212 | if (!empty($ids)) { |
||
| 213 | $oldMetaQuery = MetaPlugin::getInstance()->getElements()->getQuery(); |
||
| 214 | $oldMetaQuery->fieldId($field->id); |
||
| 215 | $oldMetaQuery->ownerId($element->id); |
||
| 216 | $oldMetaQuery->id($ids); |
||
| 217 | $oldMetaQuery->limit(null); |
||
| 218 | $oldMetaQuery->status(null); |
||
| 219 | $oldMetaQuery->enabledForSite(false); |
||
| 220 | $oldMetaQuery->siteId($element->siteId); |
||
| 221 | $oldMetaQuery->indexBy('id'); |
||
| 222 | return $oldMetaQuery->all(); |
||
| 223 | } |
||
| 224 | } |
||
| 225 | |||
| 226 | return []; |
||
| 227 | } |
||
| 228 | |||
| 229 | |||
| 230 | /******************************************* |
||
| 231 | * ELEMENT EVENTS |
||
| 232 | *******************************************/ |
||
| 233 | |||
| 234 | /** |
||
| 235 | * @param MetaField $field |
||
| 236 | * @param ElementInterface $element |
||
| 237 | * @return bool |
||
| 238 | * @throws \Throwable |
||
| 239 | */ |
||
| 240 | public function beforeElementDelete(MetaField $field, ElementInterface $element): bool |
||
| 241 | { |
||
| 242 | // Delete any meta elements that belong to this element(s) |
||
| 243 | foreach (Craft::$app->getSites()->getAllSiteIds() as $siteId) { |
||
| 244 | $query = MetaElement::find(); |
||
| 245 | $query->status(null); |
||
| 246 | $query->enabledForSite(false); |
||
| 247 | $query->fieldId($field->id); |
||
| 248 | $query->siteId($siteId); |
||
| 249 | $query->owner($element); |
||
| 250 | |||
| 251 | /** @var MetaElement $meta */ |
||
| 252 | foreach ($query->all() as $meta) { |
||
| 253 | Craft::$app->getElements()->deleteElement($meta); |
||
| 254 | } |
||
| 255 | } |
||
| 256 | |||
| 257 | return true; |
||
| 258 | } |
||
| 259 | |||
| 260 | /** |
||
| 261 | * @param Meta $field |
||
| 262 | * @param ElementInterface $owner |
||
| 263 | * @throws \Exception |
||
| 264 | * @throws \Throwable |
||
| 265 | * @throws \yii\db\Exception |
||
| 266 | */ |
||
| 267 | public function afterElementSave(MetaField $field, ElementInterface $owner) |
||
| 268 | { |
||
| 269 | /** @var Element $owner */ |
||
| 270 | |||
| 271 | /** @var MetaQuery $query */ |
||
| 272 | $query = $owner->getFieldValue($field->handle); |
||
| 273 | |||
| 274 | // Skip if the query's site ID is different than the element's |
||
| 275 | // (Indicates that the value as copied from another site for element propagation) |
||
| 276 | if ($query->siteId != $owner->siteId) { |
||
| 277 | return; |
||
| 278 | } |
||
| 279 | |||
| 280 | if (null === ($elements = $query->getCachedResult())) { |
||
| 281 | $query = clone $query; |
||
| 282 | $query->status = null; |
||
| 283 | $query->enabledForSite = false; |
||
| 284 | $elements = $query->all(); // existing meta |
||
| 285 | } |
||
| 286 | |||
| 287 | $transaction = Craft::$app->getDb()->beginTransaction(); |
||
| 288 | try { |
||
| 289 | // If this is a preexisting element, make sure that the blocks for this field/owner respect the |
||
| 290 | // field's translation setting |
||
| 291 | if ($query->ownerId) { |
||
| 292 | $this->applyFieldTranslationSetting($query->ownerId, $query->siteId, $field); |
||
|
0 ignored issues
–
show
It seems like
$query->ownerId can also be of type array<integer,integer>; however, flipbox\meta\services\Fi...eldTranslationSetting() does only seem to accept integer, maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. Loading history...
|
|||
| 293 | } |
||
| 294 | |||
| 295 | // If the query is set to fetch blocks of a different owner, we're probably duplicating an element |
||
| 296 | if ($query->ownerId && $query->ownerId != $owner->id) { |
||
| 297 | $this->duplicate($field, $owner, $query, $elements); |
||
| 298 | } else { |
||
| 299 | $this->save($field, $owner, $elements); |
||
| 300 | } |
||
| 301 | |||
| 302 | $transaction->commit(); |
||
| 303 | } catch (\Exception $e) { |
||
| 304 | $transaction->rollback(); |
||
| 305 | throw $e; |
||
| 306 | } |
||
| 307 | |||
| 308 | return; |
||
| 309 | } |
||
| 310 | |||
| 311 | /** |
||
| 312 | * @param MetaField $field |
||
| 313 | * @param ElementInterface $owner |
||
| 314 | * @param MetaQuery $query |
||
| 315 | * @param array $elements |
||
| 316 | * @throws \Throwable |
||
| 317 | * @throws \craft\errors\InvalidElementException |
||
| 318 | */ |
||
| 319 | private function duplicate(MetaField $field, ElementInterface $owner, MetaQuery $query, array $elements) |
||
| 320 | { |
||
| 321 | /** @var Element $owner */ |
||
| 322 | |||
| 323 | $newQuery = clone $query; |
||
| 324 | $newQuery->ownerId = $owner->id; |
||
| 325 | if (!$newQuery->exists()) { |
||
| 326 | // Duplicate for the new owner |
||
| 327 | $elementsService = Craft::$app->getElements(); |
||
| 328 | foreach ($elements as $element) { |
||
| 329 | $elementsService->duplicateElement($element, [ |
||
| 330 | 'ownerId' => $owner->id, |
||
| 331 | 'ownerSiteId' => $field->localize ? $owner->siteId : null |
||
| 332 | ]); |
||
| 333 | } |
||
| 334 | } |
||
| 335 | } |
||
| 336 | |||
| 337 | /** |
||
| 338 | * @param MetaField $field |
||
| 339 | * @param ElementInterface $owner |
||
| 340 | * @param MetaElement[] $elements |
||
| 341 | * @throws Exception |
||
| 342 | * @throws \Throwable |
||
| 343 | * @throws \craft\errors\ElementNotFoundException |
||
| 344 | */ |
||
| 345 | private function save(MetaField $field, ElementInterface $owner, array $elements) |
||
| 346 | { |
||
| 347 | /** @var Element $owner */ |
||
| 348 | |||
| 349 | $elementIds = []; |
||
| 350 | |||
| 351 | // Only propagate the blocks if the owner isn't being propagated |
||
| 352 | $propagate = !$owner->propagating; |
||
| 353 | |||
| 354 | /** @var MetaElement $element */ |
||
| 355 | foreach ($elements as $element) { |
||
| 356 | $element->setOwner($owner); |
||
| 357 | $element->ownerSiteId = ($field->localize ? $owner->siteId : null); |
||
| 358 | $element->propagating = $owner->propagating; |
||
| 359 | |||
| 360 | Craft::$app->getElements()->saveElement($element, false, $propagate); |
||
| 361 | |||
| 362 | $elementIds[] = $element->id; |
||
| 363 | } |
||
| 364 | |||
| 365 | // Delete any elements that have been removed |
||
| 366 | $this->deleteOld($field, $owner, $elementIds); |
||
| 367 | } |
||
| 368 | |||
| 369 | /** |
||
| 370 | * @param MetaField $field |
||
| 371 | * @param ElementInterface $owner |
||
| 372 | * @param array $excludeIds |
||
| 373 | * @throws \Throwable |
||
| 374 | */ |
||
| 375 | private function deleteOld(MetaField $field, ElementInterface $owner, array $excludeIds) |
||
| 376 | { |
||
| 377 | /** @var Element $owner */ |
||
| 378 | |||
| 379 | $deleteElementsQuery = MetaElement::find() |
||
| 380 | ->status(null) |
||
| 381 | ->enabledForSite(false) |
||
| 382 | ->ownerId($owner->id) |
||
| 383 | ->fieldId($field->id) |
||
| 384 | ->where(['not', ['elements.id' => $excludeIds]]); |
||
| 385 | |||
| 386 | if ($field->localize) { |
||
| 387 | $deleteElementsQuery->ownerSiteId($owner->siteId); |
||
| 388 | } else { |
||
| 389 | $deleteElementsQuery->siteId($owner->siteId); |
||
| 390 | } |
||
| 391 | |||
| 392 | foreach ($deleteElementsQuery->all() as $deleteElement) { |
||
| 393 | Craft::$app->getElements()->deleteElement($deleteElement); |
||
| 394 | } |
||
| 395 | } |
||
| 396 | |||
| 397 | /** |
||
| 398 | * Applies the field's translation setting to a set of blocks. |
||
| 399 | * |
||
| 400 | * @param int $ownerId |
||
| 401 | * @param int $ownerSiteId |
||
| 402 | * @param Meta $field |
||
| 403 | * @throws Exception |
||
| 404 | * @throws \Throwable |
||
| 405 | * @throws \craft\errors\ElementNotFoundException |
||
| 406 | */ |
||
| 407 | private function applyFieldTranslationSetting(int $ownerId, int $ownerSiteId, MetaField $field) |
||
| 408 | { |
||
| 409 | // If the field is translatable, see if there are any global blocks that should be localized |
||
| 410 | if ($field->localize) { |
||
| 411 | $this->saveFieldTranslations($field, $ownerId, $ownerSiteId); |
||
| 412 | } else { |
||
| 413 | // Otherwise, see if the field has any localized blocks that should be deleted |
||
| 414 | foreach (Craft::$app->getSites()->getAllSiteIds() as $siteId) { |
||
| 415 | if ($siteId != $ownerSiteId) { |
||
| 416 | /** @var MetaQuery $elements */ |
||
| 417 | $elements = MetaElement::find() |
||
|
0 ignored issues
–
show
The method
ownerSiteId() does not exist on craft\elements\db\ElementQuery. Did you maybe mean siteId()?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. Loading history...
|
|||
| 418 | ->fieldId($field->id) |
||
| 419 | ->ownerId($ownerId) |
||
| 420 | ->status(null) |
||
| 421 | ->enabledForSite(false) |
||
| 422 | ->limit(null) |
||
| 423 | ->siteId($siteId) |
||
| 424 | ->ownerSiteId($siteId) |
||
| 425 | ->all(); |
||
| 426 | |||
| 427 | foreach ($elements as $element) { |
||
| 428 | Craft::$app->getElements()->deleteElement($element); |
||
| 429 | } |
||
| 430 | } |
||
| 431 | } |
||
| 432 | } |
||
| 433 | } |
||
| 434 | |||
| 435 | /** |
||
| 436 | * @param MetaField $field |
||
| 437 | * @param int $ownerId |
||
| 438 | * @param int $ownerSiteId |
||
| 439 | * @throws Exception |
||
| 440 | * @throws \Throwable |
||
| 441 | * @throws \craft\errors\ElementNotFoundException |
||
| 442 | */ |
||
| 443 | private function saveFieldTranslations(MetaField $field, int $ownerId, int $ownerSiteId) |
||
| 444 | { |
||
| 445 | /** @var MetaQuery $elements */ |
||
| 446 | $elementQuery = MetaElement::find() |
||
|
0 ignored issues
–
show
The method
ownerSiteId() does not exist on craft\elements\db\ElementQuery. Did you maybe mean siteId()?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. Loading history...
|
|||
| 447 | ->fieldId($field->id) |
||
| 448 | ->ownerId($ownerId) |
||
| 449 | ->status(null) |
||
| 450 | ->enabledForSite(false) |
||
| 451 | ->limit(null) |
||
| 452 | ->siteId($ownerSiteId) |
||
| 453 | ->ownerSiteId(':empty:'); |
||
| 454 | |||
| 455 | $elements = $elementQuery->all(); |
||
| 456 | |||
| 457 | if (empty($elements)) { |
||
| 458 | return; |
||
| 459 | } |
||
| 460 | |||
| 461 | // Prefetch the blocks in all the other sites, in case they have any localized content |
||
| 462 | $otherSiteMeta = $this->getOtherSiteMeta($elementQuery, $ownerSiteId); |
||
| 463 | |||
| 464 | // Explicitly assign the current site's blocks to the current site |
||
| 465 | foreach ($elements as $element) { |
||
| 466 | $element->ownerSiteId = $ownerSiteId; |
||
| 467 | Craft::$app->getElements()->saveElement($element, false); |
||
| 468 | } |
||
| 469 | |||
| 470 | // Now save the other sites' blocks as new site-specific blocks |
||
| 471 | foreach ($otherSiteMeta as $siteId => $siteElements) { |
||
| 472 | foreach ($siteElements as $element) { |
||
| 473 | $element->id = null; |
||
| 474 | $element->contentId = null; |
||
| 475 | $element->siteId = (int)$siteId; |
||
| 476 | $element->ownerSiteId = (int)$siteId; |
||
| 477 | Craft::$app->getElements()->saveElement($element, false); |
||
| 478 | } |
||
| 479 | } |
||
| 480 | } |
||
| 481 | |||
| 482 | /** |
||
| 483 | * @param MetaQuery $query |
||
| 484 | * @param int $ownerSiteId |
||
| 485 | * @return array |
||
| 486 | */ |
||
| 487 | private function getOtherSiteMeta(MetaQuery $query, int $ownerSiteId) |
||
| 488 | { |
||
| 489 | // Find any relational fields |
||
| 490 | $relationFields = $this->getRelationFields($query->all()); |
||
| 491 | |||
| 492 | $otherSiteMeta = []; |
||
| 493 | foreach (Craft::$app->getSites()->getAllSiteIds() as $siteId) { |
||
| 494 | if ($siteId != $ownerSiteId) { |
||
| 495 | /** @var MetaElement[] $siteElements */ |
||
| 496 | $siteElements = $otherSiteMeta[$siteId] = $query->siteId($siteId)->all(); |
||
| 497 | |||
| 498 | // Hard-set the relation IDs |
||
| 499 | foreach ($siteElements as $element) { |
||
| 500 | foreach ($relationFields as $handle) { |
||
| 501 | /** @var ElementQueryInterface $relationQuery */ |
||
| 502 | $relationQuery = $element->getFieldValue($handle); |
||
| 503 | $element->setFieldValue($handle, $relationQuery->ids()); |
||
| 504 | } |
||
| 505 | } |
||
| 506 | } |
||
| 507 | } |
||
| 508 | |||
| 509 | return $otherSiteMeta; |
||
| 510 | } |
||
| 511 | |||
| 512 | /** |
||
| 513 | * @param array $elements |
||
| 514 | * @return array |
||
| 515 | */ |
||
| 516 | private function getRelationFields(array $elements) |
||
| 517 | { |
||
| 518 | // Find any relational fields on these blocks |
||
| 519 | $relationFields = []; |
||
| 520 | |||
| 521 | foreach ($elements as $element) { |
||
| 522 | foreach ($element->getFieldLayout()->getFields() as $field) { |
||
| 523 | if ($field instanceof BaseRelationField) { |
||
| 524 | $relationFields[] = $field->handle; |
||
| 525 | } |
||
| 526 | } |
||
| 527 | break; |
||
| 528 | } |
||
| 529 | |||
| 530 | return $relationFields; |
||
| 531 | } |
||
| 532 | |||
| 533 | /** |
||
| 534 | * @inheritdoc |
||
| 535 | */ |
||
| 536 | protected function normalizeQueryInputValue( |
||
| 537 | FieldInterface $field, |
||
| 538 | $value, |
||
| 539 | int &$sortOrder, |
||
| 540 | ElementInterface $element = null |
||
| 541 | ): SortableAssociationInterface { |
||
| 542 | |||
| 543 | throw new Exception(__METHOD__ . ' is not implemented'); |
||
| 544 | } |
||
| 545 | } |
||
| 546 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.