|
26 | 26 | use Drupal\Core\Entity\EntityTypeInterface;
|
27 | 27 | use Drupal\Core\Field\BaseFieldDefinition;
|
28 | 28 | use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
| 29 | +use Drupal\Core\Language\LanguageInterface; |
| 30 | +use Drupal\Core\TypedData\TypedDataInterface; |
29 | 31 |
|
30 | 32 | /**
|
31 | 33 | * Base field support for Apigee Entities without making them content entities.
|
@@ -536,4 +538,128 @@ public function getIterator(): \Traversable {
|
536 | 538 | return new \ArrayIterator($this->getFields());
|
537 | 539 | }
|
538 | 540 |
|
| 541 | + /** |
| 542 | + * The plain data values of the contained fields. |
| 543 | + * |
| 544 | + * This always holds the original, unchanged values of the entity. The values |
| 545 | + * are keyed by language code to follow core's suit, regardless that |
| 546 | + * Apigee Edge entities are NOT translatable. |
| 547 | + * |
| 548 | + * @todo: Add methods for getting original fields and for determining |
| 549 | + * changes. |
| 550 | + * @todo: Provide a better way for defining default values. |
| 551 | + * |
| 552 | + * @var array |
| 553 | + */ |
| 554 | + private $values = []; |
| 555 | + |
| 556 | + /** |
| 557 | + * Implements the magic method for getting object properties. |
| 558 | + * |
| 559 | + * @see https://www.drupal.org/project/drupal/issues/3281720 |
| 560 | + * @see \Drupal\Core\Entity\ContentEntityBase |
| 561 | + */ |
| 562 | + public function &__get($name) { |
| 563 | + // If this is an entity field, handle it accordingly. We first check whether |
| 564 | + // a field object has been already created. If not, we create one. |
| 565 | + if (isset($this->fields[$name][LanguageInterface::LANGCODE_NOT_SPECIFIED])) { |
| 566 | + return $this->fields[$name][LanguageInterface::LANGCODE_NOT_SPECIFIED]; |
| 567 | + } |
| 568 | + // Inline getFieldDefinition() to speed things up. |
| 569 | + if (!isset($this->fieldDefinitions)) { |
| 570 | + $this->getFieldDefinitions(); |
| 571 | + } |
| 572 | + // Apigee base fields are special, so they need special treatment. |
| 573 | + if (isset($this->fieldDefinitions[$name]) && !($this->fieldDefinitions[$name] instanceof BaseFieldDefinition)) { |
| 574 | + $return = $this->getField($name); |
| 575 | + return $return; |
| 576 | + } |
| 577 | + // Else directly read/write plain values. That way, non-field entity |
| 578 | + // properties can always be accessed directly. |
| 579 | + if (!isset($this->values[$name])) { |
| 580 | + $this->values[$name] = NULL; |
| 581 | + } |
| 582 | + return $this->values[$name]; |
| 583 | + } |
| 584 | + |
| 585 | + /** |
| 586 | + * Implements the magic method for setting object properties. |
| 587 | + * |
| 588 | + * Uses default language always. |
| 589 | + */ |
| 590 | + public function __set($name, $value) { |
| 591 | + // Inline getFieldDefinition() to speed things up. |
| 592 | + if (!isset($this->fieldDefinitions)) { |
| 593 | + $this->getFieldDefinitions(); |
| 594 | + } |
| 595 | + // Handle Field API fields. |
| 596 | + if (isset($this->fieldDefinitions[$name])) { |
| 597 | + // Support setting values via property objects. |
| 598 | + if ($value instanceof TypedDataInterface) { |
| 599 | + $value = $value->getValue(); |
| 600 | + } |
| 601 | + // If a FieldItemList object already exists, set its value. |
| 602 | + if (isset($this->fields[$name][LanguageInterface::LANGCODE_NOT_SPECIFIED])) { |
| 603 | + $this->fields[$name][LanguageInterface::LANGCODE_NOT_SPECIFIED]->setValue($value); |
| 604 | + } |
| 605 | + // If not, create one. |
| 606 | + else { |
| 607 | + $this->getField($name)->setValue($value); |
| 608 | + } |
| 609 | + } |
| 610 | + // Directly write non-field values. |
| 611 | + else { |
| 612 | + $this->values[$name] = $value; |
| 613 | + } |
| 614 | + } |
| 615 | + |
| 616 | + /** |
| 617 | + * Implements the magic method for isset(). |
| 618 | + */ |
| 619 | + public function __isset($name) { |
| 620 | + // "Official" Field API fields are always set. For non-field properties, |
| 621 | + // check the internal values. |
| 622 | + return $this->hasField($name) ? TRUE : isset($this->values[$name]); |
| 623 | + } |
| 624 | + |
| 625 | + /** |
| 626 | + * Implements the magic method for unset(). |
| 627 | + */ |
| 628 | + public function __unset($name) { |
| 629 | + // Unsetting a field means emptying it. |
| 630 | + if ($this->hasField($name)) { |
| 631 | + $this->get($name)->setValue([]); |
| 632 | + } |
| 633 | + // For non-field properties, unset the internal value. |
| 634 | + else { |
| 635 | + unset($this->values[$name]); |
| 636 | + } |
| 637 | + } |
| 638 | + |
| 639 | + /** |
| 640 | + * Gets a non-translatable field. |
| 641 | + * |
| 642 | + * @return \Drupal\Core\Field\FieldItemListInterface |
| 643 | + */ |
| 644 | + private function getField($name) { |
| 645 | + // Populate $this->fields to speed-up further look-ups and to keep track of |
| 646 | + // fields objects, possibly holding changes to field values. |
| 647 | + if (!isset($this->fields[$name][LanguageInterface::LANGCODE_NOT_SPECIFIED])) { |
| 648 | + $definition = $this->getFieldDefinition($name); |
| 649 | + if (!$definition) { |
| 650 | + throw new \InvalidArgumentException("Field $name is unknown."); |
| 651 | + } |
| 652 | + // Non-translatable fields are always stored with |
| 653 | + // LanguageInterface::LANGCODE_DEFAULT as key. |
| 654 | + $value = NULL; |
| 655 | + if (isset($this->values[$name][LanguageInterface::LANGCODE_NOT_SPECIFIED])) { |
| 656 | + $value = $this->values[$name][LanguageInterface::LANGCODE_NOT_SPECIFIED]; |
| 657 | + } |
| 658 | + $field = \Drupal::service('plugin.manager.field.field_type')->createFieldItemList($this->getTranslation(LanguageInterface::LANGCODE_NOT_SPECIFIED), $name, $value); |
| 659 | + $field->setLangcode(LanguageInterface::LANGCODE_NOT_SPECIFIED); |
| 660 | + $this->fields[$name][LanguageInterface::LANGCODE_NOT_SPECIFIED] = $field; |
| 661 | + } |
| 662 | + return $this->fields[$name][LanguageInterface::LANGCODE_NOT_SPECIFIED]; |
| 663 | + } |
| 664 | + |
539 | 665 | }
|
0 commit comments