Статус страницы «черновик» в 1с битрикс (3 способа)

Автор:
Андрей Гук — автор статьи Андрей Гук
#Кейсы

Для начала обозначим проблему. Мы пишем контент для сайтов, которые работают на самых разных системах управления (CMS). В том числе работаем и с 1с Битрикс. И тут выяснилось, что в битриксе нет встроенного функционала черновиков, как на том же вордпрессе или друпале. Есть возможность просто активировать и деактивировать элемент, но активировать так, чтобы не открывать пока в публичном доступе, а посмотреть, что получается — нет. Типичный функционал для статьи в блог, например. Короче, вот с этим и будем разбираться.

Способ 1 — через права доступа

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

Сначала в настройках инфоблока нужно включить "расширенное управление правами". Это позволит настраивать нужные права вплоть до отдельного элемента. Без этой галки установленные права доступа в настройках инфоблока наследуются для всех его разделов и элементов.

настройка расширенных прав доступа для инфоблока

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

Теперь, выбрав нужный элемент (например, статью), в этой вкладке мы можем полностью изменить доступы. В нашем случае, чтобы скрыть статью-черновик от всех подряд, выставляем для группы "все посетители" права "нет доступа", а для нужной нам группы пользователей (например, "контент-менеджеры") выставим права доступа "чтение".

вкладка доступ у элемента при расширенном режиме прав доступа

Так статья будет скрыта для обычных посетителей сайта, но будет доступна для чтения всем залогиненным пользователям, состоящим в группе "контент-менеджеры".

Группы пользователей можно отредактировать в настройках: Настройки - Пользователи - Группы пользователей. Уровни доступа тоже настраиваются: Настройки - Пользователи - Уровни доступа.

Это вполне рабочий способ решить поставленную задачу, но у него есть ряд минусов, из-за которых я его решил не использовать:

  1. Заходить во вкладку "доступ" и выставлять нужный уровень доступа для каждого элемента (статьи) — неудобно.
  2. Мне не удалось быстро придумать, как удобно отслеживать элементы с измененным доступом, например, сформировать список всех статей-черновиков на какой-то странице.

Из-за озвученных выше причин этот способ я решил не использовать. Давайте попробуем другие.

Способ 2 — через статус «активность»

Это максимально прямолинейный способ, который, как мне кажется, разработчики битрикса воспринимают как подходящий для статуса "черновик". Хочешь показывать элемент — проставь галочку в чекбоксе «Активность». Не хочешь — сними. Раз черновик, значит, не должен отображаться, но в админке посмотреть можно.

чекбокс активность в админке битрикса

Его недостаток как раз в том, что неактивные элементы можно посмотреть только в админке, а проверить, как выглядит верстка элемента — переключившись на режим «визуальный редактор».

Я стараюсь держаться от визуального редактора подальше. Во всех cms, с которыми я сталкивался, переключение на него потом ломало верстку, отступы, вставляло ненужные теги и так далее. Да и нам хочется иметь возможность посмотреть черновик не в админке, а уже в контексте всей верстки сайта глазами клиента, но пока без публикации. А для этого нам нужно иметь возможность отображать неактивные элементы на какой-то странице.

Вероятно, вывести неактивные элементы на сайте можно. Например, через метод GetList, отфильтровав только те элементы, которые неактивны. Можно сделать некий список со ссылками, чтобы можно было посмотреть, как выглядит сверстанный черновик. Но в админке останется просто индикация "активен/неактивен". И в таком статусе не будет понятно, какие элементы должны быть сняты с публикации навсегда, а какие не являются активными временно, потому что на доработке (черновики).

Поэтому этот способ я тоже отверг.

Способ 3 — через дополнительное свойство

Это способ, который я и выбрал.

Битрикс поддерживает дополнительные свойства для элементов инфоблока «из коробки» (в отличие от того же вордпресса). Свойства - это произвольные поля, где вы можете хранить любые нужные данные в подходящем формате (строка, список, файл и так далее).

Итак, у нас есть простой инфоблок с базовым набором полей (название, анонс, подробнее…), но нам нужно где-то хранить статус черновика в виде «да/нет». Чтобы добавить новое свойство, пойдем в настройки инфоблока (туда же, где мы меняли настройки доступа), выберем вкладку свойства и добавим новое.

Что важно учесть:

  1. Для дополнительных свойств битрикс не предлагает тип «чекбокс», где были бы значения только «да/нет», поэтому мы воспользуемся типом "список", в который добавим наши значения.
  2. Сортировка нужна, чтобы свойство было на нужном месте в админке. А по символьному коду вы найдете значение этого свойства потом в arResult, когда будете писать логику для вывода черновиков.
  3. У каждого свойства есть набор настроек. Чтобы их изменить, кликните на кнопку с тремя точками рядом с чекбоксом «удалить»
вкладка свойства в настройках инфоблока

В меню настроек нам нужно проверить вот что:

  1. Чтобы свойство было активно. Но эта галка проставляется автоматически при создании.
  2. Чтобы стояла галка рядом с "Показывать на странице редактирования элемента". Тогда это поле появится при добавлении или изменении элемента инфоблока.
  3. Чтобы в списке были нужные значения. Нам нужны просто "да" и "нет". XML_ID заполнять не нужно, он заполнится автоматически.
меню настроек свойства ифоблока

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

добавленное нами новое свойство черновик в списке полей элемента

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

Напомним, что мы все это затеяли для вывода статей. Для этого мы использовали комплексный компонент news (это самый простой подход), у которого за вывод списка элементов (статей) отвечает компонент news.list, а за вывод отдельного элемента (статьи) — news.detail.

