Completed
Push — master ( 54ac69...cc2d4e )
by Robbie
14s
created

ServiceConnector::getDetail()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 4
nop 1
dl 0
loc 15
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\DocumentConverter;
4
5
use CURLFile;
6
use SilverStripe\Assets\Folder;
7
use SilverStripe\Core\Config\Configurable;
8
use SilverStripe\Core\Environment;
9
use SilverStripe\Core\Injector\Injectable;
10
use SilverStripe\ORM\DataObject;
11
use ZipArchive;
12
13
/**
14
 * Utility class hiding the specifics of the document conversion process.
15
 */
16
class ServiceConnector
17
{
18
19
    use Configurable;
20
    use Injectable;
21
22
    /**
23
     * @config
24
     * @var array Docvert connection username
25
     */
26
    private static $username = null;
0 ignored issues
show
introduced by
The private property $username is not used, and could be removed.
Loading history...
27
28
    /**
29
     * @config
30
     * @var array Docvert connection password
31
     */
32
    private static $password = null;
0 ignored issues
show
introduced by
The private property $password is not used, and could be removed.
Loading history...
33
34
    /**
35
     * @config
36
     * @var array Docvert service URL
37
     */
38
    private static $url = null;
0 ignored issues
show
introduced by
The private property $url is not used, and could be removed.
Loading history...
39
40
    /**
41
     * Associative array of:
42
     * - name: the full name of the file including the extension.
43
     * - path: the path to the file on the local filesystem.
44
     * - mimeType
45
     */
46
    protected $fileDescriptor;
47
48
    /**
49
     * @var int
50
     * ID of a SilverStripe\Assets\Folder
51
     */
52
    protected $chosenFolderID;
53
54
    /**
55
     * @var array instance specific connection details
56
     */
57
    protected $docvertDetails = [
58
        'username' => null,
59
        'password' => null,
60
        'url' => null
61
    ];
62
63
    public function __construct($fileDescriptor, $chosenFolderID = null)
64
    {
65
        $this->fileDescriptor = $fileDescriptor;
66
        $this->chosenFolderID = $chosenFolderID;
67
    }
68
69
70
    /**
71
     * Retrieves detail in priority order from
72
     * 1. local instance field
73
     * 2. Config
74
     * 3. Environment
75
     *
76
     * @param string $detail key name for detail
77
     * @return string the value for that key
78
     */
79
    protected function getDetail($detail)
80
    {
81
        $fromDetails = $this->docvertDetails[$detail];
82
        if ($fromDetails) {
83
            return $fromDetails;
84
        }
85
        
86
        $fromConfig = $this->config()->get($detail);
87
        if ($fromConfig) {
88
            return $fromConfig;
89
        }
90
91
        $fromEnv = Environment::getEnv('DOCVERT_' . strtoupper($detail));
92
        if ($fromEnv) {
93
            return $fromEnv;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $fromEnv also could return the type array which is incompatible with the documented return type string.
Loading history...
94
        }
95
    }
96
97
    public function setUsername($username = null)
98
    {
99
        $this->docvertDetails['username'] = $username;
100
        return $this;
101
    }
102
103
    public function getUsername()
104
    {
105
        return $this->getDetail('username');
106
    }
107
108
    public function setPassword($password = null)
109
    {
110
        $this->docvertDetails['password'] = $password;
111
        return $this;
112
    }
113
114
    public function getPassword()
115
    {
116
        return $this->getDetail('password');
117
    }
118
119
    public function setUrl($url = null)
120
    {
121
        $this->docvertDetails['url'] = $url;
122
        return $this;
123
    }
124
125
    public function getUrl()
126
    {
127
        return $this->getDetail('url');
128
    }
129
130
    public function import()
131
    {
132
        $ch = curl_init();
133
134
        $file = new CURLFile(
135
            $this->fileDescriptor['path'],
136
            $this->fileDescriptor['mimeType'],
137
            $this->fileDescriptor['name']
138
        );
139
140
        curl_setopt_array($ch, [
141
            CURLOPT_URL => $this->getUrl(),
142
            CURLOPT_USERPWD => sprintf('%s:%s', $this->getUsername(), $this->getPassword()),
143
            CURLOPT_POST => 1,
144
            CURLOPT_POSTFIELDS => ['file' => $file],
145
            CURLOPT_CONNECTTIMEOUT => 25,
146
            CURLOPT_TIMEOUT => 100,
147
        ]);
148
149
        $chosenFolder = ($this->chosenFolderID) ? DataObject::get_by_id(Folder::class, $this->chosenFolderID) : null;
150
        $folderName = ($chosenFolder) ? '/' . $chosenFolder->Name : '';
151
        $outname = tempnam(ASSETS_PATH, 'convert');
152
        $outzip = $outname . '.zip';
153
        $out = fopen($outzip, 'w');
154
        curl_setopt($ch, CURLOPT_FILE, $out);
155
        $returnValue = curl_exec($ch);
156
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
157
        curl_close($ch);
158
        fclose($out);
0 ignored issues
show
Bug introduced by
It seems like $out can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, 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

158
        fclose(/** @scrutinizer ignore-type */ $out);
Loading history...
159
        chmod($outzip, 0666);
160
161
        if (!$returnValue || ($status != 200)) {
162
            return ['error' => _t(
163
                __CLASS__ . '.SERVERUNREACHABLE',
164
                'Could not contact document conversion server. Please try again later ' .
165
                    'or contact your system administrator.',
166
                'Document Converter process Word documents into HTML.'
167
            )];
168
        }
169
170
        // extract the converted document into assets
171
        // you need php zip, e.g. apt-get install php-zip
172
        $zip = new ZipArchive();
173
174
        if ($zip->open($outzip)) {
175
            $zip->extractTo(ASSETS_PATH .$folderName);
176
            $zip->close();
177
        }
178
179
        // remove temporary files
180
        unlink($outname);
181
        unlink($outzip);
182
183
        if (!file_exists(ASSETS_PATH . $folderName . '/index.html')) {
184
            return ['error' =>  _t(
185
                __CLASS__ . '.PROCESSFAILED',
186
                'Could not process document, please double-check you uploaded a .doc or .docx format.',
187
                'Document Converter processes Word documents into HTML.'
188
            )];
189
        }
190
191
        $content = file_get_contents(ASSETS_PATH . $folderName . '/index.html');
192
193
        unlink(ASSETS_PATH . $folderName . '/index.html');
194
195
        return $content;
196
    }
197
}
198