Содержание


Реальные проекты на PHP и MySQL. Создание персонализированных документов

Часть 2. Разработка приложения для проведения online-тестирования и подготовка сертификата в формате RTF

Comments

Серия контента:

Этот контент является частью # из серии # статей: Реальные проекты на PHP и MySQL. Создание персонализированных документов

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Реальные проекты на PHP и MySQL. Создание персонализированных документов

Следите за выходом новых статей этой серии.

Любой интерактивный сайт, ориентированный на предоставление каких-либо услуг пользователям (например, обучающий сайт или Интернет-магазин), должен обладать функциональностью для создания персонализированных документов на основе информации, введенной пользователем. Эта функциональность может использоваться для предоставления автоматически заполняемых форм и создания таких документов как контракты, сертификаты или накладные на основе полученных данных.

Об этой серии статей

Эта серия статей посвящена проблемам создания персонализированных документов на основе информации, предоставленной пользователем. Подобная функциональность присутствует практически на каждом Web-сайте, предоставляющем пользователям услуги различного рода. В представленных статьях в качестве примера используется система для проведения online-тестирования на знание технологии PHP, при этом рассматриваются как общие вопросы по созданию документов в различных форматах, так и специфические вопросы, относящиеся к приложениям подобного рода.

В первой статье этой серии обсуждалась высокоуровневая схема предлагаемого решения и выбор форматов, которые будут использоваться для создания сертификатов. Для использования в рамках проекта были выбраны форматы PDF и RTF, как обладающие широкой поддержкой среди пользователей (множество программ для просмотра документов) и разработчиков (спецификации форматов в открытом доступе и библиотеки для работы с ними). Также в этой статье был представлен первый компонент системы online-тестирования – HTML-страница со списком проверочных вопросов.

Эта статья будет посвящена созданию персонализированного сертификата в формате RTF по результатам экзамена и разработке PHP-сценария для обработки ответов, полученных от пользователя.

Обработка ответов на проверочные вопросы

В начале работы, когда пользователь хочет проверить свои знания и получить сертификат, он попадает на главную страницу сайта, изображенную на рисунке 1. Эта HTML-страница содержит список вопросов, относящихся к технологии PHP, и является формой, которую пользователь заполняет, выбирая варианты ответов. Исходный код этой HTML-формы можно найти в первой статье из этого цикла в листинге 1.

Рисунок 1. HTML-форма с вопросами для online-тестирования
Рисунок 1.
Рисунок 1.

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

Как показано в исходном коде HTML-формы, с каждым вопросом связаны три переключателя (radio button), c помощью которых пользователь может отметить правильный с его точки зрения ответ. В форме также имеется кнопка Сертифицируй меня для отправки данных, введенных пользователем, на сервер. Отправленный запрос попадает на обработку в PHP-сценарий, задача которого подсчитать число правильных ответов и на их основе определить количество баллов, полученных пользователем. Код этого сценария приведен в листинге 1.

Листинг 1. Исходный код HTML-страницы с вопросами для online-тестирования
<?php
header('Content-Type: text/html; charset = windows-1251');
  // извлечь из HTTP-запроса значения переданных параметров
  // и сохранить их в локальных переменных
  $q1 = $_POST['q1'];
  $q2 = $_POST['q2'];
  $q3 = $_POST['q3'];
  $name = $_POST['name'];

  // проверить, что пользователь ввел все необходимые данные:
  // собственное имя и три ответа на вопросы.
  if($q1==''||$q2==''||$q3==''||$name=='')
  {
    // если данных не хватает, то вывести сообщение об ошибке
    echo '<h1><p align = center><img src="rosette.gif" alt="">
                                Извините:
                                <img src="rosette.gif" alt=""></p></h1>';
    echo '<p>Вы должны ввести свою фамилию и ответить на все вопросы</p>';
  }
  else
  {
    // сравнить ответы, представленные пользователем, с правильными
    // и вычислить количество баллов, полученных пользователем.
    $score = 0;
    // в данном примере – правильным всегда является первый ответ
    if($q1 == 1) // правильный ответ на первый вопрос – 1 балл
      $score++;
    if($q2 == 1) // правильный ответ на второй вопрос – 1 балл
      $score++;
    if($q3 == 1) // правильный ответ на третий вопрос – 1 балл
      $score++;

    // преобразовать баллы в проценты для принятия решения
    $score = $score / 3 * 100;

    if($score < 50)
    {
      // пользователь не выдержал экзамен, так как набрал меньше 50%
      // показать страницу с сообщением об ошибке
      echo '<h1 align="center"><img src="rosette.gif" alt="" />
                               Очень жаль:
                               <img src="rosette.gif" alt="" /></h1>';
      echo '<p>Для того чтобы выдержать экзамен, вы должны набрать хотя бы
          50%</p>';
    }
    else
    {
      // пользователь выдержал экзамен
      // показать страницу для загрузки сертификатов

      // создать строку с результатом с точностью до знака после запятой
      $score = number_format($score, 1);

      echo '<h1 align="center"><img src="rosette.gif" alt="" />
                               Поздравляем!
                               <img src="rosette.gif" alt="" /></h1>';
      echo "<p>Вы успешно сдали экзамен, $name, ваш итог
               составляет $score%.</p>";

      // вывести ссылки на сценарии, которые создают сертификаты
      echo '<p>Пожалуйста, щелкните здесь, чтобы загрузить свой сертификат
           в виде файла Microsoft Word (RTF).</p>';
      echo '<form action="rtf.php" method="post">';
      echo '<center>
              <input type="image" src="certificate.gif" border="0">
            </center>';
      echo '<input type="hidden" name="score" value="'.$score.'">';
      echo '<input type="hidden" name="name" value="'.$name.'">';
      echo '</form>';

      echo '<p> Пожалуйста, щелкните здесь, чтобы загрузить свой сертификат
           в виде файла Portable Document Format (PDF).</p>';
      echo '<form action="pdf.php" method="post">';
      echo '<center>
              <input type="image" src="certificate.gif" border="0">
            </center>';
      echo '<input type="hidden" name="score" value="'.$score.'">';
      echo '<input type="hidden" name="name" value="'.$name.'">';
      echo '</form>';

      echo '<p> Пожалуйста, щелкните здесь, чтобы загрузить свой сертификат
           в виде файла Portable Document Format (PDF), сгенерированного
           средствами PDFLib.</p>';
      echo '<form action="pdflib.php" method="post">';
      echo '<center>
              <input type="image" src="certificate.gif" border="0">
            </center>';
      echo '<input type="hidden" name="score" value="'.$score.'">';
      echo '<input type="hidden" name="name" value="'.$name.'">';
      echo '</form>';
     }
  }
