Verification: a143cc29221c9be0

Php array diff многомерный массив

Список шорткодов WordPress

В WordPress по умолчанию регистрируются следующие шорткоды:

  • [audio]
  • [wp_caption] или [caption]
  • [embed]
  • [gallery]
  • [video]
  • [playlist]

Синтаксис шорткода

Шорткоды WordPress используют Квадратные скобки [], потому что они не являются частью какого-либо языка. Синтаксис выглядит так:

[name]

[name /]

[name attribute="value" /]

[name attr1='value1' attr2="value2" ]

[name]Контент шорткода.[/name]

[name attr="value"]Контент шорткода.[/name]

Само-закрытие (self-closing)

Шорткод можно закрыть слэшем в конце (такой слэш называется self-closing маркером).

[example /]

Пробел перед маркером необязателен. Пробелы после маркера не допускаются. Такой маркер является чисто косметическим и ни на что не влияет.

Контентные шорткоды не могут использовать self-closing маркер.

меню

Имя шорткода

Имя шорткода не может содержать следующие символы: [ ] & / ' " - \x00-\x20 \s \n\ t:

  • Квадратные скобки: []
  • Угловые скобки:
  • Амперсанд: &
  • Косая черта: /
  • Невидимые символы: пробел, перевод строки, tab
  • Непечатные символы: \x00 - \x20
  • Кавычки: ' "

Тире - разрешается в названии шорткода и оно не вызывает никаких конфликтов! Однако в официальной документации сказано что могут быть конфликты - это устаревшая информация.

меню

Атрибуты шорткода

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

Каждый атрибут должен соответствовать одному из этих форматов:

[name attribute = 'value']

[name attribute = "value"]

[name attribute = value]

[name "value" "value2"]

[name "value"]

[name value]

Пробел допускается до и после знака =: attr = value, attr= value, attr =value.

Имя атрибута

Может содержать только следующие символы: 0-9 A-Z a-z _ - (пробелы в именах запрещены):

  • Прописные и строчные буквы: A-Za-z.
  • Числа: 0-9.
  • Нижнее подчеркивание: _.
  • Дефис: -.

Имя атрибута может быть в любом регистре. После парсинга имя всегда будет в нижнем регистре: aTtR=value тоже что и attr=value.

Значение атрибута

Значение атрибута не может содержать следующие символы [ ] " '.

Заметки по значению атрибута:

  • Кавычки атрибута. Двойные кавычки " допускаются внутри значений в одинарных кавычках ' и наоборот: [name foo='1 "2" 3' bar="4 '5' 6"]

  • Кавычки атрибута. Конструкция шорткода может использовать двойные или одинарные кавычки для выделения значений атрибута, или вообще их не использоваться, если в значении нет пробела. [name foo='123' bar=456] тоже что и [name foo="123" bar="456"].

  • Атрибут без имени. Имя атрибута можно не указывать. В этом случае имя атрибута будет индекс массива $atts. Например [name 123] создаст такие параметры: $atts = array( 0 => 123 ). Такие «позиционные» атрибуты можно использовать вместе с обычными, а кавычки можно использовать когда значение содержит пробелы или другие необычные символы.

  • Квадратные скобки. Так делать нельзя: [name foo="[value]"].

  • Экранировать спец-символы в атрибутах можно через кодирование HTML символов (HTML encoding).

  • HTML символы и > поддерживаются в атрибутах ограничено. Например, этот шорткод не будет правильно работать, из-за символа >:

    [name value1="35" value2="25" compare=">"]

    Версия 4.0 умеет проверять HTML, так что следующий код будет работать:

    [name description="Greetings"]

    Чтобы полностью поддерживать HTML в атрибутах можно, сначала кодировать вводимые пользователем значения, а затем декодировать при обработке.

  • Удаляемые символы. Следующие символы, если они не экранированы, будут:

    • Неразрывный пробел (No-break space): \xC2\xA0 — заменится пробелом.
    • Безразмерный Пробел (Zero-width space): \xE2\x80\x8B — удалится.
меню

Экранирование

