Возможность записи в локальные файлы сайта на WordPress является одной из функций, которая требуется многим плагинам и темам для различных целей. Безопасность — это наиболее важный вопрос для плагинов, а темы должны заботиться об этом в процессе записи в локальные файловые системы.

WordPress работает на разных хостингах, поэтому для разработчиков становится трудно создавать плагины и темы, которые имели бы доступ к локальным файловым системам для работы в различных условиях без ущерба для безопасности.

Смотрите также:

В этом уроке мы узнаем, как использовать WordPress Filesystem API для доступа к локальной файловой системе, которая позаботится о правильном праве доступа к файлам. В процессе мы создадим плагин, который выводит форму с текстом на странице администратора, которая будет сохранять этот текст в текстовой файл.

Зачем использовать WordPress Filesystem API?

Вы можете поинтересоваться, почему бы нам просто не использовать функции PHP файловой системы для чтения и записи локальных файлов, а не начинать изучать и использовать совершенно новый набор API?

Проблема использования API файловой системы PHP состоит в том, что она не заботится о правах доступа к файлам автоматически. Предположим, вы используете shared хостинг для размещения вашего WordPress сайта, и ваш веб-сервер работает как "админ" операционной системы. Поэтому, каждый раз, когда вы создаете файлы, используя PHP, они принадлежат "администраторам".

Таким образом, любой другой веб-сайт, который размещен в том же хостинге, может также получить доступ к файлам сайта, так как он также работает в качестве "администратора", что создаст проблемы безопасности на вашем сайте. Чтобы защитить нас от этой проблемы, необходимо изменить владельцев файла и права доступа вручную с помощью PHP.

Но когда вы входите, используя SSH или FTP / SFTP для создания файлов, то они прикрепляются к учетной записи пользователя операционной системы, под которой он вошел в систему. Если FTP-сервер работает как пользователь "Admin" , а вы вошли в систему как пользователь "User", то новые файлы будут иметь владельца "User", а не "Admin".

WordPress представил Filesystem API, которая может автоматически заботится о правах доступа к файлам. Filesystem API была выпущена еще в версии WordPress 2.6. WordPress на самом деле выпустили ее для поддержки своих плагинов, тем и основных обновлений системы, но следующие плагины и темы начали использовать ее уже для своих собственных целей.

Как работает API файловой системы?

API файловой системы может делать записи в файлах, используя системные вызовы (т.е. direct, ftp, ftp socket, ssh2). Файловая система выбирает один из методов, основываясь на том, какой из представленных методов имеет соответствующий допуск, и какое PHP расширение доступно. API файловой системы сначала проверяет метод direct, затем ftp и, наконец, ssh2.

При использовании FTP или SSH вы должны будете получить учетные данные вашего пользователя. API файловой системы предоставляет специальные функции, которые облегчат этот процесс вывода на экран специальной формы для получения и хранения данных.

Создание плагина для работы с файлами

Теперь давайте создадим наш плагин, который будет отображать текст на странице, и при заполнении формы сохранять ее содержимое в локальный файл.

Вот структура директории нашего плагина:

--filesystem
    --filesystem.php
    --filesystem-demo
        --demo.txt

Создайте эти файлы в директории wp-content/plugins вашего сайта WordPress.

Для того, чтобы сделать плагин устанавливаемым, вставьте данный код в файл filesystem.php:

<?php
   
/*
Plugin Name: Filesystem API
Plugin URI: http://www.sitepoint.com
Description: A sample plugin to demonstrate Filesystem API
Version: 1.0
Author: Narayan Prusty
*/

Теперь перейдите в панель администратора и активируйте плагин.

Создание страницы управления плагином

Далее нам понадобится страница в панели администратора, где наш пример будет размещен. Ниже представлен код для создания этой страницы и отображения текста. Просто скопируйте данный код в файл filesystem.php:

function menu_item()
{
  add_submenu_page("options-general.php", "Demo", "Demo", "manage_options", "demo", "demo_page"); 
}
  
add_action("admin_menu", "menu_item");
 
function demo_page()
{
  ?>
      <div class="wrap">
         <h1>Demo</h1>
         <form method="post">
          <?php
            $output = "";
 
            if(isset($_POST["file-data"]))
            {
              $output = write_file_demo($_POST["file-data"]);
            }
            else
            {
              $output = read_file_demo();
            }
 
            if(!is_wp_error($output))
            {
                ?>
                    <textarea name="file-data"><?php echo $output; ?></textarea>
                    <?php wp_nonce_field("filesystem-nonce"); ?>
                    <br>
                    <input type="submit">
                <?php
            }
            else
            {
              echo $output->get_error_message();
            }
          ?>
         </form>
      </div>
   <?php
}

