• Как изучить/разобраться в чужом PHP коде?

    @m-haritonov
    По методике:
    Я начинаю изучение фреймворков с точки входа (скрипта, который вызывается при получении HTTP запроса, в случае веб фреймворка). Смотрю на возможные пути дальнейшего выполнения кода в этом входном скрипте. Затем изучаю каждый из путей выполнения, доходя до точки завершения работы этого пути (т.е. изучаю от входа к выходу, сверху вниз). Пытаюсь понять предназначение каждого из путей и участков кода, которые на этом пути встречаются. В итоге пытаюсь понять как данный фреймворк вписывается в известную мне модель работы веб технологий (HTTP и т.п.), какая часть фреймворка предназначена для устранения дублирования кода и т.п.

    По софту:
    Для статического анализа кода поищите по запросам «php reengineering», «php reverse engineering». Обратный инжинеринг PHP кода есть, например, в Enterprise Architect: www.sparxsystems.com.au/platforms/php_uml.html

    Для динамического анализа кода можете с помощью xdebug сделать профилирование вызова и на основе полученного файла построить граф с помощью специальной программы (например, KCacheGrind). Подробнее здесь: xdebug.org/docs/profiler

    Ещё ссылки на некоторые инструменты: stackoverflow.com/a/4156265/925775 (мне там приглянулся PHP Call Graph)

    P.S.: по софту мог где-то ошибиться, т.к. нет большого опыта в использовании описанных инструментов.
    Ответ написан
    2 комментария
  • Имеется 1000 jpeg-ов, надо в уголок каждого автоматически впечатать растром его имя файла. Как?

    @m-haritonov
    Попробуйте поискать по запросу «image watermark».
    Ответ написан
    Комментировать
  • Как обезопасить управление сервером?

    @m-haritonov
    Можно ещё устроиться в правительство или внедрить к ним своего агента.
    Ответ написан
    Комментировать
  • Плохо ли, когда http и https версии сайта совсем разные, а домен один и тот же?

    @m-haritonov
    На мой взгляд, формально это не корректно, т.к. протокол отвечает за формат передаваемых данных и использование его иным образом нарушает формальное разделение обязанностей между частями URL адреса. Трактовать часть URL адреса «https» как «закрытая область» я бы не стал (хотя подобный минимализм притягивает), т.к. по https могут передаваться и данные из общедоступной области. Плюс, в будущем может возникнуть необходимость отдавать данные открытой области по https и тогда придётся переносить закрытую область на поддомен (и, как следствие, рассылать пользователям уведомления о смене адреса, менять URL адреса во всех местах программы (т.к. поставить редирект с прежнего адреса будет нельзя) и т.п.).
    Ответ написан
    1 комментарий
  • Онлайн-ресурс для создания схематической разметки страниц для дизайнера

    @m-haritonov
    Ищите по запросам «mockups» и «sketchy». Несколько результатов:
    balsamiq.com/products/mockups/
    moqups.com/
    mockups.me/
    Ответ написан
    Комментировать
  • Вырезать битые символы из юникод XML

    @m-haritonov
    Попробуйте так:
    <?php
    $text = file_get_contents(__DIR__ . '/20720351_2010_-_1_unicode.xml');
    $text = iconv('UTF-16LE', 'UTF-8', $text);
    // http://stackoverflow.com/a/12265956
    $text = preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $text);
    $element = simplexml_load_string($text);
    var_dump($element);
    
    Ответ написан
  • Использование тернарного оператора ?: с подавлением ошибки?

    @m-haritonov
    … удалено (не туда разместил)...
    Ответ написан
    Комментировать
  • Использование тернарного оператора ?: с подавлением ошибки?

    @m-haritonov
    Этот оператор не избавляет от ошибки, а просто скрывает ее вывод.

    Собственно, это и утверждается в документации. И в случае с размещением этого оператора перед $_GET['aaa'] именно игнорирование предупреждения о неинициализованой переменной и требуется, т.к., в соответствии с предназначением данного массива, его значения приходят из вне, а не объявляются внутри программы и отсутствие предупреждений было бы уместнее, т.к. иначе приходится писать дополнительный код, которые не несёт в себе полезной нагрузки.

    Очень не рекомендую. Говорю как ZCE.

    Может, как ZCE, лучше скажите, почему Вы не рекомендуете его использовать? А то сейчас Вы обошлись простым «Это плохо, понятненько?!».
    Ответ написан
    Комментировать
  • Использование тернарного оператора ?: с подавлением ошибки?

    @m-haritonov
    У меня на PHP 5.3.16 при выполнении кода $c = @$a ? : 'default'; никаких E_NOTICE не выдаётся. Возможно, у Вас установлен свой обработчик ошибок (через set_error_handler), который игнорирует оператор "@".
    Ответ написан
    5 комментариев
  • Структура данных для поиска подходящих CSS-правил

    @m-haritonov
    Не совсем понял в чём вопрос. Если распарсить CSS, то в итоге у Вас будет объектная структура данных CSS таблиц, их правил и селекторов (с которой Вы сможете взаимодействовать программно). И в реализации функции cssTable.get_styles Вам необходимо будет написать код, выполняющий поиск соответствующих CSS правил таблицы стилей по переданному CSS селектору (например, методом сопоставления переданного CSS селектора каждому из CSS селекторов таблицы стилей).

    Т.е. когда функция, подобная Вашей cssTable.get_styles, применяется для поиска HTML элементов, она (руководствуясь переданным её CSS селектором и правилами синтаксиса CSS селекторов), находит нужный HTML элемент из всего дерева (например, сопоставляя по очереди каждый HTML элемент переданному CSS селектору). В Вашем же случае, в качестве HTML документа будет выступать таблица CSS стилей и при поиске Вы будете сопоставлять переданный функции CSS селектор каждому из CSS селектором в Вашей таблицы стилей.
    Ответ написан
  • PHPUnit + Selenium: В рамках одного теста пройти по нескольким сайтам

    @m-haritonov
    Если мне не изменяет память, то url() может принимать абсолютные URL адреса (с доменом), а через setBrowserUrl() можно задать пустой базовый путь. Т.е. попробуйте исправить свой код примерно так:

    function setUp() {
        $this->setBrowser('firefox');
        $this->setBrowserUrl('');
    }
    
    function testDo() {
        $this->url('https://www.facebook.com/facebook');
        $this->url('http://www.opera.com/computer');
    }
    
    Ответ написан
  • Проблема масштабирования адаптивной верстки на мобильных браузерах

    @m-haritonov
    Если я всё правильно понял, то у Вас имеется контент, минимальной шириной в 320px и максимальной — в 900px. И Вам надо:
    1. Если размер экрана устройства меньше 900px, то задать ширину viewport'а страницы как у экрана устройства (чтобы произошло перестроение CSS разметки под эту ширину).
    2. Если размер экрана устройства больше или равен 900px, то задать ширину viewport'а страницы в 900px (чтобы на экранах размером в 900px и больше контент увеличивался за счёт масштаба).

    Для этой задачи могу предложить следующее решение (скопируйте из данного примера на свой сайт JavaScript код, разместив его выше всех других подключений и вставок CSS и JavaScript кода). Проверял только на iPad 2.

    <!DOCTYPE html>
    <html>
    	<head>
    		<script type="text/javascript">
    			(function(){
    				// Выполняем код только на мобильных браузерах (на всякий случай)
    				if (typeof(window.orientation) !== 'undefined')
    				{
    					// Функция взята отсюда: https://makandracards.com/makandra/13743-detect-effective-horizontal-pixel-width-on-a-mobile-device-with-javascript
    					function getDeviceWidth()
    					{
    						var deviceWidth = window.orientation == 0 ? window.screen.width : window.screen.height;
    						// iOS returns available pixels, Android returns pixels / pixel ratio
    						// http://www.quirksmode.org/blog/archives/2012/07/more_about_devi.html
    						if (navigator.userAgent.indexOf('Android') >= 0 && window.devicePixelRatio)
    							deviceWidth = deviceWidth / window.devicePixelRatio;
    
    						return deviceWidth;
    					}
    
    					var deviceWidth = getDeviceWidth();
    					var maxWidth = 900;
    					
    					if (deviceWidth < maxWidth)
    					{
    						// Мои эксперименты на iPad 2 показали, что device-width всегда содержит значение ширины 
    						// экрана в книжной (portrait) ориентации (т.е. даже, если устройство находится в 
    						// альбомной (landscape) ориентации). Это же утверждалось в некоторых найденных мною статьях.
    						if (window.orientation == 0 || window.orientation == 180)
    							document.write('<meta name="viewport" content="width=device-width">');
    						else
    							document.write('<meta name="viewport" content="width=device-height">');
    					}
    					else
    						document.write('<meta name="viewport" content="width=' + maxWidth + '">');
    				}
    			})();
    		</script>
    		
    		<style type="text/css">
    			* { margin: 0; padding: 0; }
    			.content { min-width: 320px; max-width: 900px; background: #ffff99; }
    			.content div { border: 1px solid #f00; }
    		</style>
    	</head>
    	<body>
    		<div class="content">
    			<div>
    				abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc
    				abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc
    				abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc
    			</div>
    		</div>
    	</body>
    </html>
    
    Ответ написан
    3 комментария
  • Потеряет ли сайт позиции, если перекинуть домен на другую папку?

    @m-haritonov
    Если Вы говорите об изменение пути, прописанного в DocumentRoot (в случае с веб-сервером Apache) на новый, т.е. об изменении исключительно внутреннего поведения веб-сервера, то в глазах поисковых систем ничего не изменится. Поисковые системы видят только HTTP заголовки (ну и само тело запроса), отдаваемые Вашим сервером. Внутренние настройки от них скрыты.

    Если же Ваши манипуляции предполагают так же изменение URL адреса, то воспользуйтесь редиректом, как предлагает max_mara.
    Ответ написан
    Комментировать
  • Является ли оцифровка и распространение содержания школьных учебников нарушением авторских прав?

    @m-haritonov
    Ни в одном школьном учебнике «допущенном» или «рекомендованом» нет текста сообщающего, что копирование и распространение запрещено (обычно такой абзац присутствует в начале книге на странице с информацией об авторах, издательстве и т.п.). Почему?

    Потому, что по умолчанию данные действия без согласия правообладателя и так запрещены. В ГК РФ (статья 1229) сказано по этому поводу:
    Правообладатель может по своему усмотрению разрешать или запрещать другим лицам использование результата интеллектуальной деятельности или средства индивидуализации. Отсутствие запрета не считается согласием (разрешением).

    Явный запрет обычно прописывают для большей очевидности.

    Однако издательства обычно ставят значок копирайта «Все права защищены».

    Это необязательное предупреждение от правообладателя, означающее, что произведение является объектом авторского права и охраняется законом. Статья 1271 ГК РФ:
    Правообладатель для оповещения о принадлежащем ему исключительном праве на произведение вправе использовать знак охраны авторского права, который помещается на каждом экземпляре произведения и состоит из следующих элементов:
    латинской буквы «C» в окружности;
    имени или наименования правообладателя;
    года первого опубликования произведения.


    Как это следует понимать? Можно ли так: государство, гарантирующее бесплатное среднее образование, заказывает разработку учебников и содержание учебников является бесплатным для населения.

    Не важно, обеспечивает ли государство бесплатные поставки экземпляров данного учебника населению. Важно кому принадлежит право на распространение учебника. Может быть и так, что произведение уже перешло в общественное достояние и его можно свободно копировать и распространять с сохранением указания на авторство (статьи 1281 и 1282).

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

    Прав на вёрстку не существует, насколько я знаю.

    Тогда получается, что можно взять «рекомендованный» учебник, оцифровать, сверстать в форматах электронных книг. Или при этом все-таки будут нарушены чьи-то имущественные права (автор несомненно будет указан).

    Всё это стоит уточнять у владельца исключительных прав на конкретное произведение.

    P.S.: вообще, вопрос это Вам лучше бы задать на юридическом форуме.
    Ответ написан
    Комментировать
  • Неверная кодировка колонтитулов в mPDF?

    @m-haritonov
    Скачал последнюю версию с www.mpdf1.com/mpdf/download, всё работает нормально. Вот код (запускал в кодировке windows-1251):
    <?php
    $html = '
    <p>Текст</p>
    
    <htmlpagefooter name="myFooter" style="display:none">
    	<div class="footer">
    		<table class="tbl3" width=624>
    			<tr>
    				<td>Менеджера</td>
    				<td>Вася Пупкин</td>
    				</tr>
    			<tr>
    				<td>Телефон:</td>
    				<td>222 333 222</td>
    			</tr>
    		</table>
    	</div>
    </htmlpagefooter>
    <sethtmlpagefooter name="myFooter" />';
    
    require_once __DIR__ . '/MPDF57/mpdf.php';
    $mpdf = new mPDF('utf-8', 'A4', '12', '', 10, 10, 7, 7, 10, 10);
    //$mpdf->allow_charset_conversion = true;
    $mpdf->charset_in = 'cp1251';
    $mpdf->list_indent_first_level = 0;
    $mpdf->WriteHTML($html, 0);
    echo $mpdf->Output('mpdf.pdf', 'I');
    die;
    


    Могу посоветовать разве что:
    1. проверить кодировку во всех файлах (шаблон с колонтитулами, случайно, не в отдельном файле лежит?);
    2. обновить библиотеку mPDF на последнюю версию;
    3. добавить "$mpdf->allow_charset_conversion = true;", как рекомендуется в документации.
    Ответ написан
    1 комментарий
  • Drupal7: автозамена кавычек на нормальные в тексте?

    @m-haritonov
    Если говорить безотносительно Drupal, то для обработки HTML в PHP стоит использовать встроенный класс DOMDocument. Стоит, как минимум, потому, что через него (через метод loadHTML) можно пропустить HTML код с целью исправления в нём ошибок HTML форматирования (незакрытые теги и т.п.). Касательно Вашей задачи, с помощью него можно получить доступ именно к текстовым узлам дерева HTML.

    Пример парсинга (без корректного алгоритма по замене кавычек):
    <?php
    $html = '"текст в кавычках" текст "ещё текст в кавычках" <a href="http://ya.ru"><em>неправильный порядок вложенности элементов</a></em> текст <div>незакрытый элемент';
    
    $domDocument = loadHtml($html);
    $xpath = new DOMXpath($domDocument);
    
    // Выбирает только текстовые узлы
    foreach ($xpath->query('/html/body//text()') as $textNode)
    {
    	// Тут можно производить замены кавычек, учитывая текст из предыдущих $textNode
    	$textNode->data = str_replace('"', '«', $textNode->data);
    }
    
    print htmlspecialchars(saveHtml($domDocument));
    
    /*
    Выведет:
    «текст в кавычках« текст «ещё текст в кавычках« <a href="http://ya.ru"><em>неправильный порядок вложенности элементов</em></a> текст <div>незакрытый элемент</div>
    */
    


    Функции, используемые в вышеприведённом коде (содержат различные исправления для соответствующих методов класса DOMDocument):
    <?php
    /**
     * @return DOMDocument
     */
    function loadHtml($html, $charset = 'utf-8')
    {
    	$domDocument = new DOMDocument();
    
    	// Т.к. функция DOMDocument::loadHTML конвертирует сущности "&nbsp;" в обычные пробелы, 
    	// приходится экранировать эти сущности. Засипи вида "&amp;nbsp;" экранируем для того, 
    	// чтобы при обратном преобразовании они по ошибке не превратились в "&nbsp;"
    	$html = str_replace('&amp;nbsp;', '&amp;amp;nbsp;', $html);
    	$html = str_replace('&nbsp;', '&amp;nbsp;', $html);
    
    	// Удаляем символы "\r", т.к. DOMDocument::loadHTML() преобразует их в "&#13;"
    	$html = str_replace("\r", '', $html);
    
    	$html = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    		<html>
    			<head>
    				<meta http-equiv="content-type" content="text/html;charset=' . $charset . '"/>
    				<title></title>
    			</head>
    				<body>' . $html . '</body>
    		</html>
    	';
    	
    	// Функция DOMDocument::loadHTML может генерировать сообщения об ошибках, которые нам
    	// не нужны (например, о незакрытом теге), т.к. мы используем данную функцию для 
    	// коррекции HTML кода. Оператор @ ошибки у данной функции не подавляет.
    	$useErrorsOld = libxml_use_internal_errors(true);
    	$domDocument->loadHTML($html);
    	libxml_use_internal_errors($useErrorsOld);
    
    	return $domDocument;
    }
    
    /**
     * @return string
     */
    function saveHtml(DOMDocument $domDocument)
    {
    	// Экспортируем в формате XHTML
    	$html = $domDocument->saveXml();
    
    	$html = str_replace('&amp;nbsp;', '&nbsp;', $html);
    	$html = str_replace('&amp;amp;nbsp;', '&amp;nbsp;', $html);
    
    	$html = preg_replace('/^\s*\<\?xml\s*[^\>]*\>\s*/is', '', $html);
    
    	// Удаляем <![CDATA[]]>, которым оборачивается содержимое тега <script></script> при 
    	// экспорте через DOMDocument::saveXml
    	$html = preg_replace('/(\<script(\s*[^\>]*)?\>)\<\!\[CDATA\[/is', '$1', $html);
    	$html = preg_replace('/\]\]\>(\<\/script\>)/is', '$1', $html);
    
    	return preg_replace('/^.*?<body>(.*?)<\/body>\s*<\/html>$/is', '$1', $html);
    }
    


    P.S.: на хабре HTML сущности в теге <source>...</source> не экранируются для вывода кода в неизменном виде (жесть какая-то), я произвёл экранирование вручную, поэтому учтите, что код может стать некорректным, если программисты хабра исправят этот баг без должной замены в существующих сообщениях.
    Ответ написан
    Комментировать
  • Длинная строка распирает контейнер с min-width?

    @m-haritonov
    Можно перенести .breadcrumbs внутрь блока .content.

    Тогда .breadcrumbs будет иметь ширину не больше, чем .content, а в случае превышения этой ширины содержимое .breadcrumbs будет переноситься на следующую строчку. Это ведь то, что Вы имели ввиду?!

    Сейчас Вы пытаетесь сделать так, чтобы блок .wrapper мог распираться блоком .content, но при этом не мог распираться блоком .breadcrumbs.
    Ответ написан
    Комментировать
  • Как реализовать многоуровневый вложенный запуск функций?

    @m-haritonov
    Для этого, перед вызовом функции fun() в makeGroup значение root надо временно подменить на только что созданную группу. Вот новый код для makeGroup:
    var makeGroup = function(name,fun) {
        var newgroup = new group();
        newgroup.name=name;
        newgroup.status='ok';
        newgroup.stack=[];
        
        var oldRoot = root;
        root = newgroup;
        
        try {
            fun();
        }
        catch(e) {
            newgroup.status=e;
        }
        
        root = oldRoot;
        
        root.stack.push(newgroup);
    }
    
    Ответ написан
    2 комментария
  • php, опять про кодировки

    @m-haritonov
    Ок. Делаю замену как предлагает Ogra:
    — $body = iconv($data_charset, $send_charset, $body);
    + $body = iconv('utf-8', 'cp1252', $body);
    + $body = iconv('cp1251', 'KOI8-R', $body);
    Теперь тело сообщения вообще пустое.
    Причем $body теряется при utf-8=>cp1252.

    Не удивительно. Вы, во-первых переводите строку из кодировки с более обширным набором символов (utf-8) в кодировку с менее обширным (cp1252). Во-вторых, переводите строку в кодировку cp1252, которая не содержит русских символов. В-третьих, сначала перекодируете строку в кодировку cp1252, а далее почему-то считаете, что у Вас строка теперь не в кодировке cp1252, а в кодирокве cp1251 и перекодируете уже из неё обратно в utf-8.

    Если вкратце, то эта манипуляция с перекодированием не нужна, а декодеру доверять не стоит, т.к. он может иметь большую погрешность.
    Ответ написан
    5 комментариев