1 | <?php |
||
31 | class Generator |
||
32 | { |
||
33 | /** string All generated view classes will end with this suffix */ |
||
34 | const VIEW_CLASSNAME_SUFFIX = 'View'; |
||
35 | |||
36 | /** @var array Collection of PHP reserved words */ |
||
37 | protected static $reservedWords = array('list'); |
||
38 | |||
39 | /** @var Metadata[] Collection of view metadata */ |
||
40 | protected $metadata = array(); |
||
41 | |||
42 | /** @var \samsonphp\generator\Generator */ |
||
43 | protected $generator; |
||
44 | |||
45 | /** @var string Generated classes namespace prefix */ |
||
46 | protected $namespacePrefix; |
||
47 | |||
48 | /** @var string Collection of namespace parts to be ignored in generated namespaces */ |
||
49 | protected $ignoreNamespace = array(); |
||
50 | |||
51 | /** @var array Collection of view files */ |
||
52 | protected $files = array(); |
||
53 | |||
54 | /** @var string Scanning entry path */ |
||
55 | protected $entryPath; |
||
56 | |||
57 | /** @var string Parent view class name */ |
||
58 | protected $parentViewClass; |
||
59 | |||
60 | /** |
||
61 | * Generator constructor. |
||
62 | * |
||
63 | * @param \samsonphp\generator\Generator $generator PHP code generator instance |
||
64 | * @param string $namespacePrefix Generated classes namespace will have it |
||
65 | * @param array $ignoreNamespace Namespace parts that needs to ignored |
||
66 | * @param string $parentViewClass Generated classes will extend it |
||
67 | */ |
||
68 | 3 | public function __construct( |
|
80 | |||
81 | /** |
||
82 | * Change variable name to camel caps format. |
||
83 | * |
||
84 | * @param string $variable |
||
85 | * |
||
86 | * @return string Changed variable name |
||
87 | */ |
||
88 | 1 | public function changeName($variable) |
|
100 | |||
101 | /** |
||
102 | * Recursively scan path for files with specified extensions. |
||
103 | * |
||
104 | * @param string $source Entry point path |
||
105 | * @param string $path Entry path for scanning |
||
106 | * @param array $extensions Collection of file extensions without dot |
||
107 | */ |
||
108 | 3 | public function scan($source, array $extensions = array(View::DEFAULT_EXT), $path = null) |
|
127 | |||
128 | /** |
||
129 | * Analyze view file and create its metadata. |
||
130 | * |
||
131 | * @param string $file Path to view file |
||
132 | * |
||
133 | * @return Metadata View file metadata |
||
134 | */ |
||
135 | 2 | public function analyze($file) |
|
136 | { |
||
137 | 2 | $metadata = new Metadata(); |
|
138 | // Use PHP tokenizer to find variables |
||
139 | 2 | foreach ($tokens = token_get_all(file_get_contents($file)) as $idx => $token) { |
|
140 | 2 | if (!is_string($token) && $token[0] === T_VARIABLE) { |
|
141 | // Store variable |
||
142 | 1 | $variableText = $token[1]; |
|
143 | // Store variable name |
||
144 | 1 | $variableName = ltrim($token[1], '$'); |
|
145 | |||
146 | // Ignore static variables |
||
147 | 1 | if (isset($tokens[$idx-1]) && $tokens[$idx-1][0] === T_DOUBLE_COLON) { |
|
148 | 1 | $metadata->static[$variableName] = $variableText; |
|
149 | 1 | continue; |
|
150 | } |
||
151 | |||
152 | // If next token is object operator |
||
153 | 1 | if ($tokens[$idx + 1][0] === T_OBJECT_OPERATOR) { |
|
154 | // Ignore $this |
||
155 | 1 | if ($variableName === 'this') { |
|
156 | 1 | continue; |
|
157 | } |
||
158 | |||
159 | // And two more tokens |
||
160 | 1 | $variableText .= $tokens[$idx + 1][1] . $tokens[$idx + 2][1]; |
|
161 | |||
162 | // Store object variable |
||
163 | 1 | $metadata->variables[$this->changeName($variableName)] = $variableText; |
|
164 | // Store view variable key - actual object name => full variable usage |
||
165 | 1 | $metadata->originalVariables[$this->changeName($variableName)] = $variableName; |
|
166 | 1 | } else { |
|
167 | // Store original variable name |
||
168 | 1 | $metadata->originalVariables[$this->changeName($variableName)] = $variableName; |
|
169 | // Store view variable key - actual object name => full variable usage |
||
170 | 1 | $metadata->variables[$this->changeName($variableName)] = $variableText; |
|
171 | } |
||
172 | 2 | } elseif ($token[0] === T_DOC_COMMENT) { // Match doc block comments |
|
173 | // Parse variable type and name |
||
174 | 2 | if (preg_match('/@var\s+(?<type>[^ ]+)\s+(?<variable>[^*]+)/', $token[1], $matches)) { |
|
175 | 1 | $metadata->types[substr(trim($matches['variable']), 1)] = $matches['type']; |
|
176 | 1 | } |
|
177 | 2 | } |
|
178 | 2 | } |
|
179 | |||
180 | 2 | return $metadata; |
|
181 | } |
||
182 | |||
183 | /** |
||
184 | * Generic class name and its name space generator. |
||
185 | * |
||
186 | * @param string $file Full path to view file |
||
187 | * @param string $entryPath Entry path |
||
188 | * |
||
189 | * @return array Class name[0] and namespace[1] |
||
190 | * @throws GeneratedViewPathHasReservedWord |
||
191 | */ |
||
192 | 2 | protected function generateClassName($file, $entryPath) |
|
220 | |||
221 | /** |
||
222 | * Generate view classes. |
||
223 | * |
||
224 | * @param string $path Entry path for generated classes and folders |
||
225 | */ |
||
226 | 2 | public function generate($path = __DIR__) |
|
239 | |||
240 | /** @return string Hash representing generator state */ |
||
241 | 1 | public function hash() |
|
250 | |||
251 | /** |
||
252 | * Create View class ancestor. |
||
253 | * |
||
254 | * @param Metadata $metadata View file metadata |
||
255 | * @param string $path Entry path for generated classes and folders |
||
256 | */ |
||
257 | 1 | protected function generateViewClass(Metadata $metadata, $path) |
|
302 | |||
303 | /** |
||
304 | * Generate constructor for application class. |
||
305 | * |
||
306 | * @param string $variable View variable name |
||
307 | * @param string $original Original view variable name |
||
308 | * @param string $type Variable type |
||
309 | * |
||
310 | * @return string View variable setter method |
||
311 | */ |
||
312 | 1 | protected function generateViewVariableSetter($variable, $original, $type = 'mixed') |
|
330 | } |
||
331 |