Экранирование нужно, когда шорткод зарегистрирован, но его не нужно обрабатывать, а нужно показать как есть. Не зарегистрированный шорткод и так не будет обрабатываться.

Для экранирования нужно обрамить шорткод еще одними квадратными кавычками:

[[name attributes]]

[[name attributes]Любой HTML или Шорткоды.[/name]]

Другой вариант: заменить символы [] их HTML сущностями [ ]. Например [name] можно записать так: [name].

Вложенные шорткоды

Парсинг шорткодов срабатывает один раз для контента. Это значит, что если в Контентном шорткоде есть вложенный шорткод, он не будет обработан:

[name]Foo: [my_name][/name]

Обработается так:

Foo: [my_name]

Одинаковое название

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

[tag_a]
   [tag_a]
   [/tag_a]
[/tag_a]

Как это работает

При добавлении шорткода через add_shortcode() шорткод добавляется в глобальную переменную $shortcode_tags (добавляется имя и функция-обработчик).

На хуке the_content срабатывает функция do_shortcode(), которая ищет и обрабатывает все шорткоды в контенте.

Все найденные шорткоды по-очереди передаются в функцию do_shortcode_tag(). Эта функция обрабатывает данные найденные регуляркой и вызывает добавленную в $shortcode_tags функцию-обработчик шорткода (с параметрами $attr, $content, $tag).

То что вернула функция-обработчик заменят шорткод в контенте.

До срабатывания функции do_shortcode() (до парсинга шорткодов), контент обрабатывается тремя ключевыми функциями:

  • do_blocks()
  • wptexturize()
  • wpautop()
add_filter( 'the_content', 'do_blocks', 9 );
add_filter( 'the_content', 'wptexturize' );
add_filter( 'the_content', 'wpautop' );

add_filter( 'the_content', 'do_shortcode', 11 ); // AFTER wpautop().

do_shortcode() парсит контент одной регуляркой get_shortcode_regex(), поэтому добавление еще одного шорткода никак не замедляет скорость обработки - регулярка все равно будет отрабатывать.

меню

Создание шорткода

Для создания шорткода используется функция add_shortcode(). Она принимает два параметра: имя шорткода и название PHP функции, которая будет обрабатывать шорткод.

Вот самый простой PHP-код который регистрирует новый шорткод [foobar]:

add_shortcode( 'foobar', 'foobar_shortcode' );

function foobar_shortcode( $atts ){
	return 'Привет! Я шорткод.';
}

Теперь [foobar] в контенте записи изменяться на строку: «Привет! Я шорткод.»

Атрибуты шорткода

Давайте добавим поддержку атрибутов шорткоду из примера выше. Для этого используем функцию shortcode_atts():

add_shortcode( 'foobar', 'foobar_shortcode' );
function foobar_shortcode( $atts ) {

	$atts = shortcode_atts( [
		'name' => 'Noname',
		'age'  => 18,
	], $atts );

	return "Меня зовут {$atts['name']} мне {$atts['age']} лет";
}

Теперь [foobar name="Виктор" age="25"] в контенте измениться на строку: «Меня зовут Виктор мне 25 лет».

shortcode_atts() определяет какие у шорткода могут быть атрибуты, задает им дефолтные значения и удаляет неопознанные атрибуты.

shortcode_atts( $defaults, $atts );
$defaults

Ассоциативный массив который описывает возможные атрибуты шорткода (это ключи массива) и их дефолтные значения.

ВАЖНО! Ключи массива $defaults должны быть в lower-case. Не используйте camelCase или UPPER-CASE, потому что в $atts ключи всегда в lower-case.

$atts

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

$atts будет содержать массив аргументов шорткода, которые были указанны пользователем.

Если указать значение без названия параметра, то они будут добавлены в индексные элементы массива. Например для шорткода [name value attr="val2" val3] получим:

Array (
	[0]    => value
	[attr] => val2
	[1]    => val3
)

Имена атрибутов (ключи массива $atts) всегда конвертируются в lower-case (нижний регистр), значения никак не обрабатываются. Например, если мы указали шорткод так [myshortcode FOO="BAR"], то в $atts получим [ 'foo' => 'BAR' ].

