Изучаем WordPress

Загрузка WordPress

Делаем общую CSS для всех тем

Так как мы делаем свой, уникальный сайт, то будем делать и свой стиль. Чтобы не настраивать его каждый раз при тестировании новой темы (шаблона) мы сделаем в корне папку /kids/css, куда и будем загружать некоторые элементы стилей, которые мы бы хтели иметь независимо от шаблона, например, цвет заголовков и т.п. После этого, нам нужно для каждого шаблона, с которым мы экспериментируем, в файле header.php добавить перед тегом </head>строчку:

		<link rel="stylesheet" href="http://radiokidsfm/kids/css/site.css" type="text/css" media="screen, projection" />
		
	

Начинаем с разбора файловой структуры

После распаковки архива WordPress имеем следующий набор папок и файлов

Файловая структура WordPress

Все элементы, кроме выделенных красными прямоугольниками, составляют ЯДРО WP.


Первым загружается файл index.php. Вот его код:

							
<?php
	define('WP_USE_THEMES', true);

	/** Loads the WordPress Environment and Template */
	require( dirname( __FILE__ ) . '/wp-blog-header.php' );
							
						

Здесь определена переменная системы WP_USE_THEMES. Таблицу переменных системы составляем здесь. Затем загружается файл wp-blog-header.php.Вот его код:

							
<?php

 if ( !isset($wp_did_header) ) {

	$wp_did_header = true;

	// Load the WordPress library.
	require_once( dirname(__FILE__) . '/wp-load.php' );

	// Set up the WordPress query.
	wp();

	// Load the theme template.
	require_once( ABSPATH . WPINC . '/template-loader.php' );

}
							
						

Если файл wp-blog-header.php ещё не загружался (переменная-флажок $wp_did_header равна false), то загружаем библиотеку wp-load.php. Затем выполняем функцию wp - запуск WordPress. И. наконец, звгружаем шаблон wp-includes/template-loader.php.

Ниже приведена схема подключения (загрузки) файлов и выполнения функций внутри файла wp-blog-header.php.

			wp-blog-header.php
├── wp-load.php
│   ├── wp-config.php
│       ├── define DB params
│       └── wp-settings.php
│           ├── wp-includes/load.php
│           ├── wp-includes/default-constants.php
│           ├── wp-includes/version.php
│           ├── ... выполнение ряда wp-функций
│           ├── wp-includes/compat.php
│           ├── wp-includes/functions.php
│           ├── wp-includes/class-wp.php
│           ├── wp-includes/class-wp-error.php
│           ├── wp-includes/plugin.php
│           ├── wp-includes/pomo/mo.php
│           ├── ... выполнение ряда wp-функций
│           ├── wp-includes/default-filters.php
│           ├── wp-includes/ms-blogs.php
│           ├── wp-includes/ms-settings.php
│           ├── wp-includes/l10n.php
│       // Load most of WordPress.
│           ├── wp-includes/class-wp-walker.php
│           ├── wp-includes/class-wp-ajax-response.php
│           ├── wp-includes/formatting.php
│           ├── . . . . . .
│           ├── wp-includes/rest-api/class-wp-rest-server.php
│           ├── wp-includes/rest-api/class-wp-rest-response.php
│           ├── wp-includes/rest-api/class-wp-rest-request.php
│       // Load multisite-specific files.
│           ├── wp-includes/ms-functions.php
│           ├── wp-includes/ms-default-filters.php
│           ├── wp-includes/ms-deprecated.php
│       // Load must-use plugins.
│           ├── $mu_plugin
│       // Load network activated plugins. 
│           ├── $network_plugin
│           ├── ... выполнение ряда wp-функций
│       // Create common globals. 
│           ├── wp-includes/vars.php
│       // Load active plugins. 
│           ├── include_once( $plugin );
│       // Load pluggable functions. 
│           ├── wp-includes/pluggable.php
│           ├── wp-includes/pluggable-deprecated.php
│           ├── ... выполнение ряда wp-функций
│       // Fires before the theme is loaded. 
│           ├── do_action( 'setup_theme' );
│       // Define the template related constants. 
│           ├── wp_templating_constants(  );
│       // Load the default text localization domain. 
│           ├── require( $locale_file );
│           ├── wp-includes/locale.php
│       // Load the functions for the active theme, for both parent and child theme if applicable. 
│           ├── STYLESHEETPATH . '/functions.php
│           ├── TEMPLATEPATH . '/functions.php
│       // Fires after the theme is loaded. 
│           ├── do_action( 'after_setup_theme' );
│       // Set up current user. 
│           ├── $GLOBALS['wp']->init();
│       // Most of WP is loaded at this stage, and the user is authenticated. WP continues. 
│           ├── do_action( 'init' );
│       // Check site status. 
│           ├── require( $file );
│       // This hook is fired once WP, all plugins, and the theme are fully loaded and instantiated. 
│           ├── do_action( 'wp_loaded' );
├── wp()
│
└── wp-includes/template-loader.php
		├── . . .
		└── . . .
            
        

Загрузка констант, глобальных переменных и функций

Разбираем далее по шагам. Вот первая часть кода файла '/wp-load.php'

							
<?php

/** Define ABSPATH as this file's directory */
define( 'ABSPATH', dirname(__FILE__) . '/' );

error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR );

 *
 * If neither set of conditions is true, initiate loading the setup process.
 */
if ( file_exists( ABSPATH . 'wp-config.php') ) {

	/** The config file resides in ABSPATH */
	require_once( ABSPATH . 'wp-config.php' );

} elseif ( @file_exists( dirname( ABSPATH ) . '/wp-config.php' ) && ! @file_exists( dirname( ABSPATH ) . '/wp-settings.php' ) ) {

	/** The config file resides one level above ABSPATH but is not part of another install */
	require_once( dirname( ABSPATH ) . '/wp-config.php' );

} else {. . .}
							
						

Здесь определена переменная системы ABSPATH - абсолютный путь к корню системы. (Все переменные здесь).
Выполняем PHP-функцию вычисления уровня ошибок error_reporting
Далее ищем файл wp-config.php или в корне сайта, или на уровень выше.

Пояснение

ABSPATH . 'wp-config.php' - это следующий путь:
C:\OpenServer\domains\radiokidsfm/wp-config.php
dirname( ABSPATH ) . '/wp-config.php' - это другой путь на уровень выше:
C:\OpenServer\domains/wp-config.php

В нашем случае файл wp-config.php находится по первому адресу и он загружается.

Посмотрим, что там?

							
<?php
/**
 * Основные параметры WordPress.
 *
 * Скрипт для создания wp-config.php использует этот файл в процессе
 * установки. Необязательно использовать веб-интерфейс, можно
 * скопировать файл в "wp-config.php" и заполнить значения вручную.
 *
 * Этот файл содержит следующие параметры:
 *
 * * Настройки MySQL
 * * Секретные ключи
 * * Префикс таблиц базы данных
 * * ABSPATH
 *
 * @link https://codex.wordpress.org/Editing_wp-config.php
 *
 * @package WordPress
 */

// ** Параметры MySQL: Эту информацию можно получить у вашего хостинг-провайдера ** //
/** Имя базы данных для WordPress */
define('DB_NAME', 'radiokidsfm');

/** Имя пользователя MySQL */
define('DB_USER', 'root');

/** Пароль к базе данных MySQL */
define('DB_PASSWORD', '');

/** Имя сервера MySQL */
define('DB_HOST', 'localhost');

/** Кодировка базы данных для создания таблиц. */
define('DB_CHARSET', 'utf8');

/** Схема сопоставления. Не меняйте, если не уверены. */
define('DB_COLLATE', '');

/**#@+
 * Уникальные ключи и соли для аутентификации.
 *
 * Смените значение каждой константы на уникальную фразу.
 * Можно сгенерировать их с помощью {@link https://api.wordpress.org/secret-key/1.1/salt/ сервиса ключей на WordPress.org}
 * Можно изменить их, чтобы сделать существующие файлы cookies недействительными. Пользователям потребуется авторизоваться снова.
 *
 * @since 2.6.0
 */
define('AUTH_KEY',         'SPa$6_G^Q9Z?rjVSM6o*R!L_h:Pq(v}p^jGu~!aakq,AjG4zL}]>cQL^]i6T})e2');
define('SECURE_AUTH_KEY',  'KAt&%{(Q^;$iz+/t%{Ct0GZn7sh^QhO=UyZg@ub_4zY4ik^jZD2e|W*Z]q@Df+t;');
define('LOGGED_IN_KEY',    'rc*yzhDTux)yy]#KTB{gNivV<%J{aeOgJLY9?w2=)!btrM~8QdA,7C[h?n=7:W 4');
define('NONCE_KEY',        '8C$X7jh)r@QMN54seqvC6y|CU;o}Qg[A2|/x{,CFH0-7h,ZP|)1(WL$]nSc?kKz$');
define('AUTH_SALT',        'k.U[DOv6}[W,<P;8L!]l]tPTgA@7n(~R|f-lt7vLd_zc9nrO^:V-t;@j|}#H)p!U');
define('SECURE_AUTH_SALT', 'kd*Z+8(6CQu+xhm|phsRz`T=/=]#]&ck7oWmi33$W28@6O3D^a7H');

/**#@-*/