В компоненте news.list, отвечающем за вывод списка элементов, мы хотим скрыть черновики из общего списка для всех пользователей и показывать только админам и контент-менеджерам.

Для этого сначала определим, является ли посетитель залогиненным юзером, и если да, то к какой группе он относится. Мы это проверим в файле result_modifier, чтобы уже в template просто выводить нужную информацию.

/local/templates/main/components/bitrix/news.list/articles_list/result_modifier.php
if(\Bitrix\Main\Engine\CurrentUser::get()->getId()) {
	$user_groups = \Bitrix\Main\Engine\CurrentUser::get()->getUserGroups();
	if(in_array(1, $user_groups) || in_array(5, $user_groups)) {
           $arResult['SHOW_DRAFTS'] = true;
	} else {
           $arResult['SHOW_DRAFTS'] = false;
	}
}

Нужно чуть пояснить код. 1 и 5 — это id групп пользователей. 1 — админы, 5 — контент-менеджеры. Если пользователь относится к этим группам, передадим в arResult значение, показываем ли черновики (true) или не показываем (false).

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

/local/templates/main/components/bitrix/news.list/articles_list/result_modifier.php
foreach ($arResult['ITEMS'] as $itemKey => $arItem) {

	$draft_prop = CIBlockElement::GetProperty(3, $arItem['ID'], "sort", "asc", array("CODE" => "DRAFT"));
	while($ar_props = $draft_prop->Fetch()){
		if ($ar_props['VALUE_ENUM'] === 'Да') {
			$arResult['ITEMS'][$itemKey]['DRAFT'] = 'Y';
		} else {
			$arResult['ITEMS'][$itemKey]['DRAFT'] = 'N';
		}
	}
}

Чуть поясним код. Перебираем все элементы инфоблока и получаем значение свойства с помощью GetProperty(). Записываем полученные данные в arResult в массивы тех же элементов для последующего использования в файле template.php, отвечающего за рендеринг страницы.

Теперь в шаблоне (файл template.php) мы проверим, можно ли показывать черновики пользователю. Если можно, то переберем элементы и выведем просто ссылки, чтобы контент-менеджеру было проще понять, какие статьи в черновиках. А потом выведем и остальные элементы так, как мы бы вывели их для всех посетителей.

/local/templates/main/components/bitrix/news.list/articles_list/template.php
<?php if (!empty($arResult['ITEMS'])): ?>
	<?php if ($arResult['SHOW_DRAFTS'] === true) : ?> 
	<?php foreach($arResult['ITEMS'] as $arItem):?>
		<?php if($arItem['DRAFT'] === 'Y') : ?>
			<p>Черновик: <a href="<?= $arItem['DETAIL_PAGE_URL']?>"><?= $arItem['NAME']?></a></p>
		<?php endif; ?>
	<?php endforeach; ?>
	<?php endif; ?>
	<div class="row row-cols-1 row-cols-sm-2 row-cols-lg-3 row-cols-xxl-4 g-4 mb-4">
		<?php foreach($arResult['ITEMS'] as $arItem): ?>
			<?php if($arItem['DRAFT'] === 'N') : ?>
			<article class="col">
				<div class="card portfolio-wrapper portfolio-title">
					<?php if(!empty($arItem['PREVIEW_PICTURE']['SRC'])) : ?>
						<img src="<?= $arItem['PREVIEW_PICTURE']['SRC']?>" class="card-img-top">
					<?php else : ?>
						<div class="main-background dummy-title"></div>
					<?php endif; ?>					
					<div class="card-body">
						<h5 class="card-title"><?= $arItem['NAME']?></h5>
						<p class="card-text"><?= $arItem['PREVIEW_TEXT']?></p>
						<a class="read-more btn btn-primary" href="<?= $arItem['DETAIL_PAGE_URL']?>">Читать <i class="fa fa-arrow-right"></i></a>
					</div>
				</div>
			</article>
			<?php endif; ?>
		<?php endforeach; ?>
	</div>

<?php endif; ?>
Так у тех, кто должен видеть черновики в общем списке.
простой список черновиков, который виден только нужным пользователям
А так у всех остальных.
так выглядит список статей для всех пользователей

Со списком разобрались. Теперь осталось закрыть доступ к самой статье-черновику, если пользователь перейдет по прямой ссылке.

Для этого сначала проверим, какое значение у свойства "черновик". Если значение "да", определим тип пользователя (как мы уже делали в списке) и отправим код 403 (доступ запрещен) тем, кому нельзя смотреть этот материал. Тем, кому можно, покажем и упростим жизнь, добавив к названию капсом ЧЕРНОВИК, чтобы не запутались.

Все это делаем в result_modifier.php для компонента news.detail

/local/templates/main/components/bitrix/news.detail/article_single/result_modifier.php
if ($arResult['PROPERTIES']['DRAFT']['VALUE'] === 'Да') {

	if(\Bitrix\Main\Engine\CurrentUser::get()->getId()) {
		$user_groups = \Bitrix\Main\Engine\CurrentUser::get()->getUserGroups();
		if(in_array(1, $user_groups) || in_array(5, $user_groups)) {
			$arResult['NAME'] = 'ЧЕРНОВИК: '.$arResult['NAME'];
		} else {
			header("HTTP/1.1 403");
			exit;
		}
	} else {
		header("HTTP/1.1 403");
		exit;
	}
}

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

Ну вот и все. Теперь у нас битрикс стал чуть больше похож на wordpress =)