Completed
Push — master ( d966c0...876bb5 )
by Florian
16:04 queued 58s
created

SectionIO::flushFile()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
c 4
b 0
f 1
dl 0
loc 11
rs 9.4285
cc 3
eloc 6
nc 2
nop 1
1
<?php
2
3
class SectionIO extends Object implements Flushable
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
4
{
5
    private static $flush_on_dev_build = true;
0 ignored issues
show
Unused Code introduced by
The property $flush_on_dev_build is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
6
7
    private static $sitetree_flush_strategy = 'single';
0 ignored issues
show
Unused Code introduced by
The property $sitetree_flush_strategy is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
8
9
    private static $api_url = 'https://aperture.section.io/api/v1';
0 ignored issues
show
Unused Code introduced by
The property $api_url is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
10
    private static $account_id = '';
0 ignored issues
show
Unused Code introduced by
The property $account_id is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
11
    private static $application_id = '';
0 ignored issues
show
Unused Code introduced by
The property $application_id is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
12
    private static $environment_name = '';
0 ignored issues
show
Unused Code introduced by
The property $environment_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
13
    private static $proxy_name = '';
0 ignored issues
show
Unused Code introduced by
The property $proxy_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
14
    private static $username = '';
0 ignored issues
show
Unused Code introduced by
The property $username is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
15
    private static $password = '';
0 ignored issues
show
Unused Code introduced by
The property $password is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
16
17
    /**
18
     * Implementation of Flushable::flush()
19
     * Is triggered on dev/build and ?flush=1.
20
     */
21
    public static function flush()
22
    {
23
        if (Config::inst()->get('SectionIO', 'flush_on_dev_build')) {
24
            return static::flushAll();
25
        }
26
27
        return;
28
    }
29
30
    public static function flushAll()
31
    {
32
        $exp = 'obj.http.x-url ~ /';
33
34
        return static::performFlush($exp);
35
    }
36
37
    public static function flushImage($imageID)
38
    {
39
        $image = Image::get()->byID($imageID);
40
        if ($image && $image->exists()) {
41
            $exp = 'obj.http.x-url ~ "^/'.preg_quote($image->getFilename()).'$"'; // image itself
42
            $exp    .= ' || obj.http.x-url ~ "^/'.preg_quote($image->Parent()->getFilename())
0 ignored issues
show
Bug introduced by
The method Parent() does not exist on DataObject. Did you maybe mean parentClass()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
43
                    .'_resampled/(.*)\-'.preg_quote($image->Name).'$"'; // resampled versions
44
            return static::performFlush($exp);
45
        }
46
47
        return false;
48
    }
49
50
    public static function flushFile($fileID)
51
    {
52
        $file = File::get()->byID($fileID);
53
        if ($file && $file->exists()) {
54
            $exp = 'obj.http.x-url ~ "^/'.preg_quote($file->getFilename()).'$"';
55
56
            return static::performFlush($exp);
57
        }
58
59
        return false;
60
    }
61
62
    public static function flushSiteTree($sitetreeID)
63
    {
64
        $sitetree = SiteTree::get()->byID($sitetreeID);
65
        if ($sitetree && $sitetree->exists()) {
66
            $strategy = Config::inst()->get('SectionIO', 'sitetree_flush_strategy');
67
            switch ($strategy) {
68
69
                case 'single':
70
                    $exp = 'obj.http.content-type ~ "'.preg_quote('text/html').'"';
71
                    $exp .= ' && obj.http.x-url ~ "^'.preg_quote($sitetree->Link()).'$"';
72
                    break;
73
74
                case 'parents':
75
                    $exp = 'obj.http.content-type ~ "'.preg_quote('text/html').'"';
76
                    $exp .= ' && (obj.http.x-url ~ "^'.preg_quote($sitetree->Link()).'$"';
77
                    $parent = $sitetree->getParent();
78
                    while ($parent && $parent->exists()) {
79
                        $exp .= ' || obj.http.x-url ~ "^'.preg_quote($parent->Link()).'$"';
80
                        $parent = $parent->getParent();
81
                    }
82
                    $exp .= ')';
83
                    break;
84
85
                case 'all':
86
                    $exp = 'obj.http.content-type ~ "'.preg_quote('text/html').'"';
87
                    break;
88
89
                case 'everyting':
90
                default:
91
                    $exp = 'obj.http.x-url ~ /';
92
                    break;
93
94
            }
95
96
            return static::performFlush($exp);
97
        }
98
99
        return false;
100
    }
101
102
    protected static function performFlush($banExpression)
103
    {
104
        $success = true;
105
        $urls = static::getUrls();
106
        // config loaded successfully
107
        if ($urls) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $urls of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
108
            foreach ($urls as $url) {
109
110
                // get restful service object
111
                $service = static::getService($url, $banExpression);
112
113
                // prepare headers
114
                $headers = static::getHeaders();
115
116
                // prepare curl options
117
                $options = static::getOptions();
118
119
                // call API
120
                $conn = $service->request(null, 'POST', null, $headers, $options);
121
122
                if ($conn->isError()) {
123
                    user_error('SectionIO::performFlush :: '.$conn->getStatusCode().' : '.$conn->getStatusDescription().' : '.$url, E_USER_WARNING);
124
                    $success = $success && false;
125
                } else {
126
                    user_error('SectionIO::performFlush :: ban successful. url: '.$url."; ban expression: '".$banExpression."'", E_USER_NOTICE);
127
                }
128
            }
129
        } else {
130
            user_error('SectionIO::performFlush :: no URLs loaded for ban.', E_USER_WARNING);
131
        }
132
133
        return $success;
134
    }