Рассмотрим еще один пример.

Пусть мы указали в контенте шорткод [myname foo="456" bar="something"]. Тогда:

add_shortcode( 'myname', 'bartag_func' );

function my_shortcode_handler( $atts ) {

	/*
	$atts = [
		'foo' => 456,
		'bar' => 'something'
	]
	*/

	$data = shortcode_atts( [
		'title' => 'My Title',
		'foo'   => 123,
	], $atts );

	/*
	$data = [
		'title' => 'My Title',
		'foo'   => 456
	]
	*/
}

Из кода видно, что приняли мы одни данные, а получили после обработки другие. Что изменилось?

  • Полученное значение $atts['foo'] перезаписало значение по умолчанию.
  • Полученный элемент $atts['bar'] был удален, потому что его нет в списке возможных аргументов.
  • Недостающий элемент $atts['title'] был добавлен со значением по умолчанию.
меню

Вывод функции обработчика

Возвращаемое значение функции обработчика шорткода вставляется в контент записи вместо самого шорткода.

Результат функции-обработчика шорткода всегда должен возвращаться, а не выводиться на экран. Используйте return, а не echo в функции обработчике.

Буфиризация вывода

Если в шорткоде используется много HTML кода, то для удобства можно использовать функцию ob_start(), чтобы буферизировать вывод и затем его вернуть:

function my_shortcode(){
	ob_start();

	?>   ...  меню

Контентные шорткоды

Примеры выше показывали как создавать «Одиночные» (self-closing) шорткоды: [name]. Но кроме них есть еще «Контентные» (enclosing) шорткоды: [name]Контент[/name].

Для Enclosing шорткода функция-обработчик получит второй параметр содержащей контент.

function my_shortcode( $atts, $content )

Зарегистрированный шорткод всегда можно использовать как Одиночный или Контентный, поэтому при регистрации шорткода желательно всегда указывать значение по умолчанию для второго параметра $content.

Или можно использовать проверку empty( $content ) для разделения обработки данных Контентного и Одиночного шорткодов. Т.е. получается один шорткод можно использовать как два разных, в зависимости от того как он был использован.

Рассмотрим пример:

add_shortcode( 'name', 'my_shortcode' );

function my_shortcode( $atts, $content ) {
	return '' . $content . '';
}

Теперь если написать шорткод так:

[name]My Caption[/name]

Получим такой результат:

My Caption

$content передается в функцию без какой-либо очистки, поэтому в нём может быть HTML:

[name]http://example.com/">My Caption[/name]

Получим:


	My Caption

Иногда наоборот, когда HTML недопустим нужно очищать вывод, удаляя все HTML теги функцией wp_strip_all_tags().

Атрибуты в Контентном шорткоде

В Контентном шорткоде можно также как и в Одиночном, указать атрибуты. Например разрешим атрибут class:

function my_shortcode( $atts, $content ) {

	$data = shortcode_atts( [
		'class' => 'caption',
	], $atts );

	return '' . $content . '';
}

/*
[name class="headline"]My Caption[/name]

My Caption
*/

Вложенные шорткоды

Если в Контентном шорткоде есть вложенный шорткод, он не будет обработан.

[tag_a]
   [tag_b size="24"]
	  [tag_c]
   [/tag_b]
[/tag_a]

Поэтому если все же нужно нужно обработать шорткод внутри шорткода, то при обработке контента первого шорткода, нужно использовать функцию do_shortcode(), чтобы обработать вложенные шорткоды.

function my_shortcode( $atts, $content ) {
	return '' . do_shortcode( $content ) . '';
}
меню

Удаление шорткода

Для удаления (де-регистрации) используется Функция remove_shortcode( $name ).

Удалять шорткод нужно после того как он был добавлен, поэтому вызывать эту функцию лучше во время события init.

Для примера, давайте представим что плагин регистрирует шорткод [awesome], а нам он мешает. Удалим его так:

add_action( 'init', 'unregister_shortcodes', 20 );
function unregister_shortcodes(){
	remove_shortcode( 'awesome' );
}

Также в Shortcode API есть функция которая удаляет все зарегистрированные шорткоды разом: см. remove_all_shortcodes().

меню

PHP Функции

Полный список функций.

меню

Конфигурационный файл

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

Листинг 1. Конфигурационный файл скрипта phpldapread.php

#LDAP сервер для подключения ldap_server=10.54.200.1 #Base DN для подключения ldap_basedn="dc=shelton,dc=int" #Bind DN для подключения [email protected] #Пароль для пользователя, от имени которого будет выполняться подключение ldap_password="cXdlcnR5YXNkZgo 1" #Фильтр отбора записей. Он означает: отобрать объекты типа Пользователь, # у которых не установлено свойство "Заблокировать учетную запись" ldap_common_filter="(&(!(userAccountControl:1.2.840.113556.1.4.803:=2)) (sAMAccountType=805306368))" #Игнорировать перечисленных пользователей - это системные объекты ignore_list="SQLAgentCmdExec,SMSService,SMSServer_001, wsus" #Каталог, куда будет сохранен файл etcdir=/tmp #Имя файла со списком sarglist=sargusers

Зависимости, вспомогательные функции

Для работы скрипта потребуются дополнительные компоненты pear-Config и pear-Console_Getopt, а также расширение языка php-ldap. Pear-Config потребуется для чтения конфигурационного файла, pear-Console_Getopt - для разбора параметров командной строки. Надо сказать, рассматривается не весь скрипт: такие вопросы, как чтение конфигурационного файла, отображение справки или разбор командной строки являются вопросами уже достаточно хорошо описанными, поэтому соответствующие функции будут опущены, полную версию скрипта можно скачать с . Рассмотрено будет только то, что непосредственно относится к чтению данных из AD, как сервера LDAP, и некоторые нестандартные вспомогательные функции.

Функция обратного преобразования пароля приведена в Листинге 2. Вся роль так называемой "защиты" - предотвратить случайную утечку (ту, что называется eyedropper) и не более того.

Листинг 2. Функция обратного преобразования пароля.

/* * Обратное преобразование пароля * @param string $converted преобразованный пароль * @return string $passwd пароль в текстовой форме */ function demux_passwd($converted) { $_conved = explode(" ", $converted); $_passwd = ""; if ($_conved != 0) for (;$_conved != 0; $_conved--) { $_conved = $_conved . "="; } $_passwd = base64_decode($_conved); return rtrim($_passwd); }

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

Функция перекодировки из UTF-8 в KOI8-R приведена в Листинге 3. Необходимость в этой функции возникает вследствие того, что консоль во FreeBSD не использует UTF-8.

Листинг 3. Функция перекодировки строки из UTF-8 в KOI8-R

/* * Перекодировать строку из UTF-8 в KOI8-R * @param string $source строка в кодировке UTF-8 * @return string $dest строка в кодировке KOI8-R */ function _from_utf8($source) { $converted = iconv("UTF-8", "KOI8-R", $source); return($converted); }

Кроме того, используется совершенно неинтересная функция safe_logger, в задачу которой входит вывод сообщений в лог или на консоль с завершением или без завершения работы скрипта. Все эти функции сохранены в файле utils.php.

Подключение к AD

Для подключения к AD используется функция ldap_server_connect, приведенная в Листинге 4. Функция выполняет все операции по подключению и возвращает идентификатор соединения для работы с сервером. Функция сохранена в отдельный файл ldapquery.php

Листинг 4. Функция подключения к серверу AD

require_once $PATH_LIB."/utils.php"; /* * Подключение к серверу LDAP * @param array $_config массив параметров конфигурации * @return resource $ldapconn идентификатор соединения с LDAP-сервером */ function ldap_server_connect($_config) { // Получить пароль в текстовом виде $_ldap_pwd = demux_passwd($_config["root"]["ldap_password"]); // Установить соединение с сервером if (!$ldapconn = ldap_connect($_config["root"]["ldap_server"])) safe_logger(sprintf("Невозможно подключиться к LDAP-серверу %s", $_config["root"]["ldap_server"]), "DIE"); // Для подключения к AD Windows 2003 и выше нужно установить эти опции ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0); // Авторизоваться на сервере ldap_bind($ldapconn, $_config["root"]["ldap_binddn"], $_ldap_pwd); return $ldapconn; }

На что хотелось бы обратить внимание здесь.

Во-первых, опции LDAP_OPT_PROTOCOL_VERSION ("версия протокола") и LDAP_OPT_REFERRALS ("отключить реферальные ссылки") должны быть обязательно установлены соответственно в 3 и 0 - без них можно увидеть странное: авторизация на сервере пройдет, но любой поиск будет возвращать ровно нуль записей.

Во-вторых, Bind DN должен быть задан в точности как в конфигурационном файле и никаким другим образом. Неверным будет в том числе и указание полного DN.

Проверка массива на пустоту и пустые элементы в PHP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$arr = [];
if(empty($arr)){
  echo 'Массив пустой';  
}else{
  echo 'Есть элементы';
}
// Выведет сообщение, что массив пустой
 
$arr = ['']; 
if(empty($arr)){
  echo 'Массив пустой';  
}else{
  echo 'Есть элементы';
}
// Массив будет не пустым даже если в нем только кавычки.

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

1
2
3
4
$arr = ['name', '', 'num', NULL, '', false, 'Alex', ''];
var_dump($arr);
$new_arr = array_diff($arr, array('', NULL, false));
var_dump($new_arr);

Получим следующее:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
array(8) {
  [0]=>
  string(4) "name"
  [1]=>
  string(0) ""
  [2]=>
  string(3) "num"
  [3]=>
  [4]=>
  string(0) ""
  [5]=>
  [6]=>
  string(4) "Alex"
  [7]=>
  string(0) ""
}
 
array(3) {
  [0]=>
  string(4) "name"
  [2]=>
  string(3) "num"
  [6]=>
  string(4) "Alex"
}

Функция пропустит все пустые элемент массива, в том числе NULL и false и выведет только те, в которых что-то есть. Мы так же можем проверить какой именно элемент массива был пустой с помощью цикла for.

1
2
3
4
5
6
7
8
$arr = ['name', '', 'num', NULL, '', false, 'Alex', ''];
for($i=0; $i  count($arr); $i++) {
 if (empty($arr[$i])){
echo "Элемент $i пустой"."
"
; }else{ echo "Элемент $i не пустой"."
"
; } }

В итоге получим это:

1
2
3
4
5
6
7
8
Элемент 0 не пустой
Элемент 1 пустой
Элемент 2 не пустой
Элемент 3 пустой
Элемент 4 пустой
Элемент 5 пустой
Элемент 6 не пустой
Элемент 7 пустой

Но массивы бывают разные, в том числе с ключами и значениями. И цикл for в этом случае тоже справится точно так же.

1
2
3
4
5
6
7
8
$arr=['age'=> 34,'name'=>'Ivan','city'=>'', 'number'=>''];
for($i=0; $i  count($arr); $i++) {
 if (empty($arr[$i])){
echo "Элемент $i пустой"."
"
; }else{ echo "Элемент $i не пустой"."
"
; } }

При желании можно принудительно удалить ключи массива, в которых пустые значения. Для этого задействуем цикл foreach и функцию unset.

1
2
3
4
5
6
7
8
$arr=['age'=> 34,'name'=>'Ivan','city'=>'', 'number'=>''];
var_dump($arr);
foreach ($arr as $key => $value) {
  if (empty($value)) { //проверrf на пустоту
    unset($arr[$key]); // Удаляем ключ массива
}
  }
var_dump($arr);

Получаем следующее:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
array(4) {
  ["age"]=>
  int(34)
  ["name"]=>
  string(4) "Ivan"
  ["city"]=>
  string(0) ""
  ["number"]=>
  string(0) ""
}
array(2) {
  ["age"]=>
  int(34)
  ["name"]=>
  string(4) "Ivan"
}