-
Постов
53 -
Зарегистрирован
-
Посещение
-
Победитель дней
2
Вадим стал победителем дня 21 мая 2015
Вадим имел наиболее популярный контент!
Посетители профиля
Блок последних пользователей отключён и не показывается другим пользователям.
Достижения Вадим
-
Одно из тех приложений, которые я часто ставлю, пользователи любят подобные метрики.
-
Вадим изменил фотографию своего профиля
-
utf8mb4 - набор символов, используемый для хранения 4 байта в MySQL, внедрён в 2010 году начиная с версии 5.5.3. Главное отличие utf8mb4 от utf8 в том, что utf8mb4 задействует более полные возможности кодировки UTF8, позволяя поддерживать все языки и специальные символы, не поддерживающие utf8 (например японский язык или смайлики из ios - emoji). Однако, как можно догадаться, если utf8mb4 использует для хранения 1 символа 4 байта, то база данных может увеличиться в размере, если сравнивать с точно такой же базой данных в utf8. В наше время немного увеличенный размер базы данных не является существенно проблему, по этому, если вы стоите перед выбором использовать utf8 или utf8mb4 набор символов - используйте utf8mb4. О том, как перекодировать существующую базы данных в utf8mb4, рассказано в соответствующей статье - Переход с utf8 на utf8mb4 в MySQL
-
В данной статей рассказывается о переход к новому набору символов utf8mb4 в MySQL для поддержки хранения 4-х байтовых символов. Шаг 1 - резервные копии Перед любыми действиями обязательно создайте резервные копии всех баз данных, сравнение которых будете менять. Шаг 2 - версия MySQL сервера Набор символов utf8mb4 введён в MySQL начиная с версии 5.5.3, по этому, вам необходимо обновить версию MySQL сервера, если она ниже указанной, либо попросить это сделать своего системного администратора. Шаг 3 - модификация базы, таблиц, столбцов Измените набор символов и сравнение для базы данных, таблиц и столбцов на utf8mb4 вместо utf8. Для этого выполните следующие запросы: Для базы данных: ALTER DATABASE название_базы CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;Для каждой таблицы: ALTER TABLE название_таблицы CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;Для каждого столбца (не нужно копировать этот пример, для каждого столбца будет свой запрос, здесь указан лишь пример такого запроса для столбца с `VARCHAR`): ALTER TABLE название_таблицы CHANGE название_столбца название_столбца VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;Шаг 4 - проверка максимальной длины столбцов и ключей индексов Самый трудный шаг на пути к корвертированию MySQL базы данных. При конвертировании базы данных из utf8 в utf8mb4 максимальная длина столбцов или ключей индексов в байтах остаётся неизменной. Таким образом, она становится меньше в количестве символов, т.к. максимальная длина символа теперь 4 байта, вместо 3. Например, TINYTEXT столбец может вместить до 255 байт, что коррелирует 85 3-х байтовым или 63 4-х байтовым символам. Допустим у вас есть TINYTEXT столбец, который использует utf8 набор символов, но должен содержать в себе больше 63 символов. Учитывая эти данные, вы не сможете конвертировать этот столбец в utf8mb4, до тех пор, пока не измените тип данных на более вместительный, например TEXT - потому, что, если вы попытаетесь заполнить столбец 4-х байтовыми символами, вы сможете вместить только 63 символа, но не более. Тоже самое касается ключей индексов. Механизм хранения InnoDB имеет максимальную длину индекса 767 байт, поэтому для utf8 или utf8mb4 столбцов, вы можете инжексировать 255 или 191 символов, соответственно. Если у вас есть utf8 столбцы с индексами, длина которых превышает 191 символ, при использовании utf8mb4 вам нужно будет индексировать меньшее количество символов. Например: col1 VARCHAR(500) CHARACTER SET utf8, INDEX (col1(255))Запрос при использовании utf8mb4 будет выглядеть вот так: col1 VARCHAR(500) CHARACTER SET utf8mb4, INDEX (col1(191))Шаг 5 - изменение настроек сервера В конфигурационном файле MySQL необходимо изменить набор символов на utf8mb4: [client] default-character-set = utf8mb4 [mysql] default-character-set = utf8mb4 [mysqld] character-set-client-handshake = FALSE character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ciВы можете легко проверить корректность работы применимых настроек: mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%'; +--------------------------+--------------------+ | Variable_name | Value | +--------------------------+--------------------+ | character_set_client | utf8mb4 | | character_set_connection | utf8mb4 | | character_set_database | utf8mb4 | | character_set_filesystem | binary | | character_set_results | utf8mb4 | | character_set_server | utf8mb4 | | character_set_system | utf8 | | collation_connection | utf8mb4_unicode_ci | | collation_database | utf8mb4_unicode_ci | | collation_server | utf8mb4_unicode_ci | +--------------------------+--------------------+ 10 rows in set (0.00 sec)Видно, что все соответствующие параметры заданы в utf8mb4, кроме character_set_filesystem, который всегда будет двоичным и character_set_system, который всегда в utf8 и не может быть изменён. Шаг 6 - восстановление и оптимизация всех таблиц После обновления версии MySQL сервера и применения описанных выше действий, необходимо произвести восстановление и оптимизацию всех баз данных и таблиц. Для этого вы можете выполнить следующие запросы для каждой таблицы: REPAIR TABLE table_name; OPTIMIZE TABLE table_name;С использованием команды mysqlcheck $ mysqlcheck -u root -p --auto-repair --optimize --all-databasesИтог Никогда не используйте utf8, если есть возможность выбора utf8mb4. Обновление базы данных и таблиц может занять некоторое время, но оно того стоит. Копирование статьи без указания прямой ссылки на первоисточник - http://invisionbyte.ru строго запрещено!
-
Теги шаблонов - это короткие теги, которые могут быть использованы в HTML шаблонах, а некоторые из них в CSS файлах. Теги имеют вид: {tag="значение"}Некоторые теги могут содержать опции: {tag="значение" option="значении_опции" other_option="другое_значение"}Кроме того, будет интересен следующий материал - http://invisionbyte.ru/docs/dev/logika-shablonov-r38/ Языковые сроки {lang="ключ"}Возвращает фразу или слово языка, используемого пользователем в данный момент. Доступные опции: sprintf - может быть использовано для передачи значений, которые будут заменены с помощью sprint. Значение будет экранировано для предотвращения XSS атак; если в экранировании нет необходимости, можно использовать htmlsprintf.pluralize - может быть использовано для передачи плюрализационного значения. http://invisionbyte.ru/docs/dev/yazykovye-sroki-vo-mnozhestvennom-chisle-plyuralizaciya-r28/wordbreak - добавляет теги <wbr> ко всем возвращаемым значениям и может быть использовано для форматирования контента, предоставляемого пользователем, способного нарушить целостность шаблона сайта.Дата и время {datetime="699753360"}Возвращает значение для отображения даты. По умолчанию отображает дату в формате HTML5 (например: 5 минут назад), в теге <time> и автоматически адаптируется под экраны мобильных устройств. Доступные опции: norelative - отображает дату и время в обычном формате, вне тега <time> и без других дополнительных функций. Для этого нужно указать norelative="true".dateonly - работает как norelative, но не отображает время, только дату.Данные пользователя {member="name"}Возвращает значение указанного параметра для текущего авторизованного пользователя. Данный пример отобразит \IPS\Member::loggedIn()->name. Доступные опции group - вернёт значение информации о группе пользователя, то есть \IPS\Member::loggedIn()->group[ $key ]. Необходимо лишь указать group="true".id - вернёт ID авторизованного пользователя.raw - предотвратит возвращение форматированного значения для предотвращения XSS атаки на сайт. Для использования необходимо указать raw="true".Настройки {setting="board_name"}Возвращает значение параметра с указанным ключом. Настройки темы {theme="selected"}Возвращает значение параметра темы с указанным ключом. URL адреса (могут быть использованы в CSS) {url="app=core&module=system&controller=login"}Возвращает URL. Доступные опции: seoTemplate - FURL шаблон.seoTitle - title FURL, если применимо. Если необходимо использование более одного, можно разделить значения запятыми.csrf - если указано, добавит CSRF ключ в URL. Для использования нужно указать csrf="true".fragment - если указано, добавит #fragment в конечную часть URL с указанным значением.noprotocol - если указано, вернёт URL без протокола. Для использования нужно указать noprotocol="true".plain - вернёт URL в текстовом режиме, без HTML форматирования. Обычно используется для текстовых email шаблонов. Для использования нужно указать plain="true".Числа {number="1000"}Возвращает число, отформатированное локалью пользователя. Например "1,000". Размер файла {filesize="1000000"}Возвращает читаемый размер файла в байтах, например 1Мб. Доступные опции: decimal - сделает его десятичным (1000 байт= 1кБ), вместо бинарного (1024 байта = 1кБ)CSS префиксы (можно использовать в css файлах) {prefix="transition" value="0.1s all linear"}Возвращает блок CSS кода со всеми префиксами браузеров ("-webkit-", "-moz-", "-ms-" и "-o-"). Опция обязательна. Шаблон {template="userPhoto" group="global" app="core" params="$entry->author(), 'small'"}Включает в себя ещё один шаблон. Все опции обязательны. Изображения (можно использовать в CSS) {resource="image.png" app="core" location="front"}Возвращает URL адрес изображения. Все опции обязательны. Вы ражение (можно использовать в CSS) {expression="1+1"}Выполняет указанное значение как php код и возвращает результат. Доступные опции: raw - предотвращает форматирование возвращаемого результата для защиты сайта от XSS атак. Для использования необходимо указать raw="true"Перенос строки (можно использовать в CSS) {wordbreak="Здесь очень длиный текст..."}Возвращает значение с тегами <wbr>, чтобы избежать нарушения макета сайта контентом, предоставленным пользователями. Обрезать контент (можно использовать в CSS) {truncate="Длинный текст..." length="10"}Возвращает значение, укороченное до указанной в опции длины. Опция обязательна. Дополнительные опции: start - может быть указано в качестве смещенияappend - может быть указано в конце обрезанного текстаРекламные объявления {advertisement="location"}Отображение рекламного блока, настроенного для отображения в этой области.
-
В статье описывается способ применения php условий в html шаблонах в Invision Community 4. Управляющие конструкции Для большинства конструкций в Invision Community синтаксис схож с альтернативным синтаксисом управляющих структур в PHP, но конструкции заключаются в двойные фигурные скобки. В большинстве случаев скобки, двоеточия и точки с запятыми не требуются. Пример: {{if $var}} HTML код {{endif}}Сложное условие {{if $foo}} HTML код {{elseif $bar}} HTML код {{elseif $baz}} HTML код {{else}} HTML код {{endif}}{{foreach $foo as $bar}} HTML код {{endforeach}}Сокращения Вы можете использовать сокращения в различных конструкциях, например, вместо: {{if \IPS\Member::loggedIn()->member_id}} HTML код для авторизованного пользователя {{endif}}Вы можете использовать: {{if member.member_id}} HTML код для авторизованного пользователя {{endif}}Доступные сокращения: request.var соответствует \IPS\Request::i()->varmember.var соответствует \IPS\Member::loggedIn()->varsettings.var соответствует \IPS\Settings::i()->vartheme.var соответствует \IPS\Theme::i()->settings['var']cookie.var соответствует \IPS\Request::i()->cookie['var']Переменные Переменные можно использовать в обычных фигурных скобках: {$foo}Для предотвращения XSS (межсайтовый скриптинг), необходимо использовать конструкцию, исключающую отображение форматированного контента переменной: {$foo|raw}Экранирование выполняется таким способом, при котором содержание отображается без кодирования специальных символов, для возможности их кодирования необходимо использовать следующую конструкцию: {$foo|doubleencode}Теги Почти везде, где может быть использована логика шаблонов, могут быть использованы теги, для форматирования дат, чисел, языковых срок и так далее. PHP код Вы можете выполнять исходный PHP код, заключив его в двойные фигурные скобки: {{$foo = array();}}Отображение контента шаблонов В Режиме разработчика существует специальный тег, позволяющий отобразить контент шаблона. Тег можно вставлять в любое место шаблона: {{{PRINT}}}
-
ЧПУ - Человеку Понятный Урл, часто называются следующими фразами: семантические URL, SEO URL, FURL, человеческие URL, дружественные URL и так далее, это URL-адреса (Uniform Resource Locator или универсальный указатель ресурса), предназначенные для удобства восприятия и доступности веб-сайтов или сервисов, придавая смысловое значение адресу. Такие URL чаще всего передают информацию о вложенности документов относительно главной страницы. Другими причинами использовать ЧПУ является поисковая оптимизация. ЧПУ, или семантические URL адреса, не содержат в себе служебную информацию приложений, например ID записи или конечный файл index.php. Структура Несемантические URL адреса, как правило, состоят из адреса сайта, имени скрипта и сроки запроса. Параметр запроса указывает на то, какая именно информация должна быть отображена пользователю, и часто включает в себя данные, не имеющие отношения к пользователю, например внутренние цифровые индикаторы содержания, номер сессии, кодированные данные и так далее. ЧПУ же наоборот - отображают только логический путь до страницы, понятный и доступный для пользователя. Для поисковой оптимизации разработчики часто используют возможности ЧПУ, чтобы URL отображал только ключевые слова, а ненужные удалял (в том числе знаки препинания). Slug Slug является частью URL адреса и представляет собой удобный идентификатор страницы, состоящий из ключевых слов. Slug обычно расположен в конечной части URL. Эта часть URL обычно генерируется автоматически из названия страницы, однако может быть введена вручную, например, если название страницы имеет слишком большое количество символов - в этом случае SLAG может быть сокращён до разумных пределов. Slug обычно состоит из букв латинского алфавита, а пробелы заменяются на тире и символ подчёркивания. В Slug могут быть использованы буквы кириллического алфавита, однако при передачи такого URL адреса браузером, он автоматически кодируется в неудобный форма: Например адрес: http://invisionbyte.ru/forums/topic/2-семантические-url-адреса/Кодируется как: http://ipscommunitu.ru/forums/topic/2-%D1%81%D0%B5%D0%BC%D0%B0%D0%BD%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5-url-%D0%B0%D0%B4%D1%80%D0%B5%D1%81%D0%B0/
-
В Invision Community существуют языковые строки, имеющие такой вид: {# [1:comment][?:comments]}Данная конструкция подразумевает собой изменение формы числа существительного в зависимости от количественного значения. Эта фраза будет отображать в единственно числе (если будет передан параметр - 1): 1 comment, если любой другой параметр (количество комментариев): 2 comments, 3 commnets и так далее. Так как в английском языке множественное число существительных образуется в большинстве случаем с помощью добавления к существительному окончания "-s", то такая конструкция слова (указана выше) для английского языка будет исчерпывающей. Для чего тогда это сделано? Данная возможность была реализована разработчиками для придания Invision Community интернациональности, то есть, чтобы любой клиент, не зависимо от страны проживания, имел возможность максимально гибко перевести продукт на родной язык. Такая языковая фраза на русском языке примет вид: {# [1:отзыв][2:отзыва][3:отзыва][4:отзыва][21:отзыв][22:отзыва][23:отзыва][24:отзыва][31:отзыв][32:отзыва][33:отзыва][34:отзыва][41:отзыв][42:отзыва][43:отзыва][44:отзыва][51:отзыв][52:отзыва][53:отзыва][54:отзыва][61:отзыв][62:отзыва][63:отзыва][64:отзыва][71:отзыв][72:отзыва][73:отзыва][74:отзыва][81:отзыв][82:отзыва][83:отзыва][84:отзыва][91:отзыв][92:отзыва][93:отзыва][94:отзыва][?:отзывов]}То есть, для русского языка придётся перечислить в фразе практически все числа (в строке выше получится - 24532 отзывов), что нереально, а значит, придётся воспользоваться шаблонами (см ниже.) Формат фразы Формат фразы выглядит так: {#[x:значение]}1. Фигурные скобки обозначают границы слов. Знак решётки '#' обозначает расположение цифры, указывающей количество. 2. Каждое значение в квадратных скобках представляет собой возможное значение. Оно содержит в себе цифру, а через двоеточие указано слово, которое будет применено с указанной цифрой. Вместо цифры может быть знак вопроса '?', предназначенный для всех неуказанных цифр. Скрытие и перемещение цифр Если вы не хотите отображать цифру в фразе, вы можете добавить восклицательный знак '!' перед решёткой '#', например: %s {!#[1:likes][?:like]} thisВ данном случает будет отображено '%s likes this', если передаваемое значение будет 1, и '%s like this' для любых других значений. Кроме того, вы можете расположить цифру где угодно, указав '#' в любое другое место, например: {!#[1:week][?:# weeks]}В данном случае, если передаваемый параметр будет 1, то будет отображено слово 'week', соответственно, при любом другом параметре будет отображено 'x weeks' (x - цифра). Дополнительный контент В такие языковые строки вы можете включать дополнительный контент, но по правилам синтаксиса, например {# anonymous [1:member][?:members]}Будет отображено '1 anonymous member' при параметре 1 и 'X anonymous members' при любых других параметрах. Для русского языка такая конструкция будет такой: {# [1:анонимный пользователь][?:анонимных пользователей]}Шаблоны Вместо указания определённых значений или '?' для всех остальных значений, вы можете использовать шаблоны. Так знак звёздочки '*' будет соответствовать всем значениям, которые заканчиваются цифрой, указанной после этого знака. Знак '%' будет соответствовать всем значения, которые начинаются цифрой, указанной после него. Например: {# [*1:отзыв][*2:отзыва][*3:отзыва][*4:отзыва][11:отзывов][12:отзывов][13:отзывов][14:отзывов][?:отзывов]}Таким образом, воспользовавшись шаблонами, вы подкорректировали наш пример, указанный в начале статьи. В этом случае все значения, оканчивающиеся на цифру 1 будут указываться со словом 'отзыв', кроме цифры '11', так как для неё мы указали отдельно значение. (1,21,31,41,61,18751 отзыв) или (2,22,52,82,164872 отзыва). Несколько цифр Вы можете создавать строки с указанием нескольких цифр, например: {0# [1:post][*2:posts]} and {1# [1:view][*2:views]}Этак конструкция отобразит два значения, например, если будет передано два параметра 1 и 2, получится '1 post and 2 views'
-
В Invision Community встроен механизм периодической проверки обновлений вашего приложения, плагина, либо темы с отображением информационного окна в админцентре о выпуске обновления. При создании приложения, плагина или темы, вы можете указать URL адрес обновлений. Invision Community будет периодически посылать запрос на указанный URL с параметром текущего номера ID версии. Например, если вы укажите адрес следующим образом: http://сайт.ru/myapp/check.phpА кто-то использует версию приложения с ID версии "10002", то будет отправлен следующий запрос: http://сайт.ru/myapp/check.php?version=10002URL должен вернуть объект в формате JSON со следующими данными: version указывается удобочитаемая последняя доступная версия (например: "1.0.0")longversion указывается ID номер последней доступной версии (например: "100000")released указывается дата релиза версии в формате UNIX-времениupdateurl указывается URL-адрес, по которому администратор может загрузить обновлениеПример: { "longversion": 100019, "version": "4.0.0 RC5a", "released": 1426680323, "updateurl": "http:\/\/community.invisionpower.com\/blogs\/entry\/9723-ips-community-suite-400-release-candidate-available\/" }
-
Для разработки плагинов и приложений в Invision Community реализован Режим разработчика. Данный режим является небезопасным и может нести некоторую угрозу вашему сайту, поэтому, не рекомендуется активировать режим разработчика на работающем сайта, только на локальном сервере, и если вы являетесь PHP разработчиком. Для активации Режима разработчика в Invision Community необходимо: Загрузить Developer Tools с сайта разработчика, убедившись в том, что версия инструментов совпадает с версией Invision Community, если хотите загрузить инструменты разработчика для более ранних версий, воспользуйтесь областью 'Предыдущие версии'.В инструментах разработчика находятся dev папки для всех приложений Invision Community, если у вас нет каких-либо приложений, необходимо удалить dev папки этих приложений. Загрузите содержимое архива в корень вашей установки Invision Community с заменой файлов.Проверьте наличие файла constants.php в корне вашего Invision Community, если такового нет - создайте его.Разместите следующий код в файле constants.php:define( 'IN_DEV', TRUE );Имейте ввиду, что файл php обязательно должен содержать в себе начальные и конечные теги - <?php и ?>.
- 1 отзыв
-
- режим разработчика
- dev mode
-
(и ещё 1 )
C тегом:
-
Обзоры практически идентичны комментариям - они ведут себя так же, и все необязательные настройки комментариев доступны также и для обзоров. Обзоры отличаются несколькими ключевыми моментами: При отправке обзора, кроме текста, пользователи должны указать рейтинг от 1 до 5.Другие пользователи могут пометить считаю ли они этот обзор полезным или бесполезным; затем обзоры можно сортировать по их полезности.Пользователи могут отправлять только один обзор к одному элементу содержимого.Вы можете следовать инструкциям по реализации комментариев для добавления обзоров, применив несколько небольших различий. Модель Классу Вашей модели для отзывов нужно расширить \IPS\Content\Review (что в свою очередь расширяет \IPS\Content\Comment). Существует несколько обязательных дополнительных элементов databaseColumnMap: Элемент Описание rating Рейтинг (0-5), отправляемый с обзором. votes_total Общее количество полученных голосов полезный/бесполезный. votes_helpful Количество голосов votes_total, которые оценили как полезный. votes_data JSON объект, содержащий сведения о том, кто проголосовал полезный/бесполезный и что они проголосовали Изменения вносимые в модель Элемента Содержимого Вместо того, чтобы к модели Элемента Содержимого добавить новое свойство под названием $commentClass, добавьте свойство $reviewClass: /** * @brief Review Class */ public static $reviewClass = 'IPS\yourapp\YourClass'; И для $databaseColumMap: Название элемента для Комментариев Название элемента для Обзоров num_comments num_reviews last_comment last_review last_comment_by last_review_by Название элемента для Комментариев Название элемента для Обзоров unapproved_comments unapproved_reviews При желании Вы можете также добавить дополнительный элемент "рейтинг", который будет содержать текущий средний рейтинг для всех обзоров. Дополнительные свойства и методы в \IPS\Content\Item Комментарии Обзоры static $commentsPerPage static $reviewsPerPage commentPageCount() reviewPageCount() commentPagination() reviewPagination() comments( … ) reviews( … ) commentForm() reviewForm() lastCommentPageUrl() lastReviewPageUrl() canComment() canReview() moderateNewComments( … ) moderateNewReviews( … ) canViewHiddenComments( … ) canViewHiddenReviews( … ) averageReviewRating() Возвращает целое число от 1 до 5 с указанием среднего рейтинга по данному элементу Отображение Вот пример рекомендуемого HMTL для отображения обзоров: <div data-controller='core.commentFeed' data-feedID='file-{$item->id}-reviews'> {{if $item->canReview()}} <h2 class='ipsType_sectionTitle'>{lang="write_a_review"}</h2> <div class='ipsAreaBackground_light ipsPad'> {$item->reviewForm()|raw} </div> <br> {{endif}} <div class="ipsClearfix"> {{if $item->reviewPageCount() > 1}} <div class="ipsPos_left"> {$item->reviewPagination( array( 'tab', 'sort' ) )|raw}</div> {{endif}} <div class="ipsButtonBar ipsClearfix ipsResponsive_showDesktop ipsPos_right"> <ul class="ipsButtonRow ipsPos_left ipsClearfix"> <li data-action="tableFilter" data-filter=""> <a href="{$item->url()- >setQueryString( array( 'tab' => 'reviews', 'page' => 1, 'sort' => 'helpful' ) )}" class="{{if !isset( request.sort ) or request.sort != 'newest'}}ipsButtonRow_active{{endif}}" data- action="filterClick">{lang="most_helpful"}</a> </li> <li data-action="tableFilter" data- filter="members_filter_banned"> <a href="{$item->url()- >setQueryString( array( 'tab' => 'reviews', 'page' => 1, 'sort' => 'newest' ) )}" class="{{if isset( request.sort ) and request.sort == 'newest'}}ipsButtonRow_active{{endif}}" data- action="filterClick">{lang="newest"}</a> </li> </ul> </div> </div> <br><br> <div data-role='commentFeed'> {{foreach $item->reviews() as $review}} {$review->html()|raw} {{endforeach}} </div> </div>
-
Модель Скелетон namespace IPS\yourApp; class _Comment extends \IPS\Content\Comment { /** * @brief [ActiveRecord] Multiton Store */ protected static $multitons; /** * @brief Default Values */ protected static $defaultValues = NULL; /** * @brief [Content\Comment] Item Class */ public static $itemClass = 'IPS\yourApp\YourClass'; /** * @brief [ActiveRecord] Database Table */ public static $databaseTable = 'yourapp_comments'; /** * @brief [ActiveRecord] Database Prefix */ public static $databasePrefix = ‘comment_'; /** * @brief Title */ public static $title = ‘thing_comments’; /** * @brief Database Column Map */ public static $databaseColumnMap = array( 'item' => 'fid', 'author' => 'mid', 'author_name' => 'author', 'content' => 'text', 'date' => 'date', 'ip_address' => 'ip_address', ); } Введение Так же, как и сами Элементы Содержимого, Комментариям также нужна модель, которая следует элементу проектирования Active Record. Наследование схоже с Элементами Содержимого (хотя и используется \IPS\Content\Comment вместо \IPS\Content\Item, оба расширяют \IPS\Content. Требуемые свойства такие же, как и для Элементов Содержимого, с добавлением $itemClass. Элементы, необходимые для $databaseColumnMap: item должен быть колонкой, которая содержит ID элемента, к которому принадлежит колонка.author, как и item, должен быть колонкой, которая содержит ID пользователя, который опубликовал содержимое.content должен быть колонкой, которая содержит текст комментария.date должна быть колонкой, которая содержит временную отметку - когда был опубликован комментарий.ip_address должен быть колонкой, которая содержит IP адрес пользователя, который добавил комментарий.Дополнительные элементы: author_name - необязательно, но если указано, то должно быть колонкой, которая содержит юзернейм пользователя, который оставил комментарий.first должен быть колонкой, содержащей логическое значение - является ли элемент первым комментарием к элементу содержимого или нет.Имеющиеся методы В дополнение к предоставляемым \IPS\Patterns\ActiveRecord (которые работают точно так же для моделей Элементов Содержимого) доступно еще несколько дополнительных методов: url( $action=NULL ) Получает URL к данному комментарию напрямую (будет автоматически работать на правильном номере страницы и якоре). В отличие от Элементов Содержимого, этот метод уже определен. item() Возвращает объект \IPS\Content\Item элемента, которому принадлежит комментарий. author() truncated( bool $oneLine=FALSE ) canView(…) canEdit(…) canDelete(…) modPermission(…) modAction(…) Они ведут себя так же, как элементы содержимого. isFirst() Возвращает логическое значение, указывающее является ли это первым комментарием к материалу. isIgnored( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее нужно ли игнорировать этот комментарий пользователю $member (пользователь, вошедший в данный момент, если NULL). dateLine() Возвращает строку, которая может использоваться в шаблонах, отображая информацию вроде "Опубликовано 2 дня назад". html() Возвращает HTML для отображения комментария (в его шаблоне). Дополнительные свойства Можно указать ряд дополнительных свойств: static $commentTemplate Обратная функция, указывающая шаблон, который используется для отображения комментария (по умолчанию используется стандартный шаблон). static $formTemplate Обратная функция, указывающая шаблон, который используется для отображения формы для публикации комментария (по умолчанию используется стандартный шаблон). static $incrementPostCount Логическое значение, контролирующая следует ли увеличивать количество подсчитанных публикаций для комментариев данного типа. static $formLangPrefix Ведет себя так же, как и для элементов содержимого, позволяя вам менять языковые строки, используемые в форме отправки. Изменения, которые следует произвести в модели Элемента Содержимого Добавьте новое свойство к своей модели Элемента Содержимого: public static $commentClass = ‘IPS\yourapp\YourClass';Если вашему Элементу Содержимого необходим первый комментарий - например, темам в IP.Board требуется как минимум один пост, поэтому данное утверждение правдиво для тем; но файлы IP.Downloads публикуются без начального комментария, поэтому в данном случае утверждение не верно - добавьте дополнительное свойство: protected static $firstCommentRequired = TRUE;Добавляет новые элементы к $databaseColumnMap: Элемент Описание Обязательно? num_comments Число комментариев Да last_comment Unix временная отметка о том, когда был добавлен последний комментарий Нет last_comment_by ID пользователя, который оставил последний комментарий Нет last_comment_name Юзернейм пользователя, который оставил последний комментарий Нет Создайте расширение EditorLocations Для отображения текстового редактора комментария, он будет автоматически искать расширение редактора, использующее свойства $application и $module вашего элемента содержимого, поэтому вам потребуется создать расширение редактора, удовлетворяющее этому требованию. Отображение Вы можете отображать комментарии любым образом, но, если Вы хотите убедиться, что такие функции JavaScript, как AJAX-ответы и редактирование работают, вы должны применить определенные атрибуты. Вот пример разметки: <div data-controller='core.commentFeed' data-feedID='messages- {$item->id}'> <br> {{if $item->commentPageCount() > 1}} {$item->pagination()|raw} <br><br><br> {{endif}} <div data-role='commentFeed'> {{foreach $item->comments() as $comment}} {$comment->html()|raw} {{endforeach}} </div> <div data-role='replyArea'> {$item->commentForm()|raw} </div> </div> Эти методы будут использовать обобщенные шаблоны. Чтобы настроить используемый шаблон, добавьте один или оба этих метода к своей модели Комментариев (здесь показаны значения по умолчанию): /** * @brief [Content\Comment] Comment Template */ public static $commentTemplate = array( array( 'global', 'core', 'front' ), 'commentContainer' ); /** * @brief [Content\Comment] Form Template */ public static $formTemplate = array( array( 'forms', 'core', 'front' ), 'commentTemplate' ); Изменения Элементов Содержимого Дополнительные свойства и методы в \IPS\Content\Item static $commentsPerPage Контролирует количество комментариев на странице. По умолчанию - 25. commentPageCount() Возвращает число страниц комментариев. commentPagination() Возвращает HTML ссылок разбивки на страницы comments( int $limit=NULL, int $offset=NULL, string $order=‘date’, string $orderDirection=‘asc’, \IPS\Member $member=NULL ) возвращает либо объект \IPS\Content\Comment (если $limit равен 1) или массив комментариев. См. phpdocs для полной информации. commentForm() Возвращает HTML формы ответа. lastCommentPageUrl() Возвращает URL последней страницы комментариев. canComment() Возвращает логическое значение, указывающее может ли вошедший пользователь оставлять комментарии. Изменения поведения stats()теперь будет возвращать дополнительный элемент, включая количество комментариев. Поиск Комментарии могут быть включены в результаты поиска и последние действия наряду с элементами содержимого. Другие требования Поиск должен быть применен и к элементам контента. Что изменится после внедрения Комментарии будут проиндексированы и включены в результаты поиска и последние действия. Индекс будет автоматически обновлен, когда комментарии создаются, редактируются, перемещаются, скрываются, итп., и работает автоматически и с MySQL index, и со Sphinx. Дополнительные методы, доступные после внедрения Нет Как применить 1. Добавить интерфейс: implements \IPS\Content\SearchableЖалобы На комментарии можно жаловаться модераторам. Другие требования Нет Что изменится после внедрения Кнопка "Пожаловаться" будет автоматически отображаться рядом с комментарием для пользователей, у которых есть возможность отправлять жалобы на комментарии. Дополнительные методы, доступные после внедрения canReport( [$member] ) Проверяет может ли пользователь (или конкретный пользователь, или пользователь вошедший в данный момент) жаловаться на содержимое, учитывая может ли группа, к которой принадлежит пользователь, отправлять жалобы, просматривать содержимое, являются ли члены группы авторами и отправляли ли они уже жалобу на данный элемент содержимого. report( $reportContent ) Отправляет жалобу Как применить 1. Добавить интерфейс: implements \IPS\Content\ReportCenter2. Добавляет новые свойства для определения имени класса CSS в целях представления данного элемента содержимого при просмотре отчетов. public static $icon = 'icon';История редактирования Комментарии могут вести лог того, кто отредактировал комментарий, а также записывать все внесенные изменения. Другие требования Нет Что изменится после внедрения При редактировании, все данные о редактировании будут записаны в лог и отображены в комментарии. Точное поведение зависит от настроек сайта. Дополнительные методы, доступные после внедрения editLine() Возвращает строку "Отредактировано х дней назад Пользователем" для отображения рядом с комментарием. editHistory( bool $staff ) Возвращает итератор с историей редактирования. Как применить 1. Добавить интерфейс: implements \IPS\Content\EditHistory2. Добавляет следующие элементы к $databaseColumnMap Элемент Описание Требуется? edit_time Unix временная отметка - когда было внесено последнее изменение Да edit_show Логическое значение, указывающее нужно ли показывать сообщение о редактировании Да edit_member_name Юзернейм пользователя, внесшего изменения Да edit_reason Причина редактирования Нет, но рекомендуется edit_member_id ID пользователя, внесшего изменения Нет Скрытие / восстановление Комментарии могут быть скрыты для простых пользователей. Это может быть использовано для обязательного подтверждения администрацией ресурса комментариев, прежде чем их можно будет просмотреть, и как способ скрыть нежелательные комментарии. Другие требования Нет Дополнительно Полномочия модератора Что изменится после внедрения loadAndCheckPerms(…)теперь будет выдавать ошибку OutOfRange, если загружается скрытый элемент содержимого, и у вошедшего пользователя нет прав на просмотр скрытого содержимого.Скрытые комментарии теперь будут отображаться только для тех пользователей, у которых есть права на просмотр скрытых комментариев.Пользователи, имеющие соответствующие права модератора, теперь увидят кнопку скрыть/восстановить под комментарием.Комментарии от пользователей, контент от которых подлежит модерации, будут скрыты до тех пор, пока вручную не будут подтверждены администрацией.Дополнительные методы, доступные после внедрения hidden() Возвращает число, указывающее состояние скрытия: -1 означает, что содержимое скрыто, но раньше оно не было скрытым.0 означает, что содержимое не скрыто (значение по умолчанию, обычное состояние).1 означает, что содержимое скрыто и было отмечено как скрытое на момент публикации.canHide( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) скрыть элемент. Учитывает, если он уже заблокирован. canUnhide( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) отменить скрытие элемента. Учитывает, если он уже заблокирован. Новый метод также доступен в классе элемента содержимого: canViewHiddenComments( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) просматривать скрытые комментарии к публикации. Как применить 1. Добавить интерфейс: implements \IPS\Content\Hideable2. Добавляет либо элемент hidden или элемент approved к $databaseColumnMap с указанием колонки в базе данных, которая содержит статус содержимого. Элемент Значение, если не скрыт (обычный, по умолчанию) Значение, если скрыт (ранее был не скрыт) Значение, если ожидает подтверждения hidden -1 1 approved 1 -1 3. Дополнительно, вы также можете добавить элемент unapproved_comments к $databaseColumnMap в классе элемента содержимого указывает на колонку, содержащую количество комментариев, ожидающих подтверждения. 4. Комментарии от пользователей, контент от которых подлежит модерации, будут по умолчанию скрыты автоматически. Вы можете переопределить метод, который обрабатывает данную функцию, например чтобы все комментарии в определенных узлах обязательно требовали подтверждения. Чтобы сделать это, перезапишите метод moderateNewComments(…)в классе элемента содержимого - например: public static function moderateNewComments( \IPS\Member $member ) { if ( $this->item()->container()->bitoptions[‘moderation’] and !static::modPermission( 'unhide', $member, $this->item()- >container() ) ) { return TRUE; } return parent::moderateNewComments( $member ); }Репутация Пользователи могут "лайкать" или присваивать репутацию комментариям. Общая репутация отображается в профиле пользователя. Другие требования Нет Что изменится после внедрения Кнопки репутации будут автоматически отображаться рядом с комментариями. Дополнительные методы, доступные после внедрения reputation() Возвращает целое число с указанием текущей репутации элемента. canGiveReputation( int $type, \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (вошедший в данный момент пользователь, если NULL) присваивать $type (1 - положительная, -1 - отрицательная) репутации комментарию. giveReputation( $type, \IPS\Member $member=NULL ) Присваивает репутацию комментарию. Сгенерирует DomainException если $member не разрешено присваивать репутацию комментарию. repGiven( \IPS\Member $member=NULL ) Возвращает целое число (1 - положительная, -1 - отрицательная, 0 - нет репутации) с указанием какую репутацию $member (вошедший в данный момент пользователь если NULL) присвоил комментарию. Как применить 1. Добавить интерфейс: implements \IPS\Content\Reputation2. Добавьте свойство, указывающее ключ для разделения репутации, присваиваемой данному типу содержимого, от другого типа репутации. Это может быть все, что угодно, но рекомендуется использовать название колонки в таблице вашей базы данных (с префиксом), в которой хранится ID. public static $reputationType = ‘comment_id’;Подписка Пользователи могут оформлять подписку на элементы содержимого и им будет приходить уведомление, когда будет добавлен новый комментарий. Другие требования Должна быть возможность подписаться на элемент содержимого. Что изменится после внедрения После публикации нового комментария, пользователи, подписанные на контент, получат уведомление. Если комментарий требует утверждения модератором, то уведомления будут отложены до тех пор, пока комментарий не будет утвержден. Дополнительные методы, доступные после внедрения Эти методы доступны для класса элемента содержимого, а не для класса комментария: followers( int $privacy=3, array $frequencyTypes=array( ‘immediate’, ‘daily’, ‘weekly ), array $limit=array( 0, 25 ), string $order=‘name’ ) Возвращает объект \IPS\Db\Select, который может повторяться с целью получения данных о том, какие пользователи подписаны на элемент содержимого. См. phpDocs для доступных вариантов. $privacy является побитовым значением, использующим константы \IPS\Content\FOLLOW_* - значение по умолчанию 3, включает общедоступную и анонимную подписку. Как применить 1. Добавьте кнопку подписки на страницу, где можно просмотреть Ваш элемент содержимого: {template="follow" app="core" group="global" params=“'yourApp', ‘YourContentItemClass’, $item->id, $item->followers()->count( TRUE )"}
-
Введение в Content Items. Часть 1 Содержимое В некоторых областях потребуется содержимое (content) элемента. Для некоторых элементов, это будет описание, а для других, которым требуются комментарии (см. объяснение свойства $firstCommentRequired в главе 3), это будет содержимое первого комментария. Другие требования Нет Дополнительно Комментарии Что меняется после внедрения Нет Дополнительные методы, доступные после внедрения content() Возвращает содержимое. truncated( bool $oneLine=FALSE ) Возвращает содержимое в формате, в котором его можно поместить в элемент <div data-ipsTruncate> для обрезки. Как применить ЛИБО Добавьте элемент content к $databaseColumnMap с указанием колонки в базе данных, в которой содержится контент. ЛИБО Реализуйте комментарии (см. главу 3) для возвращения первого комментария. Рекомендуемое Введение Элементы контента можно помечать как рекомендуемое и отображать на главной странице или в других местах. Другие требования Нет Дополнительно Права доступа. Полномочия модератора. Что меняется после внедрения Пользователи с соответствующими правами модератора увидят инструмент для пометки таблиц элементов содержимого в качестве рекомендуемых/не рекомендуемых. Дополнительные методы, доступные после внедрения static featured( int $limit=10, string $order=‘RAND()’ ) Отображает рекомендуемое. Если включены Права Доступа, будут возвращены только те элементы, на просмотр которых есть права у вошедшего в данный момент пользователя. canFeature( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (вошедший пользователь, если NULL) помечать элемент как рекомендуемый. Принимает во внимание, если он уже рекомендуемый. canUnfeature( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (вошедший пользователь, если NULL) снимать с элемента пометку рекомендуемый. Принимает во внимание, если он уже рекомендуемый. Как применить 1. Добавить интерфейс: implements \IPS\Content\Featurable2. Добавьте элемент featured к $databaseColumnMap, указывая колонку в базе данных, которая содержит данные о том рекомендуемый элемент или нет. 3. Добавляет кнопку рекомендовать/отменить рекомендацию в шаблоне для просмотра элемента содержимого. {{if $item->canFeature()}} <a href='{$item->url()->setQueryString( array( 'do' => 'moderate', 'action' => 'feature' ) )}'>{lang="feature"}</a> {{endif}} {{if $item->canUnfeature()}} <a href='{$item->url()->setQueryString( array( 'do' => 'moderate', 'action' => 'unfeature' ) )}'>{lang="unfeature"}</a> {{endif}} Закрепление Элементы содержимого можно закрепить, чтобы они отображались в верхней части списков. Требования Контейнеры Необязательно Права модераторов Что меняется после внедрения • Закрепленные элементы будут отображаться в верхней части таблиц элементов содержимого. • Пользователи с соответствующими правами модератора увидят инструмент для пометки таблиц элементов содержимого в качестве рекомендуемых/не рекомендуемых. Дополнительные методы, доступные после внедрения canPin( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (вошедший пользователь, если NULL) закрепить элемент. Учитывает является ли элемент уже Рекомендуемым. canUnpin( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (вошедший пользователь, если NULL) отменять закрепление элемента. Учитывает является ли элемент уже Рекомендуемым. Как применить 1. Добавьте интерфейс: implements \IPS\Content\Pinnable2. Добавляет pinned элемент к $databaseColumnMap с указанием колонки в базе данных, которая содержит данные о том закреплен элемент содержимого или нет. 3. Добавляет кнопку поднять/опустить к шаблону для просмотра элемента содержимого: {{if $item->canPin()}} <a href='{$item->url()->setQueryString( array( 'do' => 'moderate', 'action' => 'pin' ) )}'>{lang="pin"}</a> {{endif}} {{if $item->canUnpin()}} <a href='{$item->url()->setQueryString( array( 'do' => 'moderate', 'action' => 'unpin' ) )}'>{lang="unpin"}</a> {{endif}}Закрыть Материалы могут быть закрыты, что означает, что в дальнейшем к ним нельзя добавлять комментарии. Другие требования Комментарии Дополнительно Права модераторов Что меняется после внедрения Заблокированные элементы больше не будут получать комментарии, если только у пользователя нет прав оставлять комментарии к заблокированным элементам.Пользователи, имеющие соответствующие права модератора, увидят инструмент для блокировки/разблокировки таблиц элементов содержимого.Дополнительные методы, доступные после внедрения canLock( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) заблокировать элемент. Принимает во внимание, если он уже заблокирован. canUnlock( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) разблокировать элемент. Учитывает, если он уже заблокирован. Как применить 1. Добавить интерфейс: implements \IPS\Content\Lockable2. Добавляет элемент locked к $databaseColumnMap с указанием колонки в базе данных, которая содержит данные о том заблокирован ли элемент содержимого или нет. Или элемент locked для текстовой колонки. 3. Добавляет кнопку поднять/опустить к шаблону для просмотра элемента содержимого: {{if $item->canLock()}} <a href='{$item->url()->setQueryString( array( 'do' => 'moderate', 'action' => 'lock' ) )}'>{lang="lock"}</a> {{endif}} {{if $item->canUnlock()}} <a href='{$item->url()->setQueryString( array( 'do' => 'moderate', 'action' => 'unlock' ) )}'>{lang="unlock"}</a> {{endif}}Скрытие / Восстановление Материалы могут быть скрыты от обычных пользователей. Это может быть использовано для запроса подтверждения от сотрудников ресурса прежде, чем определенное содержимое можно будет просматривать, и как способ для сотрудников скрыть нежелательный контент. Другие требования Нет Дополнительно КонтейнерыПолномочия модератораЧто изменится после внедрения canView(…)вернет значение "ложь" для элемента, который скрыт, если пользователь не может просматривать скрытые элементы содержимого. Это также приведет к тому, что loadAndCheckPerms(…)выдаст исключение OutOfRange, если будет загружен подобный объект.Скрытые элементы будут отображаться только тем пользователям, которые имеют права на просмотр скрытого контента.Пользователи, имеющие соответствующие права модератора, увидят инструмент для блокировки/разблокировки таблиц элементов содержимого.Контент от пользователей, который находится на премодерации, будет скрыт до тех пор, пока не будет подтвержден вручную.Дополнительные методы, доступные после внедрения hidden() Возвращает число, указывающее состояние скрытия: • -1 означает, что содержимое скрыто, но раньше оно не было скрытым. • 0 означает, что содержимое не скрыто (значение по умолчанию, обычное состояние). • 1 означает, что содержимое скрыто и было отмечено как скрытое на момент публикации. canHide( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) скрыть элемент. Принимает во внимание, если он уже заблокирован. canUnhide( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) отменить скрытие элемента. Учитывает, если он уже заблокирован. static canViewHiddenItems( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) просматривать скрытые элементы. Для проверки индивидуального элемента используйте canView(). Как применить 1. Добавить интерфейс: implements \IPS\Content\Hideable2. Добавьте либо элемент hidden или элемент approved к $databaseColumnMapс указанием колонки в базе данных, которая содержит данные о статусе содержимого. Элемент Значение, если не скрыт (обычный, по умолчанию) Значение, если скрыт (ранее был не скрыт) Значение, если ожидает утверждения hidden -1 1 approved 1 -1 При желании также можно добавить approved_by (чтобы хранить ID пользователя, который утвердил контент) и approved_date (чтобы хранить временную отметку утверждения контента). 3. Добавит кнопки скрыть/восстановить к шаблону просмотра содержимого: {{if $item->canHide()}} <li><a href='{$item->url()->setQueryString( array( 'do' => 'moderate', 'action' => 'hide' ) )}'>{lang="hide"}</a></li> {{endif}} {{if $item->canUnhide()}} <li><a href='{$item->url()->setQueryString( array( 'do' => 'moderate', 'action' => 'unhide' ) )}'>{{if $item->hidden() === 1}}{lang="approve"}{{else}}{lang="unhide"}{{endif}}</a></li> {{endif}} 4. Если контент, добавляемый пользователем, находится на премодерации, он по умолчанию будет скрыт. Вы можете переопределить этот метод таким образом, чтобы весь контент в определенных узлах всегда требовал подтверждения модератором. Чтобы сделать это, перезапишите метод moderateNewItems(…)- например: public static function moderateNewItems( \IPS\Member $member, \IPS\Node\Model $container = NULL ) { if ( $container and $container->bitoptions['moderation'] and !static::modPermission( 'unhide', $member, $container ) ) { return TRUE; } return parent::moderateNewItems( $member, $container ); } Теги Материалы могут помечаться тегами. Теги можно использовать для поиска разных типов данных с одними и теми же метками (тегами). Другие требования • Контейнеры Что изменится после внедрения Поле для ввода тегов будет добавлено к форме создания / редактирования. Префиксы и теги будут отображаться в таблицах содержимого. Дополнительные методы, доступные после внедрения static canTag( \IPS\Member $member=NULL, \IPS\Node\Model $container) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) помечать элементы в $container. Вы можете изменить этот метод, если у вас для каждого узла стоит отдельная настройка для включения/выключения тегов. static canPrefix( \IPS\Member $member=NULL, \IPS\Node\Model $container) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) добавлять префиксы к элементам в $container. Вы можете изменить этот метод, если у вас для каждого узла стоит отдельная настройка для включения/выключения префиксов tags() Возвращает массив тегов для элемента. prefix() Возвращает префикс для элемента (или NULL). Как применить 1. Добавить интерфейс: implements \IPS\Content\Tags2. Отображать теги и префиксы на странице просмотра элемента: {{if $item->prefix()}} <a href="{url="app=core&module=system&controller=tags&tag={$item- >prefix()}" seoTemplate="tags"}">{$item->prefix()}</a> {{endif}} {{if count( $file->tags() )}} <ul> {{foreach $file->tags() as $tag}} <li><a href="{url="app=core&module=system&controller=tags&tag={$tag}" seoTemplate="tags"}">{$tag}</a></li> {{endforeach}} </ul> {{endif}}Поиск Элементы содержимого можно включить в результаты поиска и в списки последних действий. Другие требования Перенаправление содержимого Теги Дополнительно КонтейнерыПрава доступаСкрытие / восстановлениеЧто изменится после внедрения Содержимое будет проиндексировано и включено в результаты поиска и последние действия. Индекс будет автоматически обновлен, когда комментарии создаются, редактируются, перемещаются, скрываются, итп., и работает автоматически и с MySQL index, и со Sphinx. Дополнительные методы, доступные после внедрения Нет Как применить Добавить интерфейс: implements \IPS\Content\SearchableРепутация Пользователи могут "лайкать" или присваивать репутацию элементам содержимого. Общая репутация отображается в профиле пользователя. Другие требования Нет Что изменится после внедрения Нет Дополнительные методы, доступные после внедрения reputation() Возвращает целое число с указанием текущей репутации элемента. canGiveReputation( int $type, \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) присваивать $type (1 - положительная, -1 - отрицательная) репутации элементу. giveReputation( $type, \IPS\Member $member=NULL ) Присваивает элементу репутацию. Сгенерирует DomainException если $member не разрешено присваивать репутацию элементу. repGiven( \IPS\Member $member=NULL ) Возвращает целое чисто (1 - положительная, -1 - отрицательная, 0 - нет репутации), указывая какую репутацию $member (вошедший в данный момент пользователь, если NULL) присвоил элементу. Как применить 1. Добавьте интерфейс: implements \IPS\Content\Reputation2. Добавьте свойство, указывающее ключ для разделения репутации, присваиваемой данному типу содержимого, от другого типа репутации. Это может быть все, что угодно, но рекомендуется использовать название колонки в таблице вашей базы данных (с префиксом), в которой хранится ID. public static $reputationType = 'item_id';3. Добавляет кнопки репутации на страницу, на которой отображается ваш элемент: {template="reputation" app="core" group="global" params=“$item"} Подписка Пользователи могут следить за контейнерами и получать уведомления, когда к ним добавляются новые элементы содержимого. Требования КонтейнерыСодержимоеЧто изменится после внедрения После публикации нового элемента содержимого, пользователи, которые подписаны на узел получат уведомление. Если контент стоит на премодерации, уведомления будут отправлены после того, как содержимое будет подтверждено модератором. Дополнительные методы, доступные после внедрения static containerFollowers( \IPS\Node\Model $container, int $privacy=3, array $frequencyTypes=array( ‘immediate’, ‘daily’, ‘weekly ), array $limit=array( 0, 25 ), string $order=‘name’ ) Возвращает объект \IPS\Db\Select, который может повторяться для получения данных о том, какие пользователи подписаны на $container. См. доступные варианты в phpDocs. $privacy является побитовым значением, использующим константы \IPS\Content\FOLLOW_* - значение по умолчанию 3, включает общедоступную и анонимную подписку. Как применить 1. Добавить интерфейс: implements \IPS\Content\Followable2. Добавляет следующую кнопку на страницу, где Вы отображаете элементы содержимого в узле: {template="follow" app="core" group="global" params=“‘yourApp’,’YourCNodeClass’, $node->_id, \IPS\yourApp \YourContentClass::containerFollowers( $node )->count( TRUE )"}Просмотры страниц Элементы Содержимого могут автоматически отслеживать сколько раз они были просмотрены. Требования Нет Что изменится после внедрения Когда просматривается материал, колонка в базе данных, которая содержит количество просмотров, будет обновляться. stats()выдаст элемент, содержащий количество просмотров. Дополнительные методы, доступные после внедрения Нет Как применить 1. Добавить интерфейс: implements \IPS\Content\Views2. Добавляет элемент views к $databaseColumnMap с указанием колонки в базе данных, которая содержит количество просмотров. 3. Убедитесь, что контроллер вызывает parent::manage()в начале метода manage() Поделиться ссылками Элементы содержимого могут предоставлять ссылки, чтобы поделиться материалами в социальных сетях. Другие требования Нет Что изменится после внедрения Нет Дополнительные методы, доступные после внедрения sharelinks() Возвращает массив ссылок для обмена. Как применить 1. Добавить интерфейс: implements \IPS\Content\Shareable2. Отображать ссылке где-то в Вашем шаблоне: {template="sharelinks" app="core" group="global" params="$item"}Жалобы На элементы содержимого можно жаловаться модераторам. Другие требования Содержимое Что изменится после внедрения Нет Дополнительные методы, доступные после внедрения canReport( [$member] ) Проверяет может ли пользователь (либо какой-то определенный, или вошедший в данный момент) жаловаться на контент, учитывая разрешено ли его группе отправлять жалобы, могут ли они просматривать содержимое, являются ли они автором или отправляли ли они уже жалобу на данный элемент содержимого. report( $reportContent ) Отправляет жалобу Как применить 1. Добавить интерфейс: implements \IPS\Content\ReportCenter2. Добавляет новые свойства для определения названия класса CSS для представления Вашего элемента содержимого при просмотре жалоб. public static $icon = 'icon';3. Отображает ссылку где-то в вашем шаблоне. Вы не должны вызывать canReport( ), чтобы проверить, есть ли у пользователя права отправлять жалобу, так как это метод средней интенсивности. Тем не менее, вы можете включить некоторые базовые проверки - что пользователь может отправлять жалобы, не является автором, итп. Например: {{if !\IPS\Member::loggedIn()->group['gbw_no_report'] and $item->author()->member_id != \IPS\Member::loggedIn()->member_id }} <a href='{$item->url('report')}' data-ipsDialog data- ipsDialog-size='narrow' data-ipsDialog- title="{lang="report_post"}" data-ipsDialog- flashMessage="{lang="node_error"}" title='{lang="report_post"}'><i class='icon-exclamation-sign'></i> {lang="report_post"}</a> {{endif}} Маркеры прочитанного Элементы содержимого могут содержать данные о том, какие пользователи уже прочитали их. Требования Нет Дополнительно Контейнеры Комментарии Что изменится после внедрения Когда просматривается элемент, то он будет помечен как прочитанный для конкретного пользователя. Дополнительные методы, доступные после внедрения static containerUnread( \IPS\Node\Model $container, \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли данный контейнер (или его дочерний элемент) содержать непрочитанные элементы. static markContainerRead( \IPS\Node\Model $container, \IPS\Member $member=NULL ) Помечает все элементы в контейнере (также и дочерние) как прочитанные. unread( \IPS\Member $member=NULL ) Возвращает 0, если элемент прочитан; -1 если не прочитан и никогда не был прочитан; или 1 если не прочитан, но был прочитанным ранее (применимо только при совместном использовании с комментариями). Если $member равен NULL, будет использовать вошедшего в данный момент пользователя. markRead( \IPS\Member $member=NULL ) Помечает элемент как прочитанный пользователей $member (пользователь, вошедший в данный момент, если NULL). timeLastRead( \IPS\Member $member=NULL ) Возвращает объект \IPS\DateTime, указывающий, когда $member (пользователь, вошедший в данный момент, если NULL) в последний раз прочитал элемент. Как применить 1. Добавить интерфейс: implements \IPS\Content\ReadMarkers2. Добавьте элемент updated к $databaseColumnMap с указанием колонки в базе данных, которая соержит либо временную отметку о том, когда в последний раз был обновлен контент. если только Вы не используете комментарии или обзоры, в этом случае нужно использовать last_comment/ last_review. 3. Убедитесь, что контроллер вызывает parent::manage()в начале метода manage(), или иным образом убедитесь, что Вы вызываете markRead()вручную при просмотре элемента содержимого. В целях использования containerUnread() и markContainerRead() ваши контейнеры должны работать со следующими методами (см. раздел Контейнеры): get items()get comments()setLastComment()getLastCommentTime()Опросы Пользователи могут добавлять опросы к элементам содержимого. Другие требования Нет Что изменится после внедрения При создании или редактировании элемента содержимого, появится новая вкладка, на которой пользователь сможет создать опрос. Дополнительные методы, доступные после внедрения static canCreatePoll( \IPS\Member $member \IPS\Node\Model $container ) Возвращает логическое значение, указывающее может ли пользователь создавать опрос в этом контейнере ($container будет NULL если ваш элемент содержимого не использует данную переменную). Вы можете изменить этот метод, чтобы добавить отдельные настройки опросов для каждого контейнера. getPoll() Возвращает объект \IPS\Poll, связанный с элементом содержимого, либо NULL если его нет. Как применить 1. Добавить интерфейс: implements \IPS\Content\Polls2. Добавьте элемент poll к $databaseColumnMap с указанием колонки в базе данных, которая содержит ID опроса. 3. Отображать опрос где-то в Вашем шаблоне: {$item->getPoll()|raw}При желании, ваш класс может следить за тем, когда кто-то голосует в опросе. Для осуществления: 1. Добавить интерфейс: implements \SplObserver2. Добавьте метод update который делает все что нужно сделать, когда в опросе появляется новый голос. Он получит объект \IPS\Poll в качестве субъекта. 3. При отображении вашего элемента, присоединит его к опросу: if ( $poll = $topic->getPoll() ) { $poll->attach( $item ); }Рейтинг Пользователи могут оценивать элементы содержимого (по шкале от 1 до 5). Это следует использовать только в том случае, если не используются обзоры (см. Главу 4). Другие требования Нет Что изменится после внедрения Нет Дополнительные методы, доступные после внедрения canRate( \IPS\Member $member = NULL ) Возвращает логическое значение, указывающее может ли вошедший в данный момент пользователь выставлять оценку элементу. averageRating() Возвращает средний рейтинг элемента содержимого. rating() Отображает статистику с указанием текущего среднего рейтинга. Если в настоящее время вошедший пользователь может выставлять оценку, он сможет нажать на звёздочки для выставления оценки. Как применить 1. Добавить интерфейс: implements \IPS\Content\Ratings2. Дополнительно можно добавить следующие элементы к $databaseColumnMap (добавление либо rating_average или rating_total и rating_hits поможет избежать необходимости запрашивать средний рейтинг при отображении формы): rating_average, для текущего среднего рейтингаrating_total, для общего показателя всех рейтинговrating_hits, сколько раз оценивали данный элемент3. Отображение рейтинга в вашем шаблоне: {$item->rating()|raw}Встраивание Когда URL-адрес вашего контента публикуется еще где-то в сообществе, ссылку можно автоматически заменить на превью содержимого. Другие требования Перенаправление Что изменится после внедрения Когда URL-адрес вашего контента публикуется еще где-то в сообществе, ссылка будет заменена на превью содержимого. Дополнительные методы, доступные после внедрения Нет Как применить 1. Убедитесь, что URL вашего контента содержит параметр "id", который является основным ID контента. Если это не так, вам потребуется изменить метод loadFromUrl в классе (это определено в \IPS\Patterns\ActiveRecord): public function loadFromUrl( \IPS\Http\Url $url ) { return static::load( ... ); }2. Добавить интерфейс: implements \IPS\Content\Embeddable3. Для получения встраиваемого контента, будет вызван URL элемента с “&do=embed” в конце ссылки. В предварительно просмотре встраиваемого содержимого убедитесь, что получили нужный результат. Введение в Content Items. Часть 1
-
Модель Скелет <?php namespace IPS\yourapp; class _YourClass extends \IPS\Content\Item { /** * @brief Multiton Store */ protected static $multitons; /** * @brief Default Values */ protected static $defaultValues = NULL; /** * @brief Application */ public static $application = 'yourapp'; /** * @brief Module */ public static $module = 'yourmodule'; /** * @brief Database Table */ public static $databaseTable = 'table'; /** * @brief Database Prefix */ public static $databasePrefix = 'prefix_'; /** * @brief Database Column Map */ public static $databaseColumnMap = array( 'author' => 'author' ); /** * @brief Title */ public static $title = ‘thing’; /** * Get URL * * @param string|NULL $action Action * @return \IPS\Http\Url */ public function url( $action=NULL ) { $url = \IPS\Http\Url::internal( ... ); if ( $action ) { $url = $url->setQueryString( 'do', $action ); } return $url; } } Введение Модель Элемента Содержимого (Content Item) представляет собой контент, созданный пользователями (например, в IP.Board тема является элементом содержимого). Если Вы добавляете дополнительные функции для Элементов Содержимого, то Вы будете их добавлять и редактировать в этом скелетоне. Наследование Ваша модель расширяет количество классов. В свою очередь, они: - \IPS\Content\Item Обеспечивает функции элементов содержимого. Он содержит весь код для различных дополнительных функций элементов содержимого, которые вы сможете активировать, добавив свойства и интерфейсы к своей модели. \IPS\Content Обеспечивает небольшое количество функций, общих и для моделей Элемента Содержимого, и для моделей Комментария к Содержимому (пояснено позже), например можно узнать автора и работать с $databaseColumnMap. \IPS\Patterns\ActiveRecord Обеспечивает функции для загрузки элементов из базы данных, работы с их свойствами, их сохранения и удаления. Необходимые свойства string $application; Ключ приложения, к которому принадлежит Элемент Содержимого. string $module; Ключ модуля, к которому принадлежит Элемент Содержимого. array $multitons array $defaultValues; Простые требования \IPS\Patterns\ActiveRecord - Вам не нужно делать ничего кроме как определить их. string $databaseTable Название таблицы базы данных, где хранится ваш Элемент Содержимого. string $databasePrefix Если все колонки в таблице вашей базы данных начинаются с одного и того же префикса, Вы можете определить его здесь, и тогда Вам не потребуется указывать его каждый раз, когда Вы будете искать значение в колонке. Важно, чтобы в таблице вашей базы данных была колонка {$databasePrefix}id, содержащая числовое значение первичного ключа. array $databaseColumnMap Функции, предоставляемые более высокими классами вашей модели, будут изучать этот массив на предмет того что хранится в определенных колонках базы данных. Обязательные элементы: author должен содержать название колонки (без $databasePrefix), которая содержит ID пользователя, который опубликовал контент.title должен содержать название колонки (без $databasePrefix), которая содержит заголовок контента.date должна содержать название колонки (без $databasePrefix), которая содержит unix-временную отметку о том, когда был создан контент.ip_address должен содержать название колонки (без $databasePrefix), которая содержит IP адрес пользователя, который опубликовал контент.string $title Ключ для языковой строки, который описывает чем является ваш элемент содержимого (например, "Тема", "Файл", "Изображение", "Событие", и т.д.) Имеющиеся методы В дополнение к методам, предоставляемым \IPS\Patterns\ActiveRecord (что точно так же работает и для Узлов), доступно несколько дополнительных методов: static getItemsWithPermission( ... ) Получает элементы содержимого. См. phpDocs для полной информации. mapped( string $key ) Возвращает значение столбца, заданного $databaseColumnMap. author() Получает объект \IPS\Member для пользователя, который опубликовал контент. Например: $item = YourClass::load( 1 ); $user = $item->author(); echo $user->name; canView() Возвращает логическое значение, указывающее может ли $member (NULL, если вошедший в данный момент пользователь) просматривать элемент содержимого. По-умолчанию будет возвращать значение TRUE, но на это влияет тот факт, включены ли Права доступа или Скрытие. canEdit( \IPS\Member $member ) Возвращает логическое значение, указывающее может ли $member (NULL если вошедший в данный момент пользователь) редактировать элемент содержимого. canDelete( \IPS\Member $member ) Возвращает логическое значение, указывающее может ли $member (NULL если вошедший в данный момент пользователь) удалить элемент содержимого. static modPermission( $type, \IPS\Member $member = NULL, \IPS\Node\Model $container = NULL ) Возвращает логическое значение, указывающее имеет ли $member (пользователь, вошедший в данный момент, если NULL) права для выполнения действия, указанного $type в узле, указанном $container (если NULL, будет проверять есть ли у них права на всех узлах). Приемлемые значения для $type: editdeletemovefeature (если разрешено Рекомендуемое)unfeature (если разрешено Рекомендуемое)pin (если разрешено Закрепление)unpin (если разрешено Закрепление)lock (если разрешена Блокировка)unlock (если разрешена Блокировка)hide (если разрешено Скрытие / Восстановление)unhide (если разрешено Скрытие / Восстановление)view_hidden (если разрешено Скрытие / Восстановление)modAction( $action, \IPS\Member $member = NULL ) Выполняет действия модератора, указанные в $action. Сгенерирует OutOfRangeException если $member (вошедший на данный момент пользователь, если NULL) не имеет права на совершение данного действия. Контроллер Скелетон namespace IPS\yourapp\modules\front\yourmodule; class _yourcontroller extends \IPS\Content\Controller { } Введение Контроллер, сразу после того как определен, дает пользователям возможность удалять содержимое, если вы присоедините “&do=delete&id=X” к URL, необходимому для доступа к контроллеру (где “X” - ID номер). Он будет автоматически проверять есть ли у пользователя права на выполнение заданного действия (что, по умолчанию, правдиво только в том случае, если пользователь является модератором с правами на удаление всего контента). Если вы добавляете дополнительные функции к своему Элементу Содержимого, контроллер будет выполнять больше действий. Естественно, вы также добавите собственные методы в целях содействия фактическому отображению содержимого. Отображение таблицы Вы можете использовать класс IPS\Helpers\Table\Content для отображения списка всех элементов содержимого в узле. $table = new \IPS\Helpers\Table\Content( 'IPS\yourApp\YourClass', $node->url(), NULL, $node ); \IPS\Output::i()->output = $table;Таблица будет автоматически разбита постранично и будет показывать только те элементы, на просмотр которых есть права у пользователей. Если вы хотите отобразить элементы по-другому, вы можете указать пользовательский шаблон для использования: $table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'yourTemplateGroup' ), 'yourTemplate' );См. пример в шаблоне по умолчанию (core —> front —> tables —> rows). Создание формы добавления публикации Вы можете создать форму для пользователей, чтобы они отправляли элементы просто вызывая метод create(): \IPS\Output::i()->output = \IPS\yourApp\YourClass::create( $node ); Вы должны передать узел, в котором создается элемент содержимого (или NULL, если ваши элементы содержимого не зависят от узлов или если вы добавите элемент в форме отправки), и метод будет автоматически обрабатывать отображение формы, создание элемента и перенаправление. Формы элементов для отображения получаем из метода formElements(array $values, \IPS\Node\Model $node), который вы можете перезаписать для добавления дополнительных элементов формы (они также будут отображаться в форме редактирования). Он автоматически будет включать элементы для заголовка, тегов (если включен - см. раздел Теги) и первого комментария (если включены комментарии, то первый комментарий является обязательным - см. главу 3); поэтому убедитесь, что вы вызываете метод в родительском классе и не перезапишете это. Названия элементов формы имеют префикс статичного свойства $formLangPrefix (которое является пустой строкой, если не переопределено) - таким образом, вы можете использовать это для настройки заголовков, используемых в элементах формы. Есть несколько методов, которые вы также можете переопределить для выполнения действий в различных точках процесса создания: canCreate( \IPS\Member $member, \IPS\Node\Model $container=NULL, bool $showError=FALSE ) Даже прежде чем будет отображена эта форма, запускается этот метод для проверки может ли пользователь создавать элемент в данном узле. Большая часть проверки прав доступа выполняется автоматически, так что вам обычно не нужно переопределять этот метод, если только нет конкретных особенностей (например, в мессенджере можно установить, чтобы пользователи могли отправлять только определенное количество сообщений в день - так что этот пункт проверяется в данном методе внутри мессенджера). processBeforeCreate( array $values ) Этот метод запускается после того как был создан объект и установлены значения по умолчанию, такие как автор, дата и любые другие поля, которые могут быть установлены в силу того, что имеют тот же ключ, как и колонка базы данных, но перед тем как элемент добавлен в базу данных. Он получает значения из формы. processForm( array $values ) Этот метод запускается сразу же после processBeforeCreate(). Он отличается от processAfterCreate() в том, что работает и для внесения изменений, и для добавления новых пунктов. Вы должны использовать его для установки любых полей, добавленных в formElements( ), которые более сложные, чем просто настройка прямого значения (что будет сделано автоматически). По умолчанию, метод устанавливает заголовок, теги (если включены - см. раздел Теги) и другие данные, поэтому убедитесь, что вызываете метод в родительском классе и не перезапишите данную настройку. processAfterCreate( \IPS\Content\Comment $comment=NULL, array $values ) Этот метод запускается после того как элемент содержимого был вставлен в базу данных и завершена вся обработка, включая создание первого комментария (если включено, см. главу 3). Если применимо, он получается объект для первого комментария и значения из формы. Заметки Подсчет постов Количество постов будет автоматически увеличиваться, когда пользователь будет публиковать элемент содержимого. Это может быть нежелательным, особенно если ваши элементы содержимого являются просто контейнерами для комментариев, что также увеличивает количество постов (как тем в IP.Board). Вы можете отключить это поведение при помощи свойства: public static $incrementPostCount = TRUE;Контейнеры Введение Элементы Содержимого, которые принадлежат к Узлам, могут определять эту взаимосвязь. Другие требования Нет Что меняется после внедрения Нет Дополнительные методы, доступные после внедрения container() Возвращает объект контейнера. canMove( \IPS\Member $member=NULL ) Возвращает логическое значение, указывающее может ли $member (пользователь, вошедший в данный момент, если NULL) перемещать элемент в другой контейнер. move( \IPS\Node\Model $container ) Перемещает элемент в другой контейнер. Дополнительные методы, доступные для класса контейнера после внедрения get_items() get_comments() get_reviews() get_unapprovedItems() get_unapprovedComments() get_unapprovedReviews() set_items( $val ) set_comments( $val ) set_reviews( $val ) set_unapprovedItems( $val ) set_unapprovedComments( $val ) set_unapprovedReviews( $val ) Получает/устанавливает количество (подтвержденных) элементов/комментариев/обзоров и количество неподтвержденных. Подтвержденный/неподтвержденный применимо только в том случае, если содержимое можно скрыть (объяснено далее). По умолчанию, все get_ методы возвращают NULL и set_ методы ничего не делает. Вы можете изменить их, если вашему контейнеру необходимо отслеживать номера. Для того чтобы неподтвержденные комментарии/обзоры надежно обследовались, ваши элементы содержимого должны иметь элементы “unapproved_comments” или “unapproved_reviews” в колонках базы данных (см. главу 3). setLastItem( \IPS\Content\Item $item ) setLastComment( \IPS\Content\Comment $comment ) setLastReview( \IPS\Content\Review $review ) Эти методы вызываются автоматически при публикации нового элемента/комментария/обзора. По умолчанию, они ничего не делают, но вы можете изменить их, если вашему контейнеру необходимо отслеживать последний элемент/комментарий/обзору внутри него. В некоторых случаях, передаваемая переменная будет NULL, и в этом случае вы должны вручную извлечь последний элемент/комментарий/обзор. Эти методы должны иметь соответствующие настройки, чтобы после применения вызывать такой же метод во всех дочерних узлах. getLastCommentTime() Если используется setLastComment( ), этот метод можно использовать в сочетании чтобы вернуть объект \IPS \DateTime, отображающей время, когда был опубликован элемент, комментарий или обзор. Используется для считывания маркировки. Как применить 1. Добавьте новое свойство: /** * @brief Node Class */ protected static $containerNodeClass = 'IPS\yourapp\YourNodeClass';2. Добавьте элемент container к $databaseColumnMap с указанием колонки в базе данных, которая содержит ID контейнера. Права доступа Введение Элементы содержимого могут автоматически проверять есть ли у пользователя права на выполнение определенных действий, проверив контейнер. См. главу 1 для получения дополнительной информации об определении прав доступа в Узлах. Другие требования Контейнеры Что меняется после внедрения canView(…)вернет "ложь" для элемента внутри узла, если у пользователя нет прав на его просмотр. Это также приведет к тому, что loadAndCheckPerms(…)выдаст исключение OutOfRange, если будет загружен подобный объект.Везде, где функции что-либо выполняют, будут проверяться права доступа. Например, canCreate(... ) теперь вернет false, если у пользователя нет прав на создание элементов содержимого в указанном узле.getItemsWithPermission(…)теперь будет возвращать только те элементы, которые дозволено просматривать вошедшему в данный момент пользователю (или если у него есть иные права доступа, указанные в параметрах).Дополнительные методы, доступные после внедрения can( string $permission[, mixed $member ] ) Проверяет есть ли у пользователя права, необходимые для выполнения указанного действия. Действие должно совпадать со значением статичного свойства $permissionMap класса контейнера. $member может быть либо NULL (что будет проверять права доступа вошедшего в данный момент пользователя), или \IPS\Member или объектом \IPS\Member\Group. permId() Возвращает ID числового значения прав доступа. Как применить 1. Добавьте интерфейс: implements \IPS\Content\PermissionsПеренаправление содержимого Введение Некоторые функции, такие как предупреждения, являются правами модератора и обрабатываются централизованно и автоматически. Для регистрации ваших элементов содержимого в ядре, вам нужно создать простой файл расширения, называемый Content Router . Другие требования Контейнеры Что меняется после внедрения При создании модератора, администраторы смогут настроить права модератора для определенных элементов содержимого.При просмотре профиля пользователя, отображаемый весь контент, опубликованный этим пользователем, будет включать ваши элементы содержимого.Если у вас включены скрытые элементы содержимого, при просмотре панели управления администратора будет показан весь скрытый контент из вашего приложения.Когда модератор дает пользователю предупреждение, если это предупреждение выдано вследствие элемента содержимого, то тогда контент будет связан с предупреждением.При восстановлении количества постов пользователя, будут считать ваши элементы содержимого.При удалении всего контента, опубликованного пользователем, будут считать ваши элементы содержимого.Дополнительные методы, доступные после внедрения Нет Как применить 1. Создайте новое расширение ContentRouter в своем приложении, используя следующий код: namespace IPS\yourApp\extensions\core\ContentRouter; class _YourClass extends \IPS\Content\ModeratorPermissions { public $classes = array( 'IPS\yourApp\YourContentItemClass' ); } 2. Добавьте свойство $modPerm к своей модели Узла с ключом, который будет использоваться как ключ для хранения узлов, на которые модератор обладает правами доступа (любыми). Создать языковую строку с таким же ключом и значением, представляющем как называются Ваши узлы (например, "Категории"). 3. Добавьте языковые строки для каждого из доступных действий модератора следующим образом: can_<action>_<title> Где “<title>” - это ключ, определяемый статичным свойством $title в вашей модели элемента содержимого. Если Ваши элементы содержимого поддерживают комментарии, повторите все действия, которые можно выполнить с комментариями (edit, delete, hide, unhide, view_hidden), где “<title>” - это ключ, определенный статичным свойством $title в вашей модели комментариев к контенту. Введение в Content Items. Часть 2
-
Узлы (nodes) создаются администратором. Хотя в Invision Community 4 узлы используются для различных целей, в этом документе рассматривается их использование в качестве контейнеров для элементов содержимого. В приложении IP.Board, forum является узлом - форумы содержат темы, которые являются элементами содержимого. В приложении IP.Downloads, category - это узел; категории содержат файлы, которые являются элементами содержимого. Примечание: Узлы могут иметь под-узлы отличного от себя класса. Поскольку это сложно и обычно не нужно для элементов содержимого, касающиеся этого методы и свойства были опущены в данной документации. Требования Модель Скелетон namespace IPS\yourApp; class _YourClass extends \IPS\Node\Model { /** * @brief [ActiveRecord] Multiton Store */ protected static $multitons; /** * @brief [ActiveRecord] Default Values */ protected static $defaultValues = NULL; /** * @brief [ActiveRecord] Database Table */ public static $databaseTable = 'table'; /** * @brief [ActiveRecord] Database Prefix */ public static $databasePrefix = 'prefix_'; /** * @brief [Node] Node Title */ public static $nodeTitle = 'categories'; /** * Get URL * * @return \IPS\Http\Url */ public function url() { return \IPS\Http\Url::internal( ... ); } /** * [Node] Add/Edit Form * * @param \IPS\Helpers\Form $form The form * @return void */ public function form( $form ) { $form->add( ... ); } } Наследование Ваша модель расширяет количество классов. В свою очередь, они: - \IPS\Node\Model Обеспечивает функцию узлов. Он содержит весь код для различных дополнительных функций элементов содержимого, которые вы сможете активировать, добавив свойства и интерфейсы к своей модели. \IPS\Patterns\ActiveRecord Обеспечивает функции для загрузки элементов из базы данных, работы с их свойствами, их сохранения и удаления. Необходимые методы и свойства array static $multitons array static $defaultValues; Простые требования \IPS\Patterns\ActiveRecord - вам не нужно ничего делать помимо их определения. string static $databaseTable Имя таблицы базы данных, в которой хранятся ваши Узлы (вам необходимо ее создать). string static $databasePrefix Если все колонки в таблице вашей базы данных начинаются с одного и того же префикса, можно указать это здесь, и тогда вам не нужно указывать его каждый раз, когда вы просматриваете значение столбца. Важно, чтобы в таблице вашей базы данных была колонка {$databasePrefix}id, содержащая числовое значение первичного ключа. string static $nodeTitle Должен быть языковой ключ, содержащий слово, которое объясняет чем являются ваши узлы (например, "форумы" или "категории»). string static $databaseColumnOrder Должна быть колонка (без префикса) в вашей базе данных, которая содержит номер позиции, из которой будут по порядку вызываться узлы (центральный код будет обрабатывать установку и использование значения, но вам нужно создать для этого поле - оно должно быть INT колонкой). url() Должно возвращать объект \IPS\Http\Url, указывающий местоположение в клиентской части, где пользователи могут просматривать элементы содержимого в вашем узле. form( \IPS\Helpers\Form $form ) См. раздел по формам ниже. Дополнительные методы bool static $nodeSortable Если вы установите значение FALSE (по умолчанию - TRUE), администраторы не смогут изменить порядок следования узлов. bool static $modalForms Если задано значение TRUE (по умолчанию - FALSE), формы добавить/редактировать будут открываться в режимных окнах. Доступные методы В дополнение к предоставляемым \IPS\Patterns\ActiveRecord, есть еще ряд дополнительных методов: static roots() Возвращает массив узлов. Если вы используете взаимосвязь родитель / дочерний элемент, он вернет только те, которые не имею родителя. static search( string $column, string $query, string $order=NULL, array $where ) Возвращает массив узлов, соответствующих критерию поиска. getButtons( \IPS\Http\Url $url ) Возвращает массив кнопок для отображения в узле дерева. Методы set и get Как уже говорилось во введении, класс \IPS\Patterns\ActiveRecord позволяет вам использовать методы для создания get и set. Некоторые специальные свойства будут применены к методам get и set ключевыми методами, поэтому Вам нужно создать методы для их обработки. В большинстве случаев вам не нужно реализовывать этот метод, так как существующего в \IPS\Node\Mode уже достаточно - создавайте метод только в том случае, если этого не достаточно (например, вы будете всегда хотеть создать метод get title(), но почти никогда - метод get id()). Свойство Описание Get/Set \IPS\Node\Model возвращает значения по-умолчанию, если вы не создали метод $_id Должен вернуть ID вашего узла. Get only Значение колонки "id" в базе данных. $_title Возвращает название вашего узла. Метод get и поиск пустая строка $_description Должен выдавать только описание узла, либо NULL, если не применимо. Get only NULL Свойство Описание Get/Set \IPS\Node\Model возвращает значения по-умолчанию, если вы не создали метод $_badge Можно использовать для возврата значка для отображения при просмотре узлов в панели управления администратора. См. phpDocs. Get only NULL $_icon Может быть использована для отображения иконки в ряду при просмотре узлой в панели управления администратора. Возвращает имя класса CSS иконки. Get only NULL $_enabled Если будет реализована, добавит значок "Enabled"/"Disabled", который будет переключать статус при нажатии. Вы должны реализовать это, если у ваших узлов есть концепция включения/выключения. Get и Set NULL $_locked Если вы используете $_enabled, это можно использовать для указания того, что у определенного узла нельзя переключить статус включен/выключен и его текущий статус заблокирован. Get only NULL $_position Возвращает позицию узла. Get only Значение в столбце в базе данных, представленное $databaseColumnOrder $_items Количество элементов содержимого в узле (см. главу 2). Get and Set NULL $_comments Число комментариев к элементу содержимого в узле (см. главу 3). Get and Set NULL $_reviews Количество обзоров к элементу содержимого в узле (см. главу 3). Get and Set NULL В качестве примера как это может работать: названия узлов почти всегда хранятся в виде языковой строки в базе данных, таким образом, большинство узлов имеют метод, который выглядит так: protected function get title() { return \IPS\Member::loggedIn()->language()- >get(“yourApp_category_{$this->id}”); } Обратите внимание, что “_title” иногда отправляется к методу search (см. Доступные Методы ниже). Поэтому вам может потребоваться перезаписать этот метод, чтобы получить узлы, которые соответствуют искомому заголовку. В качестве короткого пути, если вы используете языковые строки для заголовков по примеру, описанному выше, вы можете просто добавить статичное свойство $titleSearchPrefix к вашей модели с префиксом. public static $titleSearchPrefix = 'yourApp_category_';Формы При просмотре ваших узлов в Панели Администратора, форма добавить/изменить будет доступна автоматически. Вам необходимо определить метод form( \IPS\Helpers\Form $form ) для определения какие элементы формы будут показаны. Например: /** * [Node] Add/Edit Form * * @param \IPS\Helpers\Form $form The form * @return void */ public function form( \IPS\Helpers\Form $form ) { $form->add( new \IPS\Helpers\Form \Translatable( 'category_title', NULL, TRUE, array( 'app' => 'yourApp', 'key' => ( $this->id ? "yourApp_category_{$this->id}" : NULL ) ) ) ); $form->add( new \IPS\Helpers\Form \YesNo( 'category_example', $this->example ) ); } Это позволит создать форму с 2мя элементами - Переносным полем, позволяющим администратору устанавливать заголовок, и полем Yes/No для другого свойства. Когда форма будет сохранена, любые поля, соответствующие столбцам в таблице базы данных, будут установлены автоматически. Тем не менее, вам, возможно, потребуется проделать дополнительную работу - в данном примере, из-за того, что заголовок переносимый, его нельзя хранить в определенной колонке базы данных - поэтому мы должны хранить его в языковой системе. Это может быть сделано путем переопределение метода saveForm( array $values ). Например: /** * [Node] Save Add/Edit Form * * @param array $values Values from the form * @return void */ public function saveForm( $values ) { // Нужно сделать это, если мы создаем новый узел, у нас пока не будет ID и языковой системе он потребуется для хранения заголовка. if ( !$this->id ) { $this->save(); } \IPS\Lang::saveCustom( 'yourApp', "yourApp_category_{$this->id}", $values['category_title'] ); parent::saveForm( $values ); } Контроллер Скелетонnamespace IPS\yourApp\modules\admin\yourModule; class _yourController extends \IPS\Node\Controller { /** * Node Class */ protected $nodeClass = 'IPS\yourApp\YourClass'; } Введение Контроллер, только за счет определения, будет создавать страницу, где администраторы могут просматривать и управлять узлами. Если вы добавляете дополнительные функции к своему Элементу Содержимого, контроллер будет выполнять больше действий. Взаимосвязь "родитель-дочерний элемент" Введение Узлы могут быть дочерними элементами других узлов, что почти всегда верно для узлов, содержащих элементы содержимого (например, форум может быть подфорумом другого подфорума); укажите колонку в таблице базы данных (без префикса), в которой содержится ID номер родителя. Другие требования Нет Что меняется после внедрения Контроллер автоматически обрабатывает отображение взаимосвязь родитель / дочерний элемент и позволяет перетаскивать узлы один в другой. Дополнительные методы, доступные после внедрения static roots() Возвращает массив узлов, у которых нет родителя. parent() Возвращает непосредственного родителя. parents() Возвращает Splstack всех родительских узлов (непосредственный родительский узел, затем родительский узел этого узла, итд.) hasChildren() Возвращает логическое значение, указывающее имеет ли узел дочерние элементы. childrenCount() Возвращает число дочерних элементов. children() Возвращает массив дочерних узлов. Как применить Добавьте статичное свойство к своей модели, $databaseColumnParent, содержащее название колонки базы данных (без префикса), в которой содержится ID родительского узла. Если ваше приложение изначально было разработано для предыдущей версии Invision Community и использует значение отличное от 0 для указания узла, не имеющего родителя, добавьте дополнительное статичное свойство, $databaseColumParentRootValue, указав каким должно быть это значение. Ограничения панели управления администратора (ACP) Введение Ограничения Панели Администратора позволяют администраторам ограничивать права доступа других администраторов к панели управления. Другие требования Нет Что меняется после внедрения Контроллер автоматически проверяет ограничения панели управления администратора и отказывает в доступе к запрещенным областям. Дополнительные методы, доступные после внедрения static restrictionCheck( string $key ) static canAddRoot() canAdd() canEdit() canCopy() canManagePermissions() canDelete() Все методы возвращают логическое значение, указывающее может ли вошедший пользователь выполнить действие. Как применить Во-первых, создайте необходимые ограничения панели администратора в центре разработчика для своего приложения. Затем добавьте статичные свойства к своей модели, $restrictions, содержащие массив из трех элементов: app должен содержать ключ приложения, содержащий ограниченияmodule должен содержать ключ модуля, содержащий ограниченияТретье свойство зависит от того насколько конкретные ограничения вам нужны - см. ниже.Есть 3 пути реализации: Если вы хотите вручную указать права на выполнение каких действий следует проверять, добавьте третий элемент - map - который должен быть ассоциативным массивом. Ключи должны быть: add, edit, permissions (нужно только если ваш узел поддерживает права доступа) и delete. Значения должны быть ключами ограничения для проверки этих действий.Если вы хотите использовать эти ключи с префиксом (например, ваши ключи ограничения "foo_add”, “foo_edit”, итп.), добавьте третий элемент под названием prefix с указанием префикса (в этом примере, “foo_”.Если вы хотите использовать только одно ограничение для всех прав доступа, добавьте третий элемент под названиемall со значением, которое является ключом ограничения.Права пользователей Введение Разрешения позволяют администраторам контролировать, какие группы пользователей могут выполнять какие-либо действия (такие как просмотр элементов содержимого, создание новых элементов содержимого, добавление комментариев к элементам содержимого, итп.) в каждом узле. Другие требования Нет Что меняется после внедрения Методы hasChildren(), childrenCount()и children()будут возвращать только дочерние узлы, которые в данный момент пользователь может просматривать. Все методы используют два параметра для управления этим поведением: children( string $permissionCheck=‘view', \IPS\Member $member = NULL )$permissionCheck контролирует какие права проверяются. $member контролирует для какого пользователя следует осуществлять проверку (если NULL, то используется вошедший в данный момент пользователь). loadAndCheckPerms(…)теперь будет выдавать ошибку OutOfRange, если загружается узел, для просмотра которого у вошедшего пользователя нет прав. Дополнительные методы, доступные после внедрения static canOnAny( string $permission, \IPS\Member $member = NULL ) Возвращает логическое значение, указывающее есть ли у $member (вошедший в данный момент пользователь если NULL) права на выполнение действия $permission на узле any. Это можно использовать, например, для определения нужно ли отображать кнопку "Создать новый элемент содержимого". can( string $permission, \IPS\Member $member = NULL ) Ведет себя так же как и canOnAny(), но является объект-методом, для проверки прав на определенном узле. permissions() Возвращает массив с рядом узла из таблицы базы данных core_permission_index, в которой содержится информация о правах определенных групп. Как применить Во-первых, нужно чтобы Ваша модель использовала интерфейс \IPS\Node\Permissions. Затем добавьте три новых свойства для модели: $permApp Ключ приложения, к которому принадлежит ваш класс. $permType Уникальный ключ, представляющий ваш класс в таблице core_permissions_index (например, “forums” или “categories”). $permissionMap Вы можете использовать до 7 разных прав доступа - это свойство должно быть массивом данных с ключами, которые вы хотите использовать (которые используются при вызове методов, такие как can()) к колонкам, которые будут использоваться для хранения этих прав доступа в таблице core_permisisons_index. Каждое значение должно быть либо строкой "view" (что обязательно) или числом от 2 до 7. Например: public static $permissionMap = array( 'view' => 'view', 'read' => 2, 'add' => 3, 'download' => 4, 'reply' => 5, 'review' => 6 );В этом примере доступные ключи доступа: “view”, “read”, “add”, “download”, “reply” и “review”. “view” (может просматривать узел), “read” (модет видеть содержимое элементов в узле) и“add” (может создавать новые элементы содержимого) всегда обязательны. “reply” является обязательным, если к элементам содержимого можно оставлять комментарии. “review” является обязательным, если к вашим элементам содержимого можно оставлять обзоры. В панели управления администратора матрица прав будет показывать права доступа в том порядке, в кором вы их определили. Столбцы в матрице будут искать языковую строку с ключом "perm__{$key}" - таким образом, в этом примере, нужно будет создать новую языковую строку с ключом "perm__download" ("perm__view", "perm__read", и т.д. уже определены).