Вход Регистрация
Файл: system/libs/strings.helper.php
Строк: 601
<?php

/**
 * Разбивает строку по разделителю, затем собирает обратно в CamelCase
 * Например "my_own_string" => "MyOwnString", разделитель "_"
 *
 * @param char $delimiter Разделитель
 * @param string $string Исходная строка
 * @return string
 */
function string_to_camel($delimiter$string){

    
$result '';
    
$words explode($delimitermb_strtolower($string));

    foreach(
$words as $word){
        
$result .= ucfirst($word);
    }

    return 
$result;

}

/**
 * Вырезает теги <br> из строки
 * @param string $string
 * @return string
 */
function string_strip_br($string){

    return 
str_replace('<br>'''str_replace('<br/>'''$string));

}

/**
 * Возвращает значение языковой константы
 * Если константа не найдена, возвращает ее имя или значение по умолчанию
 *
 * Префикс LANG_ в имени константы можно не указывать
 * Регистр не имеет значения
 *
 * @param string $constant Название языковой константы
 * @param string $default
 * @return string
 */
function string_lang($constant$default=false){

    
$constant strtoupper($constant);

    if (!
$default) { $default $constant; }

    if (
strpos($constant'LANG_') === false){
        
$constant 'LANG_' $constant;
    }

    if (
defined($constant)){
        
$string constant($constant);
    } else {
        
$string $default;
    }

    return 
$string;

}

/**
 * Преобразует строку с маской URL в обычное регулярное выражение
 *
 * Пример:
 *      "my*mask is %st place" => "my(.*)mask is ([0-9]+) place"
 *
 * @param string $mask
 * @return string
 */
function string_mask_to_regular($mask){
    return 
str_replace(array(
        
'%','/','*','?','{slug}'
    
), array(
        
'([0-9]+)','/','(.*)','?','([a-z0-9-]*)'
    
), trim($mask));
}

/**
 * Разбивает текст на строки, а каждую строку на ID и VALUE, разделенные |,
 * формируя ассоциативный массив
 *
 * Пример входящей строки:
 *      "id1 | value1 n id2 | value2"
 *
 * Пример результата:
 *      array('id1' => 'value1', 'id2' => 'value2')
 *
 * @param string $string_list
 * @return array
 */
function string_parse_list($string_list){

    if (!
$string_list) { return array(); }

    
$user cmsUser::getInstance();

    
$rows explode("n"$string_list);

    
$list = array();

    foreach(
$rows as $row){

        if (!
$row) { continue; }

        
$row trim($row);

        if ( 
preg_match('/^{(.*)}$/i'$row$matches) ){
            if (!
$user->is_logged){ continue; }
            
$row trim($matches[1]);
        }

        if (!
mb_strstr($row'|')){
            
$list[] = array('value' => trim($row));
        } else {
            list(
$id$value) = explode("|"$row);
            
$list[] = array(
                
'id' => trim($id),
                
'value' => trim($value)
            );
        }

    }

    return 
$list;

}

function 
string_explode_list($string_list$index_as_value false){

    
$items = array();
    
$rows explode("n"trim($string_list));
    if (
is_array($rows)){
        foreach(
$rows as $count=>$row){
            if (
mb_strpos($row'|')){
                list(
$index$value) = explode('|'trim($row));
            } else {
                
$index $index_as_value $row : ($count 1);
                
$value $row;
            }
            
$items[trim($index)] = trim($value);
        }
    }
    return 
$items;

}

/**
 * Получает список аналогично string_parse_list() и ищет вхождение в него
 * заданной строки
 *
 * @param string $string
 * @param string $mask_list
 * @return boolean
 */
function string_in_mask_list($string$mask_list){

    if (!
$mask_list) { return false; }

    
$mask_list explode("n"$mask_list);

    foreach(
$mask_list as $item){

        
$regular string_mask_to_regular($item);
        
$regular "/^{$regular}$/iu";

        if (
preg_match($regular$string)){
            return 
true;
        }

    }

    return 
false;

}

/**
 * Генерирует случайную последовательность символов заданной длины
 * @param int $length
 * @return string
 */
