RSS новости
Играть онлайн в игры денди
 
Каталог / Кратко о RSS
Ссылка на ленту:

Заметки разработчика

Шпаргалки по найденным решениям и всякая всячина на компьютерную тему…

Загружается, подождите...

Google+ круги == Facebook списки друзей

Google+ круги == Facebook списки друзейВ последнее время много шума вокруг кругов Google+. И тут и там слышны фразы вроде «наконец-то я смогу одни фотки показывать только близким друзьям, а другие только сотрудникам» (говорится подобное в противовес Facebook). Судя по всему, многие не знают, что такая же возможность есть и была с давних времен на Facebook. Да, она не так очевидна и визуально красива (в Google+ процесс разбрасывания знакомых по кругам прямо таки затягивает :-)), но она есть и достаточно неплохо работает.

Итак, если вам нужна возможность разделять информацию для разных типов друзей на фейсбуке, и вы не в курсе этой возможности, надеюсь, мое мини руководство по созданию «кругов на Facebook» будет полезным.

В Facebook есть понятие «списки друзей» (группы контактов). Находятся эти списки здесь («Аккаунт» -> «Редактирование списка друзей») [1, 2]:

Редактирование списка друзей

Для начала нужно создать разные по смыслу группы/списки [3, 4] с расчетом на то, что в последствии персонально для каждой из них мы сможем в разной степени «перекрывать кислород» 🙂
После нажатия на кнопку №4 появится диалог (в нем же сразу можно отметить людей, которые будут находиться в создаваемом списке):

Диалог создания нового списка

Я создал для примера следующие группы (для того, чтоб создать еще один список, нужно возвращаться в пункт меню «Друзья» в меню слева):

Пример готового списка друзей

По умолчанию все ваши друзья не находятся в какой-либо из групп, поэтому нужно каждому назначить группу, подходящую контакту по смыслу. Перейдите в один из созданных вами списков [1] и увидите поле, где можно добавлять людей, набирая их имена [2]:

Заполнение списка

Так, переходя в каждый из списков, можно все их заполнить.

Когда контакт уже добавлен в какой-то из списков, если на него навести мышкой, напротив его имени появляется кнопка «Редактировать списки» [1], нажав на которую можно выбрать дополнительные группы для него, или же убрать из списков [2]:

Редактирование списка

Я предпочитаю по возможности не увлекаться и назначать контакту максимум две группы (иначе в итоге все контакты рискуют превратиться в однородную массу, и все манипуляции по разделению потеряют смысл).

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

Пример диалога на добавление нового человека в друзья

Разделяй и властвуй

Основная работа сделана. Когда все разделены, остается властвовать разобраться с тем, как публиковать материал исключительно для какой-то из групп.
К примеру, если вы публикуете свой статус, вы набираете текст [1], а потом нажимаете на кнопку с замочком [2]:

Публикация статуса

Выбираете пункт «Мои настройки», появится диалоговое окно, в котором можно указать человека [1, 2] (или нескольких) и только он будет видеть запись, так же можно указать, кто конкретно не должен видеть записи [3].

Диалог "Мои настройки конфиденциальности"

Основной момент заключается в том, что можно указывать не только персонально людей, но и названия групп контактов (я, если честно, до этого момента совсем не сразу додумался в свое время…). После того, как указаны нужные настройки, жмем кнопку «Сохранить настройки» [4] и публикуем свой статус, нажав «Поделиться».
И этот принцип работает при публикации любого типа материалов (в том числе и фотоальбомов), везде, где есть замочек.

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

Опубликованный статус (только для близких друзей)

Конфиденциальность

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

Стандартные настройки видимости

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

Переход к "Настройки конфиденциальности"

И видим две полезные ссылки, «Настройки просмотра» [1] и «Изменить настройки» [2]:

Настройки конфиденциальности

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

Настройки просмотра

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

Подробное редактирование настроек конфиденциальности

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

PS. Интерфейс Google+ действительно пока производит приятные впечатления по сравнению с Facebook, но в Facebook гораздо больше возможностей. Интересно, не запутают ли они его и не усложнят к тому времени, когда воплотят в жизнь все то, что есть у Facebook (а от активной конкуренции, нам, пользователям и разработчикам, по идее, будет только лучше :)).


Copyright © 2008 Заметки разработчика
Эта rss лента только для персонального некоммерческого использования.


CakePHP без базы данных

CakePHP без базы данныхЧасто видел в интернете упреки в сторону CakePHP в том смысле, что ему для работы обязательно нужна база данных, и это, мол, великое зло. Как-то не обращал внимания на данные утверждения (и правильно делал), так как всегда использовал базу данных. Но вот случилась необходимость сделать сайт на CakePHP без БД (временный сайт, со статикой, в будущем подразумевающий развитие до использования базы). В русскоязычной части интернета не удалось найти решения этой задачи (ясно примерно как это сделать, но хочется готового 🙂 ), к счастью, на англоязычном блоге был найден ответ.

Итак, приступим.

Сначала нужно создать для кейка новый источник данных (который будет заглушкой, по сути, и с данными никак работать не будет).

Создаем папку:
app/models/datasources/dbo

В которой нужно создать файл с именем:
dbo_dummy_source.php

В этом файле мы и опишем свой «источник данных». Вот содержимое файла:

<?php
class DboDummySource extends DataSource {
	 var $description = "This is a dummy data source";
	 function connect() {
		  $this->connected = true;
		  return $this->connected;
	 }
	 function disconnect() {
		  $this->connected = false;
		  return !$this->connected;
	 }
	 function value($string) {
		  return "\0".$string."\0";
	 }
}
?>

Вот и все. Теперь осталось только указать в файле конфигурации базы данных («app/config/database.php«) наш фиктивный драйвер, вместо реального драйвера подключения к базе данных, обычно это «mysql». Файл конфигурации в итоге должен выглядеть примерно так:

<?php
class DATABASE_CONFIG { 
	 var $default = array( 'driver' => 'dummy_source');
}
?>

И не забываем во всех моделях указать, что база данных для них не используется:

var $useTable = false;

В источнике решения автор пишет, что проверял данный код в версии кейка 1.2.x. Я проверял на 1.3 RC4 – работает.


Copyright © 2008 Заметки разработчика
Эта rss лента только для персонального некоммерческого использования.


Flv и субтитры

Flv и субтитрыПредположим, вам понравился какой-то видео файл на youtube (или в любой подобной системе, суть в том, что этот файл хранится в интернете в формате flv), и вы хотите его показать другим людям, разместив это видео на своем сайте или блоге, но, к сожалению, фильм не на русском языке. В этом случае может появиться потребность в его русификации, самый простой способ сделать это — создание субтитров для фильма.

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

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

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

Ссылка на видео файл

На данном этапе предполагается, что вы сами в состоянии узнать ссылку на нужный вам фал (обычно верный знак нужной ссылки — это расширение .flv в конце адреса).
Я для примера взял видео файл с таким адресом:
http://content.longtailvideo.com/videos/flvplayer.flv

Создаем субтитры

Я нашел только один онлайновый сервис, подходящий в данной ситуации (хотя, возможно, и существуют какие-то другие подобные инструменты) — Subtitle Horse.
После того, как заходишь на сайт, сразу же предлагается ввести адрес ролика, для которого мы хотим создать субтитры. Вставляем нашу ссылку (1) и переходим непосредственно к делу (2):

Рисунок 1

После чего появится следующее окно:

Рисунок 2

Принцип прост. Слева вы можете просматривать ролик (можно так же прокручивать ролик к нужным местам) (1), останавливая его в нужные моменты (там, где нужно будет вставлять текстовую фразу). После того, как поставите паузу, ниже пишите текст (перевод, или, допустим, все это можно использовать для вставки своих комментариев в видео). Как можно увидеть, там есть примитивные средства форматирования текста (жирность, выравнивание), которыми можно воспользоваться при необходимости (2). Когда все готово, жмем кнопку «Create» (3).

В правой части (4) вы увидите созданную запись субтитров (как и в области просмотра видео). Теперь можно отмотать видео немного назад и в режиме просмотра посмотреть, как будет выглядеть текст на практике. Также всегда в правой части можно кликнуть на нужном фрагменте текста (тогда ролик автоматически промотается к соответствующему фрагменту) и отредактировать его, откорректировав текст, сместив его по времени или указав более продолжительное время, в течение которого текст должен оставаться на экране.

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

Рисунок 3

После того, как все готово, нам нужно будет сохранить результат работы у себя на компьютере. Для этого идем в меню File — Export.

Рисунок 4

Рисунок 5

В закладке «Timed Text» (1) будет находиться текст, который нам нужен (2). Его нужно скопировать и сохранить в текстовом файле (в кодировке utf8) с расширением *.xml. Так как этот файл будет размещаться в интернете, назван он должен быть соответствующе, с использованием латинских символов и без пробелов. Я, к примеру, назвал файл именем — «my_subtitle.xml«.

