31 votes

Suppression / mappage et réécriture des identifiants PHP

Je suis d'essayer d'automatiser la suppression des espaces de noms à partir d'une classe PHP collection pour les rendre PHP 5.2 compatible. (Fournisseurs d'hébergement mutualisé n'avez pas envie de voyous PHP 5.3 installations. Aucune idée de pourquoi. Aussi le code en question n'utilise pas du tout 5.3 ajouts de fonctionnalités, c'est juste que de la syntaxe. Autoconversion semble plus facile que de le faire à la main ou de réimplanter la base de code.)

Pour la réécriture de l' *.les scripts php, je suis à la base de l'exécution sur un tokenizer liste. L'identificateur de la recherche+fusion est déjà complet. Mais je suis un peu confus maintenant comment accomplir la véritable réécriture.

function rewrite($name, $namespace, $use) {

    global $identifiers2;            // list of known/existing classes

    /*
        bounty on missing code here
    */

    return strtr($name, "\\", "_");  // goal: backslash to underscore
}

Cette fonction va être appelée sur chaque trouvé identifiant (si classe, de fonction ou de const). Recevoir des informations de contexte pour transformer un identifiant local dans une absolue/global $nom:

$name =
    rewrite(
        "classfuncconst",      # <-- foreach ($names as $name)
        "current\name\space",
        array(
           'namespc' => 'use\this\namespc',
           'alias' => 'from\name\too',
           ...
        )
    );

A ce stade, j'ai déjà préparé un $identifiers2 de la liste. Il contient une liste de toutes les classes connues, les fonctions et les noms de constantes (fusionné pour des raisons de simplicité ici).

$identifiers2 = array(             // Alternative suggestions welcome.
   "name\space\Class" => "Class",  // - list structure usable for task?
   "other\ns\func1" => "func1",    // - local name aliases helpful?
   "blip\CONST" => "CONST",        // - (ignore case-insensitivity)

L' $name paramètre tel que reçu par l' rewrite() fonction peut être un local, sans réserve, \absolue ou nom\espacés identificateur (mais juste identificateurs, aucune expression). L' $identifiers2 la liste est crucial pour résoudre non qualifiés identificateurs, qui peut se référer à des choses dans l'espace de noms courant, ou si elles n'y figurent pas, global choses.

Et les divers use namespace alias doivent être pris en compte et ajouter un peu de complication en plus de l'espace de noms de la résolution et des règles de priorité.

Alors, comment et dans quel ordre serait vous essayez de convertir les variations de la classe/les noms de fonction ici?

Paresse Mentale Bounty.

Pour en faire un moins flagrant plzsendtehcodez question: un explainative liste d'instructions ou de pseudo-code, la réponse devrait être admissible trop. Et si une autre approche serait plus adapté à la tâche, veuillez donner des précisions sur cette plutôt. (Mais non, la mise à niveau de PHP ou de changer l'hébergeur n'est pas une option.)

Je crois que j'ai compris entre temps, mais la question est toujours ouverte pour les réponses / propositions de mise en œuvre. (Sinon, la prime sera bien sûr aller à nikic.)

18voto

NikiC Points 47270

Dans une question existante sur la migration des espaces de noms de pseudo espace de noms de code , j'ai déjà introduit un outil de conversion que j'ai écrit dans le cadre d'un grand projet. Je n'ai pas continué ce projet parce que point de, mais aussi loin que je me souviens de l'espace de noms des remplaçants n'a fonctionné. (J'ai peut remettre sur pied ce projet à l'aide d'un bon analyseur à un certain point. De travail avec la plaine des jetons s'est avéré être tout à fait une tâche fastidieuse.)

Vous trouverez mes de mise en œuvre de l'espace de noms -> pseudo-résolution d'espace de noms dans le namespace.php. J'ai basé la mise en œuvre sur l' espace de noms de règles de résolution, qui sera probablement de vous aider, aussi.

Pour en faire un moins flagrant readmycodez réponse, voici les étapes de base le code:

  1. Obtenir l'identifiant à résoudre et de s'assurer qu'elle n'est pas une classe, une interface, une fonction ou une déclaration de constante (ces sont résolus dans registerClass et registerOther simplement en ajoutant l'espace de noms courant avec ns séparateurs remplacés par des underscores).
  2. Déterminer quel type de l'identificateur il est: Une classe, une fonction ou une constante. (Ils ont besoin de différentes de la résolution.)
  3. Assurez-vous que nous ne résolvent pas le self et parent classes, ni l' true, false et null des constantes.
  4. Résoudre les alias (usede la liste):
    1. Si l'identificateur est qualifié obtenir la partie avant le premier espace de noms séparateur et de vérifier s'il existe un alias de ce nom. Si elle le fait, remplacer la première partie avec l'alias d'espace de noms (maintenant l'identifiant sera pleinement qualifié). Sinon, ajouter l'espace de noms courant.
    2. Si l'identifiant est incompétent et l'identificateur de type est - class, de vérifier si l'identifiant est un alias, et si elle l'est, le remplacer par un alias de classe.
  5. Si l'identificateur est pleinement qualifié désormais le leader de l'espace de noms de séparateur et de le remplacer tous les autres noms séparateurs avec des traits de soulignement et à la fin de cet algorithme.
  6. Sinon:
    1. Si nous sommes dans l'espace de noms global, aucune autre résolution requise, ainsi la fin de cet algorithme.
    2. Si l'identificateur de type est - class ajouter l'espace de noms courant, remplacer toutes les NS de séparateurs avec des traits de soulignement et à la fin de cet algorithme.
    3. Sinon:
      1. Si la fonction / constante est définie à l'échelle mondiale quitter l'identificateur est et à la fin de cet algorithme. (Cela suppose qu'aucun des fonctions globales sont redéfinies dans un espace de noms! Dans mon code je ne fais pas cette hypothèse, j'ai donc insérer la résolution dynamique de code.)
      2. Sinon, ajouter l'espace de noms courant et de le remplacer tous les noms séparateurs avec des traits de soulignement. (On dirait que j'ai une erreur dans mon code ici: je ne fais pas cela, même si le assumeGlobal indicateur est défini. Au lieu de cela, j'ai toujours insérer la répartition dynamique de code.)

Autre remarque: N'oubliez pas que l'on peut aussi écrire namespace\some\ns. - Je résoudre ces constructions dans l' NS de la fonction (qui est également chargé de trouver des déclarations d'espace de noms).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X