/**
 * Префикс таблиц в базе данных WordPress.
 *
 * Можно установить несколько сайтов в одну базу данных, если использовать
 * разные префиксы. Пожалуйста, указывайте только цифры, буквы и знак подчеркивания.
 */
$table_prefix  = 'wp_';

/**
 * Для разработчиков: Режим отладки WordPress.
 *
 * Измените это значение на true, чтобы включить отображение уведомлений при разработке.
 * Разработчикам плагинов и тем настоятельно рекомендуется использовать WP_DEBUG
 * в своём рабочем окружении.
 * 
 * Информацию о других отладочных константах можно найти в Кодексе.
 *
 * @link https://codex.wordpress.org/Debugging_in_WordPress
 */
define('WP_DEBUG', true);

/* Это всё, дальше не редактируем. Успехов! */

/** Абсолютный путь к директории WordPress. */
if ( !defined('ABSPATH') )
	define('ABSPATH', dirname(__FILE__) . '/');

/** Инициализирует переменные WordPress и подключает файлы. */
require_once(ABSPATH . 'wp-settings.php');
							
						

Здесь сначала вводятся параметры работы с БД. Это можно делать вручную в этом файле или через админовский интерфейс. Далее загружается файл wp-settings.php, который должен инициализировать переменные WordPress.
Вот начало кода этого файла:

							
<?php
/**
 * Used to set up and fix common variables and include
 * the WordPress procedural and class library.
 *
 * Allows for some configuration in wp-config.php (see default-constants.php)
 *
 * @internal This file must be parsable by PHP4.
 *
 * @package WordPress
 */

/**
 * Stores the location of the WordPress directory of functions, classes, and core content.
 *
 * @since 1.0.0
 */
define( 'WPINC', 'wp-includes' );

// Include files required for initialization.
require( ABSPATH . WPINC . '/load.php' );
require( ABSPATH . WPINC . '/default-constants.php' );
							
						

Здесь сначала вводятся определяется переменная WPINC - путь к директории wp-includes. Затем загружается файл /wp-includes/load.php, в котором определяется большое количество функций(функции можно посмотреть здесь).
Затем загружается файл /wp-includes/default-constants.php, в котором определяются константы и глобальные переменные, которые могут быть переопределены , в основном в wp-config.php.

Проблемы

Потребление ресурсов

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

Как любая CMS, WordPress потребляет много ресурсов для собственного обслуживания, что не есть хорошо, но с этим приходится мириться... но нужно и бороться. Находим советы здесь
Прежде всего отключил сайт - дал возможность хостингу фиксировать снижение использования оперативной памяти. Включил, сайт заработал. Следую совету - установить в футере код

							
<?php echo get_num_queries(); ?> запросов. <?php timer_stop(1); ?> секунд. <?php echo memory_get_usage()/1024/1024, 2; ?> Мб
							
						

Открываю страницу просмотра кода сайта и в конце футера вижу ожидаемое сообщение:

							
34 запросов. 0,189 секунд. 14.1012039184572 Мб							
						

Вроде не так уж и страшно... хотя 34 запроса в секунду к БД и не очень мало... Решаю последовать советам, описанным здесь - почистить БД с помощью плагина WP Clean Up. Установил, почистил - он удаляет из базы ревизии постов и многое другое позволяет почистить, в частности транзитное кэширование (о котором можно прочитать здесь) - убирать его или нет - нужно решать для конкретного случая.

Теперь можно (и нужно!) убрать остатки таблиц в БД от неиспользуемых плагинов, которые подключались когда-то, но уже не используются. Для этого используем плагин WPDBSpringClean.

ВНИМАНИЕ! Перед чисткой БД с помощью этого плагина нужно сделать бэкап базы, а то можно удалить по ошибке что-нибудь лишнее!
Не знаю, пока, является ли частое обращение к БД причиной нагрузки на оперативную память, но почистить базу - не лишнее дело, нужно взять в привычку делать это на всех своих разработках на WordPress.

Проделаем то же самое с сайтом КПД. По ресурсам до чистки БД имеем:

							
61 запросов. 0,460 секунд. 16.0060806274412 Мб
							
						

После чистки с помощью WP Clean Up ничего не изменилось.

WPDBSpringClean не обнаружил остатков неиспользуемых плагинов.

Попробуем определить, какие из установленных плагинов в какой степени нагружают сервер с помощью плагина P3 - Plugin Performance Profiler.Установил. просканировал сайт - оказалось, что только этот плагин и грузил сайт на момент сканирования.

Загрузка векторных изображений

На одном из сайтов нам понадобилось, чтобы логотипы представленных там компаний, отображались в разных размерах и в одинаково хорошем качестве. Решили использовать логотипы в векторном исполнении. Но обнаружилась проблема - стандартная загрузка медиафайлов в WordPress воспринимает расширение .svg как недопустимый формат (по крайней мере на версии 4.7.3 и более ранних).

Есть много ссылок в интернете, как это преодолеть. Самый простой совет - вставить в function.php вашей темы следующий код:

							
// allow SVG uploads
add_filter('upload_mimes', 'custom_upload_mimes');
function custom_upload_mimes ( $existing_mimes=array() ) {
  $existing_mimes['svg'] = 'image/svg+xml';
  return $existing_mimes;
}
function fix_svg() {
    echo '<style type="text/css">
          .attachment-266x266, .thumbnail img {
               width: 100% !important;
               height: auto !important;
          }
          </style>';
 }
 add_action('admin_head', 'fix_svg');							
						

Это работает. Но так как уверенности в том, что это сработает во всех случаях не было, стали разбираться и проверили такую «хитрость». Загрузили логотип в формате .png. При загрузке через стандартную опцию «Медиафайлы» в папке /wp-content/uploads появилось несколько файлов изображения логотипа разных размеров, которые делает WordPress автоматически в соответствии с настройками темы.
Мы сделали векторные картинки логотипа таких же размеров и загрузили их в ту же папку с такими же именами, но с расширением .svg. Затем в базе данных в таблицах wp_posts, wp_postmeta нашли следы загруженного файла логотипа и заменили все .png на .svg. Например, в таблице wp_posts была запись со значением поля post_title соответствующим названию загруженного файла png-логотипа. В таблице wp_postmeta были обнаружены записи с ключами (meta_key) _wp_attached_file и _wp_attachment_metadata, в которых также располагались ссылки на файлы логотипа в поле meta_value. Везде заменили все .png на .svg. И это сработало! То же самое сделали и с иконкой (favicon).

Еще одна причина делать логотипы и иконки в векторе: WordPress и некоторые продвинутые темы и плагины WP формируют ссылки и метатеги для SEO в хёдере с использованием нашего фавикона и логотипа.

Например, мы обнаружили такие коды в шапке сайта, предназначенный для краулеров сторонних приложений:

							
<link rel="icon" href="http://dev.nedorub.com/wp-content/uploads/2017/03/cropped-favicon-32x32.png" sizes="32x32" />
<link rel="icon" href="http://dev.nedorub.com/wp-content/uploads/2017/03/cropped-favicon-192x192.png" sizes="192x192" />
<link rel="apple-touch-icon-precomposed" href="http://dev.nedorub.com/wp-content/uploads/2017/03/cropped-favicon-180x180.png" />
<meta name="msapplication-TileImage" content="http://dev.nedorub.com/wp-content/uploads/2017/03/cropped-favicon-270x270.png" />							
							
						

Но после того, как мы проделали описанные выше манипуляции с таблицами БД, все .png заменились на .svg. А один из плагинов, например, сгенерировал скрипты, типа этого:

							
<script type='application/ld+json'>{"@context":"http:\/\/schema.org","@type":"Organization","url":"http:\/\/dev.nedorub.com\/","sameAs":[],"@id":"#organization","name":"SAN&SAN Studio","logo":"http:\/\/dev.nedorub.com\/wp-content\/uploads\/2017\/03\/logo-sanisan-300x23.png"}</script>							
						

Следы этой ссылки на логотип были обнаружены в таблице wp_options и .png исправлен на .svg.

Безопасность сайта

Как только мы выложили сайт с локального сервера на хостинг обнаружилась неприятная проблема: стал поступать спам двух видов - регистрация на сайте явных ботов и появление спамовских записей! Стали искать способы борьбы с ними.

Изменяем wp-login

Самый простой способ для разного рода вредителей войти в ваш сайт через wp-login.php, то есть через открытые «ворота» для регистрации и залогинивания.

Простейший способ уменьшить эту угрозу описан здесь. А именно: нужно сделать три шага:

  1. Переименовать файл wp-login.php, который находится в корне сайта. Например, в abcde.php
  2. Открыть только что переименованный файл и заменить везде wp-login.php на abcde.php
  3. В файле general-template.php, который находится в папке wp-includes, заменить wp-login.php на abcde.php

Но этого оказалось недостаточно. Так, при регистрации новых пользователей им отправлялось письмо с обратной ссылкой, содержащей wp-login.php. Чтобы ссылка была корректной, нужно также заменить wp-login.php на abcde.php в файле /wp-includes/plaggeble.php.

Блокируем доступ по wp-login.php и wp-admin

Подробно эта процедура описана здесь. Делаем это через файл .htaccess

							
# Hide admin URL start
<IfModule mod_rewrite.c>
RewriteEngine On
 
RewriteRule ^new_admin/?$ /new_wp-login.php?secret_key [R,L]
 
