Completed
Push — master ( 72ecff...582962 )
by Damien
11:32
created

AbstractProviderService::linkToKey()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 9.1768
c 0
b 0
f 0
cc 5
nc 5
nop 4
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: dsmrt
5
 * Date: 2/10/18
6
 * Time: 12:12 AM
7
 */
8
9
namespace flipbox\saml\core\services;
10
11
use craft\base\Component;
12
use craft\helpers\Json;
13
use flipbox\keychain\records\KeyChainRecord;
14
use flipbox\saml\core\EnsureSAMLPlugin;
15
use flipbox\saml\core\records\AbstractProvider;
16
use flipbox\saml\core\records\LinkRecord;
17
use flipbox\saml\core\records\ProviderInterface;
18
use SAML2\XML\md\EntityDescriptor;
19
20
abstract class AbstractProviderService extends Component implements ProviderServiceInterface, EnsureSAMLPlugin
21
{
22
    /**
23
     * @inheritdoc
24
     * @deprecated
25
     */
26
    abstract public function findOwn();
27
28
    /**
29
     * @inheritdoc
30
     */
31
    public function find($condition = [])
32
    {
33
        /** @var AbstractProvider $class */
34
        $class = $this->getPlugin()->getProviderRecordClass();
35
36
        if (! $provider = $class::find()->where($condition)) {
37
            return null;
38
        }
39
40
        return $provider;
41
    }
42
43
    /**
44
     * @inheritdoc
45
     */
46
    public function findByIdp($condition = [])
47
    {
48
        return $this->findByType('idp', $condition);
49
    }
50
51
    /**
52
     * @inheritdoc
53
     */
54
    public function findBySp($condition = [])
55
    {
56
        return $this->findByType('sp', $condition);
57
    }
58
59
    /**
60
     * @inheritdoc
61
     */
62
    protected function findByType($type, $condition = [])
63
    {
64
        if (! in_array($type, ['sp', 'idp'])) {
65
            throw new \InvalidArgumentException("Type must be idp or sp.");
66
        }
67
        return $this->find(
68
            array_merge(
69
                [
70
                    'enabled' => 1,
71
                    'providerType' => $type,
72
                ],
73
                $condition
74
            )
75
        );
76
    }
77
78
    /**
79
     * @inheritdoc
80
     */
81
    public function findByEntityId($entityId)
82
    {
83
        return $this->find([
84
            'entityId' => $entityId,
85
        ]);
86
    }
87
88
    /**
89
     * @inheritdoc
90
     */
91
    public function create(EntityDescriptor $entityDescriptor, KeyChainRecord $keyChainRecord = null): ProviderInterface
92
    {
93
94
        $recordClass = $this->getPlugin()->getProviderRecordClass();
95
96
        /** @var ProviderInterface $provider */
97
        $provider = (new $recordClass())
98
            ->loadDefaultValues();
99
100
101
        $provider->providerType = $this->getPlugin()->getMyType();
0 ignored issues
show
Bug introduced by
Accessing providerType on the interface flipbox\saml\core\records\ProviderInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
102
103
        $provider->setMetadataModel($entityDescriptor);
104
105
        \Craft::configure($provider, [
106
            'entityId' => $entityDescriptor->getEntityID(),
107
            'metadata' => $provider->toXmlString(),
108
        ]);
109
110
        if ($keyChainRecord) {
111
            $provider->setKeychain($keyChainRecord);
112
        }
113
114
        return $provider;
115
    }
116
117
    /**
118
     * @inheritdoc
119
     */
120
    public function save(AbstractProvider $record, $runValidation = true, $attributeNames = null)
121
    {
122
        if ($record->isNewRecord) {
123
            $record->loadDefaultValues();
124
        }
125
126
        //save record
127
        if (! $record->save($runValidation, $attributeNames)) {
128
            throw new \Exception(Json::encode($record->getErrors()));
129
        }
130
131
        if ($record->keychain) {
132
            $this->linkToKey(
133
                $record,
134
                $record->keychain
135
            );
136
        }
137
138
        return $record;
139
    }
140
141
    /**
142
     * @inheritdoc
143
     */
144
    public function linkToKey(
145
        AbstractProvider $provider,
146
        KeyChainRecord $keyChain,
147
        $runValidation = true,
148
        $attributeNames = null
149
    ) {
150
        if (! $provider->id && ! $keyChain->id) {
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<flipbox\saml\core...cords\AbstractProvider>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
151
            throw new \Exception('Provider id and keychain id must exist before linking.');
152
        }
153
        $linkAttributes = [
154
            'providerId' => $provider->id,
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<flipbox\saml\core...cords\AbstractProvider>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
155
        ];
156
157
        /** @var LinkRecord $link */
158
        if (! $link = LinkRecord::find()->where($linkAttributes)->one()) {
159
            $link = new LinkRecord($linkAttributes);
160
        }
161
162
        $linkAttributes['keyChainId'] = $keyChain->id;
163
        \Craft::configure(
164
            $link,
0 ignored issues
show
Bug introduced by
It seems like $link defined by \flipbox\saml\core\recor...$linkAttributes)->one() on line 158 can also be of type array; however, yii\BaseYii::configure() does only seem to accept object, 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...
165
            $linkAttributes
166
        );
167
        if (! $link->save($runValidation, $attributeNames)) {
168
            throw new \Exception(Json::encode($record->getErrors()));
169
        }
170
    }
171
172
    /**
173
     * @inheritdoc
174
     */
175
    public function delete(ProviderInterface $provider)
176
    {
177
        return $provider->delete();
178
    }
179
}
180