Теперь мы готовы перейти к следующему этапу.

Вообще говоря, в этом редакторе больше возможностей, например, я подразумевал, что всю работу нужно делать в один присест (так как это не обычная программа на компьютере, где можно сохранять результат, а потом открывать его и продолжить работу). Тем временем в этом редакторе есть возможность импорта, то есть можно будет вставить в него содержимое не окоченной работы, которую ранее сохраняли в текстовый файл, и продолжить (а так же, наверняка, есть другие возможности, в которые я не вникал)… Просто моей целю не было описывать всю ее подноготную. Если же вам часто придется с ней работать, тогда, думаю, вам будет только интереснее, исследуя ее, открывать новые возможности 😉

Размещаем на сайте и «скрещиваем»…

Итак, мы имеем ссылку на видео (http://content.longtailvideo.com/videos/flvplayer.flv) и файл с субтитрами к нему («my_subtitle.xml«).

Онлайн плеер, который умеет проигрывать видео с такими субтитрами, называется «JW FLV Media Player«. Предполагается, что вы уже имели опыт работы с ним или с чем-то подобным. Если нет, то можно почитать здесь, как его устанавливать на свой сайт и указывать ему, что он должен проигрывать.

Если вы закачали необходимые файлы для проигрывателя на свой сайт и так же закачали файл субтитров, на странице, где будет размещен видеоролик, нужно будет прописать код, аналогичный следующему (сам видео-файл подгружаем с другого сайта, остальные сопутствующие файлы в данном случае лежат в той же директории, где и html файл, содержимое которого показано ниже):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Тэст субтитров</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<script type='text/javascript' src='swfobject.js'></script>
 
<div id='mediaspace'>Этот текст будет заменен роликом</div>
 
<script type='text/javascript'>
  //Указываем расположение плеера и его ширину и высоту
  var so = new SWFObject('player.swf','mpl','400','319','9');
  so.addParam('allowfullscreen','true');
  so.addParam('allowscriptaccess','always');
  so.addParam('wmode','opaque');
  //Указание месторасположения файла с субтитрами
  so.addVariable('captions','my_subtitle.xml');
  //Путь к видео-файлу
  so.addVariable('file','http://content.longtailvideo.com/videos/flvplayer.flv');
  //Отмечаем, что хотим использовать плагин субтитров
  so.addVariable('plugins','captions-1');
  //Вписываем окно плеера в div с id "mediaspace"
  so.write('mediaspace');
</script>

</body>
</html>

Вот пример того, как это работает.

После всех этих операций видео должно проигрываться с субтитрами!

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

Подводные камни

Собственно, пока я спотыкался только об один…

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

[ Скачать архив с примером ] (55 КБ)


Copyright © 2008 Заметки разработчика
Эта rss лента только для персонального некоммерческого использования.


Делаем свой RSS-канал

Делаем свой RSS-канал

После серии статей о том, что такое RSS, у многих владельцев сайтов, у которых нет RSS (а таких не так уж и мало, как могут думать некоторые), может возникнуть желание заполучить его себе:-) В этой статье я хочу перечислить способы организации RSS-канала для своего сайта. Начиная с самых простых способов и заканчивая сложными.

Изначально нужно быть уверенным, что вы знаете о том, что RSS-документ – это, по сути своей, обычный файл, в котором специальным образом в виде текста описаны те или иные новости (или статьи). В итоге понятие «у меня (у моего сайта) есть RSS-канал» будет выражаться на практике в виде интернет адреса к этому самому документу (у меня на блоге это, к примеру, адрес: http://feeds.feedburner.com/devezoterik). Ваши же читатели, имея этот адрес, в дальнейшем смогут следить за изменениями в этом файле с помощью специальных программ.

Использование сторонних сервисов (блогов)

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

То есть идея в том, что где бы вы не содержали свой сайт, вы можете параллельно поддерживать на другом сайте (сервисе, о них чуть позже) актуальную новостную ленту. На своем же сайте вы можете указать ссылку на RSS-документ, которой смогут воспользоваться посетители, желающие следить за вашими новостями.

Подобных сервисов для ведения своих блогов предостаточное количество в интернете. Одни из самых популярных и надежных это: www.blogger.com, my.ya.ru и livejournal.com (но вообще их просто несметное количество, отличающихся обычно немногим). На каждом из указанных мной сервисов есть русская версия с подробной помощью, описывающей, как «завести» свой блог.

Использование сервисов генерации RSS из обычных страниц

Этот способ так же не требует навыков программирования и подходит в первую очередь людям, которые имеют свой сайт и имеют на нем некую страницу новостей, которые они могут обновлять тем или иным способом, но, тем не менее, не имеют на этом сайте RSS-канала.

Конечно, можно воспользоваться первым способом: создать где-нибудь блог и дублировать в него новости со своего сайта (обычно это те новости, которые выводят на первой странице сайта). Но тогда ведь постоянно придется дублировать новости с сайта на блог… Предлагаемый же способ дает альтернативу для более прогрессивных/ленивых (иногда грань между этими понятиями бывает мала :)) владельцев сайта.

Смысл заключается в том, чтобы использовать сервисы, которые будут сами следить за вашей страницей новостей и создавать каждый раз (при обновлении вами страницы) актуальный RSS-документ. О подробностях этого процесса я уже писал. Писал в первую очередь для тех, кто хочет следить за чужими сайтами, но никто нам не мешает посмотреть с другой точки зрения и следить за своим 🙂 В итоге мы будет иметь ссылку на автоматически обновляемый RSS-документ, отражающий все новости на вашем сайте (правда, с задержкой около одного часа). Вам лишь нужно будет добавлять новости на свою страницу, не изменяя внутреннего форматирования html документа, чтобы сервисы «слежения» не потерялись на странице в поисках искомых новостей (чтоб узнать более подробную информацию, читайте статью по выше приведенной ссылке).

Создание RSS-документа вручную

Если по каким-либо причинам вы не хотите, чтоб RSS-документ обитал вне вашего сайта, и при этом вы не программист, остается еще один способ: создавать и обновлять этот документ у себя на сайте вручную (здесь уже понадобится опыт работы с html). В случае использования хостинга без поддержки скриптов и при не слишком частом появлении новостей (иначе вся эта затея будет очень утомительной), это вполне востребованный вариант.

Для создания и редактирования такого файла лучше всего использовать редактор Notepad++ или любой другой редактор, поддерживающий работу с кодировкой UTF-8 (без BOM). Документ должен быть в кодировке UTF-8 (без BOM). Вот пример того, как может выглядеть RSS-документ внутри (пример снабжен комментариями):

<?xml version="1.0" encoding="utf" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
	<!-- Заголовок RSS-ленты, обычно это название сайта -->
	<title>Мой сайт</title>
	<!-- Адрес сайта, которому принадлежит RSS-лента -->
	<link>http://www.moi_sait.ru</link>
	<!-- Описание RSS-ленты -->
	<description>Здесь вы сможете прочесть все последние новости сайта</description>
	<language>ru-ru</language>
	<!-- Эта секция (image) не обязательна -->
	<image>
		<!-- Ссылка на логотип для RSS-ленты -->
		<url>http://www.moi_sait.ru/logo.jpg</url> 
		<!-- Заголовок логотипа -->
		<title>Логотип моего сайта</title> 
		<!-- Адрес страницы, на которую должен будет попасть пользователь, кликнувший на логотип -->
		<link> http://www.moi_sait.ru</link> 
	</image>
	<!--Дата последнего обновления документа. Дата должна быть именно в этом формате -->
	<lastBuildDate>Sun, 07 Jun 2009 04:00:11 +0300</lastBuildDate>
	<!-- Тэг item описывает один элемент (например, одну новость, или одну статью) -->
	<item>
		<!-- Краткий заголовок новости (или название статьи) -->
		<title>На сайте реализована поддержка RSS</title>
		<!-- Ссылка на страницу, посвященную этой новости (где может быть, к примеру, более широкое описание, а может, и такое же, как в RSS) -->
		<link>http://www. moi_sait.ru/news/1.htm</link>
		<!-- Более многословное описание новости (или содержимое статьи). Нужно заметить, что внутри можно использовать html тэги для более красивого форматирования, но в экранированном виде. В примере ниже используется тэг br (перенос строки) в экранированном виде "&lt;br /&gt;"-->
		<description>Ура, наконец-то теперь есть поддержка RSS!&lt;br /&gt;Долой e-mail рассылку!</description>
		<!-- Дата, к которой привязана новость (или дата публикации новости). Формат ее должен быть такой же, как и дата в тэге lastBuildDate -->
		<pubDate>Fri, 05 Jun 2009 10:39:18 +0300</pubDate>
		<!-- Необязательный тэг. Который может в себе содержать имя автора статьи или новости -->
		<author>Станислав &lt;stanislav@mail.com&gt;</author>
		<!-- Та же ссылка на страницу новости, что и в тэге link -->
		<guid isPermaLink="true">http://www. moi_sait.ru/news/1.htm</guid>
	</item>

	<!-- ...Здесь вы можете повторять секцию item для каждой из своих новостей по аналогии с элементом выше. Стоит лишь отметить, что не желательно, чтоб документ был слишком большим, обычно размещается от 10 до 20 элементов item... -->

