Test Failed
Push — master ( c19a70...4a5f5f )
by Sebastian
05:20
created

Localization_Parser::createLanguageInstance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 11
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 19
rs 9.9
1
<?php
2
/**
3
 * File containing the {@link Localization_Parser} class.
4
 * @package Localization
5
 * @subpackage Parser
6
 * @see Localization_Parser
7
 */
8
9
declare(strict_types=1);
10
11
namespace AppLocalize;
12
13
use AppUtils\FileHelper;
14
use function AppUtils\parseVariable;
15
16
/**
17
 * File-based parsing engine that extracts translateable
18
 * application strings from PHP and Javascript code.
19
 *
20
 * Uses the built-in PHP tokenizer and Tim Whitlock's
21
 * jtokenizer for parsing javascript files. 
22
 *
23
 * @package Localization
24
 * @subpackage Parser
25
 * @author Sebastian Mordziol <[email protected]>
26
 */
27
class Localization_Parser
28
{
29
    const ERROR_INVALID_LANGUAGE_ID = 40601;
30
    const ERROR_UNSUPPORTED_FILE_EXTENSION = 40602;
31
    const ERROR_INVALID_LANGUAGE_CLASS = 40603;
32
    
33
   /**
34
    * @var Localization_Scanner
35
    */
36
    protected $scanner;
37
    
38
   /**
39
    * @var Localization_Scanner_StringsCollection
40
    */
41
    protected $collection;
42
    
43
    protected $languageMappings = array(
44
        'js' => 'Javascript',
45
        'php' => 'PHP'
46
    );
47
    
48
    public function __construct(Localization_Scanner $scanner)
49
    {
50
        $this->scanner = $scanner;
51
        $this->collection = $scanner->getCollection();
52
    }
53
    
54
   /**
55
    * Parses a source file. Must have a valid supported file extension.
56
    * 
57
    * @param string $path
58
    * @return Localization_Parser_Language
59
    * @throws Localization_Exception
60
    * 
61
    * @see Localization_Parser::ERROR_UNSUPPORTED_FILE_EXTENSION
62
    */
63
    public function parseFile(string $path) : Localization_Parser_Language
64
    {
65
        $this->requireValidFile($path);
66
         
67
        $ext = FileHelper::getExtension($path);
68
        
69
        $language = $this->createLanguage($this->languageMappings[$ext]);
70
        
71
        $language->parseFile($path);
72
        
73
        return $language;
74
    }
75
    
76
   /**
77
    * Parses the string for the specified language.
78
    * 
79
    * @param string $languageID
80
    * @param string $code
81
    * @return Localization_Parser_Language
82
    * @throws Localization_Exception
83
    * 
84
    * @see Localization_Parser::ERROR_INVALID_LANGUAGE_ID
85
    */
86
    public function parseString(string $languageID, string $code) : Localization_Parser_Language
87
    {
88
        $this->requireValidLanguageID($languageID);
89
        
90
        $language = $this->createLanguage($languageID);
91
        
92
        $language->parseString($code);
93
        
94
        return $language;
95
    }
96
97
    /**
98
     * @param string $path
99
     * @throws Localization_Exception
100
     * @see Localization_Parser::ERROR_UNSUPPORTED_FILE_EXTENSION
101
     */
102
    protected function requireValidFile(string $path)
103
    {
104
        $ext = FileHelper::getExtension($path);
105
        
106
        if($this->isExtensionSupported($ext)) {
107
            return;
108
        }
109
        
110
        throw new Localization_Exception(
111
            sprintf('Unsupported file extension [%s].', $ext),
112
            sprintf(
113
                'Tried parsing the file [%s].',
114
                $path
115
            ),
116
            self::ERROR_UNSUPPORTED_FILE_EXTENSION
117
        );
118
    }
119
120
    /**
121
     * @param string $languageID
122
     * @throws Localization_Exception
123
     * @see Localization_Parser::ERROR_INVALID_LANGUAGE_ID
124
     */
125
    protected function requireValidLanguageID(string $languageID)
126
    {
127
        $values = $this->getLanguageIDs();
128
        
129
        if(in_array($languageID, $values)) {
130
            return;
131
        }
132
133
        throw new Localization_Exception(
134
            'Unknown language ID',
135
            sprintf(
136
                'The language ID [%s] is not a known ID. Valid IDs are: [%s].',
137
                $languageID,
138
                implode(', ', $values)
139
            ),
140
            self::ERROR_INVALID_LANGUAGE_ID
141
        );
142
    }
143
    
144
   /**
145
    * Retrieves a list of all language IDs that are supported.
146
    * @return string[] IDs list like "PHP", "Javascript"
147
    */
148
    public function getLanguageIDs() : array
149
    {
150
        return array_values($this->languageMappings);
151
    }
152
    
153
   /**
154
    * @var array<string,Localization_Parser_Language>
155
    */
156
    protected $languageParsers = array();
157
158
    /**
159
     * Creates a parser for the specified language, e.g. "PHP".
160
     * NOTE: Existing parser instances are re-used.
161
     *
162
     * @param string $languageID
163
     * @return Localization_Parser_Language
164
     *
165
     * @throws Localization_Exception
166
     * @see Localization_Parser::ERROR_INVALID_LANGUAGE_ID
167
     * @see Localization_Parser::ERROR_INVALID_LANGUAGE_CLASS
168
     */
169
    public function createLanguage(string $languageID) : Localization_Parser_Language
170
    {
171
        $this->requireValidLanguageID($languageID);
172
        
173
        if(!isset($this->languageParsers[$languageID])) 
174
        {
175
            $this->languageParsers[$languageID] = $this->createLanguageInstance($languageID);
176
        }
177
        
178
        return $this->languageParsers[$languageID];
179
    }
180
181
    /**
182
     * @param string $id
183
     * @return Localization_Parser_Language
184
     * @throws Localization_Exception
185
     * @see Localization_Parser::ERROR_INVALID_LANGUAGE_CLASS
186
     */
187
    private function createLanguageInstance(string $id) : Localization_Parser_Language
188
    {
189
        $class = Localization_Parser_Language::class.'_'.$id;
190
191
        $object = new $class($this);
192
193
        if($object instanceof Localization_Parser_Language)
194
        {
195
            return $object;
196
        }
197
198
        throw new Localization_Exception(
199
            'Invalid parser language class',
200
            sprintf(
201
                'The created instance [%s] does not extend the base class [%s].',
202
                parseVariable($object)->enableType()->toString(),
203
                Localization_Parser_Language::class
204
            ),
205
            self::ERROR_INVALID_LANGUAGE_CLASS
206
        );
207
    }
208
209
   /**
210
    * Whether the specified file extension is supported.
211
    * 
212
    * @param string $ext
213
    * @return bool
214
    */
215
    public function isExtensionSupported(string $ext) : bool
216
    {
217
        $ext = strtolower($ext);
218
        
219
        return isset($this->languageMappings[$ext]);
220
    }
221
222
    /**
223
     * Checks if the target file is a file that can be
224
     * parsed, which means that it must have a supported 
225
     * file extension.
226
     *
227
     * @param string $file
228
     * @return boolean
229
     */
230
    public function isFileSupported(string $file) : bool
231
    {
232
        return $this->isExtensionSupported(FileHelper::getExtension($file));
233
    }
234
}
235