вторник, 16 ноября 2010 г.

Сефирот

В каждом из нас живет свой Сефирот, свои птеродактили, темная сторона, обратное альтер-эго, называйте, как хотите. Как сказал Винсент - в теле существует течение подобно потоку жизни, и оно сопротивляется против вредных веществ и субстанций. Одни принимают свою темную сторону, другие борятся с ней, а третьи ей потокают. Многие ее боятся...Я боюсь признать тот факт, что не идеален, потому что думаю, что если я не идеален, если у меня есть свои недостатки, то я не достоин счастья, не достоин любви или дружбы. Можно ли простить себе такие недостатки, какие есть у меня? Не знаю, не пробовал... Не пробовал... Что ж, я попробую. Потом расскажу, что из этого получилось).

четверг, 4 ноября 2010 г.

Новое увлечение

На полевых стрельбах
Ну вот и снова я. Появилось новое увлечение - стрельба из лука. Потрясающе интересное занятие, доложу я вам - задействованы все системы организма - физо, внимание, глазомер... Занимаюсь сравнительно недавно - скоро будет месяц. Изначально тяжело было с натягиванием. Мало того, что нужно натянуть тетиву, ее нужно еще и удержать N-ное время, при этом прицелится (то есть не отвлекать внимание на физическое напряжение). Попутно нужно еще контролировать стойку, положение рук... Сразу скажу - пока получается так себе, но есть желание, есть возможность, стало быть буду тренироваться. А терпение и труд как известно - все перетрут. Если сравнивать с первыми стрельбами - прогресс налицо, однако до идеала еще ОЧЕНЬ далеко. Есть идеалы - стало быть нужно к этому стремиться. Однако есть и кое-какие результаты :-[:
Случайная, но моя. Расстояние до цели - 12 метров

пятница, 29 октября 2010 г.

Наваял...

Привет всем, а вот и я!  Погода выдалась на редкость паршивая, настроение - соответствующее. Вот сел за фрутик, решил поваять. Получилось примерно следующее:



Назвать решил "Space ocean". Почитай первая моя серьезная "отсебятина". Собственно, так я свои треки и называю... Надеюсь, тому кто зайдет, и послушает - понравится.)).

суббота, 16 октября 2010 г.

Фигня

Ну вот, снова выдалась свободная минутка, и абсолютно хреновое настроение, так что сел писать новую запись. Так получается, что писать тянет только тогда, когда на душе кошки скребут от тоски, и маешься, не найдя покоя. Слова сами собой лезут на экран, я же получается только потакаю им в этом. Что сказать, снова то же самое - жизнь проходит мимо, все так же, как и всегда. Это сводит с ума, сидит занозой, которую не вытащишь. Чаще начинаю думать об уходе. Интересно каково там, за гранью? Когда-нибудь уж конечно узнаю, но наверняка лучше. Сегодня показывали телепид..., пардон, телепередачу о том, как врачи убивают детей, делая на этом бабки. То, что жизнь взрослого человека в этом мире не стоит и гроша - я знал, но чтобы детская... Странно все это... Опускаются руки, приходит абсолютная апатия. Ничего не хочу. Абсолютно. Даже комп уже не греет. Разве что общение с родными, фильмы да фрутик. Что происходит? Наверное просто надоело. Надоело надеяться, надоело ждать, надоело верить. А может... Не будем о грустном. Может... Да ни хрена не может, за 30 лет не смогло. Ладно, харе об этом. Точка. Греет то, что завтра воскресенье, никуда не надо идти. Пошел пить чай.


А это так, к слову... Хотел бы когда-нибудь увидеть такой рассвет). В шопе за пару минут сделал

суббота, 11 сентября 2010 г.

Настроение