</channel>
</rss>

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

Автоматическая генерация RSS-документа на своем сервере

Этот способ подходит уже только для более искушенных веб-программированием людей. Если информация на сайте хранится в базе данных, а сами страницы являются серверными скриптами (а ля PHP), тогда становится возможным использовать самый автономный и не обременяющий в дальнейшем способ – создавать в автоматическом режиме RSS-документ при запросе оного пользователями. Описывать, как создать подобный скрипт, не имеет смысла, так как уже есть достаточно статей на эту тему с готовыми примерами и разъяснениям к ним. Вот одни из них (для языка PHP): ссылка 1, ссылка 2, ссылка 3, ссылка 4, ссылка 5.

Скромный посредник — Feedburner

И вот у вас, наконец, есть желанный адрес своей RSS-ленты. Казалось бы, чего еще можно желать? Конечно же, подробной статистики. Именно для этого и был создан сервис feedburner. Он позволит вам получать максимально возможную статистику, такую, например, как: количество подписчиков, распределение подписчиков по странам, степень интереса подписчиков к тем или иным новостям, возможность получать ваши RSS-новости по e-mail и т.д.

Основной принцип работы feedburner`а заключается в том, что он является посредником между вашим RSS-документом и читателями. Вы указываете feedburner`у адрес своей RSS-ленты, после чего feedburner сможет отдавать эту ленту уже из другого адреса (адрес будет таким: http://feeds.feedburner.com/ + имя вашей RSS-ленты). И если пользователи будут подписываться именно на адрес от feedburner`а, вы сможете в полной мере использовать все функции данного сервиса. При этом нужно помнить, что если кто-то подпишется на настоящий адрес вашего канала, вы не сможете получить прелести использования feedburner`а.

Эта схема поможет придать больше наглядности вышеописанному:

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

О настройках feedburner можно прочесть здесь. А так же здесь, здесь и здесь.

На самом деле, помимо всего прочего, этот сервис несет в себе еще один плюс. Так как все подписчики будут подписываться на RSS-ленту, находящуюся на feedburner, то вы можете, когда захотите, поменять адрес оригинального источника RSS-ленты (например, пробуя со временем разные способы создания RSS, описанные в этой статье, или, может, вы смените адрес сайта), не потеряв при этом всех своих подписчиков (они всегда будут видеть адрес ленты на feedburner, не подозревая о изменении ваших настроек). Если же люди подписывались бы на оригинальный адрес RSS-документа (без посредника в виде feedburner), то при его смене (вами) они перестанут получать новости, так как документа по старому адресу не будет существовать.


Copyright © 2008 Заметки разработчика
Эта rss лента только для персонального некоммерческого использования.


PHP и BBCode

У меня периодически появляется потребность в использовании «интерпретатора» BBCode в своих проектах (написанного на PHP), и постоянно нет времени искать какое-то более-менее удобоваримое решение, что в итоге выливается в использование или создание «костылей» для каждого конкретного случая.
Но вот, похоже, получилось найти то, что хотелось.

Моя претензия к подобным готовым решениям обычно в первую очередь заключается в неспособности этих библиотек правильно обрабатывать абзацы. Фактически они обычно вообще не используют абзацы (тэг P), вместо этого в результате своей работы они просто вставляют тег <br /> , заменяя обычные символы переноса строки. Я считаю такой метод эмулирования абзацев в 98 процентах, мягко говоря, не уместным. Но так как перенос строк по средствам <br /> намного легче реализовать вместо «человеческих» <p>, так большинство и делает 🙁 Некоторые даже придумывают оправдания, что мол с br даже правильнее, отчасти, из-за подобной лени разработчиков различных готовых библиотек, другая часть людей думает, что тэг P является устаревшим (ведь даже во многих готовых продуктах и сайтах абзацы формируются путем использования <br />) 🙂

Приступим

Но, кажется, есть свет в конце туннеля. Это готовый класс для работы с BBCode, который, судя по всему, отлично справляется со своей задачей (ничего лучше пока не видел). Единственный минус в том, что документация, представленная на сайте, не на русском языке. Этот минус я и хочу побороть в этой статье, приведя пример использования класса с русскими комментариями.

Для начала нужно скачать библиотеку (на момент написания статьи версия библиотеки была 0.3.3). В скачанном архиве в папке src вы обнаружите два нужных нам файла: stringparser.class.php и stringparser_bbcode.class.php.

Для примера предположим, что у нас есть пустой файл «index.php» и рядом с ним мы создадим папку «/bbcode/», содержащую в себе два упомянутых выше файла.
Для примера минимальное содержимое файла «index.php» должно быть таким (запустив этот пример можно будет сразу увидеть, работает ли библиотека):

< ?php
//Вставляем файл библиотеки
require_once 'bbcode/stringparser_bbcode.class.php';

//Создаем объект класса StringParser_BBCode
$bbcode = new StringParser_BBCode ();

//Добавляем объекту класса понятие о тэге [b]
//(в итоге только этот тэг и будет
//обрабатываться этим классом)
$bbcode->addCode ('b', 'simple_replace', null, array ('start_tag' => '<b>', 'end_tag' => '</b>'),
                  'inline', array ('block', 'inline'), array ());

//Обрабатываем тестовую строку и выводим ее в браузер
echo $bbcode->parse ('Тестовый текст, это слово должно быть [b]жирным[/b]');
?>

Функция addCode

Наибольший интерес в этом коде может вызвать, пожалуй, функция addCode у объекта класса StringParser_BBCode, вот ее прототип и список описание параметров:

void addCode (string $code, string $type, string $callback, string $params, string $content_type,
              array $allowed_in, array $not_allowed_in);

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

$code (в примере имеет значение ‘b’)
Код, который нужно искать в тексте для обработки. Т.е. если указать код test , то потом в обрабатываемом тексте будет искаться тэг [test] и обрабатываться в соответствии с указаниями в других параметрах рассматриваемой функции.
$type (в примере имеет значение ‘simple_replace’)
Указание того, как тэг должен обрабатываться (какого он типа). Есть различные предопределенные типы тэгов, которые будут описаны ниже. В нашем же примере указан тип ‘simple_replace’ который указывает на то, что тэг будет парным (открывающийся тэг [b] и закрывающийся [/b]) и что эти тэги будут заменены на указанные ниже html тэги.
$callback (в примере имеет значение null)
Позволяет указать имя функции, которая должна будет вызваться при обработке найденного тэга в тексте. В случае с типом тэга ‘simple_replace’ такая функция не вызывается, и, соответственно, в этом параметре можно указать null.
$params (в примере имеет значение array(‘start_tag’ => ‘‘, ‘end_tag’ => ‘‘))
В этом параметре в основном указывается, какой нужно вставлять html тэг взамен bb тэга. Наименование параметров напрямую зависит от того, какой тип тэга мы указали в параметре $type.
$content_type (в примере имеет значение ‘inline’)
Тип внутреннего содержимого тега. Может принимать значения: ‘inline’, ‘block’, ‘link’, ‘image’. Если я не ошибаюсь, можно прописывать и свои типы чтобы потом можно было указывать для этого содержимого свои индивидуальные фильтры (пример использования фильтров смотрите ниже).
$allowed_in (в примере имеет значение array (‘block’, ‘inline’))
В этом параметре можно указать, внутри каких типов объектов может находиться создаваемый bb-код (его обработка будет просто игнорироваться в ином случае). В нашем примере мы указали, что элемент может находиться как внутри блочных элементов, так и внутри линейных.
$not_allowed_in (в примере имеет значение array ())
Имеет назначение, противоположное по смыслу предыдущему параметру.

Виды обработки тэгов

Описание вариантов значения параметра $type в функции addCode.

‘simple_replace’
Описывает простой парный тэг. При использовании этого типа обработки тэга в параметре функции ‘params’ должны обязательно присутствовать две ячейки: $params[‘start_tag’] и $params[‘end_tag’]. ‘start_tag’ должен в себе содержать аналог открывающегося тэга в хтмл, а ‘end_tag’ – закрывающегося тэга соответственно.
‘simple_replace_single’
То же самое, что ‘simple_replace’, но используется только лишь для одинарных тэгов, которые, собственно говоря, не имеют содержимого (типа br, hr и т.п.). Требует наличия только параметра $params[‘start_tag’].
‘callback_replace’
При этом типе вы перекладываете на себя обработку по найденным совпадениям (с помощью своей callback функции) для парного тэга.
‘callback_replace_single’
То же самое, что и ‘callback_replace’, но только для одинарных тэгов.
‘usecontent’
То же самое что и ‘callback_replace’, только в содержимом такого тэга другие тэги не будут обрабатываться, например, это удобно для тэга code.
‘usecontent?’
Этот тип может себя вести как ‘usecontent’ или же как ‘callback_replace’ в зависимости от ситуации. Актуальность того или иного варианта определяется за счет присутствия заранее предполагаемого атрибута в bb тэге. Если атрибут найден, то будет использоваться обработка ‘callback_replace’, в другом случае тэг будет обрабатываться как ‘usecontent’. Имя атрибута для поиска указывается через параметр $params[‘usecontent_param’]. Если указано имя default, то подразумевается значение атрибута, присвоенное непосредственно тэгу, например, [url=http://link], значением атрибута default будет текст «http://link». Этот прием часто используется, например, для тэга [URL]. Этот тэг может использоваться в двух формах: [url]http://www.example.com/[/url] и [url=http://www.example.com/]Текст ссылки, а так же [b]жирный[/b] текст[/url]. В первом случае будет использоваться тип ‘usecontent’, т.к. текст ссылки должен выводиться без какого-либо форматирования (и, собственно, сама ссылка будет некорректна, если в ней будут посторонние символы). В другом случае должен быть использован тип ‘callback_replace’, т.к. сама ссылка передается отдельным параметром, а текст, обрамленный в ссылку, вполне может содержать в себе какое-то форматирование.
Примечание: Можно указать несколько параметров для их поиска, для чего в $params[‘usecontent_param’] нужно передать не строку, а массив, содержащий строки. Например: $bbcode->addCode (…, array(‘usecontent_param’ => array (‘parameter1’, ‘parameter2’)), …);.
‘callback_replace?’
Является противоположным вариантом типа ‘usecontent?’. Если один из атрибутов, указанных в usecontent_param, встречается в тэге, он будет обработан как ‘usecontent’, в противном случае как ‘callback_replace’.

Пример кода из «боевых» условий

Вот пример файла index.php с более расширенной конфигурацией класса для обрабатывания большего числа тэгов, в нем же и можно понять, как работают callback функции и т.п.:

< ?php
//Вставляем файл библиотеки
require_once 'bbcode/stringparser_bbcode.class.php';

//Приводит разнообразные переводы строк
//разных операционных систем в единый формат (\n)
function convertlinebreaks ($text) {
	return preg_replace ("/\015\012|\015|\012/", "\n", $text);
}

//Удалить все символы, кроме переводов строк
function bbcode_stripcontents ($text) {
	return preg_replace ("/[^\n]/", '', $text);
}

//Функция для обработки ссылок
function do_bbcode_url ($action, $attributes, $content, $params, $node_object) {
	if (!isset ($attributes['default'])) {
		$url = $content;
		$text = htmlspecialchars ($content);
	} else {
		$url = $attributes['default'];
		$text = $content;
	}
	//Часть функции, которая занимается
	//только валидацией данных тэга
	if ($action == 'validate') {
		if (substr ($url, 0, 5) == 'data:' || substr ($url, 0, 5) == 'file:'
		  || substr ($url, 0, 11) == 'javascript:' || substr ($url, 0, 4) == 'jar:') {
			return false;
		}
		return true;
	}
	//Непосредственное преобразование тэга в
	//html вариант с возвращением результата
	return '<a rel="nofollow" onclick="return opnfrm(this)"  href="'.htmlspecialchars ($url).'">'.$text.'';
}

// Функция для вставки изображений
function do_bbcode_img ($action, $attributes, $content, $params, $node_object) {
	//Часть функции, которая занимается
	//только валидацией данных тэга
	if ($action == 'validate') {
		if (substr ($content, 0, 5) == 'data:' || substr ($content, 0, 5) == 'file:'
		  || substr ($content, 0, 11) == 'javascript:' || substr ($content, 0, 4) == 'jar:') {
			return false;
		}
		return true;
	}
	//Непосредственное преобразование тэга в
	//html вариант с возвращением результата
	return '<img src="'.htmlspecialchars($content).'" alt=""/>';
}

//Создаем объект класса StringParser_BBCode
$bbcode = new StringParser_BBCode();

//Добавляем фильтр (подробнее см. офф. документацию),
//задействуя нашу функцию convertlinebreaks, которая будет
//преобразовывать переводы строки в тексте к единому
$bbcode->addFilter (STRINGPARSER_FILTER_PRE, 'convertlinebreaks');

//Добавляем свои парсеры для разных типов объектов
//(подробнее см. офф. документацию)
//Мы указываем, через какую функцию должно пройти
//содержимое этих тэгов, например, через функцию
//htmlspecialchars для предотвращения XSS и т.д.
$bbcode->addParser (array ('block', 'inline', 'link', 'listitem'), 'htmlspecialchars');
$bbcode->addParser (array ('block', 'inline', 'link', 'listitem'), 'nl2br');
$bbcode->addParser ('list', 'bbcode_stripcontents');


//Добавляем bb-код [h1], используемый в виде:
//[h1]Текст заголовка первого уровня[/h1]
$bbcode->addCode ('h1', 'simple_replace', null, array ('start_tag' => '<h1>', 'end_tag' => '</h1>'),
				  'block', array ('listitem', 'block', 'link'), array ());
//Добавляем bb-код [h2], используемый в виде:
//[h2]Текст заголовка второго уровня[/h2]
$bbcode->addCode ('h2', 'simple_replace', null, array ('start_tag' => '<h2>', 'end_tag' => '</h2>'),
				  'block', array ('listitem', 'block', 'link'), array ());
//Добавляем bb-код [h3], используемый в виде:
//[h3]Текст заголовка третьего уровня[/h3]
$bbcode->addCode ('h3', 'simple_replace', null, array ('start_tag' => '<h3>', 'end_tag' => '</h3>'),
				  'block', array ('listitem', 'block', 'link'), array ());
//Добавляем bb-код [h4], используемый в виде:
//[h4]Текст заголовка четвертого уровня[/h4]
$bbcode->addCode ('h4', 'simple_replace', null, array ('start_tag' => '<h4>', 'end_tag' => '</h4>'),
				  'block', array ('listitem', 'block', 'link'), array ());
//Добавляем bb-код [h5], используемый в виде:
//[h5]Текст заголовка пятого уровня[/h5]
$bbcode->addCode ('h5', 'simple_replace', null, array ('start_tag' => '<h5>', 'end_tag' => '</h5>'),
				  'block', array ('listitem', 'block', 'link'), array ());
//Добавляем bb-код [h6], используемый в виде:
//[h6]Текст заголовка шестого уровня[/h6]
$bbcode->addCode ('h6', 'simple_replace', null, array ('start_tag' => '<h6>', 'end_tag' => '</h6>'),
				  'block', array ('listitem', 'block', 'link'), array ());

//Устанавливаем флаги для bb-кодов с h1 до h6,
//указывая, что они являются блочными элементами,
//что будет в дальнейшем благотворно влиять на умную
//генерацию html кода. Такой элемент, к примеру, не сможет
//находиться внутри других блочных элементов
$bbcode->setCodeFlag('h1', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT);
$bbcode->setCodeFlag('h2', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT);
$bbcode->setCodeFlag('h3', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT);
$bbcode->setCodeFlag('h4', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT);
$bbcode->setCodeFlag('h5', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT);
$bbcode->setCodeFlag('h6', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT);

//Добавляем bb-код [b], используемый в виде:
//[b]выделенный текст[/b]
$bbcode->addCode ('b', 'simple_replace', null, array ('start_tag' => '<b>', 'end_tag' => '</b>'),
				  'inline', array ('listitem', 'block', 'inline', 'link'), array ());
//Добавляем bb-код [i], используемый в виде:
//[i]наклонный текст[/i]
$bbcode->addCode ('i', 'simple_replace', null, array ('start_tag' => '<i>', 'end_tag' => '</i>'),
				  'inline', array ('listitem', 'block', 'inline', 'link'), array ());
//Добавляем bb-код [url], используемый в виде:
//[url]http://www.needsite.domain[/url] и 
//[url=http://www.needsite.domain]Текст ссылки[/url]
$bbcode->addCode ('url', 'usecontent?', 'do_bbcode_url', array ('usecontent_param' => 'default'),
				  'link', array ('listitem', 'block', 'inline'), array ('link'));
//Добавляем bb-код [link], используемый в виде:
//[link]http://www.needsite.domain[/link]
$bbcode->addCode ('link', 'callback_replace_single', 'do_bbcode_url', array (),
				  'link', array ('listitem', 'block', 'inline'), array ('link'));
//Добавляем bb-код [img], используемый в виде:
//[img]http://www.needsite.domain/img.jpg[/img]
$bbcode->addCode ('img', 'usecontent', 'do_bbcode_img', array (),
				  'image', array ('listitem', 'block', 'inline', 'link'), array ());
//Добавляем bb-код [bild] (по смыслу то же самое,
//что и [img]), используемый в виде:
//[bild]http://www.needsite.domain/img.jpg[/bild]
$bbcode->addCode ('bild', 'usecontent', 'do_bbcode_img', array (),
				  'image', array ('listitem', 'block', 'inline', 'link'), array ());

//Создаем группу image из bb-кодов img и bild
//для последующей возможности задания
//неких правил для этих групп
$bbcode->setOccurrenceType ('img', 'image');
$bbcode->setOccurrenceType ('bild', 'image');
//Указываем, что тэги из группы image
//могут встречаться (обрабатываться) в тексте не более
//двух раз. В нашем случае это нужно для того,
//чтобы пользователь не мог вставить более двух
//картинок в текст сообщения
$bbcode->setMaxOccurrences ('image', 2);

//Добавляем bb-код [list]
$bbcode->addCode ('list', 'simple_replace', null, array ('start_tag' => '<ul>', 'end_tag' => '</ul>'),
				  'list', array ('block', 'listitem'), array ());
//Добавляем bb-код [*], указывая, что этот тэг
//может использоваться только внутри тэга
//с типом list (этот тип мы присвоили выше тэгу [list])
$bbcode->addCode ('*', 'simple_replace', null, array ('start_tag' => '<li>', 'end_tag' => '</li>'),
				  'listitem', array ('list'), array ());

//Устанавливаем флаги для тэгов [list] и [*]
//Указываем, что для кода [*] закрывающийся тэг
//не обязателен, таким образом, возможна будет
//следующая конструкция:
//[list]
//[*] Item
//[*] Item
//[/list]
//Закрывающий тэг будет добавляться автоматически
//в процессе формирования html кода
$bbcode->setCodeFlag ('*', 'closetag', BBCODE_CLOSETAG_OPTIONAL);
//Как я понял, этот флаг обозначает, что тэг [*]
//всегда может быть использован только
//в начале новой строки
$bbcode->setCodeFlag ('*', 'paragraphs', true);
//[list] является блочным элементом
$bbcode->setCodeFlag ('list', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT);
//Перед открывающимся тэгом [list]
//символ строки будет устранен
$bbcode->setCodeFlag ('list', 'opentag.before.newline', BBCODE_NEWLINE_DROP);
//Перед закрывающимся тэгом [list]
//символ строки будет устранен
$bbcode->setCodeFlag ('list', 'closetag.before.newline', BBCODE_NEWLINE_DROP);
//В итоге мы можем использовать списки в bb-коде,
//используя вместе теги list и *:
//[list]
//[*] Элемент списка
//[*] Элемент списка
//[*] и т.д.
//[/list]


//Активируем обработку параграфов
$bbcode->setRootParagraphHandling (true);
//Как я понял, таким образом указывается,
//какими символами нужно заменять встреченный
//перенос строки внутри абзаца
//(по сути, как обрабатывать пустые абзацы).
$bbcode->setParagraphHandlingParameters ("\n", '<p>', '</p>');

$res_text = "Тестовый текст [b]для проверки[/b] работы класса";

//На всякий случай удаляем все оставшиеся
//символы переноса строки в виде "\r",
//если такие остались в тексте
$res_text = str_replace("\r", '', $res_text);

//Вуаля!
echo $bbcode->parse($res_text);

Послесловие

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

Эту библиотеку также не составляет труда внедрить в какой-либо php фреймворк, я, к примеру, с успехом проделывал это для cackePHP.

Если вы тоже встречали подобные библиотеки (корректно работающие с абзацам! 🙂 ) , интересно было бы узнать о них.


Copyright © 2008 Заметки разработчика
Эта rss лента только для персонального некоммерческого использования.


Грамотная работа в Word. Продолжение

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

После того, как мы подготовили «чистый текст», его можно, наконец, оформлять.

Для начала нужно обязательно воспринимать каждый абзац (напомню, что нажимая Enter на клавиатуре, мы их порождаем все больше и больше) как некое отдельное существо 🙂

Абзацы

Отступы

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

Горизонтальная линейка

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

Рычажки

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

На рисунке ниже можно увидеть, какой из рычажков за что отвечает.

Рычажки

— Отступ слева первой строки в абзаце (отступ красной строки).
— Отступ слева всех строк в абзаце, кроме первой.
— Отступ слева для всех строк в абзаце (по сути, двигает одновременно первые два рычкажка).
— Отступ справа для всех строк в абзаце.

Вот пример:

Пример влияния рычажков на абзацы

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

Выравнивание

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

Кнопки выравнивания

Эти же кнопки являются и индикатором текущего выравнивания выделенного абзаца (будет «вдавлен» тот вид выравнивания, который установлен в текущий момент у выделенного абзаца).

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

Практика

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

Пример оформления текста

Пояснения:

  1. Заголовок отцентрирован правильным способом (с использованием кнопок, а не пробелов), и к нему применен стиль «Заголовок 1».
  2. Цитата уменьшена и помещена в правую часть с помощью рычажков на линейке (настроек отступов абзаца). Выравнивание по правому краю в данном случае было бы не уместно (хотя многие так делают), потому как при таком способе будет неадекватно выровнена последняя строка в абзаце и т.п. Вместо этого к этому абзацу применено выравнивание «по ширине», чтобы все строки в абзаце были ровными по правому краю, так же, как и слева.
  3. «Автор цитаты» выровнен с помощью выравнивания «по правому краю».
  4. Основной текст оставляем нетронутым, разве что выравнивание «по ширине» к нему применяем, чтобы красивее было 🙂

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

Неправильный способ решения этой задачи – это разбивать абзац на несколько маленьких с помощью кнопки Enter на клавиатуре (формируя кривоватый столбец текста) и выравнивание этого столбца с помощью кнопки выравнивания «по правому краю» или же, что еще хуже — массой пробелов. В примере ниже я включил отображение невидимых символов (пробелов и обозначений окончания абзацев):

Пример неправильного оформления текста

Расширенные настройки

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

Google Docs я такой возможности не нашел)

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

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

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

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

Google Docs этой настройки нет, но, собственно, он и не претендует на полностью полноценный и «громоздкий» редактор текстов)

