Подтвердить что ты не робот

Идентификация/сопоставление и переписывание имен пространства имен PHP

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

Для переписывания скриптов *.php я в основном запускаю список

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

$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 и добавлять некоторые сложности, кроме правил разрешения имен и правил приоритета.

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

Умственная щедрость.

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

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

4b9b3361

Ответ 1

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

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

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

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

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