Задать вопрос
  • Проблема при прохождении теста node?

    @ksnk
    Из всех полученных значений найди минимальный. Вот забор такой глубины, очевидно , и будет тем, что надо. будут использованы "дорожный" участок забора и кусок забора от этого участка.
    Написано
  • Как реализовать мультивызов функции с генерацией содержимого в один контейнер?

    @ksnk
    В общем - да. Хотя register_shutdown_function сейчас, вроде как, работает достаточно корректно и всегда вызывается в разумных случаях, так что можно навесить вывод на него. Получится что-то такое. Можно было бы и дальше украшать, навесив стили и накрутив скриптовые свистелки-показывалки, но если функция занимает больше 100 строк - значить что-то идет не так :)
    <?php
    
    class debug
    {
        /**
         * Функция оставляет человекочитаемый вывод функции в html потоке
         * Работоспособна в режиме cli
         * @param mixed $msg - вывод информации
         * @param string $title - иногда удобно подписывать что тут выводится
         * @param array $options - статически сохраняемый массив параметров.
         * - root - корень проекта, минимизируем название файла, обрезая корень default: SERVER['DOCUMENT_ROOT'] или __DIR__
         * - type - [var_dump|print_r|var_export:default]
         * @return void
         */
        static function _($msg, $title = '', $options = [])
        {
            static $notafirsttime, $debug_options = [], $debug_dump = [];
            if (!empty($options)) {
                $debug_options = array_merge($debug_options, $options);
            }
            if (!empty($msg)) {
                $raw_backtrace = debug_backtrace();
    
                if (!isset($debug_options['root'])) {
                    if (isset($_SERVER) && isset($_SERVER['DOCUMENT_ROOT']) && !empty($_SERVER['DOCUMENT_ROOT'])) {
                        $debug_options['root'] = $_SERVER['DOCUMENT_ROOT'];
                    } else {
                        $debug_options['root'] = __DIR__;
                    }
                }
                $backtrace = [];
                foreach ($raw_backtrace as $bt) {
                    $line = str_replace($debug_options['root'], '~', $bt['file']) . ':' . $bt['line'];
                    if (isset($bt['class'])) {
                        $backtrace[] = $bt['class'] . '::' . $bt['function'] . ' ' . $line;
                    } elseif (isset($bt['function'])) {
                        $backtrace[] = $bt['function'] . ' ' . $line;
                    }
                }
                if (isset($debug_options['type']) && $debug_options['type'] == 'var_dump') {
                    ob_start();
                    var_dump($msg);
                    $msg = ob_get_clean();
                } elseif (isset($debug_options['type']) && $debug_options['type'] == 'print_r') {
                    $msg = print_r($msg, true);
                } else {
                    $msg = var_export($msg, true);
                }
                $debug_dump[] = [$title, implode("\n", $backtrace), $msg];
            }
            if (empty($notafirsttime)) {
                $notafirsttime = true;
                register_shutdown_function(function () use (&$debug_dump) {
                    if (!empty($debug_dump)) {
                        $headers = headers_list();
                        if (empty($headers)) {
                            $method = 'plain';
                        } else {
                            $method = 'none';
                        }
                        if (isset($_SERVER) && isset($_SERVER['HTTP_ACCEPT']) && preg_match('~text/html~', $_SERVER['HTTP_ACCEPT'])) {
                            $method = 'html';
                        }
                        foreach ($headers as $h) {
                            if (preg_match('~Content\-type\: text/html~')) $method = 'html';
                        }
                        if ($method == 'plain') {
                            foreach ($debug_dump as $dl) {
                                echo $dl[0] . ' ' . $dl[1] . ': ' . "\n" . $dl[2] . "\n";
                            }
                            // var_export($debug_dump);
                        } else {
                            $tpl = <<<'HTML'
    <style>
    div.mc__debugger {
        position:fixed; top:0;right:0;
        width:40%; height:100%;
        background: lightgray;
        overflow:auto;
    }
    div.mc__debugger.hidden {
        width:2em; height:1.5em;
        overflow: hidden;
    }
    div.control-button {
        position:fixed; top:0;right:0;
        width:2em; height:1.5em;
        background: red;
    }
    </style>
    <script>
        const $container = document.createElement(`div`);
        const $debugEntry = document.createElement(`div`);
        const $button = document.createElement(`div`);
        $container.classList.add(`mc__debugger`);
        $container.classList.add(`hidden`);
        $debugEntry.classList.add(`debug-entry`);
        $button.classList.add(`control-button`);                    
        $container.appendChild($button);
        for (let x of {{json_data}}){
            let $pre = document.createElement(`pre`);
            $pre.innerText=x;
            $debugEntry.appendChild($pre);
        }
        $container.appendChild($debugEntry);
        document.body.appendChild($container);
        $button.addEventListener("click", () => {
            $container.classList.toggle("hidden");
        });
    </script>
    HTML;
                            echo preg_replace_callback('/{{\s*([^}]+)\s*}}/', function ($m) use ($debug_dump) {
                                switch ($m[1]) {
                                    case 'json_data':
                                        return json_encode($debug_dump, JSON_UNESCAPED_UNICODE);
                                }
                                return '';
                            }, $tpl);
                        }
                    }
                    $debug_dump = [];
                });
            }
        }
    }

    ну и пример использования
    <?php
    
    include 'debug.php';
    
    // тестируем
    class testclass
    {
        function testfunc()
        {
            debug(4, 'step4');
        }
    }
    
    $x = 1;
    echo $x;
    debug($x, 'step1', ['type' => 'var_export', 'root'=>__DIR__]); // root=>$_SERVER['DOCUMENT_ROOT']
    $x++;
    echo $x;
    debug([1,2,3,[4,5,6,[7,8,9]]], 'step2');
    $t = new testclass();
    $t->testfunc();
    die();
    $x++;
    echo $x;
    debug($x, 'step3');
    Написано
  • Как реализовать мультивызов функции с генерацией содержимого в один контейнер?

    @ksnk
    Алексей Уколов, Не совсем лучше. Этот дебуг будет вызываться в случайном месте генерации html (шаблонизатор же мы не используем, правда?) Так что не факт, что мы не выведем скрипты с дивами при генерации атрибута или имени класса.
    Так что более разумно выводить код чем-то, типа ob_ функций, сохранять отладочный вывод в статике php, хотя бы в статике функции debugEntries, и вставлять отладочный вывод в нужное место при отдаче кода наружу.
    Написано
  • Как реализовать мультивызов функции с генерацией содержимого в один контейнер?

    @ksnk
    Ну, типа, debugEntry можно вызвать много раз, не правда ли? Каждый раз будет добавляться новый элемент и новый Скрипт? Надо бы статической переменной ограничить вывод debug-entry и генерировать в какой-нибудь глобальной переменной броузера нужный дамп
    Написано
  • Есть ли в PHP готовый инструмент для получения элемента массива вложенность которого хранится в другом массиве?

    @ksnk
    Евгений Николаев, приведение к массиву не работает рекурсивно вглубь, так что придется внутри цикла приводить, а это значит менять код. Почему бы сразу не написать без всяких приведений?
    Написано
  • Есть ли в PHP готовый инструмент для получения элемента массива вложенность которого хранится в другом массиве?

    @ksnk
    Все функции, которые приводятся в "рессурсе" не работают с объектом или со смесью массиво-объектов, которые забавным образом получаются из разнообразных api. Так что вот еще один велосипед, который получше (imho) того, что там.
    function val($rec, $disp = '', $default = '')
        {
            if (empty($disp) && $disp !== '0') {
                if (empty($rec)) return $default;
                return $rec;
            }
            $x = explode('|', $disp);
            $v = $rec;
            foreach ($x as $xx) {
                if (is_object($v) && property_exists($v, $xx)) {
                    $v = $v->$xx;
                } elseif (is_array($v) && array_key_exists($xx, $v)) {
                    $v = $v[$xx];
                } else {
                    $v = $default;
                    break;
                }
            }
            return $v;
        }

    В отличии от тех - умеет работать со смешанным (массив-объект) содержимым без особых проблем. Ну и выдает значение по умолчанию, которого не хватает в "тех" решениях. Примеры
    val($x, 'EMAIL|0|VALUE')
    val($founded, 'result', [])
    Мне удобно объявить это статической функцией общего класса и использовать по мере необходимости. Указание смещения строкой, а не массивом объясняется тем, что иногда такое смещение приходит из конфига, да и оформлять массивом по сравнению со строкой сложнее...
    Написано
  • Как улучшить написанный код создания глобального объекта?

    @ksnk
    Ты уж определись, тебе нужно в глобальной константе window.Tools функцию или глобальный объект с уже инициированными параметрами. Пока у тебя остается именно функция. Зато ее можно где-то там на стороне переопределить с новыми параметрами. А если выдавать объект - параметры взять, вроде как , и неоткуда...
    Слегка поубирал ненужные скобки-functions. Не это нужно ? https://jsfiddle.net/p49hjquv/
    Написано
  • Как реализовать корректную работу кнопки назад в браузере?

    @ksnk
    Подгрузил контент - history.replaceState({loaded:4},'') -- типа уже 4 страницы товаров сгрузил с сайта
    При возврате на прежнюю страницу срабатывает событие popstate и там можно попытаться понять, сколько страниц тебе надо дозагрузить с сайта
    https://developer.mozilla.org/en-US/docs/Web/API/H...
    Написано
  • Почему регулярное выражение в цикле не находит совпадения, а отдельно находит?

    @ksnk
    Попробуй вот такую регулярку
    $result_match = preg_match('/Цена(\d{1,6})[рр₽](?:[^aак]|$)|Цена(\d{1,6})(?:[^aак]|$)|[^-р](\d{1,6})[рр₽](?:[^aак]|$)|ц(\d{1,6})(?:[^в]|$)/iu', $post, $matches_gross_result );
    
        if ($result_match == true) {
            $pattern= array_shift($matches_gross_result); // $pattern - найденная подстрока, вдруг зачем то пригодится
            $matches=implode('',$matches_gross_result); // найденная цена - собственно без дополнительной магии.
    ...

    Основной смысл - если строка поиска заканчивается сразу после указания цены - старая регулярка не сработает из за [^aаk] или [^в]. И зачем ковырять цену второй регуляркой, если она и так может быт выковыряна в первой.

    Использование mb_ereg_replace сделано из каких высоких соображений ? Или так исторически сложилось?
    Написано
  • Как узнать что загружает php на сервере debian?

    @ksnk
    Нужно сначала проверить стандартные проблемы.
    Например с базой. Кривые индексы в таблицах и т.д.
    Простейший и наглядный способ в консоли покликать команду mysql <<< "show full processlist\g" Это, конечно, если mysql база... Для других баз, вероятно, тоже можно подобный запрос выполнять.
    Обычно, когда нет нагрузки вывод пустой и эпизодически проскакивают запросы. А вот если какой нибудь запрос тормозит - он будет периодически светится.
    Еще причина в ддос атаке. Не ддосит ли сайт сам себя? Это видно по логам сервера.
    Ну и в любом случае - запустить команду top и помедитировать над картинкой. Может просто памяти не хватает?
    Написано
  • Как лучше реализовать переход с excel?

    @ksnk
    Перегоняйте сотрудников в гуглдок Ну или в яндексдок и там уже отдельным скриптом конвертируйте куда кому удобно. Авторизация естественным образом появляется из яндекса/гугеля. Сотрудники испытают минимальный стресс при переезде на почти такую же систему работы.
    Чтение данных из таблицы гугла - одна строка на php, из яндекса чуть сложнее - строк 10.
    Скрипты, которые вычитывают из доков и что-то умное делают с данными предстоит написать вручную, да. Для особой оперативности - можно перечитывать "исходные" файлы периодически, раз в час, например.
    Написано
  • Какие есть способы голосового управления сайтом?

    @ksnk
    Схема - ставишь на сайт
    <input type="file" accept="audio/*" capture="user">
    Имеются противопоказания - не только лишь все броузеры такое любят и поддерживают.

    при изменении засылаешь на сайт получившийся файл, он распознается сайтом в текст, дальше поиск по тексту с пониманием что вообще хочет этот юзер, кроме как выругаться. И делаешь, если юзер сумел сказать что-то вразумительное. Сам распознаватель - Тынц. Сам код на ноде, с использованием сервисов фейсбука. Для 18 года - норм, а вот как оно сейчас будет работать - не сильно уверен...
    Написано
  • Не получаю ответ на HTTP запрос запущенный в php скрипте через curl но получаю ответ в браузере, как исправить?

    @ksnk
    Может второй строчки не хватает ?
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    В броузере редиректов в сетевой консоли не видно ?
    Написано
  • Что делает (или позволяет делать) файл auth.php в битре?

    @ksnk
    Этот файл позволяет авторизоваться как админ.
    Разумнее всего обновиться на новую версию битрикса, так как в старых довольно много дыр, которые заткнуты только в последних версиях ядра. Заодно и на 8-ку переехать. Правда достаточно сложный сайт потребует серьезной работы по переезду.
    Для иллюстрации как все непросто в этой системе - https://habr.com/ru/companies/cyberok/articles/765660/
    https://xakep.ru/2023/12/07/1c-bitrix-flaw/
    Написано
  • Как сделать кастомную кнопку телеграм авторизации на сайте?

    @ksnk
    WhiteHat, Тоже не нашел вменяемого способа кастомизировать кнопку входа через телегу. В качестве грязного варианта можно что-то такое предложить -
    <div style="width:240px;height:40px;display:inline-block;position:relative;">
    <script async ...></script>
    <div style="pointer-events:none;position:absolute;top:0;left:0;width:100%;height:100%;z-index:100;background:gray;"
    </div>

    Обрамить телеграмный фрейм своим с размещенным поверх него элементом с pointer-events:none;. Вот туда уже можно рисовать в бякграунде что угодно.
    Если по размеру не подходит - можно даже и clip использовать...
    Когда-то, когда деревья были большими, таким нехитрым образом нажималась кнопка загрузки файлов
    Написано
  • Как сделать кастомную кнопку телеграм авторизации на сайте?

    @ksnk
    А если заменить в строке на if (isset($_GET['logout'])) {
    ?
    Пример рабочий, если на глюки довольно старого кода не обращать внимания

    К примеру нужен бот, у которого настроен домен. Имя бота в коде должно быть указано без @
    Написано
  • Как сделать кастомную кнопку телеграм авторизации на сайте?

    @ksnk
    Там в конце твоей ссылочки на телегу - пример на PHP - чем не подошел ?
    Написано