END;
}
//*получаем комментарии ответы на родительский комментарий
$sql_comment_og = MysqliPrepared::select($Link, 'SELECT id FROM chaptercomm WHERE parent_id = ?', 'i', [(int) $Row['cid']]);
$parent_id = $Row['cid'];
$bookinfovar = '';
if (!empty($prefetchedCommentsByParent[$parent_id])) {
require_once __DIR__ . '/../templates/octoground/book_comments_item.php';
}
$val .= $bookinfovar;
array_push($chaptercomms[$Row['chapter_id']], $val);
array_push($chaptercomms_list[$Row['chapter_id']], $val_list);
}
// узнаем ID первой версии глав в книге
$orig_chpid = [];
$likes_count = [];
$dislikes_count = [];
$book_author = 0;
$book_author2 = 0;
$book_author3 = 0;
$sequential = 0; // покупать ли главы по порядку
$Query = 'SELECT /*095*/ book_chapters.id, IFNULL(version0_id, book_chapters.id) AS version0_id, likes, dislikes, user_id, author2id, author3id, canzoom
FROM book_chapters, books WHERE books.id=book_id AND book_id=? AND is_draft=0';
$Result = MysqliPrepared::select($Link, $Query, 'i', [(int) $book_id]);
if (!$Result) {
$log->error('Database query error in BookWithChapters: ' . mysqli_error($Link) . ' Query: ' . $Query);
return $renderError();
}
while ($Row = mysqli_fetch_assoc($Result)) {
$orig_chpid[$Row['id']] = $Row['version0_id'];
$likes_count[$Row['id']] = $Row['likes'];
$dislikes_count[$Row['id']] = $Row['dislikes'];
$book_author = (int) $Row['user_id'];
$book_author2 = (int) ($Row['author2id'] ?? 0);
$book_author3 = (int) ($Row['author3id'] ?? 0);
$sequential = ($Row['canzoom'] & 12) >> 2;
}
mysqli_free_result($Result);
// какие главы куплены
$chppurchased = [];
// понадобиться для логики удаления первой бесплатной главы:
// когда в книге ровно одна глава, пользователю (автору/админу) нужно дать возможность убрать тестовую книгу
$book_glav_for_delete_hint = 0;
if ((int) $book_id > 0) {
$bookGlavRes = MysqliPrepared::select($Link, 'SELECT glav FROM books WHERE id=? LIMIT 1', 'i', [(int) $book_id]);
if ($bookGlavRes && mysqli_num_rows($bookGlavRes) > 0) {
$bookGlavRow = mysqli_fetch_assoc($bookGlavRes);
$book_glav_for_delete_hint = (int) ($bookGlavRow['glav'] ?? 0);
}
if ($bookGlavRes) {
mysqli_free_result($bookGlavRes);
}
}
if (((int) $id === (int) $book_author) || (in_array((int) $id, array_map('intval', $z_admins), true))) {
$Query = 'SELECT /*096*/ chapter_id, COUNT(chapter_id) AS cnt FROM purchases WHERE book_id=?
AND chapter_id != 0 AND bonus_buy IN (' . BONUS_BUY_ALLOWED_VALUES . ') GROUP BY chapter_id';
$Result = MysqliPrepared::select($Link, $Query, 'i', [(int) $book_id]);
if (!$Result) {
$log->error('Database query error in BookWithChapters: ' . mysqli_error($Link) . ' Query: ' . $Query);
return $renderError();
}
while ($Row = mysqli_fetch_assoc($Result)) {
$ch_id = $Row['chapter_id'];
$chppurchased[$ch_id] = $Row['cnt'];
}
mysqli_free_result($Result);
}
$cnt_totalpages = 0;
$cnt_totalglav = 0;
$chp_controls = '';
$cntbooks = 0;
$chap_filter3 = '';
$initjscomms = '';
$isFinished = 0;
$latestfilter = '';
$edition = 0;
$protection = 0;
$booktitle = ''; // заголовок книги
$bookauthor = ''; // автор
$orig_rid = 0;
$canaudio = 0;
$ownaudio = 0;
$audioavail = '';
$numpages = 0;
$ChapterPrice = 0;
$nocomms = 0;
$not_purchased = ''; // куплены ли предыдущие главы
if ($chapter_id != 0) {
$not_purchased = PrevNotPurchased($book_id, $chapter_id);
}
$cntpages = 0;
$audioraise = [];
$Query = 'SELECT /*330-3*/ collected_rub, target_rub, payout, chapter_id FROM crowdfunding WHERE book_id=? AND
finish_date>NOW() AND raise_type=2 AND bank_closed=0';
$Result = MysqliPrepared::select($Link, $Query, 'i', [(int) $book_id]);
if (!$Result) {
$log->error('Database query error in BookWithChapters: ' . mysqli_error($Link) . ' Query: ' . $Query);
return $renderError();
}
while ($Row = mysqli_fetch_assoc($Result)) {
$audioraise[$Row['chapter_id']] = ['collected_rub' => $Row['collected_rub'],
'target_rub' => $Row['target_rub'],
'payout' => $Row['payout']];
}
mysqli_free_result($Result);
$curr_fragment = 0;
if ($chapter_id == 0) {
$latestfilter = 'and book_chapters.added != 0';
}
$chap_filter3 = '';
$chapFilter3Types = '';
$chapFilter3Params = [];
if ($chapter_id != 0) {
$chap_filter3 = ' AND book_chapters.id=?';
$chapFilter3Types = 'i';
$chapFilter3Params = [(int) $chapter_id];
}
// врем чтения глав до этого дня (за сегодняшний день - в таблице book_chapters)
$chapter_durations = [];
$Query = 'SELECT /*097-2*/ chapter_id, SUM(readduration) AS dur FROM readstat WHERE book_id=? GROUP BY chapter_id';
$Result = MysqliPrepared::select($Link, $Query, 'i', [(int) $book_id]);
if (!$Result) {
$log->error('Database query error in BookWithChapters: ' . mysqli_error($Link) . ' Query: ' . $Query);
return $renderError();
}
while ($Row = mysqli_fetch_assoc($Result)) {
$chapter_durations[$Row['chapter_id']] = $Row['dur'];
}
mysqli_free_result($Result);
// По умолчанию — прямой порядок (первая глава сверху), как в оглавлении книги, для удобства чтения
$sortorder = 'asc';
$chapters_order = "
Главы расположены по порядку: с начала книги до конца. Новые главы — внизу списка.
";
$deletedstatus = 'deleted = 0';
$deletedstatus2 = 'isdeleted = 0';
if (in_array($id, $z_admins, true)) {
$deletedstatus .= ' or deleted = 2 or deleted = 3';
$deletedstatus2 .= ' or isdeleted = 2 or isdeleted = 3';
}
// Проверяем наличие аудиокниги и собираем информацию о главах с аудио
$chapters_with_audio = [];
$audiobook_exists = false;
// Проверяем сначала наличие аудиокниги (любое состояние)
// Используем обычный запрос с экранированием для совместимости (не требует mysqlnd)
// Добавляем проверку на существование таблиц для предотвращения ошибок
if ($Link && ($Link instanceof mysqli)) {
// Проверяем существование таблицы audiobooks перед запросом
$tableCheck = MysqliPrepared::select($Link, "SHOW TABLES LIKE 'audiobooks'", '', []);
if ($tableCheck && mysqli_num_rows($tableCheck) > 0) {
mysqli_free_result($tableCheck);
$QueryAudioCheck = 'SELECT id, state FROM audiobooks WHERE book_id = ? LIMIT 1';
$ResultAudioCheck = MysqliPrepared::select($Link, $QueryAudioCheck, 'i', [(int) $book_id_int]);
if ($ResultAudioCheck && mysqli_num_rows($ResultAudioCheck) > 0) {
$AudioCheckRow = mysqli_fetch_assoc($ResultAudioCheck);
mysqli_free_result($ResultAudioCheck);
// Если аудиокнига есть, получаем главы (только для state='ready')
if (isset($AudioCheckRow['state']) && $AudioCheckRow['state'] === 'ready') {
// Проверяем существование таблицы audiobooks_chapters
$tableCheck2 = MysqliPrepared::select($Link, "SHOW TABLES LIKE 'audiobooks_chapters'", '', []);
if ($tableCheck2 && mysqli_num_rows($tableCheck2) > 0) {
mysqli_free_result($tableCheck2);
$tableCheck3 = MysqliPrepared::select($Link, "SHOW TABLES LIKE 'audiobooks_tts_jobs'", '', []);
$joinTts = ($tableCheck3 && mysqli_num_rows($tableCheck3) > 0);
if ($tableCheck3) {
mysqli_free_result($tableCheck3);
}
if ($joinTts) {
$QueryAudio = "SELECT abc.chapter_id
FROM audiobooks_chapters abc
INNER JOIN audiobooks ab ON abc.audiobook_id = ab.id
INNER JOIN audiobooks_tts_jobs j ON j.audiobook_id = ab.id AND j.status = 'completed' AND (j.chapter_id = abc.chapter_id OR j.chapter_id = abc.id)
WHERE ab.book_id = ? AND ab.state = 'ready'";
} else {
$QueryAudio = null;
}
$ResultAudio = ($QueryAudio !== null) ? MysqliPrepared::select($Link, $QueryAudio, 'i', [(int) $book_id_int]) : false;
if ($ResultAudio) {
while ($RowAudio = mysqli_fetch_assoc($ResultAudio)) {
$audiobook_exists = true;
$chapter_id_audio = (int) ($RowAudio['chapter_id'] ?? 0);
if ($chapter_id_audio > 0) {
$chapters_with_audio[$chapter_id_audio] = true;
}
}
mysqli_free_result($ResultAudio);
}
} else {
if ($tableCheck2) {
mysqli_free_result($tableCheck2);
}
}
}
} elseif ($ResultAudioCheck === false) {
// Если запрос не выполнился, просто продолжаем без аудио - это не критично
// Не логируем, чтобы не засорять логи
}
} else {
if ($tableCheck) {
mysqli_free_result($tableCheck);
}
}
}
$Query = "SELECT /*097-3*/ books.user_id, books.author2id, books.author3id, books.author2rate, books.author3rate, book_chapters.id, book_chapters.title, name, u1.realname, u2.realname as u2r, kb, price,
book_chapters.added, protection, protectedview, cntpages, nocomms, book_chapters.readduration as chaptduration, protect_override, u1.isauthor,
version, versiondate, IFNULL(version0_id, book_chapters.id) as version0_id, finished, discount, pubafter, UNIX_TIMESTAMP(pubafter) as pubtime, (UNIX_TIMESTAMP(pubafter) = 0 or pubafter= cost OR EXISTS (
SELECT 1 FROM book_subscription
WHERE user_id = ?
AND is_active = 1
AND DATE(sub_duration) >= CURDATE()
AND sub_type IN (998, 999)
)) AS onabonement, IFNULL(written_by,0) AS written_by, IFNULL(mark,0) AS mark, canzoom,
audiotrack.raise_id, mp3filename, target_rub, paid, audiotrack.dictor_id, u3.realname AS dictor_name, ownaudio, sendemails
FROM books
JOIN book_chapters
ON book_chapters.book_id=books.id{$chap_filter3}
LEFT JOIN sale
ON sale.id=sale_id AND sale.endtime>NOW() AND sale.starttime<=NOW()
JOIN users u1
ON u1.id=books.user_id AND ((u1.userdeleted=0) OR (u1.lastlogin > DATE_SUB(now(), interval 1095 day)))
LEFT JOIN users u2
ON u2.id=written_by
LEFT JOIN abonements
ON abonements.user_id=? AND abonements.book_id=books.id
LEFT JOIN library USE INDEX(byUserBook)
ON library.author_id=? AND library.user_id=books.user_id AND library.book_id=0 AND library.age18=0 AND ($deletedstatus2)
LEFT JOIN chapter_likes ON chapter_likes.chapter_id=IFNULL(version0_id, book_chapters.id) AND chapter_likes.user_id=?
LEFT JOIN audiotrack
ON chapter0_id = IFNULL(version0_id, book_chapters.id)
LEFT JOIN crowdfunding ON audiotrack.raise_id=crowdfunding.id AND raise_type=2
LEFT JOIN fundraise_log f
ON f.user_id=? AND f.raise_id=crowdfunding.id
LEFT JOIN users u3
ON u3.id=audiotrack.dictor_id
WHERE (book_chapters.book_id=?) AND ((? != u1.id) OR (u1.userro != 2))
AND book_chapters.is_draft = 0
AND ((($deletedstatus) AND (NOT u1.userdeleted)) OR (IFNULL(purchased,0) > 0) OR (books.user_id=?)) $latestfilter
ORDER BY book_chapters.added $sortorder";
$chaptersListUserId = (int) $id;
$chaptersListBookId = (int) $book_id;
$chaptersBindParams = array_merge(
$chapFilter3Params,
[
$chaptersListUserId, // book_subscription.user_id (EXISTS)
$chaptersListUserId, // abonements.user_id
$chaptersListUserId, // library.author_id
$chaptersListUserId, // chapter_likes.user_id
$chaptersListUserId, // fundraise_log.user_id
$chaptersListBookId, // book_chapters.book_id
$chaptersListUserId, // WHERE user filter
$chaptersListUserId, // books.user_id
]
);
$chaptersBindTypes = MysqliPrepared::paramTypes($chaptersBindParams);
$Result = MysqliPrepared::select($Link, $Query, $chaptersBindTypes, $chaptersBindParams);
if (!$Result) {
$log->error('Database query error in BookWithChapters: ' . mysqli_error($Link) . ' Query: ' . $Query);
return $renderError();
}
$processed_chapters = [];
while ($Row = mysqli_fetch_assoc($Result)) {
$cntpages = $Row['cntpages'];
$chapterHidden = (int) $Row['ishidden'] === 1;
$hasAuthorChapterAccess = BookWithChaptersCanAccessAuthorChapter($Row, (int) $id, (array) $z_admins);
$canManageDelayedChapter = book_with_chapters_can_manage_delayed_chapter($Row, (int) $id, (array) $z_admins);
if ($chapterHidden && !$hasAuthorChapterAccess) {
continue;
}
// echo $Row['id'];
if (isset($processed_chapters[$Row['id']])) {
continue; // Пропускаем уже обработанную главу
}
$processed_chapters[$Row['id']] = true;
if (!$canManageDelayedChapter) {
// прячем ещё не вышедшие главы
if ($Row['oktopub'] == 0) {
continue;
}
}
++$curr_fragment;
$liclass = 'wh0';
if ((($curr_fragment % 2) == 0) || ($chapter_id != 0)) {
$liclass = 'wh1';
}
$basePrice = (float) $Row['price'];
if ($basePrice >= 100 && $basePrice === (float) (int) $basePrice) {
$basePrice = $basePrice / 10.0;
}
if ($Row['discount'] > 0) {
$ChapterPrice = ($basePrice * (100 - $Row['discount'])) / 100;
} else {
$ChapterPrice = $basePrice;
}
$canaudio = ($Row['canzoom'] & 2) >> 1;
$ownaudio = $Row['ownaudio'];
$audioavail = $Row['mp3filename'];
$numpages = $Row['kb'];
++$cntbooks;
$title = $Row['title'];
$rid = $Row['id'];
$hiddenBadge = '';
if ($chapterHidden && $hasAuthorChapterAccess) {
$hiddenBadge = ' Скрыта';
}
$orig_rid = $rid;
if ($Row['version0_id']) {
$orig_rid = $Row['version0_id'];
}
$bwcChapterHref = book_with_chapters_lp('/' . ($menuitems[6] ?? 'books') . '/' . $book_id . '/' . $rid . '/') . '#page';
$bwcChapterEditHref = book_with_chapters_lp('/' . ($menuitems[1] ?? 'my') . '/' . ($submenu[5] ?? 'publish') . '/' . $book_id . '/' . $rid . '/#pub');
// Определяем ID для проверки аудио (используем orig_rid, так как аудио привязано к версии 0)
$check_audio_id = $orig_rid;
$nocomms = $Row['nocomms'];
$protection = $Row['protection'];
$edition = $Row['version'];
++$edition; // чтобы начиналось с 1
$isFinished = $Row['finished'];
if ($title == '') {
$title = 'Без названия';
}
$written_by = $Row['user_id'];
if ($Row['written_by'] > 0) {
$written_by = $Row['written_by'];
}
$title = $escapeChapterTitle($title);
$is_purchased = 0;
if (isset($purchased[$orig_rid])) {
$is_purchased = 1;
} else {
if ($Row['onabonement']) {
$is_purchased = 2;
}
}
// бесплатная книга
if ($Row['canzoom'] & 16) {
$is_purchased = 3;
}
$likes = '';
if ($nocomms == 0) {
$likes = LikesShow(
$likes_count[$orig_rid],
$dislikes_count[$orig_rid],
$orig_rid,
$written_by,
$is_purchased,
$ChapterPrice,
$Row['mark'],
$Row['finished'],
$Row['user_id'],
$Row['favorite'],
$id
);
}
$glavnum = '';
$hidechapter = '';
if (($Row['user_id'] == 4) && ($isFinished == 0)) {
$glavnum = "[#$cntbooks] ";
if ($chapter_id != 0) {
$real_cntno = 0;
$InnerQuery = 'SELECT /*069*/ id FROM book_chapters WHERE book_id=? AND added != 0 ORDER BY added ASC';
$InnerResult = MysqliPrepared::select($Link, $InnerQuery, 'i', [(int) $book_id]);
if (!$InnerResult) {
$log->error('Database query error in BookWithChapters: ' . mysqli_error($Link) . ' Query: ' . $InnerQuery);
return $renderError();
}
while ($InnerRow = mysqli_fetch_assoc($InnerResult)) {
++$real_cntno;
if ($InnerRow['id'] == $chapter_id) {
break;
}
}
mysqli_free_result($InnerResult);
$glavnum = "[#$real_cntno] ";
}
if (in_array($id, $z_admins, true)) {
$hidechapter = <<
END;
}
}
// Проверяем, есть ли аудио для этой главы
// Проверяем как по rid, так и по orig_rid, так как в audiobooks_chapters может быть любой из них
// Также проверяем все версии главы (version0_id)
$has_audio_icon = '';
if ($audiobook_exists && !empty($chapters_with_audio)) {
$has_audio = false;
// Проверяем текущий ID главы
if (isset($chapters_with_audio[$rid])) {
$has_audio = true;
}
// Проверяем оригинальный ID (версия 0)
if (!$has_audio && isset($chapters_with_audio[$orig_rid])) {
$has_audio = true;
}
// Если есть version0_id, проверяем и его
if (!$has_audio && !empty($Row['version0_id']) && isset($chapters_with_audio[(int) $Row['version0_id']])) {
$has_audio = true;
}
if ($has_audio) {
$has_audio_icon = <<
END;
}
}
$chapter_stats_link_html = '';
if ($hasAuthorChapterAccess) {
$chapter_stats_link_html = <<
END;
}
$og_btn_group = <<
$has_audio_icon
END;
$whoauthor = '';
if (($Row['user_id'] == 4) && (($isFinished == 1) || ($id == 4))) {
$urname2 = SeoAuthor($Row['u2r']);
$authorName = $escapeHtml($Row['u2r']);
$whoauthor = '' . $authorName . '. ';
}
$booktitle = $Row['name'];
$bookauthor = $Row['realname'];
$seoname = "-{$booktitle}-{$bookauthor}";
$seoname = str_replace(['.', '/', '\'', '"', '"', ''', '&', ' ', '«', '»'], ['', '', '', '', '', '', '', '_', '', ''], $seoname);
$seoname = rus2translit($seoname);
$chapter_locked = false;
$chapter_flags_html = '';
$buybtn = '';
if (!$goperation) {
// var_dump($ChapterPrice);
if (($id == $written_by) && ($id == $Row['user_id'])) {
$buybuttontitle = 'Автору бесплатно';
} else {
if ($not_purchased != '') {
$buybuttontitle = 'По порядку';
} else {
if (($Row['isauthor'] & 7) == 0) {
$buybuttontitle = 'Не продается';
} else {
if ($ChapterPrice == 0) {
$buybuttontitle = 'Бесплатно';
} else {
$buybuttontitle = "{$ChapterPrice} ₽";
}
}
}
if ($ChapterPrice == 0) {
} else {
if ($Row['favorite']) {
$buybuttontitle = 'Вам - бесплатно';
} else {
if (isset($purchased[$orig_rid])) {
$paid = $purchased[$orig_rid] - 1; // 1 чтобы отличить от 0
if ($paid > 0) {
$buybuttontitle = 'Уже куплена, читать';
} else {
$buybuttontitle = 'Беспл., уже открывали';
}
} else {
if ($Row['onabonement']) {
$buybuttontitle = 'Беспл., не открывали ещё';
} else {
if ($sequential == 1) {
$not_purchased = "$orig_rid";
}
}
}
}
}
}
$buybtn = <<
END;
if ($buybuttontitle != 'По порядку') {
$buybtn = <<
END;
}
$chapter_locked = ($ChapterPrice > 0)
&& ($is_purchased === 0)
&& empty($Row['favorite'])
&& empty($Row['onabonement']);
if ($buybuttontitle === 'По порядку' || $buybuttontitle === 'Не продается') {
$chapter_locked = true;
}
if (($Row['protection'] == 2) && ($Row['protectedview'] != 3)) {
$chapter_locked = true;
}
$chapter_flags = [];
if (isset($purchased[$orig_rid]) || ($chapter_id != 0 && $rid == $chapter_id)) {
$chapter_flags[] = '';
}
if (!empty($chapter_flags)) {
$chapter_flags_html = '' . implode('', $chapter_flags) . '';
}
$anyfrag = 'Вы можете купить любую часть, да хоть сразу из середины книги.';
if ($sequential == 1) {
$anyfrag = 'Писатель просит вас покупать части в этой книге по порядку. Таким образом, чтобы купить третью часть, вы перед этим должны купить второй.';
}
// SECURITY FIX: Исправлено условие отображения меню редактирования глав
// Меню должно отображаться если пользователь является автором книги ИЛИ автором главы (для конкурсных книг)
if ($canShowChapterAuthorMenu($Row)) { // меню автора: основной автор, соавторы, автор конкурсной главы или админ
if ($cntbooks == 1) {
// echo <<
//
// Все части книги для чтения онлайн:
//
$anyfrag Чтобы купить, нажмите на кнопку "Купить и читать" напротив заголовка части. Текст части откроется сразу же. Для удобства, в содержании книги ниже каждая вторая часть подкрашена серым цветом.
// $chapters_order
//
// END;
// echo <<
//
//
$anyfrag Чтобы купить, нажмите на кнопку "Купить и читать" напротив заголовка части. Текст части откроется сразу же.
ВНИМАНИЕ!!! Нажмите кнопку <Нужно защитить> для 'БОЛЬШОЙ' и 'ОБЫЧНОЙ' размеров страницы, иначе читатели не смогут читать эту главу!
Начните читать свою собственную главу и сделайте это прямо сейчас.
Если вы не хотите этого делать, отключите максимальную защиту - выберите базовую защиту в
'правке' книги по ссылке 'правка' под аннотацией - иначе ваши читатели не смогут читать книгу!
$chapter_flags_html $og_btn_group $buybtn
$hidechapter
END;
// Разрешаем переименование главы автору и админам даже у завершённой книги
if ($show_chapter_actions) {
echo <<
END;
}
// Удаление не расширяем на соавторов книги без отдельной бизнес-логики
if ($show_chapter_actions && $can_restricted_chapter_actions) {
$bname2 = str_replace('.', '', $Row['name']);
$SeoName = SeoBook($bname2);
echo <<
END;
}
// Кнопка редактирования текста главы только для автора (или соавтора) и админов
if ($show_chapter_actions && $canShowChapterAuthorMenu($Row)) {
echo <<
END;
}
if (($Row['protection'] != 2) && $can_override_protection) {
if ($Row['protect_override'] == 0) {
echo <<Вы уверены, что хотите принудительно выставить максимальную защиту с пятнами на эту главу, невзирая на общую защиту книги? Так делать не рекомендуется, т.к. читатели могут быть возмущены! Другие главы останутся в общей для книги защите.
Лучше защищать одинаковой защитой всю книгу, это выставляется по ссылке "правка" под аннотацией.
END;
} else {
echo <<
Принудительное назначение максимальной защиты на эту главу будет снято.
END;
switch ($Row['protectedview']) {
case 0:
echo <<<'END'
ВНИМАНИЕ: Вы должны защитить текст в обоих режимах просмотра: 15-строчном и 25-строчном.
END;
break;
case 1:
echo <<<'END'
ВНИМАНИЕ: Вы должны защитить текст в обоих режимах просмотра: 15-строчном и 25-строчном. Осталось защитить в 25-строчном режиме.
END;
break;
case 2:
echo <<<'END'
ВНИМАНИЕ: Вы должны защитить текст в обоих режимах просмотра: 15-строчном и 25-строчном. Осталось защитить в 15-строчном режиме.
END;
if ($canChangeChapterDelay) {
echo <<
Часть "$title" запланирован к публикации:
Чтобы выложить главу прямо сейчас, рекомендуется поставить время на ближайший новый час, тогда будут отправлены уведомления читателям. После достижения указанного времени нельзя будет повторно менять дату выхода.
END;
}
}
} else {
$bname2 = str_replace('.', '', $Row['name']);
if ($cntbooks == 1) {
$urname2 = SeoAuthor($Row['realname']);
$gseriesname2 = str_replace('.', '', $gseriesname);
// TODO - тут нет завязки на $Row[price], вместо это константа 10 !!!
if ($Row['discount'] > 0) {
$ChapterPr = (10 * (100 - $Row['discount'])) / 100;
} else {
$ChapterPr = 10;
}
// echo <<
//
$Row[realname] предоставил бесплатный доступ без регистрации к началу книги $bname2 (серия: $gseriesname2).
// END;
echo <<
Порядок частей
Первая часть доступна бесплатно, продолжение можно открыть по подписке или покупкой следующей части.
$chapters_order
END;
// echo <<регистрация) бесплатно, чтобы получать уведомления о новинках книг, продолжениях, оставлять комментарии о книгах и ставить оценки после прочтения каждой главы, а также общаться на литературном форуме. Все книги $Row[realname] доступны после бесплатной регистрации.
Вступите в наш книжный клуб. Бесплатная регистрация позволит читать онлайн новые главы в книге $bname2. Достаточно указать e-mail, на который придет пароль. Если вы зарегистрируетесь со страницы автора - он получит бонусы.
// ";
//
ВНИМАНИЕ: письма на микрософтовские ящики (msn.com, live.com, hotmail.com, outlook.com) могут временно
// не доходить, проблема началась с 27 февраля и решается. По возможности регистрируйтесь на другие ящики.
$chapt_desc";
if (($Row['protection'] == 2) || ($Row['protect_override'])) {
echo <<<'END'
END;
}
// для одного из режима просмотра нет защищённого представления, не показываем эту главу
if (($Row['protection'] == 2) && ($Row['protectedview'] != 3)) {
$lockIcon = $chapter_locked
? "{$lock_hint}"
: '';
echo <<$title{$lockIcon}
';
if ($remainingComments > 0) {
$btnTitle = "Показать ещё ($remainingComments)";
$loadChapterCommentsNonce = htmlspecialchars(create_nonce('load_chapter_comments'), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
echo <<$btnTitle
END;
}
$leave_comment = '';
$doban = 0;
if (($isbanned != null) && ($isbanned != '')) {
$doban = 1;
if ($userro != 3) {
$leave_comment = <<';
if ($nocomms == 0) {
// фикс - при отрисовке страницы сразу нажимаем back в списке отзывов, чтобы они норм. отображались
if ($fbcomms[$rid] > 0) {
$initjscomms .= '(function(){'
. "if(typeof sf==='function'){sf($rid);return;}"
. "if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',function(){if(typeof sf==='function'){sf($rid);}});}else{setTimeout(function(){if(typeof sf==='function'){sf($rid);}},100);}"
. '})();';
}
}
}
}
mysqli_free_result($Result);
// обновим счетчик страниц у книги
if ($chapter_id == 0) {
if (($cntpages != -1000) && ($cntpages != $cnt_totalpages)) {
$cmd = 'UPDATE /*736*/ books SET cntpages=?, glav=?, updated=updated WHERE id=?';
$Result = MysqliPrepared::exec($MasterLink, $cmd, 'iii', [(int) $cnt_totalpages, (int) $cnt_totalglav, (int) $book_id]);
if (!$Result) {
$log->error('Database query error in BookWithChapters: ' . mysqli_error($MasterLink) . ' Query: ' . $cmd);
return $renderError();
}
}
}
echo '';
if ($cntbooks == 0) {
if ($chapter_id == 0) { // показаны все главы в книге
echo '
Смотрите рейтинг лучших книг Целлюлозы
Искомой книги не найдено, но есть другие отличные книги!
Мы не нашли того, что вы искали. Возможно, у нас искомой книги не было вообще. Однако, мы хотим вам предоложить
посмотреть эти лучшие книги по количеству читателей. Их читают действительно очень много людей, и вам они, несомненно, понравятся!
';
// извлечение из кэша, который обновляется раз в минуту
$Query = 'SELECT /*507*/ text FROM bookscache WHERE no=1';
$Result = MysqliPrepared::select($Link, $Query, '', []);
if (!$Result) {
$log->error('Database query error in BookWithChapters: ' . mysqli_error($Link) . ' Query: ' . $Query);
return $renderError();
}
while ($Row = mysqli_fetch_assoc($Result)) {
echo $Row['text'];
}
mysqli_free_result($Result);
}
} else {
if (($chapter_id == 0) || (in_array($id, $z_admins, true))) {// показаны все главы в книге
if (($isFinished == 0)) {
echo <<
Читать продолжение книги.
Добавьте книгу в избранное (отметить красную звездочку рядом с обложкой).
Добавить автора, чтобы узнавать о новых книгах можно аналогично (звездочка на странице автора).
Уведомления направляются на электронную почту, если Вы сами ее раньше не прочитаете.
Вы можете получать уведомления через Telegram. Напишите боту @ZellulozaBot (команда /followbook $book_id).
END;
}
// ------------------ рецензии ------------------------
if (!$goperation) {
if ($nocomms == 0) {
echo <<<'END'
END;
if ($id > 0) {
// нельзя писать рецензии с маленькой кармой
if ($userkarma < 10) {
$gamification_url = book_with_chapters_lp('/user_checklist/');
$gamification_link = 'памятку о геймификации';
echo <<
Вам нужно не менее 10 единиц репутации, чтобы публиковать рецензии на книги. См. {$gamification_link}.
Постарайтесь беспристрастно оценить книгу целиком: оригинальность сюжета, логичность, продуманность
сюжетных линий, насколько реалистично выведены характеры героев и последовательны их поступки. За каждую рецензию дается 1 дополнительное место в черном списке. Если рецензия не будет содержать смысла,
она будет удалена и черный список сократится на 1 элемент.
';
}
// BUG-075: показывать блок рекомендаций только если есть контент (ReadAlso возвращает не пусто)
$readAlsoHtml = ReadAlso($book_id);
if ($readAlsoHtml !== '') {
echo '
Это копилка для озвучки бесплатной главы, в неё не требуются взносы. Копилка нужна в качестве
//заявки для диктора на озвучку этой части.
";
} else {
if ($book_author == 4) {
echo '
В эту копилку не требуется вносить деньги, поскольку это глава конкурсной книги, которую Целлюлоза озвучивает за счет собственных средств.';
} else {
echo "
Ваш взнос в эту копилку (10 ) даст вам право слушать аудиофрагмент, когда он будет озвучен.
Цена аудиофайла для тех, кто не участвовал в копилке, составит 15 . Покупка аудиофрагмента не дает право читать текст: текст покупается отдельно.
";
}
}
echo $audioraise;
} else {
$numrequests = (int) ($numpages * 1.5);
$isfree = '';
if ($ChapterPrice == 0) {
$isfree = 'Это бесплатная глава. Для озвучки просто создайте копилку.';
} else {
if ($book_author == 4) {
$isfree = 'Это конкурсная глава, озвучка для неё бесплатна.';
} else {
$isfree = "Для озвучки требуется: $numrequests заявок от читателей.";
}
}
$selfAudioOwnHref = htmlspecialchars(book_with_chapters_lp('/' . ($menuitems[15] ?? 'my') . '/audio/' . $orig_id . '/own'), ENT_QUOTES, 'UTF-8');
$dictorAudioHref = htmlspecialchars(book_with_chapters_lp('/' . ($menuitems[15] ?? 'my') . '/audio/' . $orig_id . '/'), ENT_QUOTES, 'UTF-8');
$raiseHref = htmlspecialchars(book_with_chapters_lp('/books/' . $book_id . '/' . $chapter_id . '/') . '#raise', ENT_QUOTES, 'UTF-8');
$selfaudio = 'Попросите писателя загрузить озвучку.';
if ($book_author == $id) {
$selfaudio = 'Создать копилку для авторской озвучки';
}
$createbydictor = '';
//if($book_author != $id)
if (0) {
$createbydictor = <<
1. Озвучка профессиональным диктором, на которого мы соберем деньги через копилку.
Тогда создайте копилку на озвучивание части, и при достижении нужной суммы задание на озвучку
передается диктору. Потом здесь появится аудио версия этой главы.
$isfree Создать копилку для озвучки диктором
2.
END;
}
echo <<
Запросить или залить озвучку для этой части
$createbydictor
Озвучка загружается писателем самостоятельно, если она у него уже есть. Копилка в этом случае
собирает деньги самому писателю, чтобы он выложил свою аудиоверсию. Участвующие в копилке получат
аудио версию за 10 , а потом цена аудио будет уже 15 . $selfaudio
Озвучка временно недоступна. Писатель запретил создавать аудио версии этой книги. Чтобы разрешить, писателю нужно включить
соответствующую галочку "Аудио Книга" по ссылке "правка" для обложки книги.
END;
}
} // audio avail == 0
}
$tojs = '';
foreach ($fbcomms as $fbc => $val) {
$tojs .= "$fbc:$val|";
}
$tolenta = '';
if (($protection == 3) && (($usersettings & 4096) >> 12)) { // 13 бит
$tolenta = "(function f(){if(typeof tolux==='function'){tolux($chapter_id);return;}
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',f);else setTimeout(f,50);})();";
}
echo <<
if (typeof Initfbcomms === 'function') {
Initfbcomms('$tojs');
} else {
// Ждём загрузки site.js
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
if (typeof Initfbcomms === 'function') {
Initfbcomms('$tojs');
}
});
} else {
// DOM уже загружен, но скрипт может быть ещё не загружен
setTimeout(function() {
if (typeof Initfbcomms === 'function') {
Initfbcomms('$tojs');
}
}, 100);
}
}
$initjscomms
$tolenta
END;
}
}
Лев Николаевич Толстой Андроид Каренина, Глава 18 (№13373510) читать онлайн - Целлюлоза.ру
Постойте, не пролистывайте! Вы только что закончили чтение фрагмента Глава 18. Поделитесь впечатлениями: каково оно? Понравилось, не понравилось, как вам текст?
Неправильно написанное слово/фраза (напишите точно так же):
А как правильно?
Почему так (до 128 букв; это комментарий для автора, пояснение вашей правки):
Войдите на сайт, чтобы предложить правку
Читать можно и без аккаунта. Войдите или зарегистрируйтесь, чтобы сохранять прогресс и закладки.