Passed
Pull Request — master (#46)
by Matthew
07:48
created

SalsifyFetchExtension   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 169
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 21
eloc 63
dl 0
loc 169
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getImporterKey() 0 3 1
A salsifyFetch() 0 27 5
A canFetchSalsify() 0 14 5
A fetchProduct() 0 27 2
A onBeforeInit() 0 3 1
A configContainsMapping() 0 11 3
A mapData() 0 7 1
A getClassMapping() 0 10 3
1
<?php
2
3
namespace Dynamic\Salsify\ORM;
4
5
use Dynamic\Salsify\Model\Fetcher;
6
use Dynamic\Salsify\Model\Mapper;
7
use Dynamic\Salsify\Task\ImportTask;
8
use Dynamic\Salsify\Traits\InstanceCreator;
9
use GuzzleHttp\Client;
10
use SilverStripe\Admin\LeftAndMainExtension;
0 ignored issues
show
Bug introduced by
The type SilverStripe\Admin\LeftAndMainExtension was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use SilverStripe\Forms\Form;
12
use SilverStripe\ORM\DataObject;
13
use SilverStripe\Security\Security;
14
15
/**
16
 * Class LeftAndMainExtension
17
 * @package Dynamic\Salsify\ORM
18
 * @property-read \SilverStripe\Admin\LeftAndMain|\Dynamic\Salsify\ORM\SalsifyFetchExtension $owner
19
 */
20
class SalsifyFetchExtension extends LeftAndMainExtension
21
{
22
    use InstanceCreator;
23
24
    /**
25
     * @var bool
26
     */
27
    private $noChannel = true;
0 ignored issues
show
introduced by
The private property $noChannel is not used, and could be removed.
Loading history...
28
29
    /**
30
     * @var array
31
     */
32
    private static $allowed_actions = [
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
33
        'salsifyFetch',
34
    ];
35
36
    /**
37
     * @return string
38
     */
39
    protected function getImporterKey()
40
    {
41
        return 'single';
42
    }
43
44
    /**
45
     *
46
     */
47
    public function onBeforeInit()
48
    {
49
        $this->createServices();
50
    }
51
52
    /**
53
     * @return boolean
54
     * @throws \Exception
55
     */
56
    public function canFetchSalsify()
57
    {
58
        $className = $this->owner->currentPage()->getClassName();
59
60
        // Only allow when product has a salsify id and has a single mapping config
61
        if (
62
            $this->owner->currentPage()->SalsifyID &&
63
            $this->hasService(Mapper::class) &&
64
            $this->configContainsMapping($className) &&
65
            $this->getFetcher()->config()->get('organizationID')
66
        ) {
67
            return true;
68
        }
69
        return false;
70
    }
71
72
    /**
73
     * @param string $className
74
     *
75
     * @return boolean
76
     * @throws \Exception
77
     */
78
    private function configContainsMapping($className)
79
    {
80
        if (!$this->getMapper()->config()->get('mapping')) {
81
            return false;
82
        }
83
84
        if (!$this->getClassMapping($className)) {
85
            return false;
86
        }
87
88
        return true;
89
    }
90
91
    /**
92
     * @param string $className
93
     * @return bool|array
94
     * @throws \Exception
95
     */
96
    private function getClassMapping($className)
97
    {
98
        $mapping = $this->getMapper()->config()->get('mapping');
99
        if (array_key_exists($className, $mapping)) {
100
            return $mapping[$className];
101
        }
102
        if (array_key_exists('\\' . $className, $mapping)) {
103
            return $mapping['\\' . $className];
104
        }
105
        return false;
106
    }
107
108
    /**
109
     * @param array $data
110
     * @param Form $form
111
     * @return \SilverStripe\Control\HTTPResponse
112
     * @throws \Exception
113
     */
114
    public function salsifyFetch($data, $form)
115
    {
116
        $className = $this->owner->currentPage()->getClassName();
117
118
        $id = $data['ID'];
119
        /** @var DataObject|\Dynamic\Salsify\ORM\SalsifyIDExtension $record */
120
        $record = DataObject::get_by_id($className, $id);
121
        if ($record && !$record->canEdit()) {
122
            return Security::permissionFailure();
123
        }
124
125
        if (!$record || !$record->SalsifyID) {
0 ignored issues
show
introduced by
$record is of type SilverStripe\ORM\DataObject, thus it always evaluated to true.
Loading history...
126
            $this->owner->httpError(404, "Bad salsify ID: $id");
127
        }
128
129
        ImportTask::config()->remove('output');
130
        $data = $this->fetchProduct($record->SalsifyID);
131
132
        $this->changeToSalsifyUser();
133
        $this->mapData($record, $data);
134
        $this->changeToPreviousUser();
135
136
        $this->owner->getResponse()->addHeader(
137
            'X-Status',
138
            rawurlencode(_t(__CLASS__ . '.UPDATED', 'Updated.'))
139
        );
140
        return $this->owner->getResponseNegotiator()->respond($this->owner->getRequest());
141
    }
142
143
    /**
144
     * @param string $salsifyID
145
     * @return array|NULL
146
     * @throws \Exception
147
     */
148
    private function fetchProduct($salsifyID)
149
    {
150
151
        $apiKey = $this->getFetcher()->config()->get('apiKey');
152
        $timeout = $this->getFetcher()->config()->get('timeout');
153
        $orgID = $this->getFetcher()->config()->get('organizationID');
154
155
        $url = "v1/orgs/{$orgID}/products/{$salsifyID}";
156
157
        $client = new Client([
158
            'base_uri' => Fetcher::API_BASE_URL,
159
            'timeout' => $timeout,
160
            'http_errors' => false,
161
            'verify' => true,
162
            'headers' => [
163
                'Authorization' => 'Bearer ' . $apiKey,
164
                'Content-Type' => 'application/json',
165
            ],
166
        ]);
167
168
        $response = $client->get($url);
169
170
        if ($response->getStatusCode() == 404) {
171
            $this->owner->httpError(404, "Bad salsify ID: $salsifyID");
172
        }
173
174
        return json_decode($response->getBody(), true);
175
    }
176
177
    /**
178
     * @param DataObject $record
179
     * @param array $data
180
     * @throws \Exception
181
     */
182
    private function mapData($record, $data)
183
    {
184
        $this->getMapper()->mapToObject(
185
            $record->getClassName(),
186
            $this->getClassMapping($record->getClassName()),
0 ignored issues
show
Bug introduced by
It seems like $this->getClassMapping($record->getClassName()) can also be of type boolean; however, parameter $mappings of Dynamic\Salsify\Model\Mapper::mapToObject() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

186
            /** @scrutinizer ignore-type */ $this->getClassMapping($record->getClassName()),
Loading history...
187
            $data,
188
            $record
189
        );
190
    }
191
}
192