Нарушение правил 🙂

В редких случаях бывает очень нужно сделать в тексте именно перенос текста, не создавая при этом нового абзаца, или, точнее сказать, нужно, чтобы при переносе программа продолжала воспринимать нужный нам блок текста как единый абзац. И выход есть, для этого нужно перенести нужный текст не с помощью одной лишь кнопки Enter на клавиатуре (так мы создадим обычный абзац), а с помощью сочетания клавиш Shift + Enter (держа зажатым Shift, нужно один раз нажать Enter). Нужно только не злоупотреблять этой возможностью и использовать ее в тех случаях, когда это действительно крайне необходимо (потому что такие абзацы могут не совсем корректно выглядеть, если вы захотите изменить ширину страницы документа и т.п.).

Оглавление

Бывает нужно сделать что-то вроде подобного оглавления:

Пример оглавления

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

На самом же деле во многих программах есть более изящный способ (работает, как минимум, в MS Word). Для его использования сначала нужно подготовить те абзацы, в которых должны быть подобные многоточия. Нужно расставить между заголовком и номером страницы один (и не более) символ табуляции, нажимая на клавиатуре кнопку Tab. Примерно вот так будет выглядеть подготовленный текст, если посмотреть на него в режиме отображения невидимых знаков (стрелочки обозначают символы табуляции).

