Рубрики
Wordpress

Создание произвольных форм в WordPress

Метод создания произвольных форм реализован с помощью плагина Oi Forms.

Скачать последнюю версию плагина Oi Forms для создания произвольных полей в WordPress можно на странице релизов тут.

Тестовая форма:

Чтобы протестировать форму, распакуйте файл и поместите его в папку oi-forms, предварительно создав ее в папке активной темы. В админке WordPress создайте новую страницу и разместите на ней шорткод:

[form form_id="Theme-PostTitle"]

Убедитесь, что плагин Oi Forms активирован.

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

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

Рубрики
PHP

БЭМ в PHP для WordPress

К хорошему привыкаешь быстро, особенно, когда верстаешь страницу в стеке Vue + Pug + Bem!

На мой взгляд это наиболее удобный стек для верстки.

Вот как выглядит код на этом стеке:

+b.product
	+e.inner
		+e.image
		+e.info
			+e.H2.title {{ product.title }}
			+e.price._new {{ product.price }}

А так этот же код выглядит на чистом HTML:

<div class="product">
	<div class="product__inner">
		<div class="product__image"></div>
		<div class="product__info">
			<h2 class="product__title">{{ product.title }}</h2>
			<div class="product__price product__price_new">{{ product.price }}</div>
		</div>
	</div>
</div>

Как видно из примера – вместо каждого +e дописывается название, взятое из предыдущего +b.

Синтаксис таков:

  • Часть названия класса, которая идет после точки компилируется в имя дочернего элемента:+e.inner > product__inner;
  • Часть названия класса, которая идет после точки и начинается с символа нижнего подчеркивания компилируется в имя миксина: +e.price._new > product__price product__price_new;

Работая с WordPress реализовать такую роскошь для создания шаблонов сложно, хотя можно… но кому это вообще надо? )

Делая очередной шаблон страницы на WordPress я очень скучал по простому созданию классов в стиле БЭМ и решил хоть как-тот облегчить себе задачу.

Техническое задание

Без использования шаблонизатора не удастся легко и просто реализовать работу через псевдо-переменные +b и +e, поэтому придется придумать что-то попроще.

Должен быть реализован синтаксис создания классов дочерних элементов и миксинов.

  1. Если указано название класса, не начинающееся с точки, это должен быть родительский класс, например product;
  2. Если за родительским классом идет один или более классов, начинающихся с точки, после которой нет символа нижнего подчеркивания, то должно быть создано столько экземпляров дочерних классов, сколько объявлено, например: product.one.two.three > product__one product__two product__three;
  3. Если после точки идет символ нижнего подчеркивания – это миксин и он должен быть дописан к каждому классу, например: product.one.two.three._first._second > product__one product__two product__three product__one_first product__one_second product__two_first product__two_second product__three_first product__three_second.

Реализация

Я хочу, чтоб это было максимально просто, на сколько это возможно в условиях создания шаблонов в WordPress, то есть в условия написания кода на чистом PHP.

Пусть функция будет называться bem и для начала пусть она принимает один параметр – строку, которая является цепочкой частей классов:

bem('product.one.two.three._first._second');

Объявим функцию:

function bem( $classTrail = '' ) {
	if ( empty( $classTrail ) ) {
		return '';
	}
}

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

Далее следует разбить строку на массив:

$classTrail = array_values( array_filter( explode( '.', $classTrail ) ) );

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

$mixins  = [];
$classes = [];
$block   = '';
$count   = sizeof( $classTrail );

Далее делаем перебор нашего массива $classTrail:

foreach ( $classTrail as $i => $item ) {
    // код
}

Первым делом следует к составному элементу $block приписать название родительского класса, в нашем случае это product. Это следует сделать только в том случае, если мы на первой итерации:

if ( 0 === $i ) {
	$block = $classTrail[ $i ];
}

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

if ( 0 === $i ) {
	$block = $classTrail[ $i ];

	if ( 1 == $count ) {
		$classes[] = $block;
	}
}

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

if ( 0 === strpos( $classTrail[ $i ], '_' ) ) {
    // код
}

