11<?php
22
3- require_once __DIR__ . '/ModuleFileParser.php ' ;
3+ use Combodo \iTop \PhpParser \Evaluation \PhpExpressionEvaluator ;
4+
45require_once __DIR__ . '/ModuleFileReaderException.php ' ;
6+ require_once APPROOT . 'sources/PhpParser/Evaluation/PhpExpressionEvaluator.php ' ;
57
68class ModuleFileReader {
79 private static ModuleFileReader $ oInstance ;
810 private static int $ iDummyClassIndex = 0 ;
911
12+ const FUNC_CALL_WHITELIST =[
13+ "function_exists " ,
14+ "class_exists " ,
15+ "method_exists "
16+ ];
17+
18+ const STATIC_CALLWHITELIST =[
19+ "utils::GetItopVersionWikiSyntax "
20+ ];
21+
1022 protected function __construct () {
1123 }
1224
@@ -32,24 +44,28 @@ public function ReadModuleFileInformation(string $sModuleFilePath) : array
3244 {
3345 try
3446 {
35- $ aNodes = ModuleFileParser::GetInstance ()->ParsePhpCode (file_get_contents ($ sModuleFilePath ));
47+ $ oParser = (new \PhpParser \ParserFactory ())->createForNewestSupportedVersion ();
48+ $ aNodes = $ oParser ->parse (file_get_contents ($ sModuleFilePath ));
3649 }
3750 catch (PhpParser \Error $ e ) {
3851 throw new \ModuleFileReaderException ($ e ->getMessage (), 0 , $ e , $ sModuleFilePath );
3952 }
4053
54+ PhpExpressionEvaluator::GetInstance ()->SetFunctionsWhitelist (static ::FUNC_CALL_WHITELIST );
55+ PhpExpressionEvaluator::GetInstance ()->SetStaticCallsWhitelist (static ::STATIC_CALLWHITELIST );
56+
4157 try {
4258 foreach ($ aNodes as $ sKey => $ oNode ) {
4359 if ($ oNode instanceof \PhpParser \Node \Stmt \Expression) {
44- $ aModuleInfo = ModuleFileParser:: GetInstance () ->GetModuleInformationFromAddModuleCall ($ sModuleFilePath , $ oNode );
60+ $ aModuleInfo = $ this ->GetModuleInformationFromAddModuleCall ($ sModuleFilePath , $ oNode );
4561 if (! is_null ($ aModuleInfo )){
4662 $ this ->CompleteModuleInfoWithFilePath ($ aModuleInfo );
4763 return $ aModuleInfo ;
4864 }
4965 }
5066
5167 if ($ oNode instanceof PhpParser \Node \Stmt \If_) {
52- $ aModuleInfo = ModuleFileParser:: GetInstance () ->GetModuleInformationFromIf ($ sModuleFilePath , $ oNode );
68+ $ aModuleInfo = $ this ->GetModuleInformationFromIf ($ sModuleFilePath , $ oNode );
5369 if (! is_null ($ aModuleInfo )){
5470 $ this ->CompleteModuleInfoWithFilePath ($ aModuleInfo );
5571 return $ aModuleInfo ;
@@ -164,4 +180,123 @@ public function GetAndCheckModuleInstallerClass($aModuleInfo) : ?string
164180
165181 return $ sModuleInstallerClass ;
166182 }
183+
184+ /**
185+ * @param string $sModuleFilePath
186+ * @param \PhpParser\Node\Expr\Assign $oAssignation
187+ *
188+ * @return array|null
189+ * @throws \ModuleFileReaderException
190+ */
191+ private function GetModuleInformationFromAddModuleCall (string $ sModuleFilePath , \PhpParser \Node \Stmt \Expression $ oExpression ) : ?array
192+ {
193+ /** @var Assign $oAssignation */
194+ $ oAssignation = $ oExpression ->expr ;
195+ if (false === ($ oAssignation instanceof PhpParser \Node \Expr \StaticCall)) {
196+ return null ;
197+ }
198+
199+ /** @var PhpParser\Node\Expr\StaticCall $oAssignation */
200+
201+ if ("SetupWebPage " !== $ oAssignation ?->class?->name) {
202+ return null ;
203+ }
204+
205+ if ("AddModule " !== $ oAssignation ?->name?->name) {
206+ return null ;
207+ }
208+
209+ $ aArgs = $ oAssignation ?->args;
210+ if (count ($ aArgs ) != 3 ) {
211+ throw new ModuleFileReaderException ("Not enough parameters when calling SetupWebPage::AddModule " , 0 , null , $ sModuleFilePath );
212+ }
213+
214+ $ oModuleId = $ aArgs [1 ];
215+ if (false === ($ oModuleId instanceof PhpParser \Node \Arg)) {
216+ throw new ModuleFileReaderException ("2nd parameter to SetupWebPage::AddModule call issue: " . get_class ($ oModuleId ), 0 , null , $ sModuleFilePath );
217+ }
218+
219+ /** @var PhpParser\Node\Arg $oModuleId */
220+ if (false === ($ oModuleId ->value instanceof PhpParser \Node \Scalar \String_)) {
221+ throw new ModuleFileReaderException ("2nd parameter to SetupWebPage::AddModule not a string: " . get_class ($ oModuleId ->value ), 0 , null , $ sModuleFilePath );
222+ }
223+
224+ $ sModuleId = PhpExpressionEvaluator::GetInstance ()->EvaluateExpression ($ oModuleId ->value );
225+
226+ $ oModuleConfigInfo = $ aArgs [2 ];
227+ if (false === ($ oModuleConfigInfo instanceof PhpParser \Node \Arg)) {
228+ throw new ModuleFileReaderException ("3rd parameter to SetupWebPage::AddModule call issue: " . get_class ($ oModuleConfigInfo ), 0 , null , $ sModuleFilePath );
229+ }
230+
231+ /** @var PhpParser\Node\Arg $oModuleConfigInfo */
232+ if (false === ($ oModuleConfigInfo ->value instanceof PhpParser \Node \Expr \Array_)) {
233+ throw new ModuleFileReaderException ("3rd parameter to SetupWebPage::AddModule not an array: " . get_class ($ oModuleConfigInfo ->value ), 0 , null , $ sModuleFilePath );
234+ }
235+
236+ $ aModuleConfig = PhpExpressionEvaluator::GetInstance ()->EvaluateExpression ($ oModuleConfigInfo ->value );
237+
238+ if (! is_array ($ aModuleConfig )){
239+ throw new ModuleFileReaderException ("3rd parameter to SetupWebPage::AddModule not an array: " . get_class ($ oModuleConfigInfo ->value ), 0 , null , $ sModuleFilePath );
240+ }
241+
242+ return [
243+ $ sModuleFilePath ,
244+ $ sModuleId ,
245+ $ aModuleConfig ,
246+ ];
247+ }
248+
249+ /**
250+ * @param string $sModuleFilePath
251+ * @param \PhpParser\Node\Stmt\If_ $oNode
252+ *
253+ * @return array|null
254+ * @throws \ModuleFileReaderException
255+ */
256+ private function GetModuleInformationFromIf (string $ sModuleFilePath , \PhpParser \Node \Stmt \If_ $ oNode ) : ?array
257+ {
258+ $ bCondition = PhpExpressionEvaluator::GetInstance ()->EvaluateExpression ($ oNode ->cond );
259+ if ($ bCondition ) {
260+ foreach ($ oNode ->stmts as $ oSubNode ) {
261+ if ($ oSubNode instanceof \PhpParser \Node \Stmt \Expression) {
262+ $ aModuleConfig = $ this ->GetModuleInformationFromAddModuleCall ($ sModuleFilePath , $ oSubNode );
263+ if (!is_null ($ aModuleConfig )) {
264+ return $ aModuleConfig ;
265+ }
266+ }
267+ }
268+
269+ return null ;
270+ }
271+
272+ if (! is_null ($ oNode ->elseifs )) {
273+ foreach ($ oNode ->elseifs as $ oElseIfSubNode ) {
274+ /** @var \PhpParser\Node\Stmt\ElseIf_ $oElseIfSubNode */
275+ $ bCondition = PhpExpressionEvaluator::GetInstance ()->EvaluateExpression ($ oElseIfSubNode ->cond );
276+ if ($ bCondition ) {
277+ return $ this ->GetModuleConfigurationFromStatement ($ sModuleFilePath , $ oElseIfSubNode ->stmts );
278+ }
279+ }
280+ }
281+
282+ if (! is_null ($ oNode ->else )) {
283+ return $ this ->GetModuleConfigurationFromStatement ($ sModuleFilePath , $ oNode ->else ->stmts );
284+ }
285+
286+ return null ;
287+ }
288+
289+ private function GetModuleConfigurationFromStatement (string $ sModuleFilePath , array $ aStmts ) : ?array
290+ {
291+ foreach ($ aStmts as $ oSubNode ) {
292+ if ($ oSubNode instanceof \PhpParser \Node \Stmt \Expression) {
293+ $ aModuleConfig = $ this ->GetModuleInformationFromAddModuleCall ($ sModuleFilePath , $ oSubNode );
294+ if (!is_null ($ aModuleConfig )) {
295+ return $ aModuleConfig ;
296+ }
297+ }
298+ }
299+
300+ return null ;
301+ }
167302}
0 commit comments