function string_random($length=32$seed=''){

    
$rand_funct 'mt_rand';
    if (
function_exists('random_int')) {
        
$rand_funct 'random_int';
    }

    if(
function_exists('random_bytes')){
        
$salt bin2hex(random_bytes(128));
    } else {
        
$salt substr(md5(md5($rand_funct(0PHP_INT_MAX).md5(md5(cmsConfig::get('db_pass'))))), $rand_funct(016), $rand_funct(815));
    }

    
$string md5(md5(md5($salt) . chr($rand_funct(0127)) . microtime(true) . chr($rand_funct(0127))) . chr($rand_funct(0127)) . md5(md5($seed)));

    if (
$length 32) { $string substr($string0$length); }

    return 
$string;

}

/**
 * Выводит разницу между переданной датой и текущим временем
 * в виде читабельной строки со склонениями
 *
 * Пример вывода: "2 года 16 дней 5 часов 12 минут"
 *
 * @param string $date
 * @param array $options Массив элементов для перечисления: y, m, d, h, i, from_date
 * @param bool $is_add_back Добавлять к строке слово "назад"?
 * @return string
 */
function string_date_age($date$options$is_add_back=false){

    if (!
$date) { return; }

    
$date2 = !empty($options['from_date']) ? $options['from_date'] : false;

    
$diff real_date_diff($date$date2);

    
$diff_str = array();

    if (
in_array('y'$options) && $diff[0]){
        
$diff_str[] = html_spellcount($diff[0], LANG_YEAR1LANG_YEAR2LANG_YEAR10);
    }
    if (
in_array('m'$options) && $diff[1]){
        
$diff_str[] = html_spellcount($diff[1], LANG_MONTH1LANG_MONTH2LANG_MONTH10);
    }
    if (
in_array('d'$options) && $diff[2]){
        
$diff_str[] = html_spellcount($diff[2], LANG_DAY1LANG_DAY2LANG_DAY10);
    }
    if (
in_array('h'$options) && $diff[3]){
        
$diff_str[] = html_spellcount($diff[3], LANG_HOUR1LANG_HOUR2LANG_HOUR10);
    }
    if (
in_array('i'$options) && $diff[4]){
        
$diff_str[] = html_spellcount($diff[4], LANG_MINUTE1LANG_MINUTE2LANG_MINUTE10);
    }

    if (!
$diff_str) {
        return 
LANG_SECONDS_AGO;
    } else {
        
$diff_str trimimplode(' '$diff_str) );
        return 
$is_add_back sprintf(LANG_DATE_AGO$diff_str) : $diff_str;
    }

}

/**
 * Выводит максимальную разницу между переданной датой и текущим временем
 * в виде читабельной строки со склонением
 *
 * Пример вывода: "3 дня"
 *
 * @param string $date
 * @param bool $is_add_back Добавлять к строке слово "назад"?
 * @return string
 */
function string_date_age_max($date$is_add_back=false){

    if (!
$date) { return; }

    
$diff real_date_diff($date);

    
$diff_str '';

    if (
$diff[0]){
        
$diff_str html_spellcount($diff[0], LANG_YEAR1LANG_YEAR2LANG_YEAR10);
    } else
    if (
$diff[1]){
        
$diff_str html_spellcount($diff[1], LANG_MONTH1LANG_MONTH2LANG_MONTH10);
    } else
    if (
$diff[2]){
        
$diff_str html_spellcount($diff[2], LANG_DAY1LANG_DAY2LANG_DAY10);
    } else
    if (
$diff[3]){
        
$diff_str html_spellcount($diff[3], LANG_HOUR1LANG_HOUR2LANG_HOUR10);
    } else
    if (
$diff[4]){
        
$diff_str html_spellcount($diff[4], LANG_MINUTE1LANG_MINUTE2LANG_MINUTE10);
    }

    if (!
$diff_str) {
        return 
LANG_JUST_NOW;
    } else {
        return 
$is_add_back sprintf(LANG_DATE_AGO$diff_str) : $diff_str;
    }

}

/**
 * Возвращает разницу между датами в виде массива
 *
 * Возвращает массив, в котором элементы:
 *  0 => число лет
 *  1 => число месяцев
 *  2 => число дней
 *  3 => число часов
 *  4 => число минут
 *  5 => число секунд
 *
 * @author Олег Савватеев @ http://savvateev.org
 *
 * @param string $date1
 * @param string $date2
 * @return array
 */
