Удаление / отображение и перезапись идентификаторов пространства имен PHP - PullRequest
31 голосов
/ 24 мая 2011

Я пытаюсь автоматизировать удаление пространств имен из коллекции классов PHP, чтобы сделать их совместимыми с PHP 5.2.(Провайдерам общего хостинга не нравятся мошеннические установки PHP 5.3. Не знаю почему. Также в рассматриваемом коде не используются какие-либо дополнения к 5.3, только этот синтаксис. Автоконверсия кажется проще, чем делать это вручную или переопределять кодовую базу.)

Для переписывания скриптов * .php я в основном работаю над списком tokenizer .Поиск идентификатора + объединение уже завершено.Но я немного запутался, как выполнить реализацию.

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

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

    /*
        bounty on missing code here
    */

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

Эта функция будет вызываться для каждого найденного идентификатора (класса, функции или const).Он получит некоторую контекстную информацию для преобразования локального идентификатора в абсолютное / глобальное $ name:

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

На этом этапе я уже подготовил список $identifiers2.Он содержит список всех известных классов, функций и имен констант (объединены для простоты здесь).

$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)

Параметр $name, полученный функцией rewrite(), может быть локальным , неквалифицированным , \ absolute или name \ spaced идентификатор (но только идентификаторы, без выражений).Список $identifiers2 имеет решающее значение для разрешения неквалифицированных идентификаторов , которые могут ссылаться на вещи в текущем пространстве имен или, если их там нет, глобальные вещи.

и различные псевдонимы use namespaceдолжны быть приняты во внимание и добавить некоторые сложности, помимо разрешения пространства имен и правил приоритета.

Итак, как / в каком порядке вы пытаетесь преобразовать варианты названий классов / функций здесь?

Mental Laziness Bounty.

Чтобы сделать этоменее вопиющий вопрос plzsendtehcodez: список пояснительных инструкций или ответ псевдокода также будут приемлемы.И если другой подход будет более подходящим для этой задачи, пожалуйста, уточните это.(Но нет, обновление PHP или смена хостера не вариант.)

Я думаю, что пока что понял это, но вопрос все еще открыт для ответов / предложений по реализации.(В противном случае щедрость, очевидно, перейдет к nikic.)

1 Ответ

18 голосов
/ 27 мая 2011

В существующем существующем вопросе о миграции пространств имен в псевдо-код пространства имен Я уже представил инструмент преобразования , который я написал как часть более крупного проекта.С тех пор я больше не поддерживал этот проект, но, насколько я помню, замены пространства имен работали.(В какой-то момент я могу переопределить этот проект с использованием правильного парсера . Работа с простыми токенами оказалась довольно утомительной задачей.)

Вы найдете мою реализацию пространства имен -> псевдоразрешение пространства имен в namespace.php .Я основал реализацию на правилах разрешения пространства имен , которые, вероятно, будут вам полезны.

Чтобы сделать этот ответ readmycodez менее вопиющим, вот основные шаги, которые выполняет код:

  1. Получите идентификатор, который нужно разрешить, и убедитесь, что он не является объявлением класса, интерфейса, функции или константы (они разрешены в registerClass и registerOther просто добавив текущее пространство имен с разделителями ns, замененными символами подчеркивания.)
  2. Определите тип идентификатора: класс, функция или константа.(Поскольку для них требуется другое разрешение.)
  3. Убедитесь, что мы не разрешаем ни классы self и parent, ни константы true, false и null.
  4. Устранить псевдонимы (use список):
    1. Если идентификатор квалифицирован, получить деталь перед первым разделителем пространства имен и проверить, существует ли псевдоним с этим именем.Если это так, замените первую часть псевдонимом пространства имен (теперь идентификатор будет полностью определен).В противном случае добавьте текущее пространство имен.
    2. Если идентификатор не определен и тип идентификатора равен class, проверьте, является ли идентификатор псевдонимом, и если это так, замените его псевдонимом класса.
  5. Если идентификатор полностью определен, теперь отбросьте ведущий разделитель пространства имен и замените все остальные разделители пространства имен подчеркиванием и завершите этот алгоритм.
  6. В противном случае:
    1. Если мы находимся вглобальное пространство имен, дальнейшее разрешение не требуется, поэтому завершите этот алгоритм.
    2. Если тип идентификатора class, предшествующий текущему пространству имен, замените все разделители NS символами подчеркивания и завершите этот алгоритм.
    3. В противном случае:
      1. Если функция / константа определена глобально, оставьте идентификатор как есть и завершите этот алгоритм.(Это предполагает, что никакие глобальные функции не переопределяются в пространстве имен! В моем коде я не делаю этого предположения, поэтому я вставляю код динамического разрешения.)
      2. В противном случае предварительно добавьте текущее пространство имен и замените все разделители пространства имен подчеркиванием,(Похоже, в моем коде произошла ошибка: я не делаю этого, даже если установлен флаг assumeGlobal. Вместо этого я всегда вставляю код динамической отправки.)

Дополнительное примечание: не забывайте, что можно также написать namespace\some\ns.Я разрешаю эти конструкции в функции NS (которая также отвечает за поиск объявлений пространства имен).

...