annotate core/lib/Drupal/Core/Field/FieldConfigBase.php @ 14:1fec387a4317

Update Drupal core to 8.5.2 via Composer
author Chris Cannam
date Mon, 23 Apr 2018 09:46:53 +0100
parents 4c8ae668cc8c
children 129ea1e6d783
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Core\Field;
Chris@0 4
Chris@0 5 use Drupal\Core\Config\Entity\ConfigEntityBase;
Chris@0 6 use Drupal\Core\Entity\EntityStorageInterface;
Chris@0 7 use Drupal\Core\Entity\FieldableEntityInterface;
Chris@0 8 use Drupal\Core\Field\TypedData\FieldItemDataDefinition;
Chris@0 9
Chris@0 10 /**
Chris@0 11 * Base class for configurable field definitions.
Chris@0 12 */
Chris@0 13 abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigInterface {
Chris@0 14
Chris@0 15 /**
Chris@0 16 * The field ID.
Chris@0 17 *
Chris@0 18 * The ID consists of 3 parts: the entity type, bundle and the field name.
Chris@0 19 *
Chris@0 20 * Example: node.article.body, user.user.field_main_image.
Chris@0 21 *
Chris@0 22 * @var string
Chris@0 23 */
Chris@0 24 protected $id;
Chris@0 25
Chris@0 26 /**
Chris@0 27 * The field name.
Chris@0 28 *
Chris@0 29 * @var string
Chris@0 30 */
Chris@0 31 protected $field_name;
Chris@0 32
Chris@0 33 /**
Chris@0 34 * The field type.
Chris@0 35 *
Chris@0 36 * This property is denormalized from the field storage for optimization of
Chris@0 37 * the "entity and render cache hits" critical paths. If not present in the
Chris@0 38 * $values passed to create(), it is populated from the field storage in
Chris@0 39 * postCreate(), and saved in config records so that it is present on
Chris@0 40 * subsequent loads.
Chris@0 41 *
Chris@0 42 * @var string
Chris@0 43 */
Chris@0 44 protected $field_type;
Chris@0 45
Chris@0 46 /**
Chris@0 47 * The name of the entity type the field is attached to.
Chris@0 48 *
Chris@0 49 * @var string
Chris@0 50 */
Chris@0 51 protected $entity_type;
Chris@0 52
Chris@0 53 /**
Chris@0 54 * The name of the bundle the field is attached to.
Chris@0 55 *
Chris@0 56 * @var string
Chris@0 57 */
Chris@0 58 protected $bundle;
Chris@0 59
Chris@0 60 /**
Chris@0 61 * The human-readable label for the field.
Chris@0 62 *
Chris@0 63 * This will be used as the title of Form API elements for the field in entity
Chris@0 64 * edit forms, or as the label for the field values in displayed entities.
Chris@0 65 *
Chris@0 66 * If not specified, this defaults to the field_name (mostly useful for fields
Chris@0 67 * created in tests).
Chris@0 68 *
Chris@0 69 * @var string
Chris@0 70 */
Chris@0 71 protected $label;
Chris@0 72
Chris@0 73 /**
Chris@0 74 * The field description.
Chris@0 75 *
Chris@0 76 * A human-readable description for the field when used with this bundle.
Chris@0 77 * For example, the description will be the help text of Form API elements for
Chris@0 78 * this field in entity edit forms.
Chris@0 79 *
Chris@0 80 * @var string
Chris@0 81 */
Chris@0 82 protected $description = '';
Chris@0 83
Chris@0 84 /**
Chris@0 85 * Field-type specific settings.
Chris@0 86 *
Chris@0 87 * An array of key/value pairs. The keys and default values are defined by the
Chris@0 88 * field type.
Chris@0 89 *
Chris@0 90 * @var array
Chris@0 91 */
Chris@0 92 protected $settings = [];
Chris@0 93
Chris@0 94 /**
Chris@0 95 * Flag indicating whether the field is required.
Chris@0 96 *
Chris@0 97 * TRUE if a value for this field is required when used with this bundle,
Chris@0 98 * FALSE otherwise. Currently, required-ness is only enforced at the Form API
Chris@0 99 * level in entity edit forms, not during direct API saves.
Chris@0 100 *
Chris@0 101 * @var bool
Chris@0 102 */
Chris@0 103 protected $required = FALSE;
Chris@0 104
Chris@0 105 /**
Chris@0 106 * Flag indicating whether the field is translatable.
Chris@0 107 *
Chris@0 108 * Defaults to TRUE.
Chris@0 109 *
Chris@0 110 * @var bool
Chris@0 111 */
Chris@0 112 protected $translatable = TRUE;
Chris@0 113
Chris@0 114 /**
Chris@0 115 * Default field value.
Chris@0 116 *
Chris@0 117 * The default value is used when an entity is created, either:
Chris@0 118 * - through an entity creation form; the form elements for the field are
Chris@0 119 * prepopulated with the default value.
Chris@0 120 * - through direct API calls (i.e. $entity->save()); the default value is
Chris@0 121 * added if the $entity object provides no explicit entry (actual values or
Chris@0 122 * "the field is empty") for the field.
Chris@0 123 *
Chris@0 124 * The default value is expressed as a numerically indexed array of items,
Chris@0 125 * each item being an array of key/value pairs matching the set of 'columns'
Chris@0 126 * defined by the "field schema" for the field type, as exposed in
Chris@0 127 * hook_field_schema(). If the number of items exceeds the cardinality of the
Chris@0 128 * field, extraneous items will be ignored.
Chris@0 129 *
Chris@0 130 * This property is overlooked if the $default_value_callback is non-empty.
Chris@0 131 *
Chris@0 132 * Example for a integer field:
Chris@0 133 * @code
Chris@0 134 * array(
Chris@0 135 * array('value' => 1),
Chris@0 136 * array('value' => 2),
Chris@0 137 * )
Chris@0 138 * @endcode
Chris@0 139 *
Chris@0 140 * @var array
Chris@0 141 */
Chris@0 142 protected $default_value = [];
Chris@0 143
Chris@0 144 /**
Chris@0 145 * The name of a callback function that returns default values.
Chris@0 146 *
Chris@0 147 * The function will be called with the following arguments:
Chris@0 148 * - \Drupal\Core\Entity\FieldableEntityInterface $entity
Chris@0 149 * The entity being created.
Chris@0 150 * - \Drupal\Core\Field\FieldDefinitionInterface $definition
Chris@0 151 * The field definition.
Chris@0 152 * It should return an array of default values, in the same format as the
Chris@0 153 * $default_value property.
Chris@0 154 *
Chris@0 155 * This property takes precedence on the list of fixed values specified in the
Chris@0 156 * $default_value property.
Chris@0 157 *
Chris@0 158 * @var string
Chris@0 159 */
Chris@0 160 protected $default_value_callback = '';
Chris@0 161
Chris@0 162 /**
Chris@0 163 * The field storage object.
Chris@0 164 *
Chris@0 165 * @var \Drupal\Core\Field\FieldStorageDefinitionInterface
Chris@0 166 */
Chris@0 167 protected $fieldStorage;
Chris@0 168
Chris@0 169 /**
Chris@0 170 * The data definition of a field item.
Chris@0 171 *
Chris@0 172 * @var \Drupal\Core\Field\TypedData\FieldItemDataDefinition
Chris@0 173 */
Chris@0 174 protected $itemDefinition;
Chris@0 175
Chris@0 176 /**
Chris@0 177 * Array of constraint options keyed by constraint plugin ID.
Chris@0 178 *
Chris@0 179 * @var array
Chris@0 180 */
Chris@0 181 protected $constraints = [];
Chris@0 182
Chris@0 183 /**
Chris@0 184 * Array of property constraint options keyed by property ID. The values are
Chris@0 185 * associative array of constraint options keyed by constraint plugin ID.
Chris@0 186 *
Chris@0 187 * @var array[]
Chris@0 188 */
Chris@0 189 protected $propertyConstraints = [];
Chris@0 190
Chris@0 191 /**
Chris@0 192 * {@inheritdoc}
Chris@0 193 */
Chris@0 194 public function id() {
Chris@0 195 return $this->entity_type . '.' . $this->bundle . '.' . $this->field_name;
Chris@0 196 }
Chris@0 197
Chris@0 198 /**
Chris@0 199 * {@inheritdoc}
Chris@0 200 */
Chris@0 201 public function getName() {
Chris@0 202 return $this->field_name;
Chris@0 203 }
Chris@0 204
Chris@0 205 /**
Chris@0 206 * {@inheritdoc}
Chris@0 207 */
Chris@0 208 public function getType() {
Chris@0 209 return $this->field_type;
Chris@0 210 }
Chris@0 211
Chris@0 212 /**
Chris@0 213 * {@inheritdoc}
Chris@0 214 */
Chris@0 215 public function getTargetEntityTypeId() {
Chris@0 216 return $this->entity_type;
Chris@0 217 }
Chris@0 218
Chris@0 219 /**
Chris@0 220 * {@inheritdoc}
Chris@0 221 */
Chris@0 222 public function getTargetBundle() {
Chris@0 223 return $this->bundle;
Chris@0 224 }
Chris@0 225
Chris@0 226 /**
Chris@0 227 * {@inheritdoc}
Chris@0 228 */
Chris@0 229 public function calculateDependencies() {
Chris@0 230 parent::calculateDependencies();
Chris@0 231 // Add dependencies from the field type plugin. We can not use
Chris@0 232 // self::calculatePluginDependencies() because instantiation of a field item
Chris@0 233 // plugin requires a parent entity.
Chris@0 234 /** @var $field_type_manager \Drupal\Core\Field\FieldTypePluginManagerInterface */
Chris@0 235 $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
Chris@0 236 $definition = $field_type_manager->getDefinition($this->getType());
Chris@0 237 $this->addDependency('module', $definition['provider']);
Chris@0 238 // Plugins can declare additional dependencies in their definition.
Chris@0 239 if (isset($definition['config_dependencies'])) {
Chris@0 240 $this->addDependencies($definition['config_dependencies']);
Chris@0 241 }
Chris@0 242 // Let the field type plugin specify its own dependencies.
Chris@0 243 // @see \Drupal\Core\Field\FieldItemInterface::calculateDependencies()
Chris@0 244 $this->addDependencies($definition['class']::calculateDependencies($this));
Chris@0 245
Chris@0 246 // Create dependency on the bundle.
Chris@0 247 $bundle_config_dependency = $this->entityManager()->getDefinition($this->entity_type)->getBundleConfigDependency($this->bundle);
Chris@0 248 $this->addDependency($bundle_config_dependency['type'], $bundle_config_dependency['name']);
Chris@0 249
Chris@0 250 return $this;
Chris@0 251 }
Chris@0 252
Chris@0 253 /**
Chris@0 254 * {@inheritdoc}
Chris@0 255 */
Chris@0 256 public function onDependencyRemoval(array $dependencies) {
Chris@0 257 $changed = parent::onDependencyRemoval($dependencies);
Chris@0 258 $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
Chris@0 259 $definition = $field_type_manager->getDefinition($this->getType());
Chris@0 260 if ($definition['class']::onDependencyRemoval($this, $dependencies)) {
Chris@0 261 $changed = TRUE;
Chris@0 262 }
Chris@0 263 return $changed;
Chris@0 264 }
Chris@0 265
Chris@0 266
Chris@0 267 /**
Chris@0 268 * {@inheritdoc}
Chris@0 269 */
Chris@0 270 public function postCreate(EntityStorageInterface $storage) {
Chris@0 271 parent::postCreate($storage);
Chris@0 272 // If it was not present in the $values passed to create(), (e.g. for
Chris@0 273 // programmatic creation), populate the denormalized field_type property
Chris@0 274 // from the field storage, so that it gets saved in the config record.
Chris@0 275 if (empty($this->field_type)) {
Chris@0 276 $this->field_type = $this->getFieldStorageDefinition()->getType();
Chris@0 277 }
Chris@0 278 }
Chris@0 279
Chris@0 280 /**
Chris@0 281 * {@inheritdoc}
Chris@0 282 */
Chris@0 283 public function postSave(EntityStorageInterface $storage, $update = TRUE) {
Chris@0 284 // Clear the cache.
Chris@0 285 $this->entityManager()->clearCachedFieldDefinitions();
Chris@0 286
Chris@0 287 // Invalidate the render cache for all affected entities.
Chris@0 288 $entity_type = $this->getFieldStorageDefinition()->getTargetEntityTypeId();
Chris@0 289 if ($this->entityManager()->hasHandler($entity_type, 'view_builder')) {
Chris@0 290 $this->entityManager()->getViewBuilder($entity_type)->resetCache();
Chris@0 291 }
Chris@0 292 }
Chris@0 293
Chris@0 294 /**
Chris@0 295 * {@inheritdoc}
Chris@0 296 */
Chris@0 297 public function getLabel() {
Chris@0 298 return $this->label();
Chris@0 299 }
Chris@0 300
Chris@0 301 /**
Chris@0 302 * {@inheritdoc}
Chris@0 303 */
Chris@0 304 public function setLabel($label) {
Chris@0 305 $this->label = $label;
Chris@0 306 return $this;
Chris@0 307 }
Chris@0 308
Chris@0 309 /**
Chris@0 310 * {@inheritdoc}
Chris@0 311 */
Chris@0 312 public function getDescription() {
Chris@0 313 return $this->description;
Chris@0 314 }
Chris@0 315
Chris@0 316 /**
Chris@0 317 * {@inheritdoc}
Chris@0 318 */
Chris@0 319 public function setDescription($description) {
Chris@0 320 $this->description = $description;
Chris@0 321 return $this;
Chris@0 322 }
Chris@0 323
Chris@0 324 /**
Chris@0 325 * {@inheritdoc}
Chris@0 326 */
Chris@0 327 public function isTranslatable() {
Chris@0 328 // A field can be enabled for translation only if translation is supported.
Chris@0 329 return $this->translatable && $this->getFieldStorageDefinition()->isTranslatable();
Chris@0 330 }
Chris@0 331
Chris@0 332 /**
Chris@0 333 * {@inheritdoc}
Chris@0 334 */
Chris@0 335 public function setTranslatable($translatable) {
Chris@0 336 $this->translatable = $translatable;
Chris@0 337 return $this;
Chris@0 338 }
Chris@0 339
Chris@0 340 /**
Chris@0 341 * {@inheritdoc}
Chris@0 342 */
Chris@0 343 public function getSettings() {
Chris@0 344 return $this->settings + $this->getFieldStorageDefinition()->getSettings();
Chris@0 345 }
Chris@0 346
Chris@0 347 /**
Chris@0 348 * {@inheritdoc}
Chris@0 349 */
Chris@0 350 public function setSettings(array $settings) {
Chris@0 351 $this->settings = $settings + $this->settings;
Chris@0 352 return $this;
Chris@0 353 }
Chris@0 354
Chris@0 355 /**
Chris@0 356 * {@inheritdoc}
Chris@0 357 */
Chris@0 358 public function getSetting($setting_name) {
Chris@0 359 if (array_key_exists($setting_name, $this->settings)) {
Chris@0 360 return $this->settings[$setting_name];
Chris@0 361 }
Chris@0 362 else {
Chris@0 363 return $this->getFieldStorageDefinition()->getSetting($setting_name);
Chris@0 364 }
Chris@0 365 }
Chris@0 366
Chris@0 367 /**
Chris@0 368 * {@inheritdoc}
Chris@0 369 */
Chris@0 370 public function setSetting($setting_name, $value) {
Chris@0 371 $this->settings[$setting_name] = $value;
Chris@0 372 return $this;
Chris@0 373 }
Chris@0 374
Chris@0 375 /**
Chris@0 376 * {@inheritdoc}
Chris@0 377 */
Chris@0 378 public function isRequired() {
Chris@0 379 return $this->required;
Chris@0 380 }
Chris@0 381
Chris@0 382 /**
Chris@0 383 * [@inheritdoc}
Chris@0 384 */
Chris@0 385 public function setRequired($required) {
Chris@0 386 $this->required = $required;
Chris@0 387 return $this;
Chris@0 388 }
Chris@0 389
Chris@0 390 /**
Chris@0 391 * {@inheritdoc}
Chris@0 392 */
Chris@0 393 public function getDefaultValue(FieldableEntityInterface $entity) {
Chris@0 394 // Allow custom default values function.
Chris@0 395 if ($callback = $this->getDefaultValueCallback()) {
Chris@0 396 $value = call_user_func($callback, $entity, $this);
Chris@0 397 }
Chris@0 398 else {
Chris@0 399 $value = $this->getDefaultValueLiteral();
Chris@0 400 }
Chris@0 401 // Allow the field type to process default values.
Chris@0 402 $field_item_list_class = $this->getClass();
Chris@0 403 return $field_item_list_class::processDefaultValue($value, $entity, $this);
Chris@0 404 }
Chris@0 405
Chris@0 406 /**
Chris@0 407 * {@inheritdoc}
Chris@0 408 */
Chris@0 409 public function getDefaultValueLiteral() {
Chris@0 410 return $this->default_value;
Chris@0 411 }
Chris@0 412
Chris@0 413 /**
Chris@0 414 * {@inheritdoc}
Chris@0 415 */
Chris@0 416 public function setDefaultValue($value) {
Chris@0 417 if (!is_array($value)) {
Chris@0 418 if ($value === NULL) {
Chris@0 419 $value = [];
Chris@0 420 }
Chris@0 421 $key = $this->getFieldStorageDefinition()->getPropertyNames()[0];
Chris@0 422 // Convert to the multi value format to support fields with a cardinality
Chris@0 423 // greater than 1.
Chris@0 424 $value = [
Chris@0 425 [$key => $value],
Chris@0 426 ];
Chris@0 427 }
Chris@0 428 $this->default_value = $value;
Chris@0 429 return $this;
Chris@0 430 }
Chris@0 431
Chris@0 432 /**
Chris@0 433 * {@inheritdoc}
Chris@0 434 */
Chris@0 435 public function getDefaultValueCallback() {
Chris@0 436 return $this->default_value_callback;
Chris@0 437 }
Chris@0 438
Chris@0 439 /**
Chris@0 440 * {@inheritdoc}
Chris@0 441 */
Chris@0 442 public function setDefaultValueCallback($callback) {
Chris@0 443 $this->default_value_callback = $callback;
Chris@0 444 return $this;
Chris@0 445 }
Chris@0 446
Chris@0 447 /**
Chris@0 448 * Implements the magic __sleep() method.
Chris@0 449 *
Chris@0 450 * Using the Serialize interface and serialize() / unserialize() methods
Chris@0 451 * breaks entity forms in PHP 5.4.
Chris@0 452 * @todo Investigate in https://www.drupal.org/node/2074253.
Chris@0 453 */
Chris@0 454 public function __sleep() {
Chris@0 455 // Only serialize necessary properties, excluding those that can be
Chris@0 456 // recalculated.
Chris@0 457 $properties = get_object_vars($this);
Chris@0 458 unset($properties['fieldStorage'], $properties['itemDefinition'], $properties['original']);
Chris@0 459 return array_keys($properties);
Chris@0 460 }
Chris@0 461
Chris@0 462 /**
Chris@0 463 * {@inheritdoc}
Chris@0 464 */
Chris@0 465 public static function createFromItemType($item_type) {
Chris@0 466 // Forward to the field definition class for creating new data definitions
Chris@0 467 // via the typed manager.
Chris@0 468 return BaseFieldDefinition::createFromItemType($item_type);
Chris@0 469 }
Chris@0 470
Chris@0 471 /**
Chris@0 472 * {@inheritdoc}
Chris@0 473 */
Chris@0 474 public static function createFromDataType($type) {
Chris@0 475 // Forward to the field definition class for creating new data definitions
Chris@0 476 // via the typed manager.
Chris@0 477 return BaseFieldDefinition::createFromDataType($type);
Chris@0 478 }
Chris@0 479
Chris@0 480 /**
Chris@0 481 * {@inheritdoc}
Chris@0 482 */
Chris@0 483 public function getDataType() {
Chris@0 484 return 'list';
Chris@0 485 }
Chris@0 486
Chris@0 487 /**
Chris@0 488 * {@inheritdoc}
Chris@0 489 */
Chris@0 490 public function isList() {
Chris@0 491 return TRUE;
Chris@0 492 }
Chris@0 493
Chris@0 494 /**
Chris@0 495 * {@inheritdoc}
Chris@0 496 */
Chris@0 497 public function getClass() {
Chris@0 498 // Derive list class from the field type.
Chris@0 499 $type_definition = \Drupal::service('plugin.manager.field.field_type')
Chris@0 500 ->getDefinition($this->getType());
Chris@0 501 return $type_definition['list_class'];
Chris@0 502 }
Chris@0 503
Chris@0 504 /**
Chris@0 505 * {@inheritdoc}
Chris@0 506 */
Chris@0 507 public function getConstraints() {
Chris@0 508 return \Drupal::typedDataManager()->getDefaultConstraints($this) + $this->constraints;
Chris@0 509 }
Chris@0 510
Chris@0 511 /**
Chris@0 512 * {@inheritdoc}
Chris@0 513 */
Chris@0 514 public function getConstraint($constraint_name) {
Chris@0 515 $constraints = $this->getConstraints();
Chris@0 516 return isset($constraints[$constraint_name]) ? $constraints[$constraint_name] : NULL;
Chris@0 517 }
Chris@0 518
Chris@0 519 /**
Chris@0 520 * {@inheritdoc}
Chris@0 521 */
Chris@0 522 public function getItemDefinition() {
Chris@0 523 if (!isset($this->itemDefinition)) {
Chris@0 524 $this->itemDefinition = FieldItemDataDefinition::create($this)
Chris@0 525 ->setSettings($this->getSettings());
Chris@0 526
Chris@0 527 // Add any custom property constraints, overwriting as required.
Chris@0 528 $item_constraints = $this->itemDefinition->getConstraint('ComplexData') ?: [];
Chris@0 529 foreach ($this->propertyConstraints as $name => $constraints) {
Chris@0 530 if (isset($item_constraints[$name])) {
Chris@0 531 $item_constraints[$name] = $constraints + $item_constraints[$name];
Chris@0 532 }
Chris@0 533 else {
Chris@0 534 $item_constraints[$name] = $constraints;
Chris@0 535 }
Chris@0 536 $this->itemDefinition->addConstraint('ComplexData', $item_constraints);
Chris@0 537 }
Chris@0 538 }
Chris@0 539
Chris@0 540 return $this->itemDefinition;
Chris@0 541 }
Chris@0 542
Chris@0 543 /**
Chris@0 544 * {@inheritdoc}
Chris@0 545 */
Chris@0 546 public function getConfig($bundle) {
Chris@0 547 return $this;
Chris@0 548 }
Chris@0 549
Chris@0 550 /**
Chris@0 551 * {@inheritdoc}
Chris@0 552 */
Chris@0 553 public function setConstraints(array $constraints) {
Chris@0 554 $this->constraints = $constraints;
Chris@0 555 return $this;
Chris@0 556 }
Chris@0 557
Chris@0 558 /**
Chris@0 559 * {@inheritdoc}
Chris@0 560 */
Chris@0 561 public function addConstraint($constraint_name, $options = NULL) {
Chris@0 562 $this->constraints[$constraint_name] = $options;
Chris@0 563 return $this;
Chris@0 564 }
Chris@0 565
Chris@0 566 /**
Chris@0 567 * {@inheritdoc}
Chris@0 568 */
Chris@0 569 public function setPropertyConstraints($name, array $constraints) {
Chris@0 570 $this->propertyConstraints[$name] = $constraints;
Chris@0 571
Chris@0 572 // Reset the field item definition so the next time it is instantiated it
Chris@0 573 // will receive the new constraints.
Chris@0 574 $this->itemDefinition = NULL;
Chris@0 575
Chris@0 576 return $this;
Chris@0 577 }
Chris@0 578
Chris@0 579 /**
Chris@0 580 * {@inheritdoc}
Chris@0 581 */
Chris@0 582 public function addPropertyConstraints($name, array $constraints) {
Chris@0 583 foreach ($constraints as $constraint_name => $options) {
Chris@0 584 $this->propertyConstraints[$name][$constraint_name] = $options;
Chris@0 585 }
Chris@0 586
Chris@0 587 // Reset the field item definition so the next time it is instantiated it
Chris@0 588 // will receive the new constraints.
Chris@0 589 $this->itemDefinition = NULL;
Chris@0 590
Chris@0 591 return $this;
Chris@0 592 }
Chris@0 593
Chris@14 594 /**
Chris@14 595 * {@inheritdoc}
Chris@14 596 */
Chris@14 597 public function isInternal() {
Chris@14 598 // Respect the definition, otherwise default to TRUE for computed fields.
Chris@14 599 if (isset($this->definition['internal'])) {
Chris@14 600 return $this->definition['internal'];
Chris@14 601 }
Chris@14 602 return $this->isComputed();
Chris@14 603 }
Chris@14 604
Chris@0 605 }