Начало создания оглавления

Основная идея в том, что для символов табуляции можно указать их размер в ширину, а так же, какой символ будет заполнять пространство, занимаемое табуляциями.

Вот более точное описание дальнейшего процесса для MS Word (версии 2003 и 2007) и OpenOffice.org Writer:

Выделяем фрагмент, где нам нужны «точечки» и ставим по одной табуляции.

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

Маркер размера табуляции

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

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

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

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

Так же стоит отметить, что в MS Word 2007 (наверняка и в каких-то других программах, в Google Docs, к примеру, тоже) имеется возможность полностью автоматизировать процесс создания оглавления. Для этого в первую очередь нужно правильно создавать заголовки в документе (как описывалось в конце предыдущей стати). После чего нужно поставить курсор в то место, где вы хотите видеть оглавление, зайти в меню «Ссылки» -> «Оглавление» и выбрать понравившийся шаблон оглавления (там же есть и более тонкие настройки).

В Google Docs такое оглавление можно создать, перейдя по меню «Вставить -> Оглавление».

Для OpenOffice.org Writer нужно перейти в «Вставка -> Оглавление и указатели -> Оглавление и указатели…» («Insert –> Indexes and Tables -> Indexes and Tables…»).

Если в используемой вами программе есть возможность делать подобное автоматическое оглавление, то, скорее всего, это будет наилучшим вариантом. Ведь при смещении глав на другие страницы номера страниц в таком оглавлении будут обновляться почти автоматически. Для обновления номеров страниц в таких оглавлениях нужно нажать на какую-то специальную кнопку появляющуюся рядом с оглавлением, если навести на него мышку или, в крайнем случае (в OpenOffice.org Writer я только так смог обновить оглавление), кликнуть правой кнопкой мыши на него и выбрать соответствующий пункт в появившемся меню. Но все равно это куда продуктивнее ручного изменения номеров в оглавлении.