RewriteCond %{HTTP_COOKIE} !^.*wordpress_logged_in_.*$
RewriteRule ^blackhole/?$ /new_wp-login.php?secret_key&redirect_to=/wp-admin/ [R,L]
 
RewriteRule ^blackhole/?$ /wp-admin/?secret_key [R,L]
 
RewriteCond %{SCRIPT_FILENAME} !^(.*)admin-ajax\.php
RewriteCond %{HTTP_REFERER} !^(.*)my_site/wp-admin
RewriteCond %{HTTP_REFERER} !^(.*)my_site/new_wp-login\.php
RewriteCond %{HTTP_REFERER} !^(.*)my_site/blackhole
RewriteCond %{QUERY_STRING} !^secret_key
RewriteCond %{QUERY_STRING} !^action=logout
RewriteCond %{QUERY_STRING} !^action=rp
RewriteCond %{QUERY_STRING} !^action=postpass
RewriteCond %{HTTP_COOKIE} !^.*wordpress_logged_in_.*$
RewriteRule ^.*wp-admin/?|^.*new_wp-login\.php /not_found [R,L]
 
RewriteCond %{QUERY_STRING} ^loggedout=true
RewriteRule ^.*$ /new_wp-login.php?secret_key [R,L]
</IfModule>
# Hide admin URL end

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

							
						

Здесь new_admin - любой адрес, по которому теперь будет доступна страница входа в админ-панель сайта; new_wp-login.php - это тот новый файл, который мы сделали вместо wp-login.php на предыдущем шаге; my_site - домен нашего сайта и secret_key - любой сложный набор символов.

Внимание! Чтобы эти коды в .htaccess работали, мне пришлось отключить первоначальные коды, которые были прописаны в WP - первый модуль в скобках # BEGIN WordPress и # END WordPress, который я закоммитил с помощью символа #, но оставил в тексте для наглядности и напоминания.

Теперь вход на сайт возможен по адресу [my_site]/new_admin или [my_site]/new_wp-login.php?secret_key, а при попытке обратиться по адресам [my_site]/wp-admin или [my_site]/wp-login.php выдается 404 ошибка.

Удаляем readme.html

По присутствию этого файла в корне сайта и его содержанию злоумышленники выудят информацию о том, что ваш сайт сделан на WordPress и узнают версию движка. Поэтому следует просто удалить readme.html.

Удаляем meta-name Generator

Вордпресс добавляет внутри <head> метатеги <meta name="generator" content="WordPress 4.6.4" /> и <meta name="generator" content="WooCommerce 2.6.4" />, если подключен WooCommerce. Очевидно, что по этим метатегам также легко определить следы WordPress. Устраним их следующим образом. В файле /wp-includes/functions.php добавляем код

							
// Полностью убираем версию WordPress
						 
add_filter('the_generator', '__return_empty_string');
							
						

Удаляем версии из ссылок на css- и js-файлы

Версия WP также присутствует на ссылках типа
<link rel='stylesheet' id='dashicons-css' href='http://back2money.club/wp-includes/css/dashicons.min.css?ver=4.6.4' type='text/css' media='all' />. Устраним эти версии из ссылок следующим образом. В файле /wp-includes/functions.php добавим код

							
// Удаление параметра ver из добавляемых скриптов и стилей
 
function rem_wp_ver_css_js( $src ) {
    if ( strpos( $src, 'ver=' ) )
        $src = remove_query_arg( 'ver', $src );
    return $src;
}
 
add_filter( 'style_loader_src', 'rem_wp_ver_css_js', 9999 );
add_filter( 'script_loader_src', 'rem_wp_ver_css_js', 9999 );
							
						
Теперь та же ссылка выглядит без ?ver=4.6.4

Изменяем логотип на странице [my site]/wp-login.php

В оргигинале страница входа выглядит так:

Чтобы заменить логотип на свой, в файле нашей темы functions.php пропишем код, который это сделает, а именно:

							
function my_login_logo(){
   echo '
   <style type="text/css">
        #login h1 a { background: url('. get_bloginfo('template_directory') .'/images/my_logo.png) no-repeat 0 0 !important;width:211px !important; height:108px !important }
    </style>';
}
add_action('login_head', 'my_login_logo');
							
						

И, соответственно, в папку нашей темы images загружаем наш логотип с именем my_logo.php

Кроме того, чтобы при клике на логотип мы отправлялись на нашу главную страницу (а не на сайт WordPress), добавим еще две строчки кода в файл functions.php

							

add_filter('login_headerurl',create_function('','return get_home_url();'));
add_filter('login_headertitle',create_function('','return "San&San Studio";'));

							
						

Теперь форма залогинивания выглядит так:

Редактируем права пользователей

Для редактирования прав пользователей мы используем плагин User Role Editor. Подробнее о плагине написано здесь

После установки плгина появляется возможность редактировать права пользователя в настройках:

Первое, что мы делаем - устанавливаем роль пользовтеля по умолчанию, который впервые регистрируется еа сайте - это самая низшая роль - Подписчик.

Редактируем общие настройки

Многие спамят обратными ссылками с британских, французских, китайских и других сайтов.

Поэтому сейчас посмотрим, как отключить обратные ссылки в постах.

Обратные ссылки выглядят, как обычные комментарии – некто ставит на своих говносайтах ссылку на вашу статью, у вас в комментариях появляется цитата с этой ссылкой и ссылкой на чужой сайт. Эта ссылка обычно по-настоящему ужасна для вашего авторитета у поисковиков.

Вот, что видно в меню «Комментарии», и это только верхняя часть всего списка обратных ссылок, которые ожидают одобрения.

Меню Комментарии с обратными ссылками

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

Комментарии с обратными ссылками

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

Никак не допишу статью о первоначальных настройках вордпресс-блога, а там будет информация и о «Настройках обсуждения». Поэтому пока просто переходим в админке в меню «Параметры» – «Обсуждения» и вверху страницы снимаем «галочки» в настройках для статьи по умолчанию:

  • «Пытаться оповестить блоги, упоминаемые в статье»
  • «Разрешить оповещения с других блогов (уведомления и обратные ссылки)»

Также можно включить опцию «Автоматически закрывать обсуждение статей старше столько-то дней».

Настройках обсуждения

Нажимаем внизу кнопку «Сохранить изменения».

Но на этом дело не закончиться, потому что для старых статей разрешены обратные ссылки.

Для одной статьи обратные ссылки отключить легко: нужно перейти к меню «Записи», нажать «Свойства» для нужной статьи и снять отметку «Разрешить отклики». После этого нажать кнопку «Обновить».

Разрешить отклики

Но если статей много, то проще всего изменить их свойства с помощью SQL-запроса в базе данных. Сделать это можно в панели phpMyAdmin или с помощью специальных плагинов WordPress.

Отключение обратных ссылок в старых статьях в панели phpMyAdmin

В панели phpMyAdmin выбираем нужную базу данных и переходим на вкладку «SQL».

SQL

В поле «Выполнить SQL-запрос(ы) к базе данных…» пишем такой запрос:

UPDATE wp_posts SET ping_status = 'closed';

Выполнить SQL-запрос

Здесь «UPDATE» - команда изменения данных в таблице, «wp _posts» - указание, что данные нужно поменять в таблице записей, «SET» - установка значения для «ping_status» (состояние обратных ссылок) как «closed» (закрыто).

После этого нажимаем кнопку «ОК» справа внизу, под полем для SQL-запросов. Если всё сделано правильно, то появится сообщение: «Затронуто столько-то строк…».

SQL-запрос

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

А можно удалить сразу все комментарии, ожидающие одобрения, с помощью другого SQL-запроса к базе данных.

В этом случае запрос будет таким:

DELETE FROM wp_comments WHERE comment_type='trackback' ;

Здесь «DELETE» - команда на удаление строк, «FROM wp_comments» – из таблицы комментариев, «WHERE comment_type» - где тип комментария соответствует значению «trackback».

Делаем собственную тему (шаблон)

Файловая структура

Начинаем с создания папки темы

В директории /wp-content/themes/ создаем папку с именем новой темы, например: test и внутри этой папки создаём 11 пустых (пока) PHP файлов и один CSS файл.

  • header.php — содержит всё то, что находиться в верхушке сайта.
  • index.php — самое ядро темы, к нему крепяться все остальные части.
  • sidebar.php — содержит боковую панель (меню)
  • footer.php — всё то, что находится в подвале темы.
  • archive.php — шаблонный файл, который отображает когда были сделаны записи, авторы и тп.
  • single.php — шаблонный файл, который отвечает за загрузку одного поста (когда вы переходите на него по ссылке).
  • comments.php — прикрепляется к концу single.php, чтобы дать людям возможность оставлять комментарии
  • page.php — подобная single.php, но используется для WordPress страниц.
  • search.php — шаблонный файл, используется для отображения результатов поиска..
  • 404.php — шаблонный файл , сообщает об ошибке 404
  • style.css — все CSS-стили вашей темы
  • functions.php — файл используется для изменения функционала WordPress без изменения ядра движка.

Сначала делаем файл index.php с пустым кодом:

				
<?php
/**
 * The main template file
 *
 * This is the most generic template file in a WordPress theme
 * and one of the two required files for a theme (the other being style.css).
 * It is used to display a page when nothing more specific matches a query.
 * For example, it puts together the home page when no home.php file exists.
 *
 * @link http://codex.wordpress.org/Template_Hierarchy
 *
 */

				
			

