Completed
Push — feature/EVO-5751-text-index-mo... ( 0ab3ac...8fecb1 )
by
unknown
62:16 queued 57:01
created

ReadOnlyFieldConstraint   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 78
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 88.57%

Importance

Changes 4
Bugs 0 Features 2
Metric Value
wmc 11
c 4
b 0
f 2
lcom 1
cbo 3
dl 0
loc 78
ccs 31
cts 35
cp 0.8857
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
C checkReadOnlyFields() 0 50 10
1
<?php
2
/**
3
 * Schema constraint that validates if readOnly: true fields are manipulated and rejects changes on those.
4
 */
5
6
namespace Graviton\SchemaBundle\Constraint;
7
8
use Graviton\JsonSchemaBundle\Validator\Constraint\Event\ConstraintEventSchema;
9
use Symfony\Component\PropertyAccess\PropertyAccess;
10
11
/**
12
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
13
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
14
 * @link     http://swisscom.ch
15
 */
16
class ReadOnlyFieldConstraint
17
{
18
19
    /**
20
     * @var array
21
     */
22
    private $fieldMap;
23
24
    /**
25
     * ReadOnlyFieldConstraint constructor.
26
     *
27
     * @param ConstraintUtils $utils             Utils
28
     * @param array           $readOnlyFieldsMap field map from compiler pass
29
     */
30 4
    public function __construct(ConstraintUtils $utils, array $readOnlyFieldsMap)
31
    {
32 4
        $this->utils = $utils;
33 4
        $this->fieldMap = $readOnlyFieldsMap;
34 4
    }
35
36
    /**
37
     * Checks the readOnly fields and sets error in event if needed
38
     *
39
     * @param ConstraintEventSchema $event event class
40
     *
41
     * @return void
42
     */
43 4
    public function checkReadOnlyFields(ConstraintEventSchema $event)
44
    {
45 4
        $schema = $event->getSchema();
46 4
        $data = $event->getElement();
47
48 4
        if (!isset($schema->{'x-documentClass'}) || !isset($data->id)) {
49
            return;
50
        }
51
52 4
        $documentClass = $schema->{'x-documentClass'};
53
54 4
        if (!isset($this->fieldMap[$documentClass])) {
55
            return;
56
        }
57
58 4
        $readOnlyFields = $this->fieldMap[$documentClass];
59
60
        // get the current record
61 4
        $currentRecord = $this->utils->getCurrentEntity();
62
63 4
        if (is_null($currentRecord)) {
64
            return;
65
        }
66
67
        // compare fields in both objects
68 4
        $accessor = PropertyAccess::createPropertyAccessor();
69 4
        foreach ($readOnlyFields as $fieldName) {
70 4
            $storedValue = null;
71 4
            if ($accessor->isReadable($currentRecord, $fieldName)) {
72 4
                $storedValue = $accessor->getValue($currentRecord, $fieldName);
73 2
            }
74
75 4
            if (is_object($storedValue)) {
76
                // skip objects as a whole, we will test their readOnly properties instead
77
                continue;
78
            }
79
80 4
            $setValue = null;
81 4
            if ($accessor->isReadable($data, $fieldName)) {
82 4
                $setValue = $accessor->getValue($data, $fieldName);
83 2
            }
84
85 4
            if ($storedValue != $setValue) {
86 2
                $event->addError(
87 3
                    sprintf('The value %s is read only.', json_encode($accessor->getValue($currentRecord, $fieldName))),
88
                    $fieldName
89 1
                );
90 1
            }
91 2
        }
92 4
    }
93
}
94