Стили оформления документа

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

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

Навигация по документу

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

Послесловие

В каждой программе есть, конечно же, свои дополнительные упрощающие жизнь инструменты, но я хотел описать основные моменты, те, которые во многих программах схожи, и с которыми сталкиваешься в первую очередь при работе с текстами. Надеюсь, статья будет полезна интересующимся. Так же приветствуются комментарии 🙂


Copyright © 2008 Заметки разработчика
Эта rss лента только для персонального некоммерческого использования.


Грамотная работа в Word

Часто сталкиваюсь с тем, что люди не умеют корректно работать в программах типа MS Word и ей подобных. Хотя обычно большинство из них уверены, что все отлично делают.

Чаще всего это проблема всех новичков, недавно научившихся в той или иной мере пользоваться вордом (а иногда и у «старичков» 😉 ). Проблема появляется тогда, когда человек, создавая документ, не знает основной «философии» работы в подобных программах, набирает текст «абы как», вставляя кучу пробелов где нужно и не нужно и т.п., стремясь к одному – «главное, чтобы выглядело как нужно». Часто со временем это приводит к выработке каких-то своих «хитростей», то есть, к изобретению достаточно некачественного велосипеда. С другой стороны, если документы создаются только чтобы их распечатать и забыть про них, а также имеют достаточно маленький размер, то такой подход вполне жизнеспособен. Но, думаю, применение правильного подхода все же может очень облегчить жизнь даже в таких случаях. Если же эти документы хранятся и предполагается их дальнейшее изменение вами или, тем более, другими людьми, то при «самобытном» способе их изготовления может начаться настоящий хаос.

Все дальнейшие рекомендации можно и нужно применять не только в MS Word, но и во всех других программах подобного плана (OpenOffice.org Writer, AbiWord, Google Docs, StarOffice и прочие, разве что к программе «Блокнот» далеко не все применимо 🙂 ), и даже в более серьезных программах, предназначенных для профессиональной верстки текстов. Также предполагается, что человек все же имеет какой-никакой опыт работы в используемой им программе.

Итак, самое главное, забудьте вначале о внешнем виде документа, «зримое не важно» 🙂 Нужно выработать привычку набирать сначала «чистый» текст, а уже потом его украшать. В этой статье я хочу описать принципы правильного создания чистого текста и его структуры, в следующей — способы «украшения» такого текста и несколько полезных «в быту» приемов.

Итак начну…

Пробелы

В первую очередь – никогда не используйте в тексте больше одного пробела. В частности, это относится к пробелам перед каждым абзацем для того, чтобы сделать красную строку или отступ перед текстом. Иногда с помощью пробелов выравнивают текст по центру или по правому краю, что является «большим грехом» 🙂

Также не очень хороши «случайные» вставки двух/трех пробелов между словами вместо одного.

Почему так делать плохо? Аргументировать могу только тем, что с такими документами в дальнейшем ужасно неудобно работать и модифицировать их. Представьте себе, к примеру, «картину»: вы сделали большой документ (для сгущения красок можно представить, что это какая-то книга) и все красные строки сделали с помощью пробелов, но вдруг неожиданно вам по каким-либо причинам нужно увеличить/уменьшить все отступы красной строки… Первый вариант, это сидеть и руками добавлять или удалять в каждой красной строке нужное количество пробелов. Второй вариант более продвинут, но все равно «не здравый» – использовать поиск и замену по всему документу, «сказав» программе «замени все подряд идущие 4 пробела на 8 подряд идущих пробелов» (можно еще усугубить условие авто-замены, чтобы не заменилось что-то лишнее), но это именно тот случай, когда изобретается «неудобный велосипед».

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

Грамотность набора (знаки препинания + пробелы)

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

Целостность абзацев

Вообще нужно как-то наказать того человека, который придумал объяснять назначение кнопки Enter как: «Это кнопка для того, чтобы текст перенести на следующую строку» 🙂

На самом же деле кнопка Enter нужна только для того, чтобы сделать новый абзац, и никак иначе. Еще с помощью нее можно делать «пустые абзацы» для увеличения расстояния между абзацами.

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

На самом же деле любой редактор переносит текст автоматически, и об этом пользователю не нужно беспокоиться. Когда вы нажимаете клавишу Enter, редактор понимает, что весь написанный блок является самостоятельными абзацем. Такой подход приносит массу удобств для последующего оформления/форматирования текста. Нажатие же Enter`а в конце каждой строки приносит лишь массу «головной боли» и ни грамма плюсов.

К примеру, попробуйте изменить формат листа для документа, у которого каждая строка перенесена с помощью Enter`а на новую строку, и вы увидите, как текст документа «скукожится» (если уменьшить размер листа) или же не будет заполнять лист во всю ширину (если увеличить лист). Правильно же набранный текст (в смысле абзацев) в какой формат листа не помести — он везде будет хорошо выглядеть, так как он будет постоянно заполнять лист во всю ширину (как вода в сосуде 🙂 ).

Пример плохого и хорошего абзаца

Для наглядности приведу пример. Синими точками обозначены пробелы, символ обозначает нажатие кнопки Enter (символ конца абзаца).

Неправильный «абзац»