Затем файл style.css с вот таким описанием:

				
/*
Theme Name: test
Theme URI: https://everpeek.com/wordpress-themes/sanradio
Description: Themes special for radiokidsfm.ru.
Author: Sergey Nedorub
Author URI: https://www.everpeek.com
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Tags: light, blue, green, orange, pink, white, gray, red, black, one-column, two-columns, right-sidebar, left-sidebar, fluid-layout, responsive-layout, custom-background, custom-colors, custom-header, custom-menu, editor-style, featured-images, flexible-header, full-width-template, microformats, post-formats, rtl-language-support, sticky-post, theme-options, threaded-comments, translation-ready
Text Domain: sanradio
*/

				
			

Эти данные из описания читает WordPress и их можно вывести с помощью функции wp_get_theme(). Вот что выдаёт эта функция с помощью php-кода print_r(wp_get_theme());:

				
WP_Theme Object ( [update] => [theme_root:WP_Theme:private] => C:\OpenServer\domains\test/wp-content/themes [headers:WP_Theme:private] => Array ( [Name] => SanRadio [ThemeURI] => https://everpeek.com/wordpress-themes/sanradio [Description] => Themes special for radiokidsfm.ru. [Author] => Sergey Nedorub [AuthorURI] => https://www,everpeek.com [Version] => 1.0.0 [Template] => [Status] => [Tags] => light, blue, green, orange, pink, white, gray, red, black, one-column, two-columns, right-sidebar, left-sidebar, fluid-layout, responsive-layout, custom-background, custom-colors, custom-header, custom-menu, editor-style, featured-images, flexible-header, full-width-template, microformats, post-formats, rtl-language-support, sticky-post, theme-options, threaded-comments, translation-ready [TextDomain] => sanradio [DomainPath] => ) [headers_sanitized:WP_Theme:private] => [name_translated:WP_Theme:private] => [errors:WP_Theme:private] => [stylesheet:WP_Theme:private] => sanradio [template:WP_Theme:private] => sanradio [parent:WP_Theme:private] => [theme_root_uri:WP_Theme:private] => [textdomain_loaded:WP_Theme:private] => [cache_hash:WP_Theme:private] => 7aa716ea677bf530f8db62f93fb73c59 )
				
			
Внимание! Название темы - очень важно. Именно это название (Theme Name) WordPress будет определять и выводить как название темы. Если мы делаем дочернюю тему, то описание несколько другое. О дочерних темах можно прочитать здесь

Эти данные можно извлекать и использовать, например, с помощью такого php-кода:

				
$my_theme = wp_get_theme( 'test' );
	if ( $my_theme->exists() ){
	echo $my_theme->get( 'Name' ) . " is version " . $my_theme->get( 'Version' );	
}
				
			

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

Мы не поленимся и создадим еще файл-картинку нашей темы (размер 300 на 225 пикселей) и загрузим в папку test под именем screenshot.png. Теперь наша тема в разделе выбора тем в админке выглядит гораздо привлекательнее:

Делаем меню

Если активировать нашу тему, то в разделе Внешний вид панели администратора увидим следующую картину:

А если активировать, например, тему Ribosome, то увидим такую картину:

Таким образом, наша тема пока не поддерживает ни Меню, ни Виджеты, ни Фон, ни Заголовок.
Все долгие поиски в интернете ответа на вопрос (и естественно, попыток этими ответами воспользоваться), не приносили успеха, пока я не наткнулся на статью Андрея Морковина. Следуя его инструкции, всё удалось настроить и научиться делать и подключать различные меню. Опишу подробнее. Начинаем с файла functions.php. Запишем в этом файле следующий сод:

				
// Регистрируем две области locations) для загрузки меню: header-menu1 и footer-menu1
function register_my_menus()
{
register_nav_menus
(
array( 'header-menu' => 'header-menu1', 'footer-menu' => 'footer-menu1')
);
}

// Инициируем подключение этих облостей при загрузке WordPress
if (function_exists('register_nav_menus'))
{
     add_action( 'init', 'register_my_menus' );
}

				
			

Перезагружаем тему и видим, что WordPress подключил нам функцию работы с меню.

Создаём несколько меню (перед этим нужно создать несколько страниц, чтобы было, что добавлять в меню) и соотносим их к определенным областям - это несложно понять, поэкспериментировав с функцией Меню в админке. Мы создали два меню с именами: header-menu-2 и footer-menu-2. Чтобы вывести меню на сайте, нужно в соответствующем месте ( в нашем случае в файлах heder.phpfooter.php вставить в html-код, где мы хотим разместить меню кусок php-кода с вызовом меню wp-функцией wp_nav_menu():
в хёдере, например:

				
<div id="navigation">
	<div class="container">
		<div class="row">
			<div class="col-md-12">
			<nav class="navbar navbar-static-top" role="navigation">
			  <div class="container-fluid">
			    <div class="navbar-header">
			      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
			        <span class="sr-only">Toggle navigation</span>
			        <span class="icon-bar"></span>
			        <span class="icon-bar"></span>
			        <span class="icon-bar"></span>
			      </button>
			    </div>
			    <div class="navbar-collapse collapse" id="bs-example-navbar-collapse-1" style="height: 1px;">
     <?php wp_nav_menu( array( 'theme_location' => 'header-menu' ) ); ?>
			      			    </div>
			  </div>
			</nav>
			</div>
		</div>
	</div>
</div>
				
			

При загрузке файла WordPress генерирует HTML-код и вставляет его вместо wp_nav_menu(). Для нашего хёдера этот код имеет вид:

				
<div class="menu-header-menu-2-container">
	<ul id="menu-header-menu-2" class="menu"><li id="menu-item-247" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-70 current_page_item current_page_parent menu-item-247"><a href="http://test/index/">KIDSFM</a></li>
		<li id="menu-item-248" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-248"><a href="http://test/%d0%be-%d0%bd%d0%b0%d1%81/">О НАС</a></li>
		<li id="menu-item-249" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-249"><a href="http://test/%d1%88%d0%ba%d0%be%d0%bb%d0%b0/">ШКОЛА</a></li>
		<li id="menu-item-250" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-250"><a href="http://test/%d0%be-%d0%bd%d0%b0%d1%81/%d0%bd%d0%b0%d1%88-%d0%b0%d0%b4%d1%80%d0%b5%d1%81/">Наш адрес</a></li>
		<li id="menu-item-251" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-251"><a href="http://test/%d0%b0%d1%84%d0%b8%d1%88%d0%b0/">АФИША</a></li>
		<li id="menu-item-252" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-252"><a href="http://test/%d1%80%d0%b0%d0%b4%d0%b8%d0%be%d0%b2%d0%b5%d0%b4%d1%83%d1%89%d0%b8%d0%b5/">РАДИОВЕДУЩИЕ</a></li>
		<li id="menu-item-253" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-253"><a href="http://test/%d0%bf%d0%b5%d1%80%d0%b5%d0%b4%d0%b0%d1%87%d0%b8/">ПЕРЕДАЧИ</a></li>
		<li id="menu-item-254" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-254"><a href="http://test/%d1%82%d0%be%d0%bf/">ТОП</a></li>
		<li id="menu-item-255" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-255"><a href="http://test/%d0%b3%d0%b0%d0%bb%d0%b5%d1%80%d0%b5%d1%8f/">ГАЛЕРЕЯ</a></li>
	</ul>
</div>
				
			

Остаётся прописать стили для всех нужных классов меню, чтобы оно выглядело так, как нам нужно. Следует обратить внимание на класс current-menu-item, который должен определять стиль для кнопки меню, соответствующей текущей отображаемой странице... всё! Дело сделано!

Заголовок Header Image

Теперь займёмся подключением функции Заголовка (Картинки заголовка). Для того, чтобы была возможность установить картинку заголовка для темы нужно включить опцию custom-header в функции add_theme_support(). Пропишем в файле functions.php следующий код:

				
/**
 * Set up the WordPress core custom header arguments and settings.
 *
 * @uses add_theme_support() to register support for 3.4 and up.
 * @uses sanfirst_header_style() to style front-end.
 * @uses sanfirst_admin_header_style() to style wp-admin form.
 * @uses sanfirst_admin_header_image() to add custom markup to wp-admin form.
 *
 * @since Sanfirst 1.0
 */
function sanfirst_custom_header_setup() {
	$args = array(
		// Text color and image (empty to use none).
		'default-text-color'     => 'EAEAEA',
		'default-image'          => '',

		// Set height and width, with a maximum value for the width.
		'height'                 => 292,
		'width'                  => 1144,
		'max-width'              => 2000,

		// Support flexible height and width.
		'flex-height'            => true,
		'flex-width'             => true,

		// Random image rotation off by default.
		'random-default'         => false,

		// Callbacks for styling the header and the admin preview.
		'wp-head-callback'       => 'sanfirst_header_style',
		'admin-head-callback'    => 'sanfirst_admin_header_style',
		'admin-preview-callback' => 'sanfirst_admin_header_image',
	);

	add_theme_support( 'custom-header', $args );
}
add_action( 'after_setup_theme', 'sanfirst_custom_header_setup' );
				
			

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

Теперь вставим в нужном месте HTML кода в хёдере вызов картинки заголовка:

				
<?php if( has_header_image() )
	echo  '<img src="'. get_header_image() .'" alt="'. get_bloginfo('title') .'">';
?>
				
			

В нашем случае картинку нужно было использовать как фон блока. Поэтому мы написали следующий код:

				
<div id="header" class="hidden-sm hidden-xs" style="background:url(<?php echo header_image() ?>); background-position:center;">
</div>
				
			

Здесь мы использовали функцию header_image(), которая выдаёт URL картинки.

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

				
<?php
if(is_home() OR is_page(91) ) {	?>

	<div id="header" ...>
	. . .
	</div>

<?php } ?>
				
			

Здесь мы использовали два условных тега: is_home() и is_page(). Причём тег is_page() можно использовать либо с ID страницы или с её наименованием, например:is_page(91) и is_page('АФИША') выдаёт один и тот же результат.

Как определить ID страницы?

  • Look in your browser status bar for the ID:
  1. Visit the related list table screen in your Administration Screen. For instance in the case of Posts visit Posts->All Posts, for Pages visit Pages->All Pages, and for Categories visit Posts->Categories.
  2. Now hover your mouse over the 'item' you need the ID. In the case of Pages, hover over that particular Page's title in the Title column and for Categories hover over the Categories Name in the Name column.
  3. Look at the status bar (at the bottom of your browser) and the you will find at the end of the line something like "post=123" or "tag_ID=67". In these cases, 123 is the Page ID, and 67 is the Category ID.
  • Install a plugin:
  1. Install and activate Reveal IDs for WP Admin or ShowID for Post/Page/Category/Tag/Comment.
  2. Find the ID displayed with each item.

Подключаем плагины

Первы плагин, который мы подключали и учились подклчать и активировать плагины, был TablePress. Нам просто понадобилось сделать красивую табличку на одной из страниц (О НАС).

Последовательность действий: 1 - скачиваем папку с архивом плагина, например, отсюда https://wordpress.org/plugins/tablepress/; 2- разархивируем и содержимое помещаем в папку /wp-content/plagins/; 3- заходим в раздел "Плагины" в левом меню админ-панели, ищем только-что подгруженный плагин и активируем его. Псле обновления в левом меню админ-панели появился раздел "TablePress":

Внимание! Некоторые плагины не отображаются в виде отдельного раздела в меню адмн-панели, но видны в разделе "Настройки", откуда и следует ими управлять и настраивать.

Кроме того, что появился раздел "TablePress" в меню админ-панели, при создании или редактирвании постов и страниц появилась новая кнопочка в редакторе:

.

Здесь можно вставлять таблицу в текст и её редактировать. Подробнее здесь.

Сайдбары - это контейнеры для вставки виджетов. Они могут быть вставлены в любом месте на сайте (не обязательно сбоку) функцией

				
 ?lt;php get_sidebar('[имя сайдбара]'); ?>
				
			

Но для того, чтобы это работало, нужно 1 - сначала создать в корне шаблона файл sidebar-[имя сайдбара].php и вставить в него следующий код:

				
 <?php if ( function_exists ( dynamic_sidebar(4) ) ) : ?>
<?php dynamic_sidebar (4); ?>
<?php endif; ?>				
			

где 4 - это номер сайдбара (по-порядку). Затем 2 - в файле functions.php добавить описание этого сайдбара:

				
/** Регистрируем сайдбары  */
if ( function_exists('register_sidebar') )
	register_sidebar(array(
		'before_widget' => '',
		'after_widget' => '',
		'before_title' => '<h3>',
		'after_title' => '</h3>',
	));
 
register_sidebar( array(
'name' => '[имя сайдбара 1]',
) );
 
register_sidebar( array(
'name' => '[имя сайдбара 2]',
) );
. . .
register_sidebar( array(
'name' => '[имя сайдбара 4]',
) );
				
			

Строим страницу постов (index.php)

После вывода хёдера начинаем строить вывод постов:

				
<!-- Content -->
<div class="col-md-9">
		<?php if ( have_posts() ) : ?>

			<?php /* Start the Loop */ ?>
			<?php while ( have_posts() ) : the_post(); ?>
				<?php get_template_part( 'content', get_post_format() ); ?>
			<?php endwhile;?>

		<?php else : ?>
...
			<?php if ( current_user_can( 'edit_posts' ) ) :
				// Show a different message to a logged-in user who can add posts.
			?>
	...
			<?php else :
				// Show the default message to everyone else.
			?>
...			<?php endif; // end current_user_can() check ?>
		<?php endif; // end have_posts() check ?>
</div>
				
			

Здесь сначала с помощью условного тега have_posts() проверяем наличие посов для данной страницы в БД. Если посты есть, запускаем цикл их выдачи.
Если посты есть, то они начинают выводиться в цикле while ..., при этом на каждом витке цикла сначала устанавливается индекс поста с помощью функции the_post() (подробнее об этой функции можно прочитать здесь), после чего в нашем случае выполняется функция get_template_part( ). Эта функция WP загружает в шаблон часть шаблона, а именно в нашем сучае, файл content.php. В этой части шаблона мы, собственно, задаем то, что именно хотим вывести и делаем html разметку.
Вот начало кода этой страницы (content.php):

				
	<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
	<?php if ( is_sticky() && is_home() ){ 
			get_template_part( SANFIRST_TEMPLATE_PARTS . 'sticky');
		}else{ ?>
		
		<?php if ( is_single() || ( is_home() && get_theme_mod('ribosome_contenido_completo_entradas_pp', '') == 1 )  ) : ?>
		<header class="entry-header">
				
			

Условный тег is_sticky() определяет, прилеплен ли данный пост к главной странице, а условный тег is_home() определет, находимся ли мы на главной странице? Если условие выполняется, то выдается чать шаблона sticky.php
Здесь следует обратить внимание на то, что такое Главная страница? Главной страницей в WP называется страница, на которой выводятся посты (записи). А страница, которая выводится первой при обращении к сайту по адресу http://my_site, является страницей Front_page. Таким образом, на главной странице is_home()==1, а на первой странице is_front_page()==1.

В админ-панели можно настроить, какая страница будет Home, а какая Front-page. Для этого перейдём в Настройки => Чтение
Настройки-чтение

Если установить «отображать - Ваши последние записи», то автоматически страница с выводом постов становится и Home, и Front_page. Если мы хотим, как в нашем случае, первой загружать страницу KIDSFM, то выбираем «отображать - Статическая страница» и выбираем, какая страница будег Front, а какая Home. Как показано на рисунке, у нас первой будет загружаться KIDSFM, а записи (посты) будут выводиться на странице ЛЕНТА
Теперь разберём, что такое sticky? Оказывается, можно «прилепить» запись на странице home, тогда эта запись будет отображаться в верхней части страницы записей, а новые записи будут отображаться ниже. Естественно, для такой прилепленной записи имеет смысл оформить стили, отличные от текущих записей. В нашем случае мы для этого и используем шаблон /template-parts/sticky.php.

Чтобы «прилепить» запись, нужно перед её публикацией поставить галочку в «Прилепить на главную страницу»

Настройки-чтение
Затем сохранить и опубликовать.

Вернемся к листингу начала кода страницы content.php. Итак, если это не приклеенный пост, то идём дальше и проверяем, является страница, на которой мы находимся single или home. Для home одновременно должно выполняться условие get_theme_mod('ribosome_contenido_completo_entradas_pp', '') == 1. Так как мы заимствовали коды из темы Ribosome, то сделаем в файле index.php включение этой моды, чтобы следовать этому сценарию (этот сценарий - выдача полного текста поста):

				
<?php set_theme_mod('ribosome_contenido_completo_entradas_pp', 1); ?>
				
			

Итак, чтобы отображение постов на странице home было таким же как и Ribosome мы забрали соответствующие стили из рибосомовского style.css в наш, а именно:

				
/**    Для постов a'la Ribosome    */

/*   Сделать и для других экранов как в Ribosome */
.excerpt-wrapper {
    border-left: 2px solid #00BCD5;
}
. . . и т.д.
				
			

После отработки sticky.php выдается заголовок поста:

				
				<?php if ( is_single() ) { ?>
					<h1 class="entry-title"><?php the_title(); ?></h1>
				<?php }else{ ?>
					<h2 class="entry-title"><?php the_title(); ?></h2>
				<?php } ?>
				
			

Выглядит это так:

Настройки-чтение

В оригинале к Рибосом отсутствует фраза «к записи [заголовок записи]», которая нам тоже не нужна. Как её убрали в Рибосом я не знаю, поэтому я просто вставил в файл style.css следующий стиль для соответствующего класса:

				
.screen-reader-text{display:none;}
				
			

Тогда строка с информацией о комментариях выглядит так, как нам нужно:

Настройки-чтение

Далее, для того, чтобы при клике на ссылку «Комментарии» в верхней строке (меню) каждого поста можно было перейти на этот пот и добавить свой комментарий необходимо было создать страницы single.php и comments.php. Коды мы заимствовали из темы Ribosome и соответствующие слассы стилейперетащили в свой файл style.css. Кроме того, в functions.php необходимо оказалось добавить следующую функцию:

				
if ( ! function_exists( 'ribosome_comment' ) ) :
/**
 * Template for comments and pingbacks.
 *
 * To override this walker in a child theme without modifying the comments template
 * simply create your own ribosome_comment(), and that function will be used instead.
 *
 * Used as a callback by wp_list_comments() for displaying the comments.
 *
 * @since Ribosome 1.0
 */
function ribosome_comment( $comment, $args, $depth ) {
	$GLOBALS['comment'] = $comment;
	switch ( $comment->comment_type ) :
		case 'pingback' :
		case 'trackback' :
		// Display trackbacks differently than normal comments.
	?>
	<li <?php comment_class(); ?> id="comment-<?php comment_ID(); ?>">
		<p><?php _e( 'Pingback:', 'ribosome' ); ?> <?php comment_author_link(); ?> <?php edit_comment_link( __( '(Edit)', 'ribosome' ), '<span class="edit-link">', '</span>' ); ?></p>
	<?php
			break;
		default :
		// Proceed with normal comments.
		global $post;
	?>
	<li <?php comment_class(); ?> id="li-comment-<?php comment_ID(); ?>">
		<article id="comment-<?php comment_ID(); ?>" class="comment">
			<header class="comment-meta comment-author vcard">
				<?php
					echo get_avatar( $comment, 44 );
					printf( '<cite><b class="fn">%1$s</b> %2$s</cite>',
						get_comment_author_link(),
						// If current post author is also comment author, make it known visually.
						( $comment->user_id === $post->post_author ) ? '<span>' . __( 'Post author', 'ribosome' ) . '</span>' : ''
					);
					printf( '<a href="%1$s"><time datetime="%2$s">%3$s</time></a>',
						esc_url( get_comment_link( $comment->comment_ID ) ),
						get_comment_time( 'c' ),
						/* translators: 1: date, 2: time */
						sprintf( __( '%1$s at %2$s', 'ribosome' ), get_comment_date(), get_comment_time() )
					);
				?>
			</header><!-- .comment-meta -->

			<?php if ( '0' == $comment->comment_approved ) : ?>
				<p class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.', 'ribosome' ); ?></p>
			<?php endif; ?>

			<section class="comment-content comment">
				<?php comment_text(); ?>
				<?php edit_comment_link( __( 'Edit', 'ribosome' ), '<p class="edit-link">', '</p>' ); ?>
			</section><!-- .comment-content -->

			<div class="reply">
				<?php comment_reply_link( array_merge( $args, array( 'reply_text' => __( 'Reply', 'ribosome' ), 'after' => ' <span>↓</span>', 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?>
			</div><!-- .reply -->
		</article><!-- #comment-## -->
	<?php
		break;
	endswitch; // end comment_type check
}
endif;
				
			

Теперь всё выглядело так же как и в теме Ribosome

Строим страницу РАДИОВЕДУЩИЕ

Для этой страницы мы делаем свой шаблон. Для этого создаём в корне темы файл presenters.php, заходим в админ панели на редактирование этой страницы и видим, что справа в разделе Атрибуты -> Шаблоны появился выбор шаблона Presenters.

Настройки-чтение

Его и выбираем! Далее в страницу presenters.php вставляем код, который будет выводить посты из категории (рубрики) ведущие. Это стандартный код вывода постов, но вначале добавляем условие того, что выводятся посты только данной рубрики:

				
<?php
	if (is_page('93') ) {
		$cat = array(16);
	} elseif ( is_page('16') ) {
		$cat = array(32);
	} elseif ( is_page('28') ) {
		$cat = array(17);
	} else {
		$cat = '';
	}

	$showposts = -1; // -1 shows all posts
	$do_not_show_stickies = 1; // 0 to show stickies
	$args=array(
	   'category__in' => $cat,
	   'showposts' => $showposts,
	   'caller_get_posts' => $do_not_show_stickies
	   );
	$my_query = new WP_Query($args); 

?>
				
			

Здесь 93 - ID страницы РАДИОВЕДУЩИЕ, а 16 - ID рубрики Ведущие.

Чтобы определить ID страницы, нужно перейти в админке в раздел СТРАНИЦЫ, навести курсор на название нужной страницы и внизу экрана появится ссылка, содержащая этот ID. Аналогично определяется ID рубрики и поста.

Как видим один шаблон можно использовать для разных страниц и выводить на них разные посты.

Исключение рубрики из HOME.page

После того, как мы начали делать записи в рубрике ведущие оказалось, что эти записи появляются как посты на страницк ЛЕНТЫ, то есть на странице home, но нам этого не нужно. Вста вопрос, как исключить показ постов из этой рубрики на странице home. Один вариант, который мы нашли - вставить в файл functions.php следующий код:

				
/**
 *  Исключаем категорию с ID=33 из показа в ленте
 *
*/ 
 function exclude_category($query) {
if ( $query->is_page ) {
$query->set('category__not_in', array(33));}
return $query;
}
add_filter('pre_get_posts', 'exclude_category');
				
			

Но это, как ни странно - не помогло. А помогло вот что: в файле index.php перед строкой

				
<?php if ( have_posts() ) : ?>
				
			

нужно вставить строку, чтобы получилось вот так:

				
        <?php if (is_home()) { query_posts('cat=-33'); } ?>
		<?php if ( have_posts() ) : ?>				
			
По идее должны работать и такие конструкции:
  • query_posts(‘cat=-3’) — Не показывать категорию id которой равно 3;
  • query_posts(‘cat=-1,-2,-3’) — Не показывать категории, id которых равны 1, 2 и 3;
  • query_posts(‘cat=2,6,17’) — Вывести категории с id равным 2, 6 и 17;
  • query_posts(‘category_name=WordPress’) — Вывести категорию с названием “WordPress”;
  • query_posts(‘name=Hello World’) — Вывести один пост с названием “Hello World”;
  • query_posts(‘p=5’) — Вывести один пост, id которого равно 5;
  • query_posts(‘page_id=7’) — Вывести страницу id которой равно 7;
  • query_posts(‘pagename=about’) — Вывести страницу с названием “about”;
  • query_posts(‘cat=18&showposts=5’) — Вывести 5 постов из категории с id=18;
  • query_posts(‘cat=3&orderby=date&order=ASC’) — Вывести посты из категории id которой равно 3, сортировать по дате в хронологическом порядке(DESC — в обратном порядке);
  • query_posts(‘posts_per_page=10’) — Вывести 10 постов на страницу (при значении -1 выводит все посты);
  • query_posts(‘cat=3&year=2008’) — Вывести посты из категории с id=3 за 2008 год;
  • query_posts(‘orderby=rand&showposts=3&cat=3’) — выводин рандомно, т.е. случайно 3 записи из 3 категории;
  • query_posts(‘orderby=rand&showposts=3’) — выводит случайно 3 записи из всех категорий;
  • query_posts(‘meta_key=cars&meta_value=volvo’) — выводит список постов с произвольным полем “cars” и значением этого поля volvo.
    Информация о примерах использования query_posts взята с сайта http://www.wp-info.ru/
    Будьте осторожны, если не до конца уверены в том что делаете.
  • Добавляем и/или редактируем роли

    Теперь нам потребовалось ведущим делегировать определенные права, то есть создать новую роль - "Ведущий".
    В WP предусмотрены базовые роли:

    • Administrator
    • Editor
    • Author
    • Contributor
    • Subscriber

    Что в русскоязычном варианте WP выглядит как:

    • Администратор
    • Редактор
    • Автор
    • Участник
    • Подписчик

    Данные о ролях и их правах хранятся в БД в таблице wp_options в записи с option_name = wp_user_roles в поле option_value в виде следующей строки:

    				
    a:6:{s:13:"administrator";a:2:{s:4:"name";s:13:"Administrator";s:12:"capabilities";a:93:{s:13:"switch_themes";b:1;s:11:"edit_themes";b:1;s:16:"activate_plugins";b:1;s:12:"edit_plugins";b:1;s:10:"edit_users";b:1;s:10:"edit_files";b:1;s:14:"manage_options";b:1;s:17:"moderate_comments";b:1;s:17:"manage_categories";b:1;s:12:"manage_links";b:1;s:12:"upload_files";b:1;s:6:"import";b:1;s:15:"unfiltered_html";b:1;s:10:"edit_posts";b:1;s:17:"edit_others_posts";b:1;s:20:"edit_published_posts";b:1;s:13:"publish_posts";b:1;s:10:"edit_pages";b:1;s:4:"read";b:1;s:8:"level_10";b:1;s:7:"level_9";b:1;s:7:"level_8";b:1;s:7:"level_7";b:1;s:7:"level_6";b:1;s:7:"level_5";b:1;s:7:"level_4";b:1;s:7:"level_3";b:1;s:7:"level_2";b:1;s:7:"level_1";b:1;s:7:"level_0";b:1;s:17:"edit_others_pages";b:1;s:20:"edit_published_pages";b:1;s:13:"publish_pages";b:1;s:12:"delete_pages";b:1;s:19:"delete_others_pages";b:1;s:22:"delete_published_pages";b:1;s:12:"delete_posts";b:1;s:19:"delete_others_posts";b:1;s:22:"delete_published_posts";b:1;s:20:"delete_private_posts";b:1;s:18:"edit_private_posts";b:1;s:18:"read_private_posts";b:1;s:20:"delete_private_pages";b:1;s:18:"edit_private_pages";b:1;s:18:"read_private_pages";b:1;s:12:"delete_users";b:1;s:12:"create_users";b:1;s:17:"unfiltered_upload";b:1;s:14:"edit_dashboard";b:1;s:14:"update_plugins";b:1;s:14:"delete_plugins";b:1;s:15:"install_plugins";b:1;s:13:"update_themes";b:1;s:14:"install_themes";b:1;s:11:"update_core";b:1;s:10:"list_users";b:1;s:12:"remove_users";b:1;s:13:"promote_users";b:1;s:18:"edit_theme_options";b:1;s:13:"delete_themes";b:1;s:6:"export";b:1;s:22:"tablepress_edit_tables";b:1;s:24:"tablepress_delete_tables";b:1;s:22:"tablepress_list_tables";b:1;s:21:"tablepress_add_tables";b:1;s:22:"tablepress_copy_tables";b:1;s:24:"tablepress_import_tables";b:1;s:24:"tablepress_export_tables";b:1;s:32:"tablepress_access_options_screen";b:1;s:30:"tablepress_access_about_screen";b:1;s:29:"tablepress_import_tables_wptr";b:1;s:23:"tablepress_edit_options";b:1;s:24:"NextGEN Gallery overview";b:1;s:19:"NextGEN Use TinyMCE";b:1;s:21:"NextGEN Upload images";b:1;s:22:"NextGEN Manage gallery";b:1;s:19:"NextGEN Manage tags";b:1;s:29:"NextGEN Manage others gallery";b:1;s:18:"NextGEN Edit album";b:1;s:20:"NextGEN Change style";b:1;s:22:"NextGEN Change options";b:1;s:24:"NextGEN Attach Interface";b:1;s:14:"ure_edit_roles";b:1;s:16:"ure_create_roles";b:1;s:16:"ure_delete_roles";b:1;s:23:"ure_create_capabilities";b:1;s:23:"ure_delete_capabilities";b:1;s:18:"ure_manage_options";b:1;s:15:"ure_reset_roles";b:1;s:22:"edit_tablepress_tables";b:1;s:29:"edit_others_tablepress_tables";b:1;s:25:"publish_tablepress_tables";b:1;s:30:"read_private_tablepress_tables";b:1;}}s:6:"author";a:2:{s:4:"name";s:6:"Author";s:12:"capabilities";a:20:{s:12:"upload_files";b:1;s:10:"edit_posts";b:1;s:20:"edit_published_posts";b:1;s:13:"publish_posts";b:1;s:4:"read";b:1;s:7:"level_2";b:1;s:7:"level_1";b:1;s:7:"level_0";b:1;s:12:"delete_posts";b:1;s:22:"delete_published_posts";b:1;s:22:"tablepress_edit_tables";b:1;s:24:"tablepress_delete_tables";b:1;s:22:"tablepress_list_tables";b:1;s:21:"tablepress_add_tables";b:1;s:22:"tablepress_copy_tables";b:1;s:24:"tablepress_import_tables";b:1;s:24:"tablepress_export_tables";b:1;s:32:"tablepress_access_options_screen";b:1;s:30:"tablepress_access_about_screen";b:1;s:19:"moderate_quick_chat";b:1;}}s:11:"contributor";a:2:{s:4:"name";s:11:"Contributor";s:12:"capabilities";a:5:{s:12:"delete_posts";b:1;s:10:"edit_posts";b:1;s:7:"level_0";b:1;s:7:"level_1";b:1;s:4:"read";b:1;}}s:6:"editor";a:2:{s:4:"name";s:6:"Editor";s:12:"capabilities";a:44:{s:17:"moderate_comments";b:1;s:17:"manage_categories";b:1;s:12:"manage_links";b:1;s:12:"upload_files";b:1;s:15:"unfiltered_html";b:1;s:10:"edit_posts";b:1;s:17:"edit_others_posts";b:1;s:20:"edit_published_posts";b:1;s:13:"publish_posts";b:1;s:10:"edit_pages";b:1;s:4:"read";b:1;s:7:"level_7";b:1;s:7:"level_6";b:1;s:7:"level_5";b:1;s:7:"level_4";b:1;s:7:"level_3";b:1;s:7:"level_2";b:1;s:7:"level_1";b:1;s:7:"level_0";b:1;s:17:"edit_others_pages";b:1;s:20:"edit_published_pages";b:1;s:13:"publish_pages";b:1;s:12:"delete_pages";b:1;s:19:"delete_others_pages";b:1;s:22:"delete_published_pages";b:1;s:12:"delete_posts";b:1;s:19:"delete_others_posts";b:1;s:22:"delete_published_posts";b:1;s:20:"delete_private_posts";b:1;s:18:"edit_private_posts";b:1;s:18:"read_private_posts";b:1;s:20:"delete_private_pages";b:1;s:18:"edit_private_pages";b:1;s:18:"read_private_pages";b:1;s:22:"tablepress_edit_tables";b:1;s:24:"tablepress_delete_tables";b:1;s:22:"tablepress_list_tables";b:1;s:21:"tablepress_add_tables";b:1;s:22:"tablepress_copy_tables";b:1;s:24:"tablepress_import_tables";b:1;s:24:"tablepress_export_tables";b:1;s:32:"tablepress_access_options_screen";b:1;s:30:"tablepress_access_about_screen";b:1;s:19:"moderate_quick_chat";b:1;}}s:10:"subscriber";a:2:{s:4:"name";s:10:"Subscriber";s:12:"capabilities";a:3:{s:4:"read";b:1;s:7:"level_0";b:1;s:19:"moderate_quick_chat";b:1;}}}
    				
    			

    Это текстовая строка в специальном формате, в котором WP хранит данные о массивах и их элементах. Подробнее об этом фрмате можно посмотреть здесь.
    Как английские наименования превращаются в русские - изучим позже, когда будем разбираться с локализацией. А сейчас займёмся созданием новой роли. Конечно, можно попробовать просто в эту строку в БД вписать тупо новую роль, но мы хотим, чтобы администратор мог это делать из панели администратора, поэтому мы подключили новый плагин - User Role Editor.
    У этого плагина, как оказалось, много возможностей и работает он хорошо, но смущает то, что в БД он прописывает странную длину строки наименования роли, если она написана кириллицей, например: s:14:"Ведущий". То есть, длина строки 14 символов, хотя в слове "Ведущий" их 7! Подозревая, что это может отобразиться на корректности работы функций WP, которые работают с ролями, будем поступать так: писать наименования латиницей, а потом займемся локализацией WP и будем ручками добавлять наименование роли на русском или другом языке.

    Вход на сайт - редактируем

    После залогинивания (входа) пользователя, WP выводит его на админ-панель, что очень плохо для нормального сайта, а не блога! Поэтому стоит задача, выводить пользователя на нужную страницу сайта в зависимости от его роли.
    После тестирования разных вариантов, оказалось, что нормально работает код, описанный в WP Codex, который нужно вставить в functions.php файл темы:

    				
    
    				
    			

    Плагины WordPress

    Плагин User Role Editor

    Убираем бокс, позволяющий редакторам изменять ник в процессе чата, то есть писать сообщения под другим ником:

    Плагин Quick Chat

    Убираем бокс, позволяющий редакторам изменять ник в процессе чата, то есть писать сообщения под другим ником:

    Для этого в админке в настройках чата убираем галочку:

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

    Теперь убираем дату и время в чате.

    				
    <div class="quick-chat-history-timestring">'+
    a.timestring+'</div>
    				
    			

    в файле quick-chat/js/quick-chat-core.js

    После подключения плагина регистрации в ВК обнаружилась проблема - в качестве имени участника чата плагин использует логин, что плохо! Нужно сделать так, чтобы высвечивалось Имя Фамилия. Делаем.
    В файле плагина /wp-content/plugins/quick-chat/quick-chat.php изменяем два куска кода:

    				
    
                global $current_user;
                get_currentuserinfo();
    
                if(isset($_COOKIE['quick_chat_alias_'.$current_user->ID])){
                    $this->user_name =  stripslashes($_COOKIE['quick_chat_alias_'.$current_user->ID]);
                } else{
                    setcookie('quick_chat_alias_'.$current_user->ID, $current_user->user_login, 0, COOKIEPATH, COOKIE_DOMAIN);
                    $this->user_name =  $current_user->user_login;
                }
    
    			. . . . . 
    
                    if($username_bad_words == 0 && (!is_user_logged_in() || (is_user_logged_in() && strcasecmp($_POST['username_check'], $current_user->user_login) != 0))){
    			
    				
    			

    Меняем на:

    				
    
                global $current_user;
                get_currentuserinfo();
                $chat_name = $current_user->first_name.' '.$current_user->last_name;
    
                if(isset($_COOKIE['quick_chat_alias_'.$current_user->ID])){
                    $this->user_name =  stripslashes($_COOKIE['quick_chat_alias_'.$current_user->ID]);
                } else{
                    setcookie('quick_chat_alias_'.$current_user->ID, $chat_name, 0, COOKIEPATH, COOKIE_DOMAIN);
                    $this->user_name =  $chat_name;
                }
    
    			. . . . .
    			
                    if($username_bad_words == 0 && (!is_user_logged_in() || (is_user_logged_in() && strcasecmp($_POST['username_check'], $chat_name) != 0))){
    
    				
    			

    Пользователи должны почистить куки!!!

    Изменяем интервал времени отключения пользователя за неактивность. Дело в том, что плагин удаляет окно чата, если пользователь не участвует какое-то время в переписке. Нам понадобилось вывести чат ведущим, но при этом они не долны в нем участвовать по определению. Чтобы чат не отключался - просто увеличим время отклчения.
    Для этого в файле wp-content/plugins/quick-chat/js/quick-chat-core.js находим строчку

    				
    
    quick_chat.users_interval&&(quick_chat.users_interval=setInterval(function(){quick_chat.update_users()},1E3*quick_chat.timeout_refresh_users));
    
    				
    			

    и меняем 1E3 на 1E6, например. Или поступаем проще: идем в админку и в настройках Quick Chat изменяем параметр в соответствующем блоке:






    Плагин TablePress

    Кроме того, что появился раздел "TablePress" в меню админ-панели, при создании или редактирвании постов и страниц появилась новая кнопочка в редакторе:

    .

    Здесь можно вставлять таблицу в текст и её редактировать. Вот пример такой таблицы (как она выглядит):

    Очень полезный и хороший плагин - РЕКОМЕНДУЕМ!!!

    Плагин Meta Slider

    Мы протестировали несколько плагинов для создания слайдеров. а именно: banner-slider, len-slider,ml-slider. Первые два забраковали, а Мета слайдер вполне подошёл: простые настройки, наличие шорт-кода, возможность устанавливать лбые размеры и прочее - очень простой и вполне достаточен. Можно создавать несколько слайдеров и вставлять как в постах и страницах, так и в сайд-барах с помощьюсоответствующего виждета. Вот пример php-кода, который мыиспользовали для вставки двух баннеров на страницах:

    				
    <?php if(is_page(70) OR is_page('РАДИОВЕДУЩИЕ') ) {	
    ?>
    <div id="top-advertising" class="hidden-sm hidden-xs">
    	<div class="container" style="position: relative;">
            <div class="row">
                <div class="col-md-12">
    			<?php echo do_shortcode("[metaslider id=344]"); ?>
                </div>
            </div>
    	</div>
    </div>
    <?php } else {?>
    
    <div id="top-advertising" class="hidden-sm hidden-xs">
    	<div class="container" style="position: relative;">
            <div class="row">
                <div class="col-md-12">
    			<?php echo do_shortcode("[metaslider id=348]"); ?>
                </div>
            </div>
    	</div>
    </div>
    <?php } ?>
    <!-- Top Banner -->
    				
    			

    При создании слайд-баннера ему автоматически присваивается ID, который видно в настройках Meta Slider в разделе "Использование" - там приводится как шорт-код, так и php-код для вставки в шаблон.

    Плагин Full Width Background Slider

    Этот слайдер создает изменяющийся бэкграунд страницы. Смотрится привлекательно. При его активации в редактировании страниц и постов появляется новая настройка

    и можно выбрать - показывать его на данной странице - или нет.

    Этот слайд-бэкграунд автоматически подключается к странице выдачи постов, то есть к index.php. Чтобы не показывать его на этой странице мы вставили в коде этой страницы перед подключением футера (именно в футере этот плагин подключает скрипт и ссылки на картинки для баннера) написали следующий стиль для блока с картинками:
    				
    . . .
    <style type="text/css" media="screen">
    <!--
    #fwbslider{display:none !important;}
    	-->
    <!--
    a.fwb_fromthis {display:none !important;}
    	-->	
    </style>
    <?php get_footer(); ?>
    . . .
    				
    			
    Кроме того, мы убрали вывод логотипа производителя с сылкой на его сайт, вставив в странице page.phpследующий стиль для этого логатипа:
    				
    				. . .
    <style type="text/css" media="screen">
    <!--
    a.fwb_fromthis {display:none !important;}
    	-->
    </style>
    	
    <?php get_footer(); ?>
    				. . .
    				
    			

    Вцелом, не очень ясно где и для чего его использовать этот слайдер для фона страниц?

    Плагин NextGEN Gallery













    БД WordPress

    Cтруктура строки массивов

    Массивы и их значения хранятся в БД в виде строк специального формата, например:
    a:5:{s:13:"administrator";a:2:{s:4:"name";s:13:"Administrator";s:12:"capabilities";a:93:{s:13:"switch_themes";b:1;s:11:"edit_themes";b:1;s:16:"activate_plugins";b:1;. . .
    Разберем, что мы видим:

    • a:N:{ это начало массива, где "N" – количество элементов массива. Например, "a:5:{" в начале строки означает, что массив состоит из пяти элементов.
    • s:N:"строка"; – "s" это строковый тип, N – количество символов в строке. Например, s:6:"author";
    • b:1; – означает логический (Boolean) тип со значением "1" or "True" (Истина)









    Разберём шаблон twentysixteen

    Первым загружается файл index.php. Вот его код:

    							
    <?php
    /**
     * The main template file
     *
     * This is the most generic template file in a WordPress theme
     * and one of the two required files for a theme (the other being style.css).
     * It is used to display a page when nothing more specific matches a query.
     * E.g., it puts together the home page when no home.php file exists.
     *
     * @link http://codex.wordpress.org/Template_Hierarchy
     *
     * @package WordPress
     * @subpackage Twenty_Sixteen
     * @since Twenty Sixteen 1.0
     */
    
    get_header(); ?>
    
    	<div id="primary" class="content-area">
    		<main id="main" class="site-main" role="main">
    
    		<?php if ( have_posts() ) : ?>
    
    			<?php if ( is_home() && ! is_front_page() ) : ?>
    				<header>
    					<h1 class="page-title screen-reader-text"><?php single_post_title(); ?></h1>
    				</header>
    			<?php endif; ?>
    
    			<?php
    			// Start the loop.
    			while ( have_posts() ) : the_post();
    
    				/*
    				 * Include the Post-Format-specific template for the content.
    				 * If you want to override this in a child theme, then include a file
    				 * called content-___.php (where ___ is the Post Format name) and that will be used instead.
    				 */
    				get_template_part( 'template-parts/content', get_post_format() );
    
    			// End the loop.
    			endwhile;
    
    			// Previous/next page navigation.
    			the_posts_pagination( array(
    				'prev_text'          => __( 'Previous page', 'twentysixteen' ),
    				'next_text'          => __( 'Next page', 'twentysixteen' ),
    				'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'twentysixteen' ) . ' </span>',
    			) );
    
    		// If no content, include the "No posts found" template.
    		else :
    			get_template_part( 'template-parts/content', 'none' );
    
    		endif;
    		?>
    
    		</main><!-- .site-main -->
    	</div><!-- .content-area -->
    
    <?php get_sidebar(); ?>
    <?php get_footer(); ?>
    		
    	

    В этом коде вызываются 9 функций, а именно:

    # Имя фунции Source File Описание
    1 get_header() wp-includes/general-template.php. the header.php template file from your current theme's directory. If a name is specified then a specialised header header-{name}.php will be included. If the theme contains no header.php file then the header from the default theme wp-includes/theme-compat/header.php will be included.
    2 have_posts() wp-includes/query.php This function checks to see if the current WordPress query has any results to loop over. This is a boolean function, meaning it returns either TRUE or FALSE..
    3 single_post_title() wp-includes/general-template.php Display or retrieve page title for post. This is optimized for single.php template file for displaying the post title. It does not support placing the separator after the title, but by leaving the prefix parameter empty, you can set the title separator manually. The prefix does not automatically place a space between the prefix, so if there should be a space, the parameter value will need to have it at the end..
    4 the_post() wp-includes/query.php. Iterate the post index in The Loop. Retrieves the next post, sets up the post, sets the 'in the loop' property to true.
    5 get_template_part wp-includes/general-template.php Load a template part into a template Makes it easy for a theme to reuse sections of code in a easy to overload way for child themes. Includes the named template part for a theme or if a name is specified then a specialised part will be included. If the theme contains no {slug}.php file then no template will be included. The template is included using require, not require_once, so you may include the same template part multiple times. For the $name parameter, if the file is called “{slug}-special.php” then specify “special”..
    6 get_post_format() wp-includes/post-formats.php Retrieve the format slug for a post
    7 the_posts_pagination wp-includes/link-template.php Display a paginated navigation to next/previous set of posts, when applicable.
    8 get_sidebar() wp-includes/general-template.php Load sidebar template. Includes the sidebar template for a theme or if a name is specified then a specialised sidebar will be included. For the parameter, if the file is called “sidebar-special.php” then specify “special”.
    9 get_footer() wp-includes/general-template.php the footer.php template file from your current theme's directory. if a name is specified then a specialised footer footer-{name}.php will be included. If the theme contains no footer.php file then the footer from the default theme wp-includes/theme-compat/footer.php will be included.

    Первая функция get_header() вставляет файл header.php из нашего шаблона. Как он должен выглядеть? Посмотрим, например, хёдер из шаблона Twentysixteen:

    							
    <?php
    /**
     * The template for displaying the header
     *
     * Displays all of the head element and everything up until the "site-content" div.
     *
     * @package WordPress
     * @subpackage Twenty_Sixteen
     * @since Twenty Sixteen 1.0
     */
    
    ?><!DOCTYPE html>
    <html <?php language_attributes(); ?> class="no-js">
    <head>
    	<meta charset="<?php bloginfo( 'charset' ); ?>">
    	<meta name="viewport" content="width=device-width, initial-scale=1">
    	<link rel="profile" href="http://gmpg.org/xfn/11">
    	<?php if ( is_singular() && pings_open( get_queried_object() ) ) : ?>
    	<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>">
    	<?php endif; ?>
    	<?php wp_head();?>
    </head>