Completed
Push — master ( 9d82a0...ac58c2 )
by Christian
11s queued 10s
created

StatementObject::fromModel()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 24
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 24
rs 6.7272
cc 7
eloc 13
nc 5
nop 1
1
<?php
2
3
/*
4
 * This file is part of the xAPI package.
5
 *
6
 * (c) Christian Flothmann <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace XApi\Repository\Doctrine\Mapping;
13
14
use Xabbuh\XApi\Model\Account;
15
use Xabbuh\XApi\Model\Activity;
16
use Xabbuh\XApi\Model\Actor as ActorModel;
17
use Xabbuh\XApi\Model\Agent;
18
use Xabbuh\XApi\Model\Definition;
19
use Xabbuh\XApi\Model\Group;
20
use Xabbuh\XApi\Model\InverseFunctionalIdentifier;
21
use Xabbuh\XApi\Model\IRI;
22
use Xabbuh\XApi\Model\IRL;
23
use Xabbuh\XApi\Model\LanguageMap;
24
use Xabbuh\XApi\Model\Object as ObjectModel;
25
use Xabbuh\XApi\Model\StatementObject as StatementObjectModel;
26
use Xabbuh\XApi\Model\StatementId;
27
use Xabbuh\XApi\Model\StatementReference;
28
use Xabbuh\XApi\Model\SubStatement;
29
30
/**
31
 * @author Christian Flothmann <[email protected]>
32
 */