Блуждая по бескрайней паутине Интернета наткнулся на "кое-что особенное" - Оранжерею. Оранжерея представляет собой цикл интернет-радиопередач от Василия Дворцова. Музыка очень интересная. Даже я, не будучи изначально поклонником стиля ambient, стал внимательно следить за новыми выпусками. Сейчас у меня уже 5 сезонов. Самое интересное - это удивительная атмосфера релакса, покоя, душевного равновесия - называйте, как хотите. Но мне понравилось это ощущение. Действительно за своими заботами и повседневными делами практически полностью отрываешься от мира, в котором живешь, и уходишь от него куда-то... Куда-то не туда. Ночь, луна, плеск моря, шум ветра, ласкающий траву, деревья, и тех, кто вышел полюбоваться ее прекрасием.) это действительно здорово! Спасибо, Василий!

вторник, 17 августа 2010 г.

Flash-сайт на MODx -проблемка

В предвкушении победы особенно обидно было увидеть сообщение
Error opening URL 'http://test_adamant.ru/main.xml' в Debug-консоли Flash. Видимо дело в том, что Flash не умеет работать с URL-ами, он умеет загружать XML-файлы... Как следствие придется написать модуль, который будет преобразовывать документы MODx (уже готовый XML - ах, как обидно) в файл XML...

Flash-сайт на MODx

Выдалась свободная минутка, и я пишу, дабы в будущем не забыть. У меня получилось)). Я знаю (пока теоретически) как использовать MODx, как Flash CMS. Фишка вот в чем. Флэш не умеет общаться с БД (MySQL в частности) напрямую. Нужен посредник. Обычно в качестве оного выступает скрипт PHP, который выполняет запрос к БД, результат его получает в виде XML (точнее генерирует XML на основе полученного результата). Но. В моем случае эту функцию, как и функцию редактора и контрольной панели выполняет система MODx.

Итак, как это сделать:
1. Чтобы HTML-тэги не интерпретировались, как XML-тэги, создадим сниппет, который соберет содержимое документа "до кучи")), назовем его HTML2XML_Converter:


<?php
include_once('manager/includes/config.inc.php');
include_once(MODX_MANAGER_PATH.'/includes/document.parser.class.inc.php');
include_once('classes/docAPI.php');
$modx = new DocumentParser;

$doc=new Document($docId);
$content=htmlentities($doc->get('content'));
//Если содержимое документа является сниппетом

echo $content;
?>



2. Создаем шаблон, назовем его XML_Template

<?xml version="1.0" encoding="UTF-8" ?>
<root>
<password>[*password*]</password>
<pagetitle>[*pagetitle*]</pagetitle>
<content>[!HTML2XML_Converter? &docId=`[*id*]`!]</content>
</root>


3. Заходим в настройки страницы, и меняем тип содержимого на text/xml

Отдельный момент. Если в содержимом документа есть вызовы сниппета, их необходимо вывести в шаблон. Простой пример - галерея. Вызов: [[Ditto? &tpl=`ditto_xml`]]. Но при выборке его из [*content*] будет возвращен вызов сниппета, а не результат его работы. Чтобы этого не случилось, необходимо перенести его вызов в шаблон:


<?xml version="1.0" encoding="UTF-8" ?>
<root>
<password>[*password*]</password>
<pagetitle>[*pagetitle*]</pagetitle>
<content>[[Ditto? &tpl=`ditto_xml`]]</content>
</root>


P.S.: Содержимое файла docApi:


<?
/***************************************************************
Класс для Создания/Редактирования/Удаления документов MODx
Версия 0.5.1a
Автор: ur001
Контакты: ur001@mail.ru
Использование:
Пример 1 (создание):
require_once('assets/libs/docapi/document.class.inc.php');
$doc = new Document();
$doc->Set('parent',$folder);
$doc->Set('alias','post'.time());
$doc->Set('content','Текст документа');
$doc->Set('template','GuestBookComments');
$doc->Set('tvComment','Комментарий к посту');
$doc->Save();

Пример 2 (редактирование):
require_once('assets/libs/docapi/document.class.inc.php');
$doc = new Document($id,'content');
$content=$doc->Get('content');
$doc->Set('content', '

'.$content.'

');
$doc->Save();

Область применения:
Написание гостевых книг, блогов, форумов, модулей для
администрирования из frontedn-а (новоси, галлереи)

TODO:
* Необходимо тестирование
* document_groups

Важно:
1) Это не врапер для MODx API. Это дополнение функционала
для создания и редактирования документов
2) Не следует создавать этот класс только для получения
значений TV или удаления документов в цикле. Для этого
есть соответствующие функции, такие как
$modx->getTemplateVars(); и $modx->db->delete();

***************************************************************/
class Document{
var $fields; // Массив полей документа
var $tvs; // Массив TV

var $tvNames; // Массив возможных имен TV
var $oldTVs; // Массив уже определенных в документе значений TV
var $isNew; // true - новый документ, false - существующий

/***********************************************
Инициализация класса
$id - идентификатор существующего документа
или 0 для создание нового
$fields - список полей разделенных запятой
************************************************/
function Document($id=0,$fields="*"){
global $modx;
$this->isNew = $id==0;
if(!$this->isNew){
$this->fields = $modx->getPageInfo($id,0,$fields);
$this->fields['id']=$id;
}
else
$this->fields = array(
'pagetitle' => 'Новый документ',
'alias' => '',
'parent' => 0,
'createdon' => time(),
'createdby' => '0',
'editedon' => '0',
'editedby' => '0',
'published' => '1',
'deleted' => '0',
'hidemenu' => '0',
'template' => '0',
'content' => ''
);
}

/***********************************************
Сохранение/Обновление документа
************************************************/
function Save(){
global $modx;
$tablename=$modx->getFullTableName('site_content');
if($this->isNew){
$this->fields['id']=$modx->db->insert(&$this->fields, $tablename);
$this->isNew = false;
} else {
$id=$this->fields['id'];
$modx->db->update(&$this->fields, $tablename, "id=$id");
}
if(is_array($this->tvs)) $this->saveTVs();
}


/***********************************************
Получение значения поля документа или TV
$field - Имя поля документа или имя TV
с префиксом 'tv'
Результат: значение поля, TV или null
************************************************/
function Get($field){
switch(1){
case substr($field,0,2)=='tv': return $this->GetTV(substr($field,2));
default: return isset($this->fields[$field]) ? $this->fields[$field] : null;
}
}

/***********************************************
Установка значения поля документа (включая TV)
$field - Имя поля документа. Для установки TV
следует добавить префикс 'tv'
$value - Значение
Результат: true, или false при неудаче
************************************************/
function Set($field, $value){
switch(1){
case substr($field,0,2)=='tv': return $this->SetTV(substr($field,2), $value);
case $field=='template': return $this->SetTemplate($value);
default: $this->fields[$field]=$value; return true;
}
}


/***********************************************
Получение значения TV.
$name - имя TV
************************************************/
function GetTV($tv){
if(!is_array($this->tvs)){
if($this->isNew) return null;
$this->tvs=array();
}
// Поиск в значениях установленных функцией Set()
if(isset($this->tvs[$tv])) return $this->tvs[$tv];
// Поиск в TV уже определенных для документа
// Если они еще не получены вызываем fillOldTVValues()
if(!is_array($this->oldTVs)){
if($this->isNew) return null;
$this->fillOldTVValues();
}
if(isset($this->oldTVs[$tv])) return $this->oldTVs[$tv];
return null;
}

/***********************************************
Установка TV
************************************************/
function SetTV($tv,$value){
if(!is_array($this->tvs)) $this->tvs=array();
$this->tvs[$tv]=$value;
}

/***********************************************
Установка шаблона документа
$tpl - Имя или идентификатор шаблона
************************************************/
function SetTemplate($tpl){
global $modx;
// Если указано имч шаблона, получаем id
if(!is_numeric($tpl)) {
$tablename=$modx->getFullTableName('site_templates');
$tpl = $modx->db->getValue("SELECT id FROM $tablename WHERE templatename='$tpl' LIMIT 1");
if(empty($tpl)) return false;
}

$this->fields['template']=$tpl;
return true;
}

/************************************************************
Удаление доккумента и связанных с ним TV
*************************************************************/
function Delete(){
if($this->isNew) return;
global $modx;
$id=$this->fields['id'];
$modx->db->delete($modx->getFullTableName('site_content'),"id=$id");
$modx->db->delete($modx->getFullTableName('site_tmplvar_contentvalues'),"contentid=$id");
$this->isNew=true;
}

/************************************************************
Сохранение значений TV, служебная функция. Сохраняются
тлько значения поределенные в $tvNames, если Такое имя TV
уже есть в oldTVs, происходит update, иначе insert
*************************************************************/
function saveTVs(){
global $modx;
if(!is_array($this->tvNames))$this->fillTVNames();
if(!is_array($this->oldTVs) && !$this->isNew)
$this->fillOldTVValues();
else
$this->oldTVs = array();

if(!is_array($this->tvNames))$this->fillTVNames();
$tvc = $modx->getFullTableName('site_tmplvar_contentvalues');
$id=$this->fields['id'];
foreach($this->tvs as $tv=>$value)
if(isset($this->tvNames[$tv])){
$tmplvarid=$this->tvNames[$tv];
if(isset($this->oldTVs[$tv])){
if($this->oldTVs[$tv]==$this->tvNames[$tv]) continue;
$sql="UPDATE $tvc SET value='$value' WHERE tmplvarid=$tmplvarid AND contentid=$id";
}
else
$sql="INSERT INTO $tvc (tmplvarid,value,contentid) VALUES ($tmplvarid,'$value',$id)";
$modx->db->query($sql);
}
}

/************************************************************
Заполнение массива значений TV ($oldTVs), служебная функция.
В отличие от $modx->getTemplateVars, берет только
фактические значения игнорируя значения "по-умолчанию"
*************************************************************/
function fillOldTVValues(){
global $modx;
$tvc = $modx->getFullTableName('site_tmplvar_contentvalues');
$tvs = $modx->getFullTableName('site_tmplvars');
$sql = 'SELECT tvs.name as name, tvc.value as value '.
"FROM $tvc tvc INNER JOIN $tvs tvs ".
'ON tvs.id=tvc.tmplvarid WHERE tvc.contentid ='.$this->fields['id'];
$result = $modx->db->query($sql);
$this->oldTVs = array();
while ($row = mysql_fetch_assoc($result)) $this->oldTVs[$row['name']] = $row['value'];
}

/************************************************************
Заполнение массива имен TV ($tvNames)), служебная функция.
*************************************************************/
function fillTVNames(){
global $modx;
$this->tvNames = array();
$tvs = $modx->getFullTableName('site_tmplvars');
$result = $modx->db->select('id, name', $modx->getFullTableName('site_tmplvars'));
while ($row = mysql_fetch_assoc($result)) $this->tvNames[$row['name']] = $row['id'];
}
}
?>