function real_date_diff($date1$date2 null){

    
$diff = array();

    if (!
is_string($date1)){ return false; }

    
//Если вторая дата не задана принимаем ее как текущую
    
if(!$date2) {
        
$cd getdate();
    } else {
        
$cd getdate(strtotime($date2));
    }

    
$date2 $cd['year'].'-'.$cd['mon'].'-'.$cd['mday'].' '.$cd['hours'].':'.$cd['minutes'].':'.$cd['seconds'];

    
//Преобразуем даты в массив
    
$pattern '/(d+)-(d+)-(d+)(s+(d+):(d+):(d+))?/';
    
preg_match($pattern$date1$matches);
    
$d1 = array((int)$matches[1], (int)$matches[2], (int)$matches[3], (int)$matches[5], (int)$matches[6], (int)$matches[7]);
    
preg_match($pattern$date2$matches);
    
$d2 = array((int)$matches[1], (int)$matches[2], (int)$matches[3], (int)$matches[5], (int)$matches[6], (int)$matches[7]);

    
//Если вторая дата меньше чем первая, меняем их местами
    
for($i=0$i<count($d2); $i++) {
        if(
$d2[$i]>$d1[$i]) break;
        if(
$d2[$i]<$d1[$i]) {
            
$t $d1;
            
$d1 $d2;
            
$d2 $t;
            break;
        }
    }

    
//Вычисляем разность между датами (как в столбик)
    
$md1 = array(31$d1[0]%4||(!($d1[0]%100)&&$d1[0]%400)?28:2931303130313130313031);
    
$md2 = array(31$d2[0]%4||(!($d2[0]%100)&&$d2[0]%400)?28:2931303130313130313031);
    
$min_v = array(NULL11000);
    
$max_v = array(NULL12$d2[1]==1?$md2[11]:$md2[$d2[1]-2], 235959);
    for(
$i=5$i>=0$i--) {
        if(
$d2[$i]<$min_v[$i]) {
            
$d2[$i-1]--;
            
$d2[$i]=$max_v[$i];
        }
        
$diff[$i] = $d2[$i]-$d1[$i];
        if(
$diff[$i]<0) {
            
$d2[$i-1]--;
            
$i==$diff[$i] += $md1[$d1[1]-1] : $diff[$i] += $max_v[$i]-$min_v[$i]+1;
        }
    }

    
//Возвращаем результат
    
return $diff;

}

/**
 * Форматирует дату в формат "сегодня", "вчера", "1 января 2017"
 *
 * @param string $date Исходная дата. Может быть как отформатированном виде, так и timestamp
 * @param boolean $is_time Дополнять часом и минутами
 * @return string
 */
function string_date_format($date$is_time false){

    if(!
$date){
        return 
'';
    }

    if(!
is_numeric($date)){
        
$timestamp strtotime($date);
    } else {
        
$timestamp $date;
    }

    
$item_date date('j F Y'$timestamp);

    
$today_date     date('j F Y');
    
$yesterday_date date('j F Y'time()-3600*24);

    switch(
$item_date){
        case 
$today_date$result LANG_TODAY;
            break;
        case 
$yesterday_date$result LANG_YESTERDAY;
            break;
        default: 
$result lang_date($item_date);
    }

    if (
$is_time){

        
$result .= ' '.LANG_IN.' ' date('H:i'$timestamp);

    }

    return 
$result;

}
/**
 * Находит в строке все выражения вида {file_name%icon_name} и заменяет на svg иконку
 * где file_name - имя svg файла по пути /templates/шаблон/images/icons/
 * icon_name - имя иконки svg спрайта
 *
 * @param string $string
 * @return string
 */
function string_replace_svg_icons($string){

    
$matches_count preg_match_all('/{([a-z0-9_-]+)%([a-z0-9_-]+)}/i'$string$matches);

    if (
$matches_count){
        for(
$i=0$i<$matches_count$i++){

            
$tag  $matches[0][$i];
            
$file $matches[1][$i];
            
$name $matches[2][$i];

            
$string str_replace($taghtml_svg_icon($file$name16false), $string);
        }
    }

    return 
$string;
}
/**
 * Находит в строке все выражения вида {user.property} и заменяет property
 * на соответствующее свойство объекта cmsUser
 *
 * @param string $string
 * @return string
 */