Объясним, как данный код работает:

  • Сперва, мы добавили страницу в меню "Настройки". demo_page является коллбеком для отображения содержимого страницы.
  • Внутри страницы мы разместим HTML-форму с областью для текста. Там также есть кнопка submit для отправки формы. Текстовое поле называется file-data. Поле nonce было добавлено для предотвращения атаки CSRF.
  • Когда страница открыта, мы возвращаем сохраненную информацию из файлов с помощью функции read_file_demo. При отправке формы мы сохраняем содержимое текстового поля в файл с помощью функции write_file_demo.
  • Если read_file_demo или write_file_demo возвращает экземпляр объекта WP_Error, то на экране появится сообщение об ошибке.

Обратите внимание, что данный код "поломает" ваш WordPress сайт, поскольку мы еще не создали функции read_file_demo и write_file_demo. Поэтому давайте создадим их прямо сейчас!

Запись в файл

Ниже представлена реализация нашей функции write_file_demo:

function connect_fs($url, $method, $context, $fields = null)
{
  global $wp_filesystem;
  if(false === ($credentials = request_filesystem_credentials($url, $method, false, $context, $fields))) 
  {
    return false;
  }
 
  //check if credentials are correct or not.
  if(!WP_Filesystem($credentials)) 
  {
    request_filesystem_credentials($url, $method, true, $context);
    return false;
  }
 
  return true;
}
 
function write_file_demo($text)
{
  global $wp_filesystem;
 
  $url = wp_nonce_url("options-general.php?page=demo", "filesystem-nonce");
  $form_fields = array("file-data");
 
  if(connect_fs($url, "", WP_PLUGIN_DIR . "/filesystem/filesystem-demo", $form_fields))
  {
    $dir = $wp_filesystem->find_folder(WP_PLUGIN_DIR . "/filesystem/filesystem-demo");
    $file = trailingslashit($dir) . "demo.txt";
    $wp_filesystem->put_contents($file, $text, FS_CHMOD_FILE);
 
    return $text;
  }
  else
  {
    return new WP_Error("filesystem_error", "Cannot initialize filesystem");
  }
}

Вот как данный код работает:

  • Сначала, мы ссылаемся на глобальный объект $wp_filesystem внутри функции. Этот объект является экземпляром класса WP_Filesystem. Он отвечает за извлечение различных методов для чтения, создания, написания и удаления файлов.
  • Далее, мы создаем nonce URL для страницы нашей формы и массив с полем имен из нашей формы.
  • Наконец, мы присоединяемся к файловой системе, используя функцию connect_fs.
  • connect_fs использует функцию request_filesystem_credentials, предоставленную WordPress, чтобы найти подходящий способ подключения к файловой системе (direct, FTP или SSH). В случае с FTP или SSH будет выполнено обращение к форме, чтобы задать учетные данные пользователя. В случае прямого (direct) метода, он просто возвращает значение true.
  • Когда форма TextArea представлена и request_filesystem_credentials выбирает метод FTP или SSH, мы выводим форму с учетными данными и скрываем информацию из поля файла данных.
  • Первый параметр функции request_filesystem_credentials принимает URL, куда следует перенаправить пользователя, как только он получил правильные учетные данные. Редирект является типом запроса POST. Request_filesystem_credentials — последний параметр, который является массивом поля имен к записи, которую перенаправляют по URL.
  • Как только форма с учетными данными заполнена, она перенаправляется обратно к первоначальной форме, предоставляя URL с надлежащими полями имен и значениями, которые были введены пользователем.
  • Весь процесс опять начинается и мы запускаем write_file_demo. На этот раз request_filesystem_credentials имеет необходимые полномочия, следовательно, он просто вернет значение true.
  • Затем мы используем $wp_filesystem-> find_folder, где мы ссылаемся на необходимую папку. После этого мы строим полный путь к файлу demo.txt.
  • Мы использовали $wp_filesystem-> put_contents для записи данных в файл.

Примечание: Если вы попытаетесь использовать методы объекта $wp_filesystem без запроса и подтверждения учетных данных, то они не будут работать.

Чтение файла

Ниже размещена реализация функции read_file_demo:

function read_file_demo()
{
  global $wp_filesystem;
 
  $url = wp_nonce_url("options-general.php?page=demo", "filesystem-nonce");
 
  if(connect_fs($url, "", WP_PLUGIN_DIR . "/filesystem/filesystem-demo"))
  {
    $dir = $wp_filesystem->find_folder(WP_PLUGIN_DIR . "/filesystem/filesystem-demo");
    $file = trailingslashit($dir) . "demo.txt";
 
    if($wp_filesystem->exists($file))
    {
      $text = $wp_filesystem->get_contents($file);
      if(!$text)
      {
        return "";
      }
      else
      {
        return $text;
      }
    } 
    else
    {
      return new WP_Error("filesystem_error", "File doesn't exist");      
    } 
  }
  else
  {
    return new WP_Error("filesystem_error", "Cannot initialize filesystem");
  }
}