воскресенье, 25 июля 2010 г.

Интерресный заказик (3)

На оф. сайте сообщества modx (http://modxcms.com/forums) задал вопрос по поводу использования modx api во внешнем php-файле. Оказалось, что имеются кардинальные различия в вызове api в EVO и REVO. В MODx Revolution подключение API осуществляется так:


define('MODX_CORE_PATH', 'full/path/to/your/modx/core/');
define('MODX_CONFIG_KEY', 'config');
require_once MODX_CORE_PATH . 'model/modx/modx.class.php';
$modx= new modX();
$modx->initialize('mgr');

пятница, 23 июля 2010 г.

Интерресный заказик (2)

Итак, касательно парсера: все оказалось достаточно просто. В качестве инструмента решил использовать SimpleXML. Учитывая то, что не будучи с ним знаком вообще, разобрался с его использованием за пол-дня - он полностью оправдывает свое название:

<?
$doc="http://example.com/catalog.xml";
$res=simplexml_load_file($doc);
?>


Таким образом получаем массив $nodes, содержащий все корневые элементы каталога. Последующий доступ к ним до неприличия прост:


//доступ к 1-му элементу каталога (тэг class), и получение значения аттрибута 'name' его первого дочернего элемента (тэг art):
echo $res->class[0]->art[0]->attributes()->name;


То есть можно получить доступ к элементу любого уровня или его аттрибуту. Вывод осуществляется в формате SimpleXML, в конечном итоге представляющем формат String. Для указания надценки придется преобразовывать String в Double, а затем обратно в String для сохранения значения в TV MODx на конечной стадии работы парсера. Но - глаза боятся, руки делают!)) Итак - осталось сформировать цикл для прохода по всем позициям каталога. Единственный момент... Придется учесть такой момент, что практически невозможно отследить удаленные позиции каталога. Так что придется придерживаться следующего алгоритма:

  1. Полное удаление каталога (скрипт)
  2. Сброс счетчика (скрипт)
  3. Обработка каталога (скрипт)
  4. Сортировка пунктов (вручную? - пока да...)