function string_replace_user_properties($string){

    
$matches_count preg_match_all('/{user.([a-z0-9_]+)}/i'$string$matches);

    if (
$matches_count){

        
$user cmsUser::getInstance();

        for(
$i=0$i<$matches_count$i++){

            
$tag $matches[0][$i];
            
$property $matches[1][$i];

            if (isset(
$user->$property)){
                
$string str_replace($tag$user->$property$string);
            }

        }

    }

    return 
$string;

}

/**
 * Находит внутри строки $string все выражения вида {key}, где key - это ключ
 * массива $data и заменяет на значение соответствующего элемента
 *
 * @param string $string
 * @param array $data
 */
function string_replace_keys_values($string$data){

    if(
strpos($string'{') === false){ return $string; }

    foreach(
$data as $k=>$v){
        if (
is_array($v) || is_object($v)) { unset($data[$k]); }
    }

    
$keys array_map(function($key){ return '{'.$key.'}'; }, array_keys($data));

    return 
str_replace($keysarray_values($data), $string);

}

/**
 * Находит внутри строки $string все выражения вида {key}, где key - это ключ
 * массива $data и заменяет на значение соответствующего элемента
 * отличительной особенностью от функции выше является возможность обработки значений функциями
 * например, выражение {age|html_spellcount:год:года:лет} после обработки напишет "21 год, 22 года, 29 лет"
 * при значении age 21, 22 и 29 соответственно
 * выражение {nickname:профиль пользователя %s самый лучший} после обработки станет "профиль пользователя Василий самый лучший"
 * при значении поля nickname в массиве $data "Василий"
 *
 * @param string $string
 * @param array $data
 */
function string_replace_keys_values_extended($string$data){

    
$matches_count preg_match_all('/{([^}]+)}/ui'$string$matches);

    if (
$matches_count){

        for(
$i=0$i<$matches_count$i++){

            
$tag $matches[0][$i];
            
$property $matches[1][$i];

            
$func false$func_params = array(); $func_params_property_key 0;

            
// есть ли обработка функцией
            
if(strpos($property'|') !== false){
                
$params explode('|'$property);
                
// второй параметр - функция
                
$func $params[1];
                if(
function_exists($func) || strpos($func':') !== false){

                    
// первый параметр остаётся как $property
                    
$property $params[0];
                    
// $property ставим как первый параметр функции
                    
$func_params = array($property);
                    
// смотрим есть ли у функции параметры
                    
if(strpos($func':') !== false){
                        
$par explode(':'$func);
                        
$func $par[0]; unset($par[0]);
                        if(
function_exists($func)){
                            foreach (
$par as $k => $p) {
                                
// если параметр - массив
                                
if(strpos($p'=') !== false){
                                    
$out = array(); parse_str($p$out);
                                    
$par[$k] = $out;
                                }
                            }
                            
$func_params $func_params $par;
                        } else {
                            
$func false;
                        }
                    }

                } else {

                    
// значит рандомные значения из списка
                    
$values explode('|'$property);

                    
$string str_replace($tag$values[mt_rand(0, (count($values)-1))], $string);

                    continue;

                }
            } else
            
// нужно прогнать через sprintf
            
if(strpos($property':') !== false){
                
$params explode(':'$property);
                
$property $params[0];
                
$func 'sprintf';
                
$func_params array_reverse($params);
                
$func_params_property_key 1;
            }

            if (isset(
$data[$property]) && !is_array($data[$property]) && !is_object($data[$property])){

                
$data_property $data[$property];

                if(
$func && function_exists($func)){

                    
$func_params[$func_params_property_key] = $data_property;

                    
$data_property call_user_func_array($func$func_params);

                }

                
$string str_replace($tag$data_property$string);

            } else {
                
$string str_replace($tag''$string);
            }

        }

    }

    return 
$string;

}

/**
 * Делает активными гиперссылки внутри строки
 *
 * @param string $string
 * @return string
 */
function string_make_links($string){
    return 
preg_replace('@(https?://([-w.]+[-w])+(:d+)?(/([w/_.#-]*(?S+)?[^.s])?)?)@''<a href="$1" class="auto-link" target="_blank" rel="noopener noreferrer">$1</a>'$string);
}

//============================================================================//

