Completed
Pull Request — master (#157)
by
unknown
01:57
created

DriverFieldBase::getProcessedValues()   C

Complexity

Conditions 8
Paths 18

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
c 0
b 0
f 0
rs 5.3846
cc 8
eloc 19
nc 18
nop 0
1
<?php
2
3
namespace Drupal\Driver\Wrapper\Field;
4
5
use Drupal\Driver\Plugin\DriverPluginManagerInterface;
6
use Drupal\Driver\Plugin\DriverFieldPluginManager;
7
8
/**
9
 * A base class for a Driver field wrapper.
10
 */
11
abstract class DriverFieldBase implements DriverFieldInterface {
12
13
  /**
14
   * Human-readable text intended to identify the field instance.
15
   *
16
   * @var string
17
   */
18
  protected $identifier;
19
20
  /**
21
   * Field instance's machine name.
22
   *
23
   * @var string
24
   */
25
  protected $name;
26
27
  /**
28
   * Entity type.
29
   *
30
   * @var string
31
   */
32
  protected $entityType;
33
34
  /**
35
   * Entity bundle.
36
   *
37
   * @var string
38
   */
39
  protected $bundle;
40
41
  /**
42
   * Raw field values before processing by DriverField plugins.
43
   *
44
   * @var array
45
   */
46
  protected $rawValues;
47
48
  /**
49
   * Field values after processing by DriverField plugins.
50
   *
51
   * @var array
52
   */
53
  protected $processedValues;
54
55
  /**
56
   * A driver field plugin manager object.
57
   *
58
   * @var \Drupal\Driver\Plugin\DriverPluginManagerInterface
59
   */
60
  protected $fieldPluginManager;
61
62
  /**
63
   * Directory to search for additional project-specific driver plugins.
64
   *
65
   * @var string
66
   */
67
  protected $projectPluginRoot;
68
69
  /**
70
   * Construct a DriverField object.
71
   *
72
   * @param mixed $rawValues
73
   *   Raw values for the field. Typically an array, one for each value of a
74
   *   multivalue field, but can be single. Values are typically string.
75
   * @param string $identifier
76
   *   The machine name of the field or property.
77
   * @param string $entityType
78
   *   The machine name of the entity type the field is attached to.
79
   * @param string $bundle
80
   *   (optional) Machine name of the entity bundle the field is attached to.
81
   * @param string $projectPluginRoot
82
   *   The directory to search for additional project-specific driver plugins.
83
   * @param null|\Drupal\Driver\Plugin\DriverPluginManagerInterface $fieldPluginManager
84
   *   (optional) A driver field plugin manager.
85
   */
86
  public function __construct(
87
        $rawValues,
88
        $identifier,
89
        $entityType,
90
        $bundle = NULL,
91
        $projectPluginRoot = NULL,
92
        $fieldPluginManager = NULL
93
    ) {
94
95
    // Default to entity type as bundle if no bundle specified.
96
    if (empty($bundle)) {
97
      $bundle = $entityType;
98
    }
99
    // Wrap single values into an array so single and multivalue fields can be
100
    // handled identically.
101
    if (!is_array($rawValues)) {
102
      $rawValues = [$rawValues];
103
    }
104
    $this->projectPluginRoot = $projectPluginRoot;
105
    $this->setFieldPluginManager($fieldPluginManager, $projectPluginRoot);
106
    $this->rawValues = $rawValues;
107
    $this->entityType = $entityType;
108
    $this->bundle = $bundle;
109
    $this->name = $this->identify($identifier);
110
    $this->identifier = $identifier;
111
  }
112
113
  /**
114
   * {@inheritdoc}
115
   */
116
  public function getBundle() {
117
    return $this->bundle;
118
  }
119
120
  /**
121
   * {@inheritdoc}
122
   */
123
  public function getEntityType() {
124
    return $this->entityType;
125
  }
126
127
  /**
128
   * {@inheritdoc}
129
   */
130
  public function getName() {
131
    return $this->name;
132
  }
133
134
  /**
135
   * {@inheritdoc}
136
   */
137
  public function getProcessedValues() {
138
    if (is_null($this->processedValues)) {
139
      $this->setProcessedValues($this->getRawValues());
140
      $fieldPluginManager = $this->getFieldPluginManager();
141
      $definitions = $fieldPluginManager->getMatchedDefinitions($this);
142
      // Process values through matched plugins, until a plugin
143
      // declares it is the final one.
144
      foreach ($definitions as $definition) {
145
        $plugin = $fieldPluginManager->createInstance($definition['id'], ['field' => $this]);
146
        $processedValues = $plugin->processValues($this->processedValues);
147
        if (!is_array($processedValues)) {
148
          throw new \Exception("Field plugin failed to return array of processed values.");
149
        }
150
        $this->setProcessedValues($processedValues);
151
        if ($plugin->isFinal($this)) {
152
          break;
153
        };
154
      }
155
    }
156
157
    // Don't pass an array back to singleton config properties.
158
    if ($this->isConfigProperty()) {
159
      if ($this->getType() !== 'sequence') {
160
        if (count($this->processedValues) > 1) {
161
          throw new \Exception("Config properties not of the type sequence should not have array input.");
162
        }
163
        return $this->processedValues[0];
164
      }
165
    }
166
    return $this->processedValues;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->processedValues; of type null|array adds the type array to the return on line 166 which is incompatible with the return type declared by the interface Drupal\Driver\Wrapper\Fi...ace::getProcessedValues of type string.
Loading history...
167
  }
168
169
  /**
170
   * {@inheritdoc}
171
   */
172
  public function getProjectPluginRoot() {
173
    return $this->projectPluginRoot;
174
  }
175
176
  /**
177
   * {@inheritdoc}
178
   */
179
  public function getRawValues() {
180
    return $this->rawValues;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->rawValues; (array) is incompatible with the return type declared by the interface Drupal\Driver\Wrapper\Fi...Interface::getRawValues of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
181
  }
182
183
  /**
184
   * Sets the processed values.
185
   *
186
   * @return \Drupal\Driver\Plugin\DriverPluginManagerInterface
187
   *   The field plugin manager.
188
   */
189
  protected function getFieldPluginManager() {
190
    return $this->fieldPluginManager;
191
  }
192
193
  /**
194
   * {@inheritdoc}
195
   */
196
  public function isConfigProperty() {
197
    return FALSE;
198
  }
199
200
  /**
201
   * Sets the processed values.
202
   *
203
   * @param array $values
204
   *   An array of processed field value sets.
205
   */
206
  protected function setProcessedValues(array $values) {
207
    $this->processedValues = $values;
208
  }
209
210
  /**
211
   * Set the driver field plugin manager.
212
   *
213
   * @param mixed $manager
214
   *   The driver entity plugin manager.
215
   * @param string $projectPluginRoot
216
   *   The directory to search for additional project-specific driver plugins.
217
   */
218
  protected function setFieldPluginManager($manager, $projectPluginRoot) {
219 View Code Duplication
    if (!($manager instanceof DriverPluginManagerInterface)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
220
      $manager = new DriverFieldPluginManager($this->namespaces, $this->cache_backend, $this->module_handler, $this->version, $projectPluginRoot);
0 ignored issues
show
Bug introduced by
The property namespaces does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The property cache_backend does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The property module_handler does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The property version does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
221
    }
222
    $this->fieldPluginManager = $manager;
223
  }
224
225
}
226