четверг, 22 июля 2010 г.

Различия в синтаксисе внутренних тэгов EVO и REVO

Сегодня попробовал использовать новую версию MODx - Revolution. Устанавливаю на DENWER. Все идет как по маслу - без сучка и задоринки. Верстаю шаблон. Вставляю привычные для себя тэги [*pagetitle*], [(site_url)]... И вот тут-то и попался! Не работают. Давай проверять, - не работают, и все тут. Начинаю искать информацию на оф. сайте. И вот тут-то и выплывают "расписные":


Content Elements Evolution (Old) Revolution (New)
Templates no tag representation no tag representation
Template Variables [*templatevar*] [[*templatevar]]
Chunks {{chunk }} [[$chunk]]
Snippets [[snippet]] [[snippet]]
Plugins no tag representation no tag representation
Modules no tag representation does not exist in Revolution
Content Tags
Placeholders [+placeholder+] [[+placeholder]]
Links [~link~] [[~link]]
System Settings [(system_setting)] [[++system_setting]]
Language no tag representation [[%language_string_key]] 



Оригинал - здесь.

Так что подстроился, и все заработало. Теперь вопрос в том, что нужно найти Shopkeeper для REVO... Ушел искать))

Интерресный заказик

Поступил заказ на создание сайта на основе каталога поставщиков, предоставленного  в формате XML, на платформе MODx. Очень интересная тема. Хочу задействовать движок ShopKeeper. Единственная загвоздка на данный момент - с XML я на "вы". Точнее как - разобрать, что и где лежит я-то смогу, но обработать эти данные программно... Нужен XML-парсер. Пока присматриваюсь к XPath. Чем дальше, тем интереснее - в MODx обнаружил функционал для... FLASH CMS!!! MODx - золотая находка - воистину мощная платформа для сайтов любой сложности... Если так, то может быть станет возможным интернет-магазин, реализованный во Flash ?! Мечты, мечты...))). Структура XML-файла очень грамотная. Теперь осталось отпарсить ее. Если все получится, можно будет поделиться реализацией и платформой с поставщиком)). Принимаюсь за работу.

среда, 21 июля 2010 г.

Валидность и стили в кроссбраузерном коде

Ну вот выдалась свободная минутка, решил сделать про запас несколько заметок по части веб-верстки. На данный момент в Интернете наиболее распространены 4 движка: Gecko (FireFox, SeaMonkey), Internet Explorer (Internet Explorer, Maxthon), WebKit (Google Chrome, Safari) и NetScape (NetScape Navigator, Opera). Все они по разному реагируют на таблицы стилей. Увы, Internet Explorer бьет все рекорды по некорректному отображению страниц, если быть точным, то по отображению не того, что задумывал веб-верстальщик. В связи с этим появились CSS "хаки" - куски кода, которые встраиваются либо в код, либо непосредственно в файл CSS, и все бы хорошо, если бы не... валидность. С одной стороны можно просто наплевать на нее, но, справедливости ради скажу, что валидность кода радует глаз не только заказчику, но и мне, как человеку, сдающему работу, кроме того валидность дает относительные гарантии по поводу отображения кода в разных браузерах. Выход для себя я нашел достаточно простой - php-сниппет, определяющий тип браузера, и подключающий нужный стиль в зависимости от движка:

<?

$browser=$_SERVER['HTTP_USER_AGENT'];
if(ereg('MSIE',$browser)){
    echo "/link href="[(site_url)]styles/styles_ie.css" media="all" rel="stylesheet" type="text/css"/\r\n";
}else{
    echo "/link href="[(site_url)]styles/styles.css" media="all" rel="stylesheet" type="text/css"/\r\n";
}

?>


Сниппет заточен для использования в среде MODx, и является более иллюстрацией, чем материалом для копи-паста. Итак, немного разберемся в коде: сначала получаем значение суперглобального массива $_SERVER, и значение его параметра HTTP_USER_AGENT  в частности, в котором хранится тип браузера. Далее - идет проверка на наличие в этом значении слова MSIE (MicroSoft Internet Explorer). Далее все просто - если есть, - вставляем линк на стиль styles_ie.css, если нет - соответственно. Во внутреннем тэге MODx [(site_url)] хранится корневой URL сайта (к примеру - http://example.com), и к нему приставляется остальная часть пути к CSS-файлу, в итоге получаем строку:

Для IE

<link href="http://example.com/styles/styles_ie.css" media="all" rel="stylesheet" type="text/css" />


Для других браузеров:

<link href="http://example.com/styles/styles.css" media="all" rel="stylesheet" type="text/css" />


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

понедельник, 22 февраля 2010 г.

Связь

Вышел на балкон покурить... Низко стелятся облака, гор уже практически не видно. Дует сильный ветер... Задумался о программировании, и в частности об API. И вдруг все выстроилось в четкую схему, - ВОТ ОНО!!! В голове промелькнули процедуры, прорисовывающие окна, и свойства, и все-все-все, как наглядно все, и как просто, в то же время сколько мелких деталей! Схема, система, построенная для того, чтобы упростить обращение к нужной функции, или процедуре. И вдруг в голове возникла четкая параллель между алгоритмами программирования, и алгоритмами нашего с вами социального устройства. Повсеместное алоритмирование, подгон людей под законы компьютерного моделирования, - попытка превратить нас с вами в винтики огромной машины под громким названием ГОСУДАРСТВО. Не знаю, насколько все это хорошо, или плохо, знаю одно, - мы не должны забывать того, КТО мы. Мы - люди, человеки! Нет, упаси Боже, я не говорю о том, что нужно разрушать систему, нет! Но, живя в этой системе, мы должны использовать лучшие ее моменты, такие, как социальная защищенность, или социальные обязательства (да, поскольку мы живем в обществе, у каждого из нас есть и свои права, и свои обязанности), но при этом не забывать о душе нашей человеческой, и о Боге, который прислал нас сюда. Прислал с определенной целью. Вот что главное в жизни. По крайней мере в моей...

воскресенье, 10 января 2010 г.

Ушедшее

Прошли новогодние праздники, ушел старый 2009-й... Что бы не случилось в ушедшем году,  теперь это в прошлом, - хочу я этого, или нет. Прошлое - часть жизни без которого у человека нет будущего, однако оно может только корректировать взгляды на жизнь, в противном случае жизнь превращается в охоту за призраками, - был в моей жизни и такой период (когда я  искал запахи, звуки, ощущения, которые испытывал в прошлом). Важно осознать, что прошлое ушло, на его место приходит настоящее, которое уже стремится стать прошлым, и далекое, скрытое  от взгляда будущее. Прошлое остается в прошлом, - как говорил Иисус Христос - "...пусть мертвые хоронят своих мертвецов..."