И если это миксин, сразу добавим его в список миксинов:

if ( 0 === strpos( $classTrail[ $i ], '_' ) ) {
	$mixins[] = $classTrail[ $i ];
}

Если при этом в нашей цепочке всего 2 элемента, это означает, что указан родительский класс и миксин: product._new, в этом случае следует часть составного класса добавить в список классов:

if ( 0 === strpos( $classTrail[ $i ], '_' ) ) {
	$mixins[] = $classTrail[ $i ];
	if ( 2 == $count ) {
		$classes[] = $block;
	}
}

В ином случае, если это не миксин, мы понимаем, что это дочерний класс, который сразу добавим в список классов:

if ( 0 === strpos( $classTrail[ $i ], '_' ) ) {
	$mixins[] = $classTrail[ $i ];
	if ( 2 == $count ) {
		$classes[] = $block;
	}
}
else {
	$classes[] = $block . '__' . $classTrail[ $i ];
}

Таким образом мы составили список классов и миксинов:

$mixins  = [];
$classes = [];
$block   = '';
$count   = sizeof( $classTrail );
foreach ( $classTrail as $i => $item ) {
	if ( 0 === $i ) {
		$block = $classTrail[ $i ];

		if ( 1 == $count ) {
			$classes[] = $block;
		}
	}
	else {

		if ( 0 === strpos( $classTrail[ $i ], '_' ) ) {
			$mixins[] = $classTrail[ $i ];
			if ( 2 == $count ) {
				$classes[] = $block;
			}
		}
		else {
			$classes[] = $block . '__' . $classTrail[ $i ];
		}
	}
}

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

foreach ( $classes as $i => $class ) {
	foreach ( $mixins as $j => $mixin ) {
		$classes[] = $classes[ $i ] . $mixin;
	}
}

Работа практически завершена, но лично у меня есть потребность создавать различные наборы классов. Скажем одна цепочка служит для создания набора классов для описания внешнего вида, вторая для указания селекторов для использования в JS, например:

bem('product._new js.product');
// в результатае будет: product product_new js__product

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

$trails = [];

$classTrails = array_values( array_filter( explode( ' ', $classTrail ) ) );

foreach ( $classTrails as $classTrail ) {

	$classTrail = array_values( array_filter( explode( '.', $classTrail ) ) );

	$mixins  = [];
	$classes = [];
	$block   = '';
	$count   = sizeof( $classTrail );
	foreach ( $classTrail as $i => $item ) {
		if ( 0 === $i ) {
			$block = $classTrail[ $i ];

			if ( 1 == $count ) {
				$classes[] = $block;
			}
		}
		else {

			if ( 0 === strpos( $classTrail[ $i ], '_' ) ) {
				$mixins[] = $classTrail[ $i ];
				if ( 2 == $count ) {
					$classes[] = $block;
				}
			}
			else {
				$classes[] = $block . '__' . $classTrail[ $i ];
			}
		}
	}

	foreach ( $classes as $i => $class ) {
		foreach ( $mixins as $j => $mixin ) {
			$classes[] = $classes[ $i ] . $mixin;
		}
	}

	$trails = array_merge( $trails, $classes );
}

Теперь осталось вернуть результат. Его можно вернуть в виде:

  • массива;
  • строки;
  • строки вида class="product product_new".

Для этого я ввел еще два входных параметра в функции, мне удобно было именно так:

  • $toAttribute = false – венуть классы внутри атрибута class;
  • $isArray = true – вернуть массив.
bem('product._new js.product', true);
// вернет class="product product_new"

bem('product._new js.product', false, false);
// вернет 'product product_new'

bem('product._new js.product');
// вернет массив

Полный код функции

/**
 * Function that creates the classes chain in BEM style
 *
 * @param string $classTrail
 * @param bool   $toAttribute
 * @param bool   $isArray
 *
 * @return array|string
 */
