Completed
Push — develop ( e95e4d...4fd8e7 )
by Adrien
61:55
created

IOFactory::getSearchLocations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet;
4
5
use PhpOffice\PhpSpreadsheet\Shared\File;
6
7
class IOFactory
8
{
9
    /**
10
     * Search locations.
11
     *
12
     * @var array
13
     * @static
14
     */
15
    private static $searchLocations = [
16
        ['type' => 'IWriter', 'path' => 'PhpSpreadsheet/Writer/{0}.php', 'class' => '\\PhpOffice\\PhpSpreadsheet\\Writer\\{0}'],
17
        ['type' => 'IReader', 'path' => 'PhpSpreadsheet/Reader/{0}.php', 'class' => '\\PhpOffice\\PhpSpreadsheet\\Reader\\{0}'],
18
    ];
19
20
    /**
21
     * Autoresolve classes.
22
     *
23
     * @var array
24
     * @static
25
     */
26
    private static $autoResolveClasses = [
27
        'Xlsx',
28
        'Xls',
29
        'Xml',
30
        'Ods',
31
        'Slk',
32
        'Gnumeric',
33
        'Html',
34
        'Csv',
35
    ];
36
37
    /**
38
     * Private constructor for IOFactory.
39
     */
40
    private function __construct()
41
    {
42
    }
43
44
    /**
45
     * Get search locations.
46
     *
47
     * @static
48
     *
49
     * @return array
50
     */
51
    public static function getSearchLocations()
52
    {
53
        return self::$searchLocations;
54
    }
55
56
    /**
57
     * Set search locations.
58
     *
59
     * @static
60
     *
61
     * @param array $value
62
     *
63
     * @throws Reader\Exception
64
     */
65
    public static function setSearchLocations(array $value)
66
    {
67
        self::$searchLocations = $value;
68
    }
69
70
    /**
71
     * Add search location.
72
     *
73
     * @static
74
     *
75
     * @param string $type Example: IWriter
76
     * @param string $location Example: PhpSpreadsheet/Writer/{0}.php
77
     * @param string $classname Example: Writer\{0}
78
     */
79
    public static function addSearchLocation($type, $location, $classname)
80
    {
81
        self::$searchLocations[] = ['type' => $type, 'path' => $location, 'class' => $classname];
82
    }
83
84
    /**
85
     * Create Writer\IWriter.
86
     *
87
     * @static
88
     *
89
     * @param Spreadsheet $spreadsheet
90
     * @param string $writerType Example: Xlsx
91
     *
92
     * @throws Writer\Exception
93
     *
94
     * @return Writer\IWriter
95
     */
96 60 View Code Duplication
    public static function createWriter(Spreadsheet $spreadsheet, $writerType)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
97
    {
98
        // Search type
99 60
        $searchType = 'IWriter';
100
101
        // Include class
102 60
        foreach (self::$searchLocations as $searchLocation) {
103 60
            if ($searchLocation['type'] == $searchType) {
104 60
                $className = str_replace('{0}', $writerType, $searchLocation['class']);
105
106 60
                $instance = new $className($spreadsheet);
107 60
                if ($instance !== null) {
108 60
                    return $instance;
109
                }
110
            }
111
        }
112
113
        // Nothing found...
114
        throw new Writer\Exception("No $searchType found for type $writerType");
115
    }
116
117
    /**
118
     * Create Reader\IReader.
119
     *
120
     * @static
121
     *
122
     * @param string $readerType Example: Xlsx
123
     *
124
     * @throws Reader\Exception
125
     *
126
     * @return Reader\IReader
127
     */
128 46 View Code Duplication
    public static function createReader($readerType)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
129
    {
130
        // Search type
131 46
        $searchType = 'IReader';
132
133
        // Include class
134 46
        foreach (self::$searchLocations as $searchLocation) {
135 46
            if ($searchLocation['type'] == $searchType) {
136 46
                $className = str_replace('{0}', $readerType, $searchLocation['class']);
137
138 46
                $instance = new $className();
139 46
                if ($instance !== null) {
140 46
                    return $instance;
141
                }
142
            }
143
        }
144
145
        // Nothing found...
146
        throw new Reader\Exception("No $searchType found for type $readerType");
147
    }
148
149
    /**
150
     * Loads Spreadsheet from file using automatic Reader\IReader resolution.
151
     *
152
     * @static
153
     *
154
     * @param string $pFilename The name of the spreadsheet file
155
     *
156
     * @throws Reader\Exception
157
     *
158
     * @return Spreadsheet
159
     */
160 11
    public static function load($pFilename)
161
    {
162 11
        $reader = self::createReaderForFile($pFilename);
163
164 10
        return $reader->load($pFilename);
165
    }
166
167
    /**
168
     * Identify file type using automatic Reader\IReader resolution.
169
     *
170
     * @static
171
     *
172
     * @param string $pFilename The name of the spreadsheet file to identify
173
     *
174
     * @throws Reader\Exception
175
     *
176
     * @return string
177
     */
178 10
    public static function identify($pFilename)
179
    {
180 10
        $reader = self::createReaderForFile($pFilename);
181 8
        $className = get_class($reader);
182 8
        $classType = explode('\\', $className);
183 8
        unset($reader);
184
185 8
        return array_pop($classType);
186
    }
187
188
    /**
189
     * Create Reader\IReader for file using automatic Reader\IReader resolution.
190
     *
191
     * @static
192
     *
193
     * @param string $pFilename The name of the spreadsheet file
194
     *
195
     * @throws Reader\Exception
196
     *
197
     * @return Reader\IReader
198
     */
199 21
    public static function createReaderForFile($pFilename)
200
    {
201 21
        File::assertFile($pFilename);
202
203
        // First, lucky guess by inspecting file extension
204 18
        $pathinfo = pathinfo($pFilename);
205
206 18
        $extensionType = null;
207 18
        if (isset($pathinfo['extension'])) {
208 18
            switch (strtolower($pathinfo['extension'])) {
209 18
                case 'xlsx':            //    Excel (OfficeOpenXML) Spreadsheet
210 13
                case 'xlsm':            //    Excel (OfficeOpenXML) Macro Spreadsheet (macros will be discarded)
211 13
                case 'xltx':            //    Excel (OfficeOpenXML) Template
212 13
                case 'xltm':            //    Excel (OfficeOpenXML) Macro Template (macros will be discarded)
213 5
                    $extensionType = 'Xlsx';
214 5
215 13
                    break;
216 8
                case 'xls':                //    Excel (BIFF) Spreadsheet
217 5
                case 'xlt':                //    Excel (BIFF) Template
218 5
                    $extensionType = 'Xls';
219 8
220 6
                    break;
221 2
                case 'ods':                //    Open/Libre Offic Calc
222 2
                case 'ots':                //    Open/Libre Offic Calc Template
223 6
                    $extensionType = 'Ods';
224 2
225 2
                    break;
226 4
                case 'slk':
227 2
                    $extensionType = 'Slk';
228 2
229 2
                    break;
230 2
                case 'xml':                //    Excel 2003 SpreadSheetML
231 2
                    $extensionType = 'Xml';
232
233
                    break;
234
                case 'gnumeric':
235
                    $extensionType = 'Gnumeric';
236
237
                    break;
238
                case 'htm':
239
                case 'html':
240
                    $extensionType = 'Html';
241
242
                    break;
243
                case 'csv':
244
                    // Do nothing
245 18
                    // We must not try to use CSV reader since it loads
246 18
                    // all files including Excel files etc.
247
                    break;
248 18
                default:
249 18
                    break;
250
            }
251
252
            if ($extensionType !== null) {
253
                $reader = self::createReader($extensionType);
254
                // Let's see if we are lucky
255
                if (isset($reader) && $reader->canRead($pFilename)) {
256
                    return $reader;
257
                }
258
            }
259
        }
260
261
        // If we reach here then "lucky guess" didn't give any result
262
        // Try walking through all the options in self::$autoResolveClasses
263
        foreach (self::$autoResolveClasses as $autoResolveClass) {
264
            //    Ignore our original guess, we know that won't work
265
            if ($autoResolveClass !== $extensionType) {
266
                $reader = self::createReader($autoResolveClass);
267
                if ($reader->canRead($pFilename)) {
268
                    return $reader;
269
                }
270
            }
271
        }
272
273
        throw new Reader\Exception('Unable to identify a reader for this file');
274
    }
275
}
276