33
class StatementObject
34
{
35
    const TYPE_ACTIVITY = 'activity';
36
    const TYPE_AGENT = 'agent';
37
    const TYPE_GROUP = 'group';
38
    const TYPE_STATEMENT_REFERENCE = 'statement_reference';
39
    const TYPE_SUB_STATEMENT = 'sub_statement';
40
41
    public $identifier;
42
43
    /**
44
     * @var string
45
     */
46
    public $type;
47
48
    /**
49
     * @var string|null
50
     */
51
    public $activityId;
52
53
    /**
54
     * @var bool|null
55
     */
56
    public $hasActivityDefinition;
57
58
    /**
59
     * @var bool|null
60
     */
61
    public $hasActivityName;
62
63
    /**
64
     * @var array|null
65
     */
66
    public $activityName;
67
68
    /**
69
     * @var bool|null
70
     */
71
    public $hasActivityDescription;
72
73
    /**
74
     * @var array|null
75
     */
76
    public $activityDescription;
77
78
    /**
79
     * @var string|null
80
     */
81
    public $activityType;
82
83
    /**
84
     * @var string|null
85
     */
86
    public $activityMoreInfo;
87
88
    /**
89
     * @var Extensions|null
90
     */
91
    public $activityExtensions;
92
93
    /**
94
     * @var string|null
95
     */
96
    public $mbox;
97
98
    /**
99
     * @var string|null
100
     */
101
    public $mboxSha1Sum;
102
103
    /**
104
     * @var string|null
105
     */
106
    public $openId;
107
108
    /**
109
     * @var string|null
110
     */
111
    public $accountName;
112
113
    /**
114
     * @var string|null
115
     */
116
    public $accountHomePage;
117
118
    /**
119
     * @var string|null
120
     */
121
    public $name;
122
123
    /**
124
     * @var StatementObject[]|null
125
     */
126
    public $members;
127
128
    /**
129
     * @var StatementObject|null
130
     */
131
    public $group;
132
133
    /**
134
     * @var string|null
135
     */
136
    public $referencedStatementId;
137
138
    /**
139
     * @var StatementObject|null
140
     */
141
    public $actor;
142
143
    /**
144
     * @var Verb|null
145
     */
146
    public $verb;
147
148
    /**
149
     * @var StatementObject|null
150
     */
151
    public $object;
152
153
    /**
154
     * @var Result|null
155
     */
156
    public $result;
157
158
    /**
159
     * @var Context|null
160
     */
161
    public $context;
162
163
    /**
164
     * @var Statement|null
165
     */
166
    public $parentContext;
167
168
    /**
169
     * @var Statement|null
170
     */
171
    public $groupingContext;
172
173
    /**
174
     * @var Statement|null
175
     */
176
    public $categoryContext;
177
178
    /**
179
     * @var Statement|null
180
     */
181
    public $otherContext;
182
183
    public static function fromModel($model)
184
    {
185
        if (!$model instanceof ObjectModel && !$model instanceof StatementObjectModel) {
0 ignored issues
show
Bug introduced by
The class Xabbuh\XApi\Model\Object does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
186
            throw new \InvalidArgumentException(sprintf('Expected a statement object but got %s', is_object($model) ? get_class($model) : gettype($model)));
187
        }
188
189
        if ($model instanceof ActorModel) {
190
            return self::fromActor($model);
191
        }
192
193
        if ($model instanceof StatementReference) {
194
            $object = new self();
195
            $object->type = self::TYPE_STATEMENT_REFERENCE;
196
            $object->referencedStatementId = $model->getStatementId()->getValue();
197
198
            return $object;
199
        }
200
201
        if ($model instanceof SubStatement) {
202
            return self::fromSubStatement($model);
203
        }
204
205
        return self::fromActivity($model);
0 ignored issues
show
Bug introduced by
It seems like $model can also be of type object<Xabbuh\XApi\Model\StatementObject>; however, XApi\Repository\Doctrine...tObject::fromActivity() does only seem to accept object<Xabbuh\XApi\Model\Activity>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
206
    }
207
208
    public function getModel()
209
    {
210
        if (self::TYPE_AGENT === $this->type || self::TYPE_GROUP === $this->type) {
211
            return $this->getActorModel();
212
        }
213
214
        if (self::TYPE_STATEMENT_REFERENCE === $this->type) {
215
            return new StatementReference(StatementId::fromString($this->referencedStatementId));
216
        }
217
218
        if (self::TYPE_SUB_STATEMENT === $this->type) {
219
            return $this->getSubStatementModel();
220
        }
221
222
        return $this->getActivityModel();
223
    }
224
225
    private static function fromActivity(Activity $model)
226
    {
227
        $object = new self();
228
        $object->activityId = $model->getId()->getValue();
229
230
        if (null !== $definition = $model->getDefinition()) {
231
            $object->hasActivityDefinition = true;
232
233 View Code Duplication
            if (null !== $name = $definition->getName()) {
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...
234
                $object->hasActivityName = true;
235
                $object->activityName = array();
236
237
                foreach ($name->languageTags() as $languageTag) {
238
                    $object->activityName[$languageTag] = $name[$languageTag];
239
                }
240
            } else {
241
                $object->hasActivityName = false;
242
            }
243
244 View Code Duplication
            if (null !== $description = $definition->getDescription()) {
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...
245
                $object->hasActivityDescription = true;
246
                $object->activityDescription = array();
247
248
                foreach ($description->languageTags() as $languageTag) {
249
                    $object->activityDescription[$languageTag] = $description[$languageTag];
250
                }
251
            } else {
252
                $object->hasActivityDescription = false;
253
            }
254
255
            if (null !== $type = $definition->getType()) {
256
                $object->activityType = $type->getValue();
257
            }
258
259
            if (null !== $moreInfo = $definition->getMoreInfo()) {
260
                $object->activityMoreInfo = $moreInfo->getValue();
261
            }
262
263
            if (null !== $extensions = $definition->getExtensions()) {
264
                $object->activityExtensions = Extensions::fromModel($extensions);
265
            }
266
        } else {
267
            $object->hasActivityDefinition = false;
268
        }
269
270
        return $object;
271
    }
272
273
    private static function fromActor(ActorModel $model)
274
    {
275
        $inverseFunctionalIdentifier = $model->getInverseFunctionalIdentifier();
276
277
        $object = new self();
278
        $object->mboxSha1Sum = $inverseFunctionalIdentifier->getMboxSha1Sum();
279
        $object->openId = $inverseFunctionalIdentifier->getOpenId();
280
281
        if (null !== $mbox = $inverseFunctionalIdentifier->getMbox()) {
282
            $object->mbox = $mbox->getValue();
283
        }
284
285
        if (null !== $account = $inverseFunctionalIdentifier->getAccount()) {
286
            $object->accountName = $account->getName();
287
            $object->accountHomePage = $account->getHomePage()->getValue();
288
        }
289
290
        if ($model instanceof Group) {
291
            $object->type = self::TYPE_GROUP;
292
            $object->members = array();
293
294
            foreach ($model->getMembers() as $agent) {
295
                $object->members[] = self::fromActor($agent);
296
            }
297
        } else {
298
            $object->type = self::TYPE_AGENT;
299
        }
300
301
        return $object;
302
    }
303
304
    private static function fromSubStatement(SubStatement $model)
305
    {
306
        $object = new self();
307
        $object->type = self::TYPE_SUB_STATEMENT;
308
        $object->actor = StatementObject::fromModel($model->getActor());
309
        $object->verb = Verb::fromModel($model->getVerb());
310
        $object->object = StatementObject::fromModel($model->getObject());
311
312
        return $object;
313
    }
314
315
    private function getActivityModel()
316
    {
317
        $definition = null;
318
        $type = null;
319
        $moreInfo = null;
320
321
        if ($this->hasActivityDefinition) {
322
            $name = null;
323
            $description = null;
324
            $extensions = null;
325
326
            if ($this->hasActivityName) {
327
                $name = LanguageMap::create($this->activityName);
0 ignored issues
show
Bug introduced by
It seems like $this->activityName can also be of type null; however, Xabbuh\XApi\Model\LanguageMap::create() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
328
            }
329
330
            if ($this->hasActivityDescription) {
331
                $description = LanguageMap::create($this->activityDescription);
0 ignored issues
show
Bug introduced by
It seems like $this->activityDescription can also be of type null; however, Xabbuh\XApi\Model\LanguageMap::create() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
332
            }
333
334
            if (null !== $this->activityType) {
335
                $type = IRI::fromString($this->activityType);
336
            }
337
338
            if (null !== $this->activityMoreInfo) {
339
                $moreInfo = IRL::fromString($this->activityMoreInfo);
340
            }
341
342
            if (null !== $this->activityExtensions) {
343
                $extensions = $this->activityExtensions->getModel();
344
            }
345
346
            $definition = new Definition($name, $description, $type, $moreInfo, $extensions);
347
        }
348
349
        return new Activity(IRI::fromString($this->activityId), $definition);
350
    }
351
352 View Code Duplication
    private function getActorModel()
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...
353
    {
354
        $inverseFunctionalIdentifier = null;
355
356
        if (null !== $this->mbox) {
357
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withMbox(IRI::fromString($this->mbox));
358
        } elseif (null !== $this->mboxSha1Sum) {
359
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withMboxSha1Sum($this->mboxSha1Sum);
360
        } elseif (null !== $this->openId) {
361
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withOpenId($this->openId);
362
        } elseif (null !== $this->accountName && null !== $this->accountHomePage) {
363
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withAccount(new Account($this->accountName, IRL::fromString($this->accountHomePage)));
364
        }
365
366
        if (self::TYPE_GROUP === $this->type) {
367
            $members = array();
368
369
            foreach ($this->members as $agent) {
0 ignored issues
show
Bug introduced by
The expression $this->members of type array<integer,object<XAp...\StatementObject>>|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
370
                $members[] = $agent->getModel();
371
            }
372
373
            return new Group($inverseFunctionalIdentifier, $this->name, $members);
374
        }
375
376
        return new Agent($inverseFunctionalIdentifier, $this->name);
0 ignored issues
show
Bug introduced by
It seems like $inverseFunctionalIdentifier defined by null on line 354 can also be of type null; however, Xabbuh\XApi\Model\Agent::__construct() does only seem to accept object<Xabbuh\XApi\Model...seFunctionalIdentifier>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
377
    }
378
379
    private function getSubStatementModel()
380
    {
381
        $result = null;
382
        $context = null;
383
384
        return new SubStatement(
385
            $this->actor->getModel(),
386
            $this->verb->getModel(),
387
            $this->object->getModel(),
388
            $result,
389
            $context
390
        );
391
    }
392
}
393