function bem( $classTrail = '', $toAttribute = false, $isArray = true ) {
	if ( empty( $classTrail ) ) {
		return '';
	}

	$trails = [];

	$classTrails = array_values( array_filter( explode( ' ', $classTrail ) ) );

	foreach ( $classTrails as $classTrail ) {

		$classTrail = array_values( array_filter( explode( '.', $classTrail ) ) );

		$mixins  = [];
		$classes = [];
		$block   = '';
		$count   = sizeof( $classTrail );
		foreach ( $classTrail as $i => $item ) {
			if ( 0 === $i ) {
				$block = $classTrail[ $i ];

				if ( 1 == $count ) {
					$classes[] = $block;
				}
			}
			else {

				if ( 0 === strpos( $classTrail[ $i ], '_' ) ) {
					$mixins[] = $classTrail[ $i ];
					if ( 2 == $count ) {
						$classes[] = $block;
					}
				}
				else {
					$classes[] = $block . '__' . $classTrail[ $i ];
				}
			}
		}

		foreach ( $classes as $i => $class ) {
			foreach ( $mixins as $j => $mixin ) {
				$classes[] = $classes[ $i ] . $mixin;
			}
		}

		$trails = array_merge( $trails, $classes );
	}

	if ( ! empty( $toAttribute ) ) {
		return ' class="' . join( ' ', $trails ) . '" ';
	}

	// if $isArray is false
	if ( empty( $isArray ) ) {
		$trails = join( ' ', $trails );
	}

	// return classes as array
	return $trails;
}

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

Благодаря данной функции наш шаблон станет выглядеть так:

<div <?php echo bem( 'product', true ); ?>>
	<div <?php echo bem( 'product.inner', true ); ?>>
		<div <?php echo bem( 'product.image', true ); ?>></div>
		<div <?php echo bem( 'product.info', true ); ?>>
			<h2 <?php echo bem( 'product.title', true ); ?>>{{ product.title }}</h2>
			<div <?php echo bem( 'product.price', true ); ?>>{{ product.price }}</div>
		</div>
	</div>
</div>

Кому-то может показаться, что стало хуже… но этот только в том случае, если вы не работаете с БЭМ, да еще и в WordPress ))

Могу сказать, что на практике это упростит читабельность классов и сделает их более структурированными.

Рубрики
Wordpress

Как изменить имя и адрес отправителя WordPress

При различных событиях в WordPress система отправляет письма пользователям и администратору сайта и подставляет стандартные имя и адрес отправителя WordPress. Это могут быть письма отправляемые при регистрации, восстановлении пароля, регистрации нового пользователя, нового блога(при включенном режиме multisite) и все письма отправляются с адреса по умолчанию WordPress <wordpress@mysite.ru>, где mysite.ru – это домен Вашего сайта. Есть множество случаев, когда это не приемлемо. Например, если сайт является корпоративным сайтом компании и необходимо, чтобы вся корреспонденция исходила от действующего адреса компании, например info@company.ru.

Рубрики
Wordpress

Создание произвольных таблиц в WordPress

При создании плагина для WordPress может возникнуть необходимость сохранять данные в базу данных WordPress. Есть несколько способов решения данной задачи. Можно создать страницу настроек, используя Settings API, либо сохранять данные прямо в таблицу с опциями, используя update_option() и get_option() или создать свою собственную таблицу в базе данных.

В данном примере будет рассмотрена возможность создания произвольной таблицы с использованием возможностей WordPress.

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

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

Создание таблиц wordpress при активации плагина

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

В основном файле плагина вы можете написать следующий код:

register_activation_hook( __FILE__, 'create_plugin_tables' );
function create_plugin_tables()
{
	// введите код создания таблиц
}

При создании таблиц в WordPress важно соблюдать стандарты и не забыть указать префиксы таблиц. Стандартным префиксом является сочетание wp_, но вы можете изменить этот префикс либо во время установки WordPress, либо отредактировав файл wp-config.php. Для того, что бы избежать ошибки указания префика необходимо использовать данные из объекта $wpdb.

function create_plugin_tables()
{
	global $wpdb;
	// префикс текущего сайта
	echo $wpdb->prefix . 'tablename';

	// мультисайт, оригинальный префикс
	echo $wpdb->base_prefix . 'tablename';
}