Пример неправильного "абзаца"
Пробелами сделана красная строка, нажатие Enter`а в конце каждой строки, да еще и искусственное создание выравнивания текста по ширине с помощью пробелов 😥

Правильный абзац

Пример правильного абзаца
Чистота и порядок, прямо идиллия 🙂

Текст с «новой страницы»

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

Часто в программах есть возможность вставить «Разрыв страницы». В MS Word для этого нужно нажать комбинацию клавиш Ctrl+Enter, курсор перескочит на новую страницу, и если на месте курсора расположить нужные текст, он всегда будет начинаться с начала новой страницы, какие бы не происходили сдвиги текста вверху. Разрыв страницы является неким «скачком», к примеру, из середины листа в начало следующего листа.

Заголовки и логическая структура документа

Очень часто, когда хотят сделать заголовок (всего документа и подзаголовки), просто пишут нужные текст, изменяют его размер на больший по сравнению с остальным текстом, добавляют ему жирности и т.п. И это не правильно…

Во всех программах, про которые эта статья, есть понятие заголовков, т.е. подразумевается, что вы можете выделить нужный абзац и указать, что этот абзац является заголовком, и больше ничего делать не нужно. Причем, указывать заголовки нужно с учетом их иерархии, поэтому вы можете указать не только факт заголовка как такового, но и еще какого именно он уровня: «Заголовок 1 уровня», «Заголовок 2 уровня», «Заголовок 3 уровня» и т.д.

Выбор уровня заголовка в MS Word 2007 Выбор уровня заголовка в MS Word 2003 Выбор уровня заголовка в OpenOffice.org Writer Выбор уровня заголовка в Google Docs

Пока не обращайте внимания на то, что такие заголовки могут выглядеть не так, как бы вам хотелось. Главная идея в том, чтобы программа могла «опознавать» логическую структуру документа, где располагается обычный текст, а где заголовки, и кто чей «ребенок».

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

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

Так же немаловажна возможность изменять в дальнейшем внешний вид этих заголовков в несколько кликов и лишиться «удовольствия» делать это вручную для каждого из них.

«Скелет» готов

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


Copyright © 2008 Заметки разработчика
Эта rss лента только для персонального некоммерческого использования.


Отсылка e-mail через C#

Отсылка e-mail через C#Этот кусок кода показывает, как можно программно отослать электронное письмо средствами C#. Письмо отсылается через указанный SMTP-сервер, который требует авторизацию. Так же к письму можно прикрепить одно или несколько вложений.

//Адрес SMTP-сервера
String smtpHost = "SMTP.SERVER.RU";
//Порт SMTP-сервера
int smtpPort = 25;
//Логин
String smtpUserName = "LOGIN";
//Пароль
String smtpUserPass = "PASSWORD";

//Создание подключения
SmtpClient client = new SmtpClient(smtpHost, smtpPort);
client.Credentials = new NetworkCredential(smtpUserName, smtpUserPass);

//Адрес для поля "От"
String msgFrom = "LOGIN@SERVER.RU";
//Адрес для поля "Кому" (адрес получателя)
String msgTo = "KUDA@TO.RU";
//Тема письма
String msgSubject = "Письмо от C#";
//Текст письма
String msgBody = "Привет!\r\n\r\nЭто тестовое письмо\r\n\r\n--\r\nС уважением, C# :-)";
//Вложение для письма
//Если нужно больше вложений, для каждого вложения создаем свой объект Attachment с нужным путем к файлу
Attachment attachData = new Attachment("D:\Тестовое вложение.zip");

//Создание сообщения
MailMessage message = new MailMessage(msgFrom, msgTo, msgSubject, msgBody);
//Крепим к сообщению подготовленное заранее вложение
message.Attachments.Add(attachData);

try
{
    //Отсылаем сообщение
    client.Send(message);
}
catch (SmtpException ex)
{
    //В случае ошибки при отсылке сообщения можем увидеть, в чем проблема
    Console.WriteLine(ex.InnerException.Message.ToString());
}

Тело письма и его заголовок будут созданы и отосланы в кодировке — UTF-8. Если же захочется отослать письмо в кодировке windows-1251, то начинаются проблемы. Мне удалось найти только одно достаточно подробное описание этой проблемы. И в более свежих версиях фреймворка (помимо .Net Framework 2.0) точно такая же проблема.

Да, отчасти помогает прописывание вручную заголовка, говорящего о кодировке всего письма, но с другой стороны, не так уж все радужно. Итак, перед кодом отсылки сообщения (после 29-ой строки) добавляем следующий код:

message.SubjectEncoding = Encoding.Default;
message.BodyEncoding = Encoding.Default;
message.Headers["Content-type"] = "text/plain; charset=windows-1251";

В итоге мы имеем письмо, у которого два раза (второй раз вставляется автоматом) повторяется заголовок Content-type, в первом указана кодировка windows-1251, а во втором настырный .Net вставляет UTF-8. Не думаю, что такое дублирование заголовков можно назвать корректным. Но это, похоже, единственный способ добиться какой-то адекватности отображения тела письма в почтовой программе, которая получит его.

Для просмотра писем я использую Mozilla Thunderbird. В нем тело письма отображается нормально, но при этом он не понимает кодировки заголовка письма и отображает его некорректно. Если оставить заголовок в кодировке UTF-8, а тело письма создавать в windows-1251:

message.BodyEncoding = Encoding.Default;
message.Headers["Content-type"] = "text/plain; charset=windows-1251";

Тогда Thunderbird правильно отображает письмо. Но все эти ухищрения достаточно сомнительны из-за того, что каждый почтовый клиент может по-своему трактовать двойной и противоречивый заголовок Content-type. Так, к примеру, если посмотреть на такое письмо через вэбовский клиент mail.ru, то при любых раскладах тело письма отображается коряво. Тема же отображается правильно, только если отсылать ее в UTF-8.

Глядя на эту печальную картину, в голову приходит только два варианта решения проблемы. Плюнуть и отсылать письма в UTF-8 или же самостоятельно подключаться к SMTP-серверу и «вручную общаться» с ним по протоколу SMTP, а не использовать готовую реализацию в виде класса SmtpClient.


Copyright © 2008 Заметки разработчика
Эта rss лента только для персонального некоммерческого использования.


Правильный редактор для PHP

Иногда очень сильно не хватает какого-то хорошего редактора для PHP именно с точки зрения комфортной работы с кодом, что-то посерьезней, чем простая подсветка синтаксиса. При этом обычных редакторов пруд пруди, в которых, к сожалению, та же подсветка синтаксиса далеко не всегда корректно работает.

Хочется иметь нормальную реализацию IntelliSense, а не «деревянную» пародию на него в виде заранее определенного списка методов и констант языка, «вываливающегося» во время работы по поводу и без повода в виде полного списка. IntelliSense обязательно должен «знать» о всех используемыми вами классах, о их методах и переменных, то есть подключил через #include файл с определением своего класса, и редактор сразу же его подхватывает, подсказывая информацию о всех «внутренностях» объектов этого класса.

Не помешали бы так же подсказки во время набора названия функции в виде краткого описания функции (принимаемые параметры, есть ли перегруженные функции и т.п.). Особенно этого не хватает для самописных функций, в некоторых типичных редакторах я видел такие подсказки, но только для родных функций PHP. Ах да, еще очень удобно быстро переходить к определению функции из места ее вызова. Вообще, много чего еще хочется, причем все эти возможности считаю лишь толикой самых необходимых вещей в процессе кодинга и никак не излишеством…

Пример работы Intellisense в Visual Assist

Можно сказать, что в этом смысле моим идеалом является связка MS Visual Studio + Visual Assist, которую я использую при работе с C# и C++ (Visual Assist в этой связке просто как спасательный круг). Когда лишний раз не лезешь в другие файлы, чтобы посмотреть принимаемые параметры функции или названия тех или иных членов класса, это в любом случае способствует производительности и «приятности» процесса. Отсутствие среди своего инструментария такого редактора очень удручает, учитывая все большую (от версии к версии) объектно-ориентированность PHP.

И вот оно!

Логотип KomodoВсе же нашел для себя достаточно неплохой редактор — Komodo Edit. Если вы, как я, пользовались обычными редакторами, заменяющими стандартный «блокнот» и тоже жаждали человеческого IntelliSense, советую обязательно попробовать его. Он ко всему еще и бесплатный (о платной версии ниже) и работает на базе мозиловского фреймворка (XPFE), что делает его так же мультиплатформенным.

Komodo Edit

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

Стоит так же отметить поддержку и других языков (Perl, Python, Ruby, Tcl), а так же JavaScript, CSS, HTML, XML и много другого (судя по списку файлов, которые он может открыть, он знает еще много языков и технологий, но не уверен насчет работы IntelliSense для них всех). Приятно удивила поддержка многих популярных фрейворков для JavaScript (для моего знакомства с jQuery это было кстати).

Я наверняка еще не успел изучить весь функционал Komodo Edit, но некоторые моменты хотел бы описать.

Первым делом я настроил под себя цветовую схему подсветки кода для PHP (Edit -> Preferences… -> Fonts and Colors), так как привык уже к цветам из Notepad++.

Настройка цветовой схемы для подсветки PHP кода

Так же полезным дополнением оказался плагин, который находит все TODO в открытом проекте или файле и выводит их в один список (на подобие того, как это реализовано в VS). И плагин, позволяющий видеть в виде одного списка все классы и методы, определенные в открытом файле (Source Tree) для быстрой навигации по ним.

Вообще перед использованием Komodo имеет смысл изучить его настройки, изменив те или иные параметры под себя. Я, к примеру, еще переопределил горячую клавишу для перехода к определению функций (сделал F12, как в Visual Studio 🙂 ).

В целом все работает достаточно хорошо, «земля и небо» по сравнению с кодингом в обычном редакторе.

Немного неудобно, что для полноценной поддержки IntelliSense обязательно нужно создавать файл проекта (его нужно просто сохранить в корневой каталог сайта). То есть если открыть один файл вне рамок проекта Komodo, все инклуды, прописанные в нем, не будут обрабатываться как-либо, и, соответственно, Komodo не будет ничего знать о функциях и классах, определенных в подключаемых файлах. Но, в целом, это маленькое неудобство пережить можно 🙂

С другой стороны, создание файла проекта дает возможность выполнить более тонкие настройки проекта, которые сохраняются и при каждом открытии проекта, Komodo будет помнить о них. Через него, к примеру, можно указать дополнительные директории для того, чтобы Komodo при работе с вашим проектом все время имел ввиду структуру классов и методов (для IntelliSense и различных подсказок), реализованных в файлах, которые лежат в подключаемой директории, даже если эти файлы ни как фактически не подключены (через include или require) к редактируемому файлу. Еще можно производить поиск или замену текста во всех файлах проекта. Так же, Komodo запоминает сделанные вами закладки внутри кода (Ctrl+F2) для каждого файла, это очень удобно.

Немного неприятно удивило, что Komodo Edit ничего не знает о встроенных в PHP классах (может, я делаю что-то не так?). К примеру, если нужно использовать класс mysqli:

$mysqli = new mysqli(HOST, USER, PASS, MBASE);
if (mysqli_connect_errno()) {
	print "Connect failed: ".mysqli_connect_error();
	exit();
}
$mysqli->query('INSERT.......');
$mysqli->close();

Когда после написания слова «$mysqli» я начинаю обращаться к методам этого объекта (пишу знак «->»), Komodo Edit не хочет подсказывать ничего о методах query, close и т.д., а в строке состояния ругается, что, мол, в глаза не видел определения этого класса… При этом со встроенными в PHP функциями проблем нет, к примеру, о семействе функций mysqli_* (оберткой над которыми и является класс mysqli) Komodo прекрасно знает. Но, надеюсь, эту недоработку когда-нибудь поправят. Если же вы, к примеру, работаете с базой через свой класс — обертку (или через что-то вроде PEAR), то проблем с IntelliSense не должно возникать.

Один раз у меня случилось так, что при редактировании js файла Komodo не понял, какой Java Script фреймворк я использую. Но это, к счастью, всегда можно поправить в его настройках (Edit -> Preferences… -> Code Intelligence).

Окно настройки, позволяющее указать используемые Java Script фреймворки

Существует платная версия Komodo, называемая Komodo IDE. Как я понял, основное отличие от Komodo Edit в функциях, свойственных многим IDE. Комодо IDE имеет встроенные инструменты для работы с системой управления версиями (SVN) и отладчик кода.

Кстати, в Komodo Edit все же есть примитивный отладчик, который на ходу уведомляет о таких мелких ошибках, как забытая точка с запятой в конце строки, незакрытая скобка и т.п. Такие ошибки он подчеркивает красной волнистой линией. Для того, чтобы такая отладка работала, нужно в настройках программы указать путь к исполняемому файлу PHP и php.ini (Edit -> Preferences… -> Languages -> PHP).

Указание пути к исполняемому файлу PHP и php.ini

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

Послесловие

Komodo Edit теперь мой повседневный инструмент 🙂 Плюс, для коротких правок каких-то мелочей в эпизодических случаях я продолжаю использовать аналог продвинутого блокнота — Notepad++, то есть использую его по своему настоящему назначению.

До Komodo Edit я еще пробовал интересный плагин к Visual Studio, который называется VS.Php. Он встраивается в Visual Studio и позволяет работать с PHP так же, как, к примеру, с C# (можно отлаживать код, работает IntelliSense и т.п.). Но как-то он не особо впечатлил, особенно на фоне своей платности. К тому же, как я понял, работая в нем можно полностью забыть про поддержку Java Script и т.п. Интересно еще то, что в нем точно так же, как в Komodo, не работает IntelliSense для классов, встроенных в PHP. Так же этот VS.Php конфликтует с Visual Assist.

Есть еще два подобных редактора, о которых я слышал, но как-то не случилось их попробовать (дальше лишь ИМХО и догадки на основе «слухов»):

***

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

В общем, долой примитивную подсветку кода с вагоном ненужных функций! Это «наболевший» камень в огород постоянно появляющихся простых редакторов кода, выставляющих на передний план среди своих «достоинств» встроенный проводник по файловой системе или что-то вроде мини редактора/вьювера базы данных (ну зачем это нужно, если нет самых важных вещей именно для того, для чего изначально предполагается использовать редактор кода) и т.п. и т.д.. Почему-то почти каждый начинающий (хотя, может, не всегда начинающий) программист хочет «быстренько» сделать свой «мега» редактор, который часто вырождается в «опять что-то до боли знакомое»… очевидно, это традиция из серии «Hellow World!» 😉


Copyright © 2008 Заметки разработчика
Эта rss лента только для персонального некоммерческого использования.


Борьба со спамом в форумах phpBB2

Борьба со спамом (c) :-)Недавно на своем форуме изменил тактику борьбы со спамом (по сути, просто поставил другой мод 🙂 ), что принесло свои плоды.

Раньше для борьбы со спамерскими роботами был установлен мод расширенной графической капчиAdvanced Visual Confirmation и одна из первых версия мода Stop Advertisement Bots (уже есть более свежая версия).

Stop Advertisement Bots скрывает от глаз посетителей поле для ввода сайта и при этом определяет, что регистрационную форму заполнил робот, если заполнено это скрытое поле.

Еще установлен прекрасный мод, который автоматически удаляет пользователей (и их сообщения), которые использовали более чем 1 ссылку в тексте своего поста (Detector Bots) (макс. допустимое количество ссылок в одном сообщении можно настраивать).

И еще один небольшой мод (в некоторых ситуациях просто незаменим…) — URL Censor Hack. Он заставляет работать более корректно встроенный в phpBB2 автоцензор. Без него автоцензор не хочет заменять указанные фразы (например, вы хотите заменить vasa.ru на слово «цензура»), которые находятся непосредственно в адресе ссылок (при этом в области обычного текста стандартный автоцензор работает нормально).
С этим же модом все прекрасно работает. Он помогает бороться с редкими случаями навязчивых спамеров, рекламирующих один и тот же сайт (в моем случае в сообщение вставляли постоянно одну и ту же порно картинку…), которые при этом регистрируются вручную, используя разные e-mail`ы и ip адреса (т.е. нельзя предотвратить их повторную регистрацию). Потом такие сообщения все равно нужно удалять вручную, но, по крайней мере, таким образом можно сделать, чтобы пользователи не имели «удовольствия» лицезреть всякие пакости в виде картинки или ссылки (которые могут вести на вредоносные сайты с левыми скриптами или же с каким-нибудь «разводом»).

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