Описание того, как этот код каботает:

  • В то время как будет происходить чтение файла demo.txt, мы подключаемся к файловой системе, используя функцию request_filesystem_credentials.
  • В этот раз мы не будем проходить никакую форму поля в последнем параметре, потому что форма не представлена. Мы просто пропустим переадресацию URL, так чтобы она произошла, как только учетные данные будут извлечены.
  • После этого мы проверим существует ли файл, используя функцию $wp_filesystem->exists. Если файл не существует, на экране появится сообщение об ошибке. В противном случае, мы считаем файл с помощью функции $wp_filesystem-> get_contents и возвратим содержимое.

Предполагая, что WordPress выбрал FTP как подходящий способ для создания файлов, мы прикрепляем скриншоты всего процесса.

Сначала, когда мы открываем демо-страницу, мы должны увидеть эту форму:

Здесь мы должны ввести полномочия FTP или FTPS и подтвердить. После того, как мы подтверждаем действие, мы увидим эту форму:

На экран было выведено пустое поле для текста. Введите туда "Hello World!!!" и отправьте форму. Вы снова увидите форму для учетных данных.

Вы должны еще раз заполнить ее, потому что WordPress не сохраняет пароль FTP по умолчанию (вы можете сделать это в WP-config.php, но об этом позже). Таким образом, каждый раз, когда ваш плагин должен работать с файловой системой, она должна запрашивать данные. Теперь подтверждение этого перенаправит обратно на URL с полями имен и значений, представленных ранее. Вот как будет выглядеть текстовое поле:

api04

Здесь мы считываем содержимое из файла и выводим его.

Другие методы объекта $wp_filesystem

Объект $wp_filesystem предоставляет множество других методов для выполнения различных других операций с файлами и директориями. Мы только что видели операции записи и чтения файла. Вы можете найти полный список функций WP_Filesystem_Base () на странице документации.

Давайте рассмотрим несколько важных из них:

  • $wp_filesystem->delete: используется для удаления файла или директории. Вам необходимо выбрать строку, обозначив к ней путь.
  • $wp_filesystem->mkdir: используется для создания директории. Берется строка, которая будет представлять родительский директорию.
  • $wp_filesystem->move: используется для перемещения файла. Берется два параметра: первый — путь к файлу и второй — директория, в которую его необходимо переместить.
  • $wp_filesystem->size: возвращает размер файла в байтах. Вам необходимо провести путь к файлу.
  • $wp_filesystem->chmod: используется для изменения прав доступа к файлу. Используется три аргумента: путь к файлу, разрешение (восьмеричное число) и булевые переменные для представления рекурсии.

Вы можете выяснить, какой метод связи использует WordPress для доступа к файловой системе, используя публичный метод $wp_filesystem->method.

Постоянное хранение учетных данных

Вы уже успели заметить, что WordPress не хранит полномочия на доступ FTP или SSH на постоянной основе. Это не очень удобно, обращаться к пользователю снова и снова за необходимой информацией. Поэтому, существует способ хранения данных на постоянной основе, используя файл wp-config.php.

Используйте эти параметры для хранения полномочий FTP и SSH:

  • FTP_HOST: имя хостинга сервера
  • FTP_USER: имя пользователя для использования при подключении
  • FTP_PASS: пароль для использования при подключении
  • FTP_PUBKEY: путь к публичному ключу, который будет использоваться при соединении SSH2
  • FTP_PRIKEY: путь к приватному ключу, который будет использоваться при соединении SSH2

Заключение

В этой статье мы увидели процесс создания плагина, который имеет доступ к нашей файловой системе, используя WordPress Filesystem API. В случае, если вы попытаетесь получить доступ к файловой системе в фоновом режиме (например, с помощью cron job), то будет невозможно отобразить учетные данные, поэтому не забудьте сообщить пользователю, чтобы он сделал учетные данные константными в файле wp-config.php. Двигайтесь дальше, развивайтесь, экспериментируйте с этим API и обязательно делитесь своим опытом с нами ниже.

Источник: sitepoint.com

Вам понравился материал?

Добавить комментарий

Такой e-mail уже зарегистрирован. Воспользуйтесь формой входа или введите другой.

Вы ввели некорректные логин или пароль

Извините, для комментирования необходимо войти.

1 комментарий

сначала новые
по рейтингу сначала новые по хронологии
Андрей

Никак не получается запустить API из functions.php моей темы.
если писать
if ( ! WP_Filesystem($creds) ) {
request_filesystem_credentials($url, '', true, false, null);
return;
}
то просто получаю ошибку
[22-Apr-2016 07:34:48 UTC] PHP Fatal error: Call to undefined function WP_Filesystem() in ...