/**
 * Возвращает строку с перечислением самых часто используемых
 * слов из исходного текста
 *
 * @param string $text
 * @param int $min_length Минимальная длина каждого слова
 * @param int $limit Количество слов в результирующей строке
 * @return string
 */
function string_get_meta_keywords($text$min_length=5$limit=10){

    
$stat = array();

    
$text str_replace(array("n"'<br>''<br/>'), ' '$text);
    
$text strip_tags($text);
    
$text mb_strtolower($text);

    
$stopwords string_get_stopwords(cmsCore::getLanguageName());

    
$words explode(' '$text);

    foreach(
$words as $word){

        
$word trim($word);
        
$word str_replace(array('(',')','+','-','.','!',':','{','}','|','"',',',"'"), ''$word);
        
$word preg_replace("/.,(){}/ui"''$word);

        if(
$stopwords && in_array($word$stopwords)){
            continue;
        }

        if (
mb_strlen($word)>=$min_length){
            
$stat[$word] = isset($stat[$word]) ? $stat[$word]+1;
        }
    }

    
asort($stat);
    
$stat array_reverse($stattrue);
    
$stat array_slice($stat0$limittrue);

    return 
implode(', 'array_keys($stat));

}

/**
 * Подготавливает текст для использования в теге meta description
 *
 * @param string $text
 * @param int $limit Максимальная длина результата
 * @return string
 */
function string_get_meta_description($text$limit=250){

    return 
string_short($text$limit);

}

/**
 * Возвращает массив стоп слов
 * @staticvar array $words
 * @param string $lang Язык, например ru, en
 * @return array
 */
function string_get_stopwords($lang='ru') {
    static 
$words null;
    if(isset(
$words[$lang])){
        return 
$words[$lang];
    }
    
$file PATH.'/system/languages/'.$lang.'/stopwords/stopwords.php';
    if(
file_exists($file)){
        
$words[$lang] = include $file;
    } else {
        
$words[$lang] = array();
    }
    return 
$words[$lang];
}

/**
 * Обрезает исходный текст до указанной длины (или последнего предложения/слова),
 * удаляя HTML-разметку
 *
 * @param string $string
 * @param integer $length Максимальная длина результата
 * @param string $postfix Строка, добавляемая к результату, если исходную пришлось обрезать
 * @param string $type Тип обрезки:
 *              s (sentence) - по последнему предложению
 *              w (word) - по последнему слову
 *              пустая строка или любой другой символ - обрезать в любом месте
 * @return string
 */
function string_short($string$length 0$postfix ''$type 's'){

    
// строка может быть без переносов
    // и после strip_tags не будет пробелов между словами
    
$string str_replace(array("n""r"'<br>''<br/>''</p>'), ' '$string);
    
$string strip_tags($string);
    
$string preg_replace('#ss+#u'' '$string);

    if (!
$length || mb_strlen($string) <= $length) { return $string; }

    
$length -= min($lengthmb_strlen($postfix));

    switch (
strtolower($type)) {
        
// Обрезаем по последнему предложению
        
case 's':
            
$string mb_substr($string0$length);
            
preg_match('/^(.+)([.!?…]+)(.*)$/u'$string$matches);
            if (!empty(
$matches[2])) { $string $matches[1].$matches[2]; }
            break;
        
// Обрезаем по последнему слову
        
case 'w':
            
$string mb_substr($string0$length 1);
            
preg_match('/^(.*)([W]+)(w*)$/uU'$string$matches);
            if (!empty(
$matches[1])) { $string $matches[1]; }
            break;
        
// Обрезаем как получится
        
default:
            
$string mb_substr($string0$length);
    }

    return 
$string $postfix;

}

/**
 * Вырезает из строки CSS/JS-комментарии, табуляции, переносы строк и лишние пробелы
 *
 * @param string $string
 * @return string
 */
function string_compress($string){

    
$string preg_replace('!/*[^*]**+([^/][^*]**+)*/!'''$string);
    
$string preg_replace('/s{2,}/'''$string);
    
$string str_replace(["rn""r""n""t"], ''$string);

    return 
$string;

}

/**
 * Преобразует первый символ строки в верхний регистр
 * multi-bytes ucfirst
 *
 * @param string $str
 * @return string
 */
function string_ucfirst($string) {
    return 
mb_strtoupper(mb_substr($string01)).mb_substr($string1);
}
//============================================================================//

/**
 * Возвращает массив значений определенного поля для всех элементов коллекции
 *
 * Аналогично функции array_column из PHP 5.5
 *
 * @param type $collection
 * @param type $key
 * @param type $value
 * @return type
 */
function array_collection_to_list($collection$key$value=false){

    
$value $value $value $key;

    
$list = array();

    if (
is_array($collection)){
        foreach(
$collection as $item){
            
$list$item[$key] ] = $item[$value];
        }
    }

    return 
$list;

}

/**
 * Рекурсивная версия array_filter
 * @param array $input
 * @return array
 */
function array_filter_recursive($input) {
    foreach (
$input as &$value) {
        if (
is_array($value)) {
            
$value array_filter_recursive($value);
        }
    }
    return 
array_filter($input);
}

/**
 * Возвращает значение ячейки массива
 * по переданной вложенности $needle
 *
 * @param array|string $needle Путь до необходимого ключа, например key:subkey:subsubkey
 * @param array $haystack Массив, в котором ищем
 * @param string $delimiter Разделитель ключей в пути, если $needle строка
 * @return mixed Значение или null, если ключ не найден
 */
function array_value_recursive($needle$haystack$delimiter ':') {

    if(!
is_array($haystack)){ return null; }

    
$name_parts = !is_array($needle) ? explode($delimiter$needle) : $needle;

    foreach (
$name_parts as $name) {
        if(!
is_array($haystack) || !array_key_exists($name$haystack)){
            return 
null;
        } else {
            
$haystack $haystack[$name];
            if(
$haystack === null){ $haystack false; }
        }
    }

    return 
$haystack;

}

/**
 * Устанавливает значение ключа массив
 * по переданной вложенности ключей $path
 *
 * @param array|string $path Путь до необходимого ключа, например key:subkey:subsubkey
 * @param array $array Изменяемый массив
 * @param mixed $value Значение ключа
 * @param string $delimiter Разделитель ключей в пути, если $path строка
 * @return mixed Возвращает изменённый массив $array
 */
function set_array_value_recursive($path$array$value$delimiter ':') {

    
$name_parts = !is_array($path) ? explode($delimiter$path) : $path;

    
$_array = &$array;

    foreach (
$name_parts as $name) {
        
$_array = &$_array[$name];
    }

    
$_array $value;

    return 
$array;

}

/**
 * Сортирует двумерный ассоциативный массив по полю (полям)
 *
 * $fields может содержать как просто имя поля для сортировки,
 * так и массив полей с направлениями сортировок, например:
 * array(array('by' => 'ordering', 'to' => 'asc'), array('by' => 'title', 'to' => 'desc'))
 *
 * @param array &$array
 * @param string | array $fields
 * @param string $direction
 * @return boolean
 */
function array_order_by(&$array$fields$direction 'asc') {

    if(!
$array){ return false; }

    if(
is_string($fields)){
        
$list = array(array(
            
'by' => $fields,
            
'to' => $direction
        
));
    } else {
        
$list $fields;
    }

    
$args = array();

    foreach (
$array as $k => $item) {

        
$key 0;

        foreach (
$list as $order) {

            
$args[$key][$k] = $item[$order['by']];
                
$key++;
            
$args[$key] = constant('SORT_'.strtoupper($order['to']));
                
$key++;

        }

    }

    
$args[] = &$array;

    return 
call_user_func_array('array_multisort'$args);

}

function 
multi_array_unique($array) {

    
$result array_map('unserialize'array_unique(array_map('serialize'$array)));

    foreach (
$result as $key => $value) {
        if (
is_array($value)) {
            
$result[$key] = multi_array_unique($value);
        }
    }

    return 
$result;

}

function 
get_localized_value($field$data) {

    
$lang cmsCore::getLanguageHrefPrefix();

    
$field .= ($lang '_'.$lang '');

    if(
array_key_exists($field$data)){
        return 
$data[$field];
    }

    return 
null;

}
//============================================================================//

/**
 * Выводит переменную рекурсивно
 * @param mixed $var
*/
function dump($var$halt=true){
    echo 
'<pre>'print_r($var); echo '</pre>';
    if (
$halt) { die(); }
}
Онлайн: 0
Реклама