Это решение, в общем-то, помогало, но со временем все возвращалось на круги своя…

Как было…

У меня получалась следующая картина (каждые сутки примерно одно и то же).

Detector Bots
Обрезал около 40 спамерских сообщений, содержащих в себе много ссылок, то есть каким-то образом боты все же обходили изощренную капчу. Сложно сказать, обходили ли ее боты или же ее распознавали люди.

Stop Advertisement Bots
Отсекал около 10 спамеров, так как уже далеко не все боты при регистрации указывают адрес сайта в соответствующем скрытом поле (зато часто лепят свой сайт во все остальные поля…).

Advanced Visual Confirmation
Трудно сказать, скольких именно спамеров в сутки этот мод отсекал, так как никакой статистики он не ведет, но то, что его обходили многие боты, это точно. Варианты искажений символов тоже менял – ничего не изменилось.

Также регулярно накапливались не активированные пользователи/боты, которые, очевидно, указывали «левые» e-mail`ы при регистрации (примерно 10 пользователей в сутки, то есть они проходили капчу и скрытое поле для сайта).

Для постоянных зачисток таких «призрачных» пользователей очень хорошо помогает мод Prune Users (с помощью него удобно также удалять пользователей, которые, к примеру, за пол года не написали ни одного сообщения).

В итоге, около 5 сообщений в сутки проходили все барьеры, и их приходилось убивать вручную.

Как стало…

Убрал из прежнего «арсенала» моды Advanced Visual Confirmation и Stop Advertisement Bots. Вместо них поставил Anti Bot Question Hack (ABQ). Его суть в том, что он задает регистрирующемуся посетителю вопрос, на который нужно правильно ответить (на манер «отгадаешь три загадки — пропущу» 🙂 ). Вопрос может быть как в текстовом виде, так и в графическом (к примеру, «что за предмет изображен на рисунке?»). Я пока ограничился лишь текстовыми вопросами.

Пример использования мода ABQ

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

В данный момент у меня за неделю зарегистрировалось только 4 пользователя (настоящих!). И в некоторые дни было не более двух зарегистрировавшихся спамеров (очевидно, ручками 🙂 на вопросы отвечали), которые сразу же автоматически обрезались с помощью Detector Bots, так как после регистрации они создавали темы с кучей рекламных ссылок. В общем, прогресс, мягко говоря, очень ощутим. Конечно, что-то будет проскакивать, но все легче, чем было…

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

Но если и эта защита будет легко обходиться ботами, найдутся новые/другие способы борьбы 😉

Я вот думаю об варианте ужесточения защиты, запретив размещать новичкам даже 1 ссылку (изменив настройки мода Detector Bots)… 😈 Но не на всяком форуме это уместно.

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

Технический нюанс

Автор топика, посвященного моду ABQ, советует ставить версию 1.0.3, как я понял, из-за того, что она не нагружена лишними функциями и при этом хорошо справляется со своей задачей. Я поставил именно ее, но теперь сомневаюсь в правильности выбора 🙂 Меня жутко напрягает то, что в этой версии нет блокировки пользователя после трех неверных ответов (как это происходит при использовании графической капчи). В третьей же версии этого мода, судя по исходникам, есть такая блокировка… В общем, буду пытаться прикрутить эту функцию к версии 1.0.3. В случае неудачи придется ставить третью версию 🙂

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

PS. Так же пользуясь случаем хочу поздравить всех с Днем Победы в Великой Отечественной Войне!


Copyright © 2008 Заметки разработчика
Эта rss лента только для персонального некоммерческого использования.