Перейти к содержанию
  • Введение в Content Items. Часть 2

       (0 отзывов)

    Вадим

    Введение в 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\Featurable

    2.    Добавьте элемент 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\Pinnable

    2.    Добавляет 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\Lockable

    2.    Добавляет элемент 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\Hideable

    2.    Добавьте либо элемент 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\Tags

    2.    Отображать теги и префиксы на странице просмотра элемента:

    {{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\Reputation

    2.    Добавьте свойство, указывающее ключ для разделения репутации, присваиваемой данному типу содержимого, от другого типа репутации. Это может быть все, что угодно, но рекомендуется использовать название колонки в таблице вашей базы данных (с префиксом), в которой хранится 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\Followable

    2.    Добавляет следующую кнопку на страницу, где Вы отображаете элементы содержимого в узле:

    {template="follow" app="core" group="global" params=“‘yourApp’,’YourCNodeClass’, $node->_id, \IPS\yourApp
    \YourContentClass::containerFollowers( $node )->count( TRUE )"}

    Просмотры страниц

    Элементы Содержимого могут автоматически отслеживать сколько раз они были просмотрены.

    Требования

    Нет

    Что изменится после внедрения

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

    Дополнительные методы, доступные после внедрения

    Нет

    Как применить

    1.    Добавить интерфейс:

    implements \IPS\Content\Views

    2.    Добавляет элемент views к $databaseColumnMap с указанием колонки в базе данных, которая содержит количество просмотров.

    3.    Убедитесь, что контроллер вызывает parent::manage()в начале метода manage()

    Поделиться ссылками

    Элементы содержимого могут предоставлять ссылки, чтобы поделиться материалами в социальных сетях.

    Другие требования

    Нет

    Что изменится после внедрения

    Нет

    Дополнительные методы, доступные после внедрения

    sharelinks()
    Возвращает массив ссылок для обмена.

    Как применить

    1.    Добавить интерфейс:

    implements \IPS\Content\Shareable

    2.    Отображать ссылке где-то в Вашем шаблоне:

    {template="sharelinks" app="core" group="global" params="$item"}

    Жалобы

    На элементы содержимого можно жаловаться модераторам.

    Другие требования

    Содержимое

    Что изменится после внедрения

    Нет

    Дополнительные методы, доступные после внедрения

    canReport( [$member] )
    Проверяет может ли пользователь (либо какой-то определенный, или вошедший в данный момент) жаловаться на контент, учитывая разрешено ли его группе отправлять жалобы, могут ли они просматривать содержимое, являются ли они автором или отправляли ли они уже жалобу на данный элемент содержимого.

    report( $reportContent )
    Отправляет жалобу

    Как применить

    1.    Добавить интерфейс:

    implements \IPS\Content\ReportCenter

    2.    Добавляет новые свойства для определения названия класса 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>&nbsp; {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\ReadMarkers

    2.    Добавьте элемент 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\Polls

    2.    Добавьте элемент poll к $databaseColumnMap с указанием колонки в базе данных, которая содержит ID опроса.

    3.    Отображать опрос где-то в Вашем шаблоне:

    {$item->getPoll()|raw}

    При желании, ваш класс может следить за тем, когда кто-то голосует в опросе. Для осуществления:

    1.    Добавить интерфейс:

    implements \SplObserver

    2.    Добавьте метод 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\Ratings

    2.    Дополнительно можно добавить следующие элементы к $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\Embeddable

    3.    Для получения встраиваемого контента, будет вызван URL элемента с “&do=embed” в конце ссылки. В предварительно просмотре встраиваемого содержимого убедитесь, что получили нужный результат.
     

    Введение в Content Items. Часть 1

     

    Изменено пользователем Вадим



    Обратная связь

    Рекомендуемые комментарии

    Комментариев нет



    Присоединяйтесь к обсуждению

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

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

    ×   Вставлено с форматированием.   Вставить как обычный текст

      Разрешено использовать не более 75 эмодзи.

    ×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

    ×   Ваш предыдущий контент был восстановлен.   Очистить редактор

    ×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

    Загрузка...

×
×
  • Создать...

Важная информация

Используя наш сайт вы соглашаетесь с нашей Политикой конфиденциальности