Архив рубрики «Про сайт»

Давно хотел сделать на сайте такую штуку – календарь года (текущего и каждого из прошлых), в котором с каждой даты ссылка ведёт на подборку соответствующих постов в блоге (если в тот день что-то было опубликовано) – то есть, «календарь года как в ЖЖ». В ЖЖ такой календарь существовал и был очень удобен в качестве одного из способов поиска старых записей и/или анализа активности блога (своего или чужого). А вот, например, в WordPress такого календаря нет и, если я правильно помню, не было никогда (ну или был настолько давно, что я уже полностью забыл о его существовании) – есть только аналогичный календарь по месяцам, что совсем неудобно для большинства видов поиска и анализа.
На реализацию такой штуки своими силами нужно было некоторое количество свободного времени – и я наконец-то его нашёл! Что ещё более важно и интересно, это время я потратил не зря: сделать календарь-архив у меня получилось. Работающий пример можно посмотреть по ссылке, а в данном посте я перечислю словами все характеристики и приведу базовые PHP и CSS коды.
Характеристики моего годового календаря блога для WordPress:
– полный календарь года (видны все 12 месяцев, какая бы дата ни была на дворе на момент просмотра);
– возможность просматривать прошлые годы (но не ранее, чем год самой первой публичной записи в блоге);
– дни с публичными записями автоматически превращаются в ссылки на соответствующие даты в архиве записей;
– при наведении курсора на день ссылку всплывает подсказка с числом записей за соответствующую дату;
– в календарях за прошлые годы дата просмотра («сегодняшняя») выделяется заметной рамкой;
– у ячеек с датами, в которые была опубликована хотя бы одна запись, меняется фоновый цвет;
– у календаря – адаптивный дизайн: на больших и средних экранах показывается сетка 3×4 месяца, а на маленьких экранах месяцы года выстроены в столбик;
– запросы к базе данных оптимизированы таким образом, чтобы календарь не «тормозил» даже в блогах с десятками тысяч записей.
Ну а теперь – сами коды календаря (надеюсь, вы прочитали весь текст выше – он может вам помочь сориентироваться).
PHP-код, который можно испытывать прямо в таком виде – его легко вставить в свой макет страницы обыкновенным копипастом:

<?php
global $wpdb;


