2013-02-13 9 views
5

Ich versuche, den Tokenizer zu verwenden, um eine Datei zu durchsuchen, um alle definierten Klassen, alles, was sie erweitern, alle erstellten Instanzen und wann immer sie statisch aufgerufen wurden, zu finden.Wie finde ich alle in einer PHP-Datei verwendeten Klassen?

<?php 

$tokens = token_get_all(file_get_contents($file)); 

$used_classes = array(); 
$defined_classes = array(); 
$variable_classes = array(); 

foreach($tokens as $i => $token) { 

    if(is_array($token)) { 

     if(isset($tokens[$i - 2][0], $tokens[$i - 1][0])) { 

      // new [class] 
      if ($tokens[$i - 2][0] == T_NEW AND $tokens[$i - 1][0] == T_WHITESPACE) { 

       if($tokens[$i][0] == T_STRING) { 
        $used_classes[$token[1]] = TRUE; 

       // new $variable() 
       } elseif($tokens[$i][0] == T_VARIABLE) {  

        // @todo, this is really broken. However, do best to look for the assignment 
        if(preg_match('~\$var\s*=\s*([\'"])((?:(?!\1).)*)\1~', $text, $match)) { 
         if(empty($extension_classes[$match[2]])) { 
          $used_classes[$match[2]] = TRUE; 
         } 
        } elseif($token[1] !== '$this') { 
         $variable_classes[$token[1]] = TRUE; 
        } 
       } 

      } 

      // class [class] 
      if ($tokens[$i - 2][0] == T_CLASS AND $tokens[$i - 1][0] == T_WHITESPACE) { 

       if($tokens[$i][0] == T_STRING) { 
        $defined_classes[$token[1]] = TRUE; 
       } 
      } 


      // @todo: find more classes \/ 

      // class [classname] extends [class] ??? 
      // [class]::method()??? 
     } 
    } 
} 

Wie kann ich diesen Code erweitern, um zusätzliche Instanzen von PHP-Klassen wie oben erwähnt zu finden?

+0

In PHP gibt es eine magische Konstante __ FILE __ (ohne Leerzeichen). Du kannst diese Datei öffnen (fopen oder file_get_contents) und sie über preg_match (sowas wie /^\s*class(.*)$/ und /(.*)::(.*)/ und so) suchen. Kenne diese ziemlich nicht-straigh Lösung, also wird vielleicht jemand einen besseren finden. Wenn Sie alle Klassen finden möchten, können Sie die Funktion get_declared_classes (http://php.net/manual/en/function.get-declared-classes.php) und so verwenden, aber denken Sie daran, dass auch Kern-Klassen enthalten sind. – tomis

+0

Von Ihren drei Empfehlungen hat nur die Suche mit Regex etwas mit der statischen Analyse von PHP-Code zu tun. Allerdings würde ich lieber Regex vermeiden, da der PHP-Parser vertrauenswürdiger ist. Ich kann mir auch nicht vorstellen, wie komplex die Regex sein müsste, um eine variable Variable zu finden. – Xeoncross

+0

Nun, ich fürchte, dass die vollständige Füllung, die Sie anfordern (Klassendefinition und Aufrufe in der Zieldatei), nicht möglich ist ... – tomis

Antwort

2

Parsing und dann PHP-Code zu interpretieren ist nicht etwas, das gut gelöst werden kann, einen regulären Ausdruck verwenden. Sie würden etwas sehr viel schlaueres benötigen, wie eine Zustandsmaschine, die Dinge wie Umfang, Klassennamen, Vererbung usw. wirklich verstehen kann, um zu tun, was Sie wollen.

Es passiert einfach so, dass ich einen PHP-to-Javascript Konverter geschrieben haben zufällig auf der Grundlage einer Zustandsmaschine, die fast zu tun werden die meisten von dem, was Sie tun möchten:

alle definierten Klassen

Ja, alle Klassen erstellen ein ClassScope mit allen aufgelisteten Variablen, und ihre Methoden werden als FunctionScope erstellt, sodass Sie sehen können, welche Methoden eine Klasse hat.

alles, was sie erweitern

Ja, hat jede Klasse, es ist übergeordneten Klassen aufgeführt in ClassScope -> $ parentClasses

alle erstellt Instanzen

Nö, aber wouldn‘ Es ist schwer, zusätzlichen Code hinzuzufügen, um diese aufzuzeichnen.

, wann immer sie statisch aufgerufen wurden.

Nein - aber das könnte eigentlich mit einer Regex gemacht werden.

Obwohl es nicht genau Ihr Problem löst, würde das Projekt, wie es steht, Sie 95% des Weges in Richtung was Sie tun möchten, erhalten, was ein paar Wochen Arbeit sparen würde.

0

Inclued ist wahrscheinlich wert in hier suchen, obwohl ich es Sie nicht denken, werden nur irgendwelche Daten über welche Dateien/Klassen enthalten waren und wie oft.

+0

Das ist ein gutes Werkzeug, aber leider erfordert es, dass Sie den Code ausführen. Ich suche nach statischen Analysen, da es nicht realistisch ist, jeden Aspekt eines PHP-Systems auszuführen, das keine vollständige Code-Abdeckung von Komponententests enthält. – Xeoncross

0

Ich glaube nicht, dass Sie dies tun können, indem Sie nur Tokens analysieren.

Sie müssen für jeden Klassennamen wissen, welche tatsächliche Definition er darstellt, einschließlich Vererbungsbeziehungen und ob er in Ihrem Code zur Implementierung einer Schnittstelle verwendet wurde. Die Klasse/Schnittstellendefinition kann sich in einer anderen Datei befinden; Diese Datei kann unter bestimmten Bedingungen enthalten sein. Möglicherweise haben Sie denselben Klassennamen in verschiedenen Dateien unterschiedlich definiert. Also müssen Sie im Allgemeinen alle Dateien, die Ihr System bilden, gleichzeitig verarbeiten.

Was Sie als Grundlage benötigen, ist ein Werkzeug, das PHP analysiert und echte Symboltabellen erstellt. Vielleicht können Sie daraus Ihr Ergebnis berechnen. (Ein solches Tool analysiert Token als Startpunkt, aber es ist weitaus mehr Arbeit als das Scannen von trivialen Token).

0

Wenn Sie nur den Code laden, können Sie die integrierte Reflection-API (ReflectionClass::_construct() usw.) verwenden, um jede Klasse zu untersuchen.

Um die Klassen selbst zu erhalten, verwenden Sie die integrierte get_declared_classes().

. (Anmerkung: Ich kann das nicht versucht haben, so YMMV)

+0

Das ist nicht wirklich akzeptabel, aber vielleicht könnte ich einen Prozess forkieren und laden Sie die Datei (auch wenn es alles abreißt) und die neuen Funktionen/Klassen zurückgeben. – Xeoncross