135
136
    protected static function getService($url, $banExpression)
137
    {
138
        // prepare API call
139
        $service = new RestfulService(
140
            $url,
141
            0 // expiry time 0: do not cache the API call
142
        );
143
        // set basic auth
144
        $username = Config::inst()->get('SectionIO', 'username');
145
        $password = Config::inst()->get('SectionIO', 'password');
146
        $service->basicAuth($username, $password);
147
        // set query string (ban expression)
148
        $service->setQueryString(array(
149
            'banExpression' => $banExpression,
150
        ));
151
152
        return $service;
153
    }
154
155
    protected static function getOptions()
156
    {
157
        // prepare curl options for ssl verification
158
        $cert = static::getCertificates();
159
        $options = array(
160
            CURLOPT_SSL_VERIFYPEER => 1,
161
            CURLOPT_SSL_VERIFYHOST => 2,
162
            CURLOPT_CAINFO => $cert,
163
        );
164
165
        return $options;
166
    }
167
168
    protected static function getCertificates()
169
    {
170
        $cert = ini_get('curl.cainfo');
171
        if (!$cert) {
172
            $cert = BASE_PATH.'/'.SECTIONIO_BASE.'/cert/cacert.pem';
173
        }
174
175
        return $cert;
176
    }
177
178
    protected static function getHeaders()
179
    {
180
        $headers = array(
181
            'Content-Type: application/json',
182
            'Accept: application/json',
183
        );
184
185
        return $headers;
186
    }
187
188
    protected static function getUrls()
189
    {
190
        $urls = array();
191
192
        if (static::checkConfig()) {
193
            $api_url = Config::inst()->get('SectionIO', 'api_url');
194
            $account_id = Config::inst()->get('SectionIO', 'account_id');
195
            $application_id = Config::inst()->get('SectionIO', 'application_id');
196
            $application_ids = array();
197
            if (is_string($application_id)) {
198
                $application_ids = preg_split("/[\s,]+/", $application_id);
199
            } elseif (is_array($application_id)) {
200
                $application_ids = $application_id;
201
            }
202
            $environment_name = Config::inst()->get('SectionIO', 'environment_name');
203
            $proxy_name = Config::inst()->get('SectionIO', 'proxy_name');
204
205
            foreach ($application_ids as $appid) {
206
                // build API URL: /account/{accountId}/application/{applicationId}/environment/{environmentName}/proxy/{proxyName}/state
207
                $urls[] = Controller::join_links(
208
                    $api_url,
209
                    'account',
210
                    $account_id,
211
                    'application',
212
                    $appid,
213
                    'environment',
214
                    $environment_name,
215
                    'proxy',
216
                    $proxy_name,
217
                    'state'
218
                );
219
            }
220
        }
221
222
        return $urls;
223
    }
224
225
    protected static function checkConfig()
226
    {
227
        $success = true;
228
        // check config
229
        $api_url = Config::inst()->get('SectionIO', 'api_url');
230 View Code Duplication
        if (!isset($api_url) || strlen($api_url) < 1) {
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...
231
            user_error('Value for SectionIO.api_url needs to be configured.', E_USER_WARNING);
232
            $success = false;
233
        }
234
        $account_id = Config::inst()->get('SectionIO', 'account_id');
235 View Code Duplication
        if (!isset($account_id) || strlen($account_id) < 1) {
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...
236
            user_error('Value for SectionIO.account_id needs to be configured.', E_USER_WARNING);
237
            $success = false;
238
        }
239
        $application_id = Config::inst()->get('SectionIO', 'application_id');
240 View Code Duplication
        if (!isset($application_id) || (!is_array($application_id) && strlen((string) $application_id) < 1)) {
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...
241
            user_error('Value for SectionIO.application_id needs to be configured.', E_USER_WARNING);
242
            $success = false;
243
        }
244
        $environment_name = Config::inst()->get('SectionIO', 'environment_name');
245 View Code Duplication
        if (!isset($environment_name) || strlen($environment_name) < 1) {
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...
246
            user_error('Value for SectionIO.environment_name needs to be configured.', E_USER_WARNING);
247
            $success = false;
248
        }
249
        $proxy_name = Config::inst()->get('SectionIO', 'proxy_name');
250 View Code Duplication
        if (!isset($proxy_name) || strlen($proxy_name) < 1) {
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...
251
            user_error('Value for SectionIO.proxy_name needs to be configured.', E_USER_WARNING);
252
            $success = false;
253
        }
254
        $username = Config::inst()->get('SectionIO', 'username');
255 View Code Duplication
        if (!isset($username) || strlen($username) < 1) {
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...
256
            user_error('Value for SectionIO.username needs to be configured.', E_USER_WARNING);
257
            $success = false;
258
        }
259
        $password = Config::inst()->get('SectionIO', 'password');
260 View Code Duplication
        if (!isset($password) || strlen($password) < 1) {
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...
261
            user_error('Value for SectionIO.password needs to be configured.', E_USER_WARNING);
262
            $success = false;
263
        }
264
265
        return $success;
266
    }
267
}
268