/* ======================================
   1. PRIMO ANNO DEL BLOG
====================================== */
$first_post_date = $wpdb->get_var("
SELECT post_date
FROM $wpdb->posts
WHERE post_status='publish'
AND post_type='post'
ORDER BY post_date ASC
LIMIT 1
");

$first_year = date('Y', strtotime($first_post_date));
$current_year = date('Y');
$year = isset($_GET['yr']) ? intval($_GET['yr']) : $current_year;

if ($year < $first_year) $year = $first_year;
if ($year > $current_year) $year = $current_year;


/* ======================================
   2. DATE DEI POST (QUERY SQL OTTIMIZZATA + CACHE)
====================================== */
$cache_key = 'calendar_'.$year;
$post_dates = get_transient($cache_key);
if ($post_dates === false){
	$post_dates = [];
	$results = $wpdb->get_results($wpdb->prepare("
	SELECT DATE(post_date) as post_day, COUNT(ID) as total
	FROM $wpdb->posts
	WHERE post_status='publish'
	AND post_type='post'
	AND YEAR(post_date)=%d
	GROUP BY post_day
	", $year));
	foreach ($results as $row){
		$post_dates[$row->post_day] = $row->total;
	}
	set_transient($cache_key,$post_dates,12*HOUR_IN_SECONDS);
	}


/* ======================================
   3. NAVIGAZIONE CON TUTTI GLI ANNI
====================================== */
echo '<div class="calendar-nav">';
for ($y=$first_year; $y<=$current_year; $y++){
	if ($y==$year){
		echo '<span class="current-year">'.$y.'</span>';
	}else{
		echo '<a href="?yr='.$y.'">'.$y.'</a> ';
	}
}
echo '</div>';


/* ======================================
   4. CONTROLLO "OGGI NEGLI ANNI PASSATI"
====================================== */
$today_month = date('m');
$today_day = date('d');
$today_key = $year.'-'.$today_month.'-'.$today_day;
$today_has_posts = isset($post_dates[$today_key]);


/* ======================================
   5. CONTENITORE ANNO
====================================== */
echo '<div class="calendar-year">';


/* ======================================
   6. CICLO MESI
====================================== */
for ($month=1; $month<=12; $month++) {
	echo '<div class="calendar-month-block">';
	$month_name = date_i18n('F', mktime(0,0,0,$month,1,$year));
	$month_has_posts = false;
	foreach ($post_dates as $date => $count){
		if (strpos($date,$year.'-'.sprintf('%02d',$month))===0){
			$month_has_posts = true;
			break;
		}
	}

/* titolo mese */
if ($month_has_posts){
	echo '<h3 class="month-title">
	<a href="'.get_month_link($year,$month).'">'.$month_name.'</a>
	</h3>';
	}else{
	echo '<h2 class="month-title">'.$month_name.'</h2>';
	}


/* ======================================
   7. TABELLA CALENDARIO
====================================== */
echo '<table class="calendar-month">';
echo '<thead><tr>';
$weekdays = ['L','M','M','G','V','S','D']; //da cambiare per le lingue diverse da quella italiana
foreach ($weekdays as $w){
	echo '<th>'.$w.'</th>';
	}
echo '</tr></thead>';
echo '<tbody><tr>';

/* primo giorno mese */
$first_day = date('N', strtotime("$year-$month-01"));
for ($i=1;$i<$first_day;$i++){
	echo '<td class="empty"></td>';
	}
$days = cal_days_in_month(CAL_GREGORIAN,$month,$year);
$weekday = $first_day;


/* ======================================
   8. CICLO GIORNI
====================================== */
for ($day=1;$day<=$days;$day++){
	$date = $year.'-'.sprintf('%02d',$month).'-'.sprintf('%02d',$day);
	$is_today_past = false;
	/* controllo "oggi negli anni passati" */
	if ($year < $current_year && $month==$today_month && $day==$today_day){
		$is_today_past = true;
	}
	$classes = [];
	if ($is_today_past) $classes[] = 'today-past';
	if (isset($post_dates[$date])){
		$classes[] = 'has-posts';
	} else {
		$classes[] = 'no-posts';
	}
	echo '<td class="'.implode(' ', $classes).'">';
	if (isset($post_dates[$date])){
		$count = $post_dates[$date];
		$title = ($count==1) ? '1 articolo' : $count.' articoli';
		echo '<a class="day-link" href="'.get_day_link($year,$month,$day).'" title="'.$title.'">'.$day.'</a>';
	}else{
		echo '<span class="day-number">'.$day.'</span>';
	}
	echo '</td>';
	if ($weekday==7){
		echo '</tr><tr>';
		$weekday=1;
	}else{
		$weekday++;
	}
	}

/* celle finali */
while ($weekday<=7){
	echo '<td class="empty"></td>';
	$weekday++;
	}
echo '</tr></tbody></table>';
echo '</div>';
}

echo '</div>';
?>

CSS-код визуализации календаря – скопируйте его в файл style.css вашей темы или подключите отдельно:

/* ===== navigazione anni ===== */
.calendar-nav{
	text-align:center;
	margin:40px 0;
	font-size:22px;
	line-height:2;
}
.calendar-nav a{
	margin:0 10px;
	text-decoration:none;
}
.current-year{
	font-weight:bold;
	margin:0 15px;
}
/* ===== layout mesi ===== */
.calendar-year{ display:block; }
.calendar-month-block{ margin-bottom:40px; }
/* ===== titolo mese ===== */
.month-title{
	text-align:center;
	margin-bottom:10px;
}
/* ===== tabella ===== */
.calendar-month{
	width:100%;
	border-collapse:collapse;
}
.calendar-month th{
	padding:5px;
	text-align:center;
	font-weight:bold;
}
.calendar-month td{
	padding:0;
	height:32px;
	text-align:center;
}
/* ===== giorni ===== */
.day-number{
	display:block;
	padding:6px;
}
/* celle con articoli */
.calendar-month td.has-posts{ background:#C5C5C5; }
/* link riempie tutta la cella */
.day-link{
	display:block;
	width:100%;
	height:100%;
	padding:6px;
	text-decoration:none;
	font-weight:bold;
	background:transparent; /* IMPORTANTISSIMO */
}
/* celle senza articoli */
.calendar-month td.no-posts{ background:#FFFFFF; }
/* numeri non linkati */
.day-number{
	display:block;
	padding:6px;
	background:#FFFFFF; /* garantisce bianco pieno */
}
.today-past{ outline:2px dashed #FF9800; }
/* hover */
.day-link:hover{ background:#C5C5C5; }
/* celle vuote */
.empty{ background:#FFFFFF; }
/* ===== layout desktop ===== */
@media (min-width:1024px){
.calendar-year{
	display:grid;
	grid-template-columns:repeat(3,1fr);
	gap:30px;
	align-items:start;
}
.calendar-month-block{ margin-bottom:0; }
}

В таком виде, с таким функционалом – это именно тот календарь блога, который мне был нужен. Что к нему можно или нужно добавить – даже и не знаю. Если придумаю (или кто-то подскажет) – выпущу вторую версию и о ней сообщу.


Один хороший человек недавно прислал ссылку на партию аудио-файлов, которых недоставало в моём архиве исторических передач «Эха Москвы». И вот у меня дошли руки систематизировать этот ценнейший подарок: удалить несколько повторов, привести названия файлов к моему «архивному» стандарту и залить всё на сервер вместе с обновлённым xml-файлом.
И вот теперь я могу официально объявить, что и архив эховской передачи «Цена революции» выложен у меня на сайте почти полностью!
Так что если вы – любитель той передачи и уже давно ожидали вышеуказанного обновления, заходите и слушайте с новой силой.
Правда, приславший недостающие файлы человек был уверен, что высылает мне записи передачи «Цена победы», но и во времена выхода двух передач на радио иногда происходила некоторая организационная путаница, так что не стоит предъявлять какие-то претензии…
А если у вас сохранились архивные файлы, пригодные для публикации – можете и поделиться ими со мной…


Наконец-то собрался обновить страницу с так называемыми «пустыми темами» (blank themes) для WordPress. У меня на той странице уже много лет лежало шесть тем – или корректнее называть их макетами? – которые на сегодняшний день можно назвать настоящим веб-антиквариатом: они были технически актуальны до WordPress 4.9.xx.
Теперь же эти макеты доступны и в полностью переделанном мною виде: с точки зрения кода, внутренней архитектуры и самого набора файлов.

В общем, пользуйтесь, если вам такое нужно и полезно.


Земной свой путь пройдя до половины, я создал свою первую краудфандинговую кампанию на Indiegogo. Не знаю ещё, что может из этого получиться, но не попробовав – никогда бы и не узнал, да?
Но пойдём по порядку…
Если этот пост – не первое, что вы читаете на моём сайте, то уже, скорее всего, знаете, что на этом же сайте уже давно существует несколько бесплатных и безлимитных инструментов для транслитерации в латиницу – романизации – некоторых не латинских алфавитов (армянский, белорусский, болгарский, греческий, грузинский, киргизский, македонский, русский и украинский). Некоторые из этих моих транслитеров – относительно популярны среди пользователей, некоторые другие – совсем нет. Но каждый из этих инструментов сделан с одинаковым вниманием к деталям и с одной и той же целью: создать полезный, точный и, в то же время, простой в использовании инструмент, который мог бы производить транслитерацию (романизацию) «своего» алфавита следуя любой из существующих систем правил. Думаю, с только что обозначенной задачей я справился – хотя и продолжаю надеяться на дельные замечания от специалистов.
Сейчас же я решил, что пришёл момент добавить к моим уже существующим транслитерам ещё один: транслитер еврейского алфавита. Конечно же, в основе этой моей идеи остаётся всё тот же технический принцип: транслитерация еврейского алфавита должна быть возможна по правилам любой из существующих систем (не важно, действующих и на сегодняшний день или нет). Я уже теоретически понимаю, как создать такой инструмент, и даже собрал для работы над ним весь необходимый научный материал. Я уже готов приступить к работе, но…
Чтобы хорошо сделать подобную работу – довольно нудную, объёмную и требующую внимания к большому числу мелких деталей (можете, например, поинтересоваться у специалистов, сколько существует способов обозначения гласных…) – мне необходимо освободить немалое количество рабочего времени: того времени, в течение которого я не буду отвлекаться на оплачиваемые профессиональные задачи. Вот почему я запустил краудфандинговую кампанию на Indiegogo. Перейдя по ссылке, вы сможете прочитать о технических особенностях задуманного мною продукта и поучаствовать – если у вас есть на это желание и финансовые возможности – в сборе средств на создание моего транслитера еврейского алфавита. Сразу предупрежу, что все участники сбора средств не только получат гарантированно бесплатный и качественный инструмент, но и смогут получить (при желании) рекламное пространство на странице инструмента или на любой другой странице моего сайта.
Если моё предложение вас заинтересовало – участвуйте в кампании на Indiegogo. И / или расскажите о ней тем, кого она может заинтересовать: мне было бы очень приятно, если бы всё получилось.

P.S.: все те, кто хочет поддержать финансово какие-то другие части моего сайта (или вообще весь сайт целиком), могут сделать это в любой удобный момент одним из способов, перечисленных на специальной странице.


Что-то давно у меня на сайте библиотека электронных книг не пополнялась.
Но вот залил, наконец-то, книги троих новых авторов:
– Джонатан Свифт (7 книг),
– Иван Тургенев (31 книга, 5 из них – пьесы),
– Уильям Шекспир (18 пьес).
Все доступные теперь для скачивания файлы ходили по интернету в очень плохом состоянии, но я, по традиции, привёл их немного в порядок. И, тоже по традиции, опубликовал в трёх форматах: fb2, epub и mobi.
Продолжение воспоследует – как только найду время обработать новые книги.
А стоит ли публиковать их и в каких-то ещё форматах – я до сих пор не понял.


Уже несколько лет собирался это сделать, но каждый раз вспоминал об этой «идее» ближе к концу зимнего праздничного периода. В этом же году организоваться решил заранее и «ёлочную» функцию написал ещё в середине января. И вот, теперь стоит (если читаете с экрана средних или больших размеров – посмотрите в правый верхний угол):

Осталось придумать, как под неё класть подарки… Но не могу же я взять, и сделать всё сразу! Как только придумаю – сообщу отдельным постом.


Или как это там говорится?.. В общем, одним из последних «тормозов», которые ещё не освоили криптокошельки, был я. Но больше таковым не являюсь вот уже несколько дней: я наконец-то разобрался со всем минимально необходимым функционалом Binance! (Нет, большие суммы через санкционный барьер мне переводить необходимости не было и нет, а маленькие или средние легко доставляются другими способами; играть на крипто-биржах я тоже не собираюсь.)
А с Бинансом на самом деле всё гораздо проще, чем кажется некоторым моим не сильно компьютеризованным (или просто пожилым) друзьям, знакомым и родственникам. За примерно месяц ленивого вечернего ковыряния в многочисленных меню я почти всё понял, а оставшиеся детали прояснил при помощи ИИ. Мог бы, конечно, сделать наоборот, но для получения именно понимания (а не информации) важно сначала поработать собственной головой, без подсказок  из конца учебника.
Единственной процедурой, заставившей меня вспомнить много нехороших слов, оказалась начальная верификация личности. Но, к счастью, моё упорство и разнообразие опций помогли преодолеть даже неспособность сайта с первого раза поверить в существование моего физического адреса (и прочитать его в документах).
Если получилось у меня, то и у вас получится. Не давайте любителям простых и/или преступных решений ограничивать себя в перемещении средств по миру.
P.S.: одного только я так и не понял на Binance. Почему он не даёт скопировать QR-коды с адресами кошельков? Ведь для сбора донатов (популярнейшая в интернете тема) они часто очень полезны. Так что приходится генерировать самому через сторонние сервисы. Для биткоинов получается вот такое:

А для, например, USDT (TRC 20) вот такое:

В остальном же Binance – нормальный инструмент, можно пользоваться.


Что-то давно у меня на сайте библиотека электронных книг не пополнялась.
Но вот залил, наконец-то, книги четырёх новых авторов:
–  Леонид Андреев (собрание сочинений в 6 томах),
–  Козьма Прутков (три сборника разных видов текстов),
–  Иван Путилин (на само деле, единственная его опубликованная книга),
–  Даниил Хармс (собрание сочинений и сборник прозы.
Все доступные теперь для скачивания файлы ходили по интернету в очень плохом состоянии, но я, по традиции, привёл их немного в порядок. И, тоже по традиции, опубликовал в трёх форматах: fb2, epub и mobi.
Продолжение воспоследует – как только найду время обработать новые книги.
А стоит ли публиковать их и в каких-то ещё форматах – я до сих пор не понял.


Сегодня могу, наконец-то, сообщить всем заинтересованным, что на моём сайте появился транслитер киргизского алфавита. Как вы знаете – или как можете легко догадаться – имеется в виду инструмент, при помощи которого можно в один щелчок мышью конвертировать киргизские кириллические буквы в латиницу. В конкретном случае моего инструмента, транслитерация – или, если предпочитаете, романизация – киргизского алфавита может производиться по правилам любой из 7 существующих систем (официальных и неофициальных). Также, присутствует функция обратной транслитерации.
Тестируйте и рекламируйте среди людей, которым этот инструмент может оказаться полезным. И, конечно же, сообщайте мне о замеченных недостатках и ошибках. Надеюсь, что этот транслитер пригодится хотя бы одному жителю нашей планеты.

О других новых готовых транслитерах буду сообщать отдельными постами по мере поступления.
Самые заинтересованные пользователи могут написать мне, в транслитере какого алфавита они нуждаются в первую очередь.


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

Если и вам случится заметить на сайте какие-нибудь неточности и/или баги – сообщайте мне о них: любые ваши замечания могут сильно упростить жизнь не только мне одному.