CerField.inc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <?php
  2. /**
  3. * @file
  4. * Contains the base class for CER field plugins.
  5. *
  6. * A field plugin tells CER how to interact with fields of a certain type. If a particular
  7. * field type integrates with Entity API, its CER plugin can be as simple as extending
  8. * CerField and implementing the getTargetType() method.
  9. *
  10. * @todo
  11. * More info about extending CerFieldHandler to further customize field plugins.
  12. */
  13. /**
  14. * @class
  15. * Represents a single field instance.
  16. */
  17. abstract class CerField extends FieldInstance {
  18. /**
  19. * @var array
  20. * The plugin definition.
  21. */
  22. protected $plugin;
  23. /**
  24. * @var array
  25. */
  26. protected $settings = array();
  27. /**
  28. * @var string
  29. */
  30. public $fieldTypeLabel;
  31. /**
  32. * Gets the type of entity that can be referenced by this field, e.g. 'node'.
  33. *
  34. * @return string
  35. */
  36. abstract public function getTargetType();
  37. /**
  38. * Constructor. Pretty self-explanatory!
  39. */
  40. public function __construct(array $plugin) {
  41. // Store a copy of our plugin definition.
  42. $this->plugin = $plugin;
  43. list ($entity_type, $bundle, $field_name) = explode(':', $plugin['identifier']);
  44. parent::__construct($entity_type, $bundle, $field_name);
  45. // Store a copy of the field settings for convenience. At the time of this
  46. // writing, this is needed by the Entity Reference, Node Reference,
  47. // and Term Reference plugins.
  48. $info = field_info_field($this->name);
  49. $this->settings = $info['settings'];
  50. $type_info = field_info_field_types($info['type']);
  51. $this->fieldTypeLabel = $type_info['label'];
  52. }
  53. /**
  54. * Returns a CerFieldHandler subclass instance for the given entity.
  55. *
  56. * @param object $entity
  57. * The entity to be wrapped by the handler.
  58. *
  59. * @return CerFieldHandler
  60. */
  61. public function getHandler(EntityDrupalWrapper $entity) {
  62. return new $this->plugin['handler']($this, $entity);
  63. }
  64. /**
  65. * Returns the bundles that this field instance can reference.
  66. *
  67. * @return array
  68. */
  69. public function getTargetBundles() {
  70. $info = entity_get_info($this->getTargetType());
  71. return array_keys($info['bundles']);
  72. }
  73. /**
  74. * Overridden.
  75. */
  76. public function requireParent() {
  77. return $this->plugin['require parent'];
  78. }
  79. /**
  80. * Overridden.
  81. */
  82. public function getParents() {
  83. return array_map('CerField::getPlugin', $this->plugin['parents']);
  84. }
  85. /**
  86. * Returns information about a particular field plugin by its identifier, or all
  87. * available plugins (i.e., defined by hook_cer_fields()) if no identifier is given.
  88. * The aggregated result of hook_cer_fields() is statically cached.
  89. */
  90. public static function getPluginInfo($identifier = NULL) {
  91. $info = &drupal_static(__METHOD__);
  92. if (! isset($info)) {
  93. $info = module_invoke_all('cer_fields');
  94. foreach ($info as $key => &$field) {
  95. $field += array(
  96. 'identifier' =>
  97. $key,
  98. 'parents' =>
  99. array(),
  100. 'require parent' =>
  101. FALSE,
  102. 'handler' =>
  103. 'CerFieldHandler',
  104. );
  105. }
  106. drupal_alter('cer_fields', $info);
  107. }
  108. return ($identifier ? (isset($info[$identifier]) ? $info[$identifier] : NULL) : $info);
  109. }
  110. /**
  111. * Returns a single field plugin instance, by its identifier. All plugin instances
  112. * are statically cached.
  113. *
  114. * @param string $identifier
  115. * The plugin's identifier, in the format entity_type:bundle:field_name.
  116. *
  117. * @return CerField
  118. *
  119. * @throws Exception if there's no plugin for the given identifier. Why so harsh, you
  120. * ask? Because CerFieldChain::unpack() utterly depends on being able to get plugin
  121. * instances for every field in the chain, and if it can't, it could result in myriad
  122. * weird and serious problems. Throwing an exception will head that off at the pass.
  123. */
  124. public static function getPlugin($identifier) {
  125. $instances = &drupal_static(__METHOD__);
  126. if (! isset($instances[$identifier])) {
  127. $info = self::getPluginInfo($identifier);
  128. if ($info) {
  129. $instances[$identifier] = new $info['class']($info);
  130. }
  131. else {
  132. throw new Exception("Cannot get instance of invalid plugin $identifier.");
  133. }
  134. }
  135. return $instances[$identifier];
  136. }
  137. }