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

DriverFieldBase::getProcessedValues()   C

Complexity

Conditions 8
Paths 18

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 32
rs 5.3846
c 0
b 0
f 0
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 object that holds information about a Drupal
10
 * entity field.
11
 */
12
abstract class DriverFieldBase implements DriverFieldInterface
13
{
14
15
  /**
16
   * Human-readable text intended to identify the field instance.
17
   *
18
   * @var string
19
   */
20
    protected $identifier;
21
22
  /**
23
   * Field instance's machine name.
24
   *
25
   * @var string
26
   */
27
    protected $name;
28
29
  /**
30
   * Entity type.
31
   *
32
   * @var string
33
   */
34
    protected $entityType;
35
36
  /**
37
   * Entity bundle.
38
   *
39
   * @var string
40
   */
41
    protected $bundle;
42
43
  /**
44
   * Raw field values before processing by DriverField plugins.
45
   *
46
   * @var array
47
   */
48
    protected $rawValues;
49
50
  /**
51
   * Field values after processing by DriverField plugins.
52
   *
53
   * @var array
54
   */
55
    protected $processedValues;
56
57
  /**
58
   * A driver field plugin manager object.
59
   *
60
   * @var \Drupal\Driver\Plugin\DriverPluginManagerInterface
61
   */
62
    protected $fieldPluginManager;
63
64
  /**
65
   * Directory to search for additional project-specific driver plugins.
66
   *
67
   * @var string
68
   */
69
    protected $projectPluginRoot;
70
71
  /**
72
   * Construct a DriverField object.
73
   *
74
   * @param mixed
75
   *   Raw values for the field. Typically an array, one for each value of a
76
   *   multivalue field, but can be single. Values are typically string.
77
   * @param string $fieldName
0 ignored issues
show
Bug introduced by
There is no parameter named $fieldName. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
78
   *   The machine name of the field.
79
   * @param string $entityType
80
   *   The machine name of the entity type the field is attached to.
81
   * @param string $bundle
82
   *   (optional) The machine name of the entity bundle the field is attached to.
83
   * @param string $projectPluginRoot
84
   *   The directory to search for additional project-specific driver plugins.
85
   * @param NULL|\Drupal\Driver\Plugin\DriverPluginManagerInterface $fieldPluginManager
86
   *   (optional) A driver field plugin manager.
87
   *
88
   */
89
    public function __construct(
90
        $rawValues,
91
        $identifier,
92
        $entityType,
93
        $bundle = null,
94
        $projectPluginRoot = null,
95
        $fieldPluginManager = null
96
    ) {
97
98
        // Default to entity type as bundle if no bundle specified.
99
        if (empty($bundle)) {
100
            $bundle = $entityType;
101
        }
102
        // Wrap single values into an array so single and multivalue fields can be
103
        // handled identically.
104
        if (!is_array($rawValues)) {
105
            $rawValues = [$rawValues];
106
        }
107
        $this->projectPluginRoot = $projectPluginRoot;
108
        $this->setFieldPluginManager($fieldPluginManager, $projectPluginRoot);
0 ignored issues
show
Bug introduced by
It seems like $fieldPluginManager defined by parameter $fieldPluginManager on line 95 can be null; however, Drupal\Driver\Wrapper\Fi...setFieldPluginManager() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
109
        $this->rawValues = $rawValues;
110
        $this->entityType = $entityType;
111
        $this->bundle = $bundle;
112
        $this->name = $this->identify($identifier);
113
        $this->identifier = $identifier;
114
    }
115
116
117
  /**
118
   * {@inheritdoc}
119
   */
120
    public function getBundle()
121
    {
122
        return $this->bundle;
123
    }
124
125
  /**
126
   * {@inheritdoc}
127
   */
128
    public function getEntityType()
129
    {
130
        return $this->entityType;
131
    }
132
133
  /**
134
   * {@inheritdoc}
135
   */
136
    public function getName()
137
    {
138
        return $this->name;
139
    }
140
141
  /**
142
   * {@inheritdoc}
143
   */
144
    public function getProcessedValues()
145
    {
146
        if (is_null($this->processedValues)) {
147
            $this->setProcessedValues($this->getRawValues());
148
            $fieldPluginManager = $this->getFieldPluginManager();
149
            $definitions = $fieldPluginManager->getMatchedDefinitions($this);
150
            // Process values through matched plugins, until a plugin
151
            // declares it is the final one.
152
            foreach ($definitions as $definition) {
153
                $plugin = $fieldPluginManager->createInstance($definition['id'], ['field' => $this]);
154
                $processedValues = $plugin->processValues($this->processedValues);
155
                if (!is_array($processedValues)) {
156
                    throw new \Exception("Field plugin failed to return array of processed values.");
157
                }
158
                $this->setProcessedValues($processedValues);
159
                if ($plugin->isFinal($this)) {
160
                    break;
161
                };
162
            }
163
        }
164
165
        // Don't pass an array back to singleton config properties.
166
        if ($this->isConfigProperty()) {
167
            if ($this->getType() !== 'sequence') {
168
                if (count($this->processedValues) > 1) {
169
                    throw new \Exception("Config properties not of the type sequence should not have array input.");
170
                }
171
                return $this->processedValues[0];
172
            }
173
        }
174
        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 174 which is incompatible with the return type declared by the interface Drupal\Driver\Wrapper\Fi...ace::getProcessedValues of type string.
Loading history...
175
    }
176
177
  /**
178
   * {@inheritdoc}
179
   */
180
    public function getProjectPluginRoot()
181
    {
182
        return $this->projectPluginRoot;
183
    }
184
185
  /**
186
   * {@inheritdoc}
187
   */
188
    public function getRawValues()
189
    {
190
        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...
191
    }
192
193
  /**
194
   * Sets the processed values.
195
   *
196
   * @return \Drupal\Driver\Plugin\DriverPluginManagerInterface
197
   *   The field plugin manager.
198
   */
199
    protected function getFieldPluginManager()
200
    {
201
        return $this->fieldPluginManager;
202
    }
203
204
  /**
205
   * {@inheritdoc}
206
   */
207
    public function isConfigProperty()
208
    {
209
        return false;
210
    }
211
212
  /**
213
   * Sets the processed values.
214
   *
215
   * @param array $values
216
   *   An array of processed field value sets.
217
   */
218
    protected function setProcessedValues(array $values)
219
    {
220
        $this->processedValues = $values;
221
    }
222
223
  /**
224
   * Set the driver field plugin manager.
225
   *
226
   * @param \Drupal\Driver\Plugin\DriverPluginManagerInterface $manager
227
   *   The driver entity plugin manager.
228
   * @param string $projectPluginRoot
229
   *   The directory to search for additional project-specific driver plugins.
230
   */
231 View Code Duplication
    protected function setFieldPluginManager($manager, $projectPluginRoot)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
232
    {
233
        if (!($manager instanceof DriverPluginManagerInterface)) {
234
            $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...
235
        }
236
        $this->fieldPluginManager = $manager;
237
    }
238
}
239