?>

Если пользователь ответил правильно только на один вопрос (набрал менее 50%) или не ввел все необходимые данные, то PHP-сценарий выведет уведомление о допущенной ошибке. Если же пользователь ответил правильно, как минимум на два вопроса, тогда ему предоставляется доступ к PHP-сценариям для создания сертификата. HTML-страница с ссылками для загрузки сертификатов показана на рисунке 2. При этом посетителю становятся доступны две ссылки для загрузки сертификата в формате PDF и одна ссылка на файл в формате RTF.

Рисунок 2. HTML-страница с ссылками для загрузки сертификата
Рисунок 2.
Рисунок 2.

Создание сертификата в формате RTF

После того как результаты тестирования были успешно обработаны можно переходить к созданию сертификата в формате RTF. Хотя для этого достаточно просто записать ASCII-текст в файл или строковую переменную, но потребуется потратить время на изучение синтаксиса, используемого в формате RTF. Пример простого RTF-документа показан в листинге 2.

Листинг 2. Пример RTF-документа
1	{\rtf1
2	{\fonttb1 {\f0 Arial;}{\f1 Times New Roman;}}
3	\f0\fs28 Заголовок\par
4	\f1\fs20 Это простой rtf-документ. \par
5	}

В представленном RTF-документе содержится следующая информация. На второй строке выполняется установка таблицы шрифтов, содержащую два элемента: шрифт Arial, для ссылки на который будет использоваться указатель f0, и шрифт Times New Roman, к которому можно обращаться через указатель f1. На третьей строке в документ записывается строка Заголовок с использованием шрифта f0 размером 28. На этой же строке управляющая последовательность \par указывает на конец абзаца. На четвертой строке выполняется запись строки Это простой rtf-документ с использованием шрифта f1 размером 20.

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

Поэтому более эффективным и удобным способом создания документа будет получение его из заранее подготовленного шаблона. Исходный шаблон, а это может быть довольно сложный документ, показанный на рисунке 3, можно создать в любом текстовом редакторе. На шаблоне, изображенном на рисунке 3, имеются заполнители (англ. placeholder), использующиеся для выделения мест, куда потом будут вставляться динамические данные. Эти заполнители могут выглядеть как угодно, так как на данном этапе это не важно. Важно чтобы вид этих заполнителей не совпадал с другими конструкциями в документе, иначе появится неопределенность и автоматическая обработка шаблона станет невозможной. Создание шаблона можно упростить, если проследить, чтобы длина заполнителей совпадало с длинной данных, которые будут в них выводиться. Обычно заполнители называются в соответствии с данными, которые будут выводиться вместо них, при этом разница в регистре, использующемся в имени заполнителя: NAME или name, определяет в каком регистре в него будет выводиться текст. В приведенном на рисунке 3 документе все заполнители уже заменены на реальный текст.

Рисунок 3. Шаблон сертификата для системы online-тестирования
Рисунок 3.
Рисунок 3.

В листинге 3 приведен PHP-сценарий для персонализации шаблона RTF-документа, изображенного на рисунке 3.

Листинг 3. PHP-сценарий для создания персонализированного сертификата
<?php
  // извлечь из HTTP-запроса значения переданных параметров
  // и сохранить их в локальных переменных
  $name = $_POST['name'];
  $score = $_POST['score'];
  // проверить, что в запросе имеются все необходимые параметры:
  // имя пользователя и его результат тестирования.
  if( !$name || !$score )
  {
    //если параметров не хватает, то вывести уведомление об ошибке
    echo '<h1>Ошибка:</h1>Страница вызвана некорректно';
  }
  else
  {
    // установить HTTP-заголовки, которые упростят web-браузеру
    // выбор приложения для обработки полученного документа
    header('Content-Type: text/html; charset = windows-1251');
    header( 'Content-Type: application/msword' );
    header( 'Content-Disposition: inline, filename=cert.rtf');

    $date = date( 'F d, Y' );

    // открыть файл шаблона
    $filename = 'PHPCertification.rtf';
    $output = file_get_contents($filename);

    // заменить заполнители в шаблоне 
    //на значения соответствующих переменных
    $output = str_replace( '<<NAME>>', strtoupper( $name ), $output );
    $output = str_replace( '<<Name>>', $name, $output );
    $output = str_replace( '<<score>>', $score, $output );
    $output = str_replace( '<<mm/dd/yyyy>>', $date, $output );

    // отправить получившийся документ в web-браузер пользователя
    echo $output;
  }
?>

Как и в случае с предыдущем сценарием, в листинге 3 сначала выполняется проверка на наличие обязательных параметров в запросе. Однако в отличие от сценария из листинга 2, в данном случае вывод генерируется не в виде HTML-страницы, а виде RTF-файла. Так как это нестандартный формат, то web-браузер клиента получает уведомление о том, какое приложение лучше использовать для открытия полученного документа. Для этого с помощью PHP-функции header() в соответствующем HTTP-заголовке указывается MIME тип выводимого файла, как показано ниже:

    header( 'Content-Type: application/msword' );
    header( 'Content-Disposition: inline, filename=cert.rtf');

Первый заголовок сообщает web-браузеру, что отправляемый документ имеет тип msword (документ MS Word), а второй указывает на необходимость автоматического отображения документа с именем cert.rtf. Именно так будет называться файл с сертификатом, если пользователь захочет его сохранить на свою локальную станцию. При этом если web-браузер не распознает автоматически формат документа, то будет показано стандартное диалоговое окно «Загрузка файла», изображенное на рисунке 4.

Рисунок 4. Диалоговое окно для загрузки RTF-документа
Рисунок 4.
Рисунок 4.

После отправки HTTP-заголовков выполняется открытие RTF-файла с шаблоном и его содержимое записывается в переменную $output. Для замены заполнителей в шаблоне на фактические данные используется функция str_replace(), как показано ниже:

    $output = str_replace( '<<NAME>>', strtoupper( $name ), $output );

На этой строке функция str_replace() заменяет все вхождения заполнителя <<NAME>> на значение переменной $name, преобразованное в верхний регистр. Функция str_replace() обладает достаточным быстродействием, в общем случае не зависящим от размера переменой $output. После выполнения всех замен результат передается на вывод в окно браузера.

Недостатки, связанные с использованием формата RTF

Не смотря на простоту использования и распространенность формата RTF (а может и благодаря им) при использовании этого формата возникает следующая проблема. После передачи сертификата пользователю его можно будет загрузить в текстовый редактор, что позволит внести изменения в уже сформированный документ, например, улучшить результат тестирования или изменить имя пользователя. На самом деле формат RTF не позволяет создать документ, предназначенный только для чтения.

Поэтому в следующей статье будет разбираться, как создать персонализированный сертификат на основе общего шаблона, но уже в формате PDF. Алгоритм работы c форматом PDF особо не отличается от работы с форматом RTF, но при этом необходимо учитывать, что при создании PDF-файла некоторые заполнители могут быть перепутаны с кодами форматирования. Это зависит от используемой версии Adobe Acrobat Reader или других подобных программ, так как формат шаблона в PDF-файле может варьироваться в зависимости от программы, использованной для его создания. Из-за этого исходный код шаблона в PDF-формате должен быть тщательно протестирован и при необходимости откорректирован для правильного отображения в различных средах.

Заключение

В этой статье из серии «Реальные проекты на PHP и MySQL. Создание персонализированных документов» были разработаны PHP-сценарии для оценки результатов online-тестирования и создания сертификата в формате RTF. Также была представлена общая информация о формате RTF, использовании шаблонов для создания персонализированных документов и передаче в Web-браузер HTTP-заголовков для отображения нестандартного HTTP-ответа (RTF-документа).


Ресурсы для скачивания


Комментарии

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux, Open source
ArticleID=629318
ArticleTitle=Реальные проекты на PHP и MySQL. Создание персонализированных документов: Часть 2. Разработка приложения для проведения online-тестирования и подготовка сертификата в формате RTF
publish-date=02242011