Разница между свойствами prefix и base_prefix видна при использовании режима мультисайт. При использовании $wpdb->prefix возвращается префикс для текущего сайта, а при использовании $wpdb->base_prefix возвращается значение указанное в wp-config.php.

Для создания таблицы в WordPress необходимо написать SQL запрос и поместить его в специальную переменную, чтобы потом вставить в функцию dbDelta().

function create_plugin_tables()
{
	global $wpdb;
	$table_name = $wpdb->prefix . 'tablename';
	$sql = "CREATE TABLE $table_name (
			id int(11) NOT NULL AUTO_INCREMENT,
			name varchar(255) DEFAULT NULL,
			UNIQUE KEY id (id)
	);";
	require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
	dbDelta( $sql );
}


Функция dbDelta() проверит базу данных на предмет существования в ней таблицы, указанной в запросе, и если такая таблица уже существует запрос не будет выполняться повторно.

Что бы функция dbDelta() была доступна, перед ее вызовом надо позаботиться о том, что бы подключить содержащий ее файл /wp-admin/includes/upgrade.php.

После того, как плагин будет вновь активирован таблица будет создана.

Добавление информации в произвольную таблицу

Для добавления данных во вновь созданную таблицу потребуется вновь использовать объект $wpdb, который содержит метод insert(). Этот метод позволяет добавлять данные в существующие таблицы.

Метод insert() имеет три параметра: название таблицы, массив данных для вставки и формат вставляемых данных. Формат данных указывается для предотвращения конфликтов типов данных.

function insert_custom_table()
{
	global $wpdb;
	$wpdb->insert(
			'table',
			array(
				'id' => 1,
				'name' => 'John'
			),
		array(
			'%d',
			'%s'
		)
	);
}

Получение данных из произвольной таблицы

Для извлечения данных из таблицы используется все тот же $wpdb объект. Есть два способа получить данные, метод $wpdb->get_row() и метод $wpdb->get_results().

Метод get_row() возвращает только одну строку, его следует использовать при запросе первичного ключа таблицы.

function get_by_id( $id )
{
	global $wpdb;
	$table_name = $wpdb->prefix . 'tablename';
	$row = $wpdb->get_row( $wpdb->prepare('SELECT * FROM '.$table_name.' WHERE id = %d', $id) );
	return $row;
}


Метод get_results() вернет все строки, удовлетворяющие строке запроса.

function get_by_name( $name )
{
	global $wpdb;
	$table_name = $wpdb->prefix . 'tablename';
	$results = $wpdb->get_results( $wpdb->prepare('SELECT * FROM '.$table_name.' WHERE name = %s', $name) );
	return $results;
}

Для выполнения каких-либо функций при дизактивации плагина используют хук – register_deactivation_hook().

Удаление таблицы при деинсталяции плагина

Чтобы удалить таблицу при деинсталяции плагина используется хук – register_uninstall_hook().

register_uninstall_hook( __FILE__, 'drop_plugin_tables');
function drop_plugin_tables()
{
	//drop a custom db table
	global $wpdb;
	$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'tablename' );
}

Подробнее об объекте $wpdb читайте здесь(статья на английском).

Рубрики
Wordpress

Плагин – Яндекс.Карты для WordPress

Я написал плагин для Яндекс.Карты для WordPress.
История создания подобного плагина началась давно, в конце 2011 года. Тогда работа с Яндекс.Картами была одной из возможностей системы управления сайтом агентства недвижимости. Спустя некоторое время необходимость публиковать карты с указанием каких-либо объектов возникла и на других сайтах, которые я разрабатывал.

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

Плагин Яндекс.Карт корректно работает со всеми современными версиями WP.
Устанавливайте, комментируйте, пишите замечания.

Скачать Яндекс.Карты для WordPress:

Скачать плагин можно тут.

Рубрики
Wordpress

Неудачное обновление WordPress

Если при обновлении Wordpress ошибка и система не обновилась до конца и теперь вы видите сообщение “Brieflyunavailable for scheduled maintenance. Check back in a minute.”