Текст книги "Разрботка расширений для CMS Joomla"
Автор книги: Яна Седова
Жанр:
Программирование
сообщить о нарушении
Текущая страница: 9 (всего у книги 10 страниц)
С помощью метода JComponentHelper::getParams() мы получаем объект JParameter, а затем используем его метод get() для получения параметров, задавая значения по умолчанию.
Изменим также код фронтенда. Откройте файл /components/com_myquestions/controller.phpи измените функцию QuestionController::addQuestion() следующим образом:
… $mailer =& JFactory::getMailer(); $option = JRequest::getVar('option','com_myquestions'); $params = JComponentHelper::getParams($option); $mailer->setSender($params->get('email_admin','[email protected]')); $mailer->addRecipient($params->get('email_admin','[email protected]')); …
Задайте с помощью кнопки " Настройки" собственные значения адресов электронной почты администратора сайта и эксперта. Добавьте на сайт вопрос, отправьте уведомление о нем эксперту, об ответе – автору вопроса и убедитесь, что в папке <путь к Денверу>/tmp/!sendmailпоявилось три письма с заданными вами значениями адресов электронной почты в соответствующих полях.
Упаковка компонента
Создайте в любом месте на диске новую папку, а в ней – папки adminи site, а также файл myquestions.xml:
Теги, задающие метаданные, такие как author, creationDate и другие, скопированы из файла /modules/mod_myquestions/mod_myquestions.xml.
Тег
Далее следует тег files со значением атрибута folder, равным site, т.е. описаны папки и файлы, которые находятся в папке siteустановочного пакета. Обратите внимание, что содержимое подпапок ( modelsи views) не описывается, указывается только имя подпапки.
Содержимое тега
Оставшуюся часть файла myquestions.xmlзанимает тег
Добавьте в файл /administrator/language/ru-RU/ru-RU.com_myquestions.sys.iniстроки:
COM_MYQUESTIONS="Моя система «вопрос – ответ»" COM_MYQUESTIONS_XML_DESCRIPTION="Моя система «вопрос – ответ»"
В папку adminскопируйте содержимое папки /administrator/components/com_myquestions, а в папку site– /components/com_myquestions.
Кроме того, создайте в папке siteпапку language, в ней – папку ru-RU. Скопируйте в нее файл ru-RU.com_myquestions.iniиз language/ru-RU.
Создайте в папке adminпапку language, в ней – папку ru-RUи скопируйте в нее файлы ru-RU.com_myquestions.sys.iniи ru-RU.com_myquestions.iniиз /administrator/language/ru-RU.
Наконец, создайте в папке adminподпапку sql, а в ней создайте файлы install.sqlи uninstall.sql.
Получившееся дерево папок показано на рис. 8.3.
Рис. 8.3. Дерево папок установочного пакета
В файл install.sqlвставьте код
DROP TABLE IF EXISTS `#__myquestions`; DROP TABLE IF EXISTS `#__myquestions_categories`; CREATE TABLE `#__myquestions` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(255) NOT NULL, `date` DATETIME NOT NULL, `question` TEXT NOT NULL, `city` VARCHAR(50) NULL, `email` VARCHAR(50) NOT NULL, `IP` VARCHAR(15) NOT NULL, `id_cat` INT NOT NULL, `published` TINYINT(1) NULL DEFAULT '1', `expiration_date` DATETIME NULL DEFAULT '0000-00-00 00:00:00', `senttoexpert` TINYINT(1) NULL DEFAULT '0', `answer` TEXT NULL DEFAULT '', `senttoauthor` TINYINT(1) NULL DEFAULT '0' ); CREATE TABLE `#__myquestions_categories` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(255) NOT NULL, `desc` TEXT NOT NULL DEFAULT '' ); INSERT INTO `#__myquestions_categories`(`name`, `desc`) VALUES('Без категории','');
В сущности, это тот самый код, который использовался нами ранее для создания таблиц, но вместо реального префикса таблиц указан символический. До создания таблиц мы выполняем запросы для удаления таблиц с теми же названиями, если они существуют, чтобы избежать ошибок при переустановке компонента.
В таблицу #__myquestions_categories сразу же вставляется запись для категории под названием " Без категории". Так как таблица только что создана, эта запись получит id, равный 1, то совпадающий с id категории, который в нашем компоненте присваивается новому вопросу при добавлении.
Запросы из скрипта uninstall.sqlудаляют обе таблицы:
DROP TABLE `#__myquestions`; DROP TABLE `#__myquestions_categories`;
Упакуйте папки admin, siteи файл myquestions.xmlв архив com_myquestions.zip. Установочный пакет компонента готов. Для проверки его работоспособности создайте новую установку Joomla и установите на нее ваш компонент с помощью менеджера расширений в панели управления.
Манифест для модуля
Настройки модуля
Создайте файл /modules/mod_myquestions/mod_myquestions.xml:
Значения атрибутов тега
Описаны пять параметров модуля, три из которых – random, author и date – являются переключателями, а остальные два – items и maxlen – текстовыми полями. Для переключателей с помощью тега
Теперь создайте языковой файл для модуля /language/ru-RU/ru-RU.mod_myquestions.ini:
MOD_MYQUESTIONS_XML_DESCRIPTION="Выводит вопросы из системы Вопрос – ответ" MOD_MYQUESTIONS_RANDOMIZE_LABEL="Случайный вопрос" MOD_MYQUESTIONS_RANDOMIZE_LABEL_DESC="Выводить один случайный вопрос?" MOD_MYQUESTIONS_ITEMS_LABEL="Количество вопросов"; MOD_MYQUESTIONS_ITEMS_LABEL_DESC="Сколько вопросов выводить?" MOD_MYQUESTIONS_MAXLEN_LABEL="Длина вопроса" MOD_MYQUESTIONS_MAXLEN_LABEL_DESC="Сколько первых символов вопроса отображать?" MOD_MYQUESTIONS_AUTHOR_LABEL="Автор вопроса" MOD_MYQUESTIONS_AUTHOR_LABEL_DESC="Выводить имя автора?" MOD_MYQUESTIONS_DATE_LABEL="Дата вопроса" MOD_MYQUESTIONS_DATE_LABEL_DESC="Выводить дату написания вопроса?"
В панели управления перейдите в " Расширения" – " Менеджер модулей". Выберите из списка модуль " Новые вопросы", и в правой части открывшейся страницы будет отображена группа элементов формы для установки параметров модуля (рис. 8.4).
Рис. 8.4. Установка параметров модуля
Упаковка модуля
Для упаковки модуля добавьте в файл /modules/mod_myquestions/mod_myquestions.xmlвыделенный код:
(есть увеличенное изображение)
Создайте в папке /modules/mod_myquestionsпапку language, в ней – папку ru-RU. Скопируйте в нее файл ru-RU.mod_myquestions.iniиз папки language/ru-RU. Создайте файл /modules/mod_myquestions/language/ru-RU/ru-RU.mod_myquestions.sys.ini:
MOD_MYQUESTIONS="Новые вопросы" MOD_MYQUESTIONS_XML_DESCRIPTION="Выводит вопросы из системы Вопрос – ответ"
Создайте из содержимого папки /modules/mod_myquestionsархив mod_myquestions.zip. Это и есть установочный пакет для модуля. Обратите внимание, что в архиве должно находиться именно содержимое папки mod_myquestions, а не сама эта папка.
Ключевые термины
Манифест – файл XML, содержащий метаданные о расширении, данные для установки и/или описание его настроек.
Краткие итоги
Для каждого расширения Joomla может существовать файл-манифест, содержащий метаданные о расширении, данные для установки и/или описание его настроек. Манифест должен называться <имя расширения>.xmlи находиться в корневой директории установочного пакета.
Настройки расширения описаны для модулей непосредственно в манифесте, а для компонентов – в отдельном файле config.xmlв корневой директории бэкенда компонента.
Установочные пакеты для модуля и для компонента представляют собой ZIP-архивы определенной структуры.
Для компонента установочный пакет включает манифест и папки adminи site, содержащие файлы и папки бэкенда и фронтенда соответственно и, возможно, некоторые дополнительные файлы и папки, например, SQL-скрипты.
Для модуля установочный пакет просто включает все его папки и файлы.
Вопросы
Какие данные содержит манифест расширения Joomla?
Где описаны настройки модулей и компонентов?
Какова структура установочного пакет для модуля и для компонента?
Упражнения
Адаптируйте код из раздела " Практика" для своего варианта (см. список вариантов в дополнительных материалах).
Заключение
В рамках курса были рассмотрены основы программирования под CMS Joomla. Были предложены для изучения такие темы, как архитектура Joomla, работа с базой данных, генерация элементов HTML, организация иерархии пунктов меню, создание и отправка электронных писем, генерация SEF-ссылок, основы реализации архитектуры MVC с помощью Joomla, разработка простых модулей, организация постраничного вывода списков, управление навигационной цепочкой, создание манифестов расширений и установочных пакетов. Изучен ряд классов фреймворка Joomla. Таким образом, успешное освоение материалов данного курса достаточно для разработки небольших компонентов и модулей для Joomla.
Общий глоссарий
JAdministrator– приложение, управляющее функциями для администрирования Joomla. JApplication– класс, позволяющий работать с очередью сообщений, осуществлять перенаправление браузера, получать параметры конфигурации сайта, определять тип запущенного приложения Joomla. JController– абстрактный класс для реализации контроллеров. JDatabase– абстрактный класс, предоставляющий доступ к соединению с базой данных, создающемуся при инициализации приложения Joomla. JDatabaseQuery– класс, методы которого совпадают с ключевыми словами языка SQL и позволяют упростить создание сложных SQL-запросов. JDate– класс для работы с датами. JDocument– класс для работы с документом. JEditor– класс для работы с WYSIWYG-редактором. JError– класс для работы с ошибками. JFactory– класс Joomla, реализующий паттерн «фабрика» и позволяющий получить доступ к глобальным объектам фреймворка. JHTML– класс для вывода элементов XHTML. JHTMLBehavior– поддерживающий класс, который позволяет вывести календарь, дерево элементов, файловый загрузчик и некоторые другие элементы управления. JHTMLEmail– поддерживающий класс, содержащий метод для скрытия адреса электронной почты в целях его защиты от спам-ботов. JHTMLForm– поддерживающий класс, содержащий метод, который возвращает код скрытого поля формы для уменьшения риска CSRF-атак. JHTMLGrid– поддерживающий класс, позволяющий вывести в таблице в панели управления такие элементы, как чекбокс, пиктограмма для переключения состояния «опубликовано»/"не опубликовано", отобразить заголовок столбца как ссылки для сортировки по этому столбцу и др. JHTMLImage– поддерживающий класс, содержащий методы для поиска изображения в фронтенде и бэкенде. JHTMLList– поддерживающий класс для создания списков некоторых конкретных значений. JHTMLSelect– поддерживающий класс для генерации кода списков. JInstallation– приложение, которое запускается при установке Joomla. JMail– класс для создания и отправки электронных писем. JMailHelper– класс для очистки данных перед добавлением к электронному письму и проверки, является ли заданная строка корректным адресом электронной почты. JModel– абстрактный класс для реализации моделей. JPagination– класс для вывода элементов формы для разбивки на страницы списков элементов. JPathway– класс для управления навигационной цепочкой. JRequest– класс Joomla, использующийся для работы с переменными HTTP-запроса. JRoute– класс для создания SEF-ссылок. JSite– приложение, отвечающее за компоновку и отображение фронтенда. JTable– класс, реализующий паттерн Active Record и использующийся для управления таблицами базы данных. JToolBarHelper– класс Joomla, содержащий методы, которые генерируют HTML-код для построения кнопок панелей инструментов. JURI– класс для работы с URI. JUser– класс для работы с данными о пользователе. JView– абстрактный класс для реализации представлений. XML-RPC– приложение, позволяющее администрировать сайт Joomla удаленно. Библиотека– файл, который требуется для работы фреймворка или сторонних расширений. Бэкенд– система администрирования сайта. Документ– буфер, использующийся для хранения содержимого веб-страницы, которая будет показана пользователю после выполнения запроса. Иерархия пунктов меню– дерево, состоящее из пунктов меню и организованное с помощью вложенных множеств. Ключ– эквивалент текста, подлежащего переводу. Компонент– основной тип расширений Joomla, вызов которого происходит при каждом обращении к Joomla. Манифест– файл XML, содержащий метаданные о расширении, данные для установки и/или описание его настроек. Модуль– расширение Joomla, использующееся для отображения небольших фрагментов контента, обычно в левой или правой колонке или верхней или нижней областях страницы. Основной метод класса JHTML– метод JHTML::_(), который вызывает метод, определяющийся его первым параметром, и передает ему свои остальные параметры. Очередь сообщений– массив строк, которые будут выведены на экран при следующей загрузке какой-либо страницы. Перевод– строка, содержащая перевод текста, соответствующего заданному ключу, на какой-либо язык. Плагин– расширение Joomla, позволяющее зарегистрировать функции и классы для обработки каких-либо событий, вызванных Joomla, например, поиск по сайту. Поддерживающие классы– классы для вывода элементов XHTML и поведений Javascript. Префикс таблиц базы данных– строка, которая присоединяется к названию каждой таблицы Joomla в базе данных. Приложение– глобальный объект, использующийся для обработки запросов. Реальный префикс– то конкретное сочетание символов, которое используется в названиях таблиц базы данных. Регистрация задачи– сопоставление ее какому-либо методу класса, производного от JController. Связывание– процесс присвоения каждому полю производного от JTable класса значения элемента массива переменных запроса, так что ключ элемента совпадает с названием поля. Символический префикс– сочетание «#__» (решетка и два знака подчеркивания), которое используется в запросах вместо реального префикса. Уровень приложения– часть архитектуры Joomla, которая состоит из приложений, расширяющих абстрактный класс JApplication. Уровень расширений– часть архитектуры Joomla, которая состоит из расширений фреймворка Joomla и приложений. Уровень фреймворка– часть архитектуры Joomla, которая обеспечивает ее базовую функциональность с помощью набора библиотек и плагинов и собственно ядра Joomla. Фреймворк Joomla («ядро»)– набор классов, обеспечивающих базовую функциональность Joomla (JDatabase, JUser, JForm, JEditor и т.д.). Фронтенд– часть сайта, доступная пользователю. Функция генерации SEF-ссылок– функция, которая принимает массив элементов HTTP-запроса и возвращает массив сегментов SEF-ссылки. Функция декодирования SEF-ссылок– функция, которая из массива сегментов SEF-ссылки создает массив переменных HTTP-запроса. Шаблон– расширение Joomla, отвечающее за внешний вид сайта. Шаблон SEF-ссылок– последовательность сегментов. Языковый файл– расширение Joomla, позволяющее представить ее контент на нескольких языках.
Список сокращений
CCK Content Construction Kit Конструктор контента CMS Content Management System Система управления контентом MVC Model – View – Controller Архитектура "Модель – Представление – Контроллер" SEF Search Engine Friendly Ссылка, удобная для восприятия поисковыми системами
Варианты заданий для лабораторных работ
Варианты заданий для лабораторных работ
1. Интернет-магазинДля товара храните в базе данных его код, название, цену, описание и фотографию (можно хранить название файла с фотографией, а сами файлы помещать в какую-нибудь папку). Пользователь может заказать товар – для этого он нажимает на кнопку " Заказать" и вводит свой адрес. Для каждого заказа храните в базе данных его дату, адрес покупателя и код товара. Должна быть также возможность добавлять и удалять товары, а также просматривать список товаров, страницу с конкретным товаром и список заказов. При удалении товара заодно удаляйте с диска файл с изображением. Формы: добавление товара, заказ товара. 2. Фотогалерея с категориямиДля фотографии храните в базе данных его код, название соответствующего файла, название фотографии, описание фотографии, место съемки, размер файла, код категории. Можно хранить в базе данных только название файла с фотографией, а сами файлы помещать в какую-нибудь папку. Для каждой категории храните в базе данных ее код и название. Обеспечьте возможность добавления и удаления фотографий и категорий, просмотра списка всех категорий, списка всех фотографий в конкретной категории, просмотра одной фотографии. При удалении записи о фотографии из базы данных заодно удаляйте с диска файл с фотографией. Формы: добавление фотографии, добавление категории. 3. Архив mp3 с категориямиДля аудиофайла храните в базе данных его код, название файла, название песни, имя исполнителя, длительность звучания песни, размер файла, код категории. Сам файл храните в какой-нибудь папке на диске. Обеспечьте возможность просмотра списка категорий, списка песен в конкретной категории, просмотра определенной песни (то есть должна быть страница, на которой выводятся все данные об аудиофайле и можно прослушать песню). Должна быть также возможность добавлять песни и удалять их, а также добавлять и удалять категории. Для каждой категории храните в базе данных ее код и название. При удалении записи об аудиофайле из базы данных заодно удаляйте с диска сам файл. Формы: добавление песни, добавление категории. 4. Видеогалерея с категориямиДля видеофайла храните в базе данных его код, название файла, название видеоролика, описание видеоролика, длительность видеоролика, размер файла, код категории. Сам файл храните в какой-нибудь папке на диске. Обеспечьте возможность просмотра списка категорий, списка всех видеофайлов в конкретной категории, просмотра определенного файла (то есть должна быть страница, на которой выводятся все данные о видеофайле и можно посмотреть это видео). Должна быть также возможность добавлять файлы, просматривать их список и удалять их, а также добавлять и удалять категории. Для каждой категории храните в базе данных ее код и название.
При удалении записи о видеофайле из базы данных заодно удаляйте с диска сам файл. Формы: добавление видеоролика, добавление категории. 5. Гостевая книгаДля каждой записи (сообщения) вашей гостевой книги храните в базе данных ее код, имя автора записи, e-mail автора записи, ICQ автора записи, дату добавления записи, текст записи. Для каждого ответа на запись храните его код, текст и код записи, к которой относится этот ответ. Должна быть страница, на которой выводятся все сообщения. Обеспечьте возможность просмотра одного сообщения со всеми ответами на него, добавления сообщения, удаления сообщения, ответа на сообщение. Формы: добавление сообщения, добавление ответа на сообщение.
Обратите внимание, что на странице для ответа на сообщение выводится поле для ответа как textarea, в которое можно ввести текст, а остальные поля записи выводятся как текст (не для редактирования). 6. ФорумДля каждого сообщения в базе данных храните его код, автора, текст, дату добавления и код темы. Для каждой темы – ее код и название. Обеспечьте возможность создания темы, ответа на тему, просмотра списка всех тем, просмотр темы (то есть всех ее сообщений), удаления темы, удаления сообщения. Ответить на тему – значит добавить в нее сообщение. Формы: добавление темы, добавление сообщения. 7. Новостная система с категориямиДля каждой новости храните в базе данных ее код, автора, текст, дату добавления и код категории. Для каждой категории – ее код и название. Обеспечьте возможность создания новости, создания категории, удаления новости, удаления категории, просмотра списка всех категорий, просмотра списка всех новостей в конкретной категории, просмотра конкретной новости. Формы: добавление новости, добавление категории. 8. Ротатор баннеровДля каждого баннера храните в базе данных его код, название файла с изображением, ссылка, на которую будет переходить пользователь по нажатию на баннер, количество кликов – нажатий на данный баннер, количество показов баннера, код категории. Сами файлы с изображениями хранятся в какой-либо папке. Для каждой категории храните ее код и название.
Обеспечьте возможность добавления и удаления баннеров, добавления и удаления категорий, просмотра списка категорий, списка баннеров в категории. При удалении баннера из базы данных заодно удаляйте с диска файл с изображением.
На главной странице должен отображаться всегда только один баннер, выбранный случайным образом. Для этого сначала выберите случайным образом категорию, а затем, также случайным образом, – баннер, относящийся к этой категории. Формы: добавление баннера, добавление категории. 9. Доска объявлений с категориямиДля каждого объявления храните в базе данных его код, автора, текст, дату добавления и код категории. Для каждой категории – ее код и название. Обеспечьте возможность добавления объявления, добавления категории, удаления объявления, удаления категории, просмотра списка всех категорий, просмотра списка всех объявлений в конкретной категории, просмотра конкретного объявления. Формы: добавление объявления, добавление категории. 10. Система управления контентомДля каждой страницы храните в базе данных ее код, автора, текст, дату добавления и код раздела. Для каждого раздела – его код, название и текстовое описание. Обеспечьте возможность создания страницы, создания раздела, удаления страницы, удаления раздела. Физически страницу на диске можно не создавать, достаточно, чтобы ее текст хранился в базе данных. Ссылки на все страницы выводятся в левой части главной страницы как пункты меню сайта. При нажатии на какой-либо пункт меню справа отображается текст соответствующей страницы, а также имя автора, дата добавления и название раздела. При этом название раздела отображается как гиперссылка, при нажатии на которую загружается страница с описанием этого раздела.
Обеспечьте также возможность просмотра всех категорий и просмотра списка страниц в определенной категории. Формы: добавление страницы, добавление раздела. 11. Блог с облаком теговДля каждой дневниковой записи храните в базе данных ее код, название записи, текст записи, автора записи, дату добавления записи. Для каждого тега храните в базе данных его код и название. Создайте третью таблицу в базе данных, связывающую теги с записями блога (поля: код, код записи, код тега). Обеспечьте возможность добавления и удаления записей и тегов, просмотра блога как списка всех записей, просмотра одной записи, списка тегов. В форме добавления записи в блог должен выводиться список со множественным выбором, в который выводятся все названия тегов из соответствующей таблицы базы данных. Формы: добавление записи в блог, добавление тега. 12. Статьи с облаком теговДля каждой статьи храните в базе данных ее код, автора, текст, дату добавления. Для каждого тега храните в базе данных его код и название. Физически страницу на диске можно не создавать, достаточно, чтобы ее текст хранился в базе данных. Создайте третью таблицу в базе данных, связывающую теги со статьями (поля: код, код статьи, код тега). Обеспечьте возможность добавления и удаления как статей, так и тегов, просмотра списка статей, просмотра конкретной статьи и просмотра списка тегов.
В форме добавления статьи должен выводиться список со множественным выбором, в который выводятся все названия тегов из соответствующей таблицы базы данных. Формы: добавление статьи, добавление тега. 13. Портфолио с категориямиДля каждой работы храните в базе данных ее код, название файла с изображением, название работы, описание работы, сроки, в которые выполнялась работа, код категории. Можно хранить в базе данных только название файла с фотографией, а сами файлы помещать в какую-нибудь папку. Для каждой категории храните в базе данных ее код и название. Обеспечьте возможность добавления и удаления работ и категорий, просмотра списка всех категорий, просмотра списка всех работ в конкретной категории, просмотра одной работы.
При удалении записи о работе из базы данных заодно удаляйте с диска файл с изображением. Формы: добавление работы, добавление категории. 14. Система «Вопрос-ответ»Для каждого вопроса храните в базе данных его код, имя автора, текст вопроса, дату добавления. Для каждого ответа – его код, код вопроса и текст ответа. Обеспечьте возможность добавления вопроса в конкретную категорию, просмотра вопроса (с ответом, если есть ответ), удаления вопроса, ответа на вопрос (на один вопрос может быть несколько ответов), просмотра списка вопросов в конкретной категории, просмотра списка категорий, добавления и удаления категорий. Формы: добавление вопроса, добавление категории, ответ на вопрос. 15. Блог с категориямиДля каждой дневниковой записи храните в базе данных ее код, название записи, текст записи, автора записи, дату добавления записи, код категории. Для каждой категории храните в базе данных ее код и название. Обеспечьте возможность добавления и удаления записей и категорий, просмотра блога как списка всех записей, просмотра списка записей в конкретной категории, просмотра одной записи. Формы: добавление записи в блог, добавление категории. 16. Статьи с категориямиДля каждой статьи храните в базе данных ее код, автора, текст, дату добавления и код раздела. Для каждого раздела – его код, название и текстовое описание. Физически страницу на диске можно не создавать, достаточно, чтобы ее текст хранился в базе данных. Обеспечьте возможность добавления и удаления как страниц, так и разделов, просмотра статей по разделам, просмотра конкретной статьи и списка разделов. Формы: добавление статьи, добавление раздела. 17. Календарь событийДля каждого события храните в базе данных его код, описание, дату, код места проведения. Для каждого места проведения – его код, название и фотографию (можно хранить в базе данных только названия файлов с фотографиями, а сами файлы хранить в какой-нибудь папке на диске). Обеспечьте возможность создания события, создания описания места проведения, удаления события, удаления описания места проведения, просмотра списка мест проведения событий. При удалении описания места удаляйте с диска и соответствующий файл с изображением.
События должны просматриваться по одному либо в виде календаря. В случае, если на определенную дату есть события, дата в ячейке календаря должна выводиться в виде гиперссылки, при нажатии на которую загружается страница со списком всех событий, которые относятся к этой дате. Формы: добавление события, добавление места проведения. 18. Почтовая рассылкаДля каждого сообщения рассылки храните в базе данных его код, название, текст, дату добавления. Для каждого подписчика – его код, e-mail и имя. Обеспечьте возможность добавления сообщения, регистрации подписчика, удаления подписчика, просмотра списка всех сообщений и списка всех подписчиков.