Флуд #7
Все, не могу больше это читать, держусь за живот от смеха))) Нет, ну серьезно, последнее время все чаще вижу ссылки на блог и обсуждения трактора как какого-то большого программного продукта) Человек видит код, который впервые заставил вывести запись из БД на экран, и делает заключение, что я неправильно учу бедных несчастных начинающих программистов)))
Я, конечно, понимаю, без контекста трудно понять идею, но и защищать меня тоже особенно не нужно, ребят) Я не учу, я показываю свой ход мысли, и он, этот ход, почти наверняка неправильный по большей части, я ведь учусь как и вы. Велосипед не сразу становится продуктом для всех. Сейчас это продукт для меня и, может быть, для тех кто хорошо в нем может разобраться. Но каждый программист проходит этап велосипедописания, и у каждого он будет свой, или хобби так и останется хобби.
И да, я в курсе что трактор слабо разделяет логику и представление)))) У нас админка – одна сплошная логика, но это не значит что она не должна работать или будет такой кривой до конца жизни) Фьююф, отвел душу, надо картинку к посту поискать.
Флуд #6
Продолжаем рефакторить накопленный код. Во-первых, хочу сказать – никогда так не пишите) Нет, серьезно, в классе, который я вам сейчас покажу есть недостатки, и ваша задача их определить. Если вы их не видите, то вам срочно нужно пополнить свои знания в ООП. Для этого почитайте, например Зандстра Мэтт «PHP. Объекты, шаблоны и методики программирования. – 2010». Перевод убогий, но читать можно, если под шаблонами подразумевать паттерны.
Поехали. Библиотека /lib/db_types.php
class TEComment { public $id; public $authorName; public $authorEmail; public $authorId; public $articleId; public $text; public $date; function __construct($id=false, $authorName=false,$authorEmail=false, $authorId=false,$articleId=false,$text=false,$date=false) { if ($id) { $this->id = intval($id); $result = mysql_query(' SELECT * FROM '.PREFIX.'comment WHERE id = "'.$this->id.'"') or die(mysql_error()); $comment=mysql_fetch_assoc($result); $this->authorName = $comment['author']; $this->authorEmail = $comment['email']; $this->authorId = $comment['author_id']; $this->articleId = $comment['article_id']; $this->text = $comment['content']; $this->date = $comment['stamp']; } else { $this->authorName = mysql_escape_string(htmlspecialchars($authorName)); $this->authorEmail = mysql_escape_string(htmlspecialchars($authorEmail)); $this->authorId = intval($authorId); $this->articleId = intval($articleId); $this->text = mysql_escape_string(htmlspecialchars($text)); $this->date = mysql_escape_string(htmlspecialchars($date)); } } public function addRecord() { //выбираем комментарии к данной статье с таким же текстом $res = mysql_query(' SELECT * FROM '.PREFIX.'comment WHERE content = "'.$this->text.'" AND article_id = "'.$this->articleId.'" ORDER BY id' ) or die(mysql_error()); if ( mysql_num_rows($res) < 1 && $this->text !== '' && strlen($this->text) < 2048 ) { if ($this->authorName == '') $this->authorName = 'UFO'; $sql = mysql_query('INSERT into '.PREFIX.'comment ( article_id, author_id, email, author, content, date ) values ( "'.$this->articleId.'", "'.$this->authorId.'", "'.$this->authorEmail.'", "'.$this->authorName.'", "'.$this->text.'", "'.$this->date.'" );' )or die(mysql_error()); if ($sql) return true; else return false; } } public function delRecord() { if ( (isset($_SESSION['author_id'])&&($_SESSION['author_id'] == $this->authorId)) || @$_SESSION['status'] == 'admin') { $sql_del = mysql_query('DELETE FROM '.PREFIX.'comment WHERE id="'.$this->id.'"') or die(mysql_error()); } if ($sql_del) return true; else return false; } }
В последствии, я надеюсь, этот класс будет видоизменяться, если появятся другие.
P.S. Оно же https://github.com/noisywiz/tractor/blob/master/_engine/lib/db_types.php
Интересный был баг
tomato catch up! –
I don't like you anymore
Весна? Нет, серьезно, время пролетело как турбированный холерик. Запасшись кофе и булкой, я тут решил начать описывать Tractor Engine v2.2. Снаружи найти изменения будет нелегко, по сути оно одно − в редакторе статьи появилась возможность указывать и изменять дату/время создания записи. Сортировка записей производится именно по этому параметру, так что фича в целом полезная)
Аннет, еще кое что видное снаружи изменилось, и тоже в редакторе. Кнопочка “Вставить разрыв страницы” в визуальном редакторе теперь делает то же, что тег <!–more–>, а именно, все что до − помещается в описание (поле article.description) записи, и генерируется ссылочка “Читать полностью”.
Чем я тут вообще занимался столько времени? Да в кишечках, дело, ребят, в кишечках. Я тут залез в библиотеку cultivator и ужаснулся, когда мне пришлось туда новую функцию-обработчик вставить. Какой инопланетянен все это писал? Точно не я) Нет, ну то есть все не так уж убийственно плохо, но захотелось многое переделать.
Ах да, из-за чего я, собственно, туда полез. Наткнулся на такой хост, на котором, внимание, невозможно в .htaccess отключить magic_quotes_gpc. Это меня, признаться, немного сломало, сервер выдавал “Ошибку 500” пока я не убрал из упомянутого конф файла строку, выключающую магические кавычки. А когда убрал, соответственно, пришлось всюду, где есть ввод из формы, втискивать функцию, которая выпилит лишние обратные слеши. Ну да обо всем по порядку. › Читать полностью
Флуд #5

Do This Anymore - Nickelback
Привет! Извините, что давно не писал. На то есть несколько причин, но основная – мне нечего рассказать. Трактор, который мы с вами делали на протяжении стольких постов, дорос до такого состояния, когда я уже не знаю, что делать дальше. Я, конечно, не хочу сказать, что он идеален, неа, он – завершенная поделка, которую я люблю, и которой горжусь.
Tractor Engine создавался с целью получения опыта, цель оправдала средства, движок можно использовать для конкретных задач. В нем для меня есть все, что нужно для развертывания любой системы, на которую теоретически хватит моих текущих способностей.
Что дальше? Конечно, Трактор будет развиваться (здесь можно расслабится и отхлебнуть кофе, отправить в рот трюфель). Как он будет развиваться? Исключительно экстенсивно. Революций не будет пока я нахожусь на том уровне, на котором эээ нахожусь))
К чему это все? Ближайшее время, как вы понимаете, мне будет не до революций и даже не до эволюций, не то чтобы меня особенно напрягает сессия, она просто немного отвлекает.
Из обновлений версии 2.1. (единичка мажорная, потому что изменена структура БД, а не из-за красоты). Добавил ранжирование категорий; пофиксил небольшой баг, связанный с генерацией ссылок в разных режимах ЧПУ (проблемка возникала только в случае использования русских чпу и адреса вида ээ не помню какого); и ошибку при смене шаблона при открытом для редактирования файле шаблона тоже устранил.
Ну и, как обещал, расскажу об обновленном модуле xmpp-оповещений. Shadow-модуль klaxon выглядит так:
//jabber-аккаунт отправителя define ("XS_HOST", "talk.google.com");//xmpp.ya.ru define ("XS_PORT", 5222); define ("XS_LOGIN", "login"); //ваш логин define ("XS_PASS", "password"); //пароль define ("XS_SERVER", "gmail.com"); if (isset($_EVENT['new_comment'])) { flush (); $text = 'Комментарий '.SITE_URL.'/?id='.$_REQUEST['id'].' '. $_REQUEST['comment_text']; // Получатели письма - все администраторы $result = mysql_query('SELECT * FROM '.PREFIX.'users WHERE status = "admin" ORDER BY id') or die(mysql_error()); for ($tos=array(); $row2=mysql_fetch_assoc($result); $tos[]=$row2); include ('lib/XMPPHP/XMPP.php'); $conn = new XMPPHP_XMPP(XS_HOST, XS_PORT, XS_LOGIN, XS_PASS, 'xmpphp', XS_SERVER, $printlog=false, $loglevel=XMPPHP_Log::LEVEL_INFO); try { //timeout = 5сек $conn->connect(5); $conn->processUntil('session_start'); $conn->presence(); foreach ($tos as $to) { $conn->message($to['email'], $text); } $conn->disconnect(); } catch(XMPPHP_Exception $e) { $text = 'Комментарий '.SITE_URL.'/?id='.$_REQUEST['id'].' '.$_REQUEST['comment_text']; include_once ('lib/mail_lib.php'); // Считываем шаблон. $tmpl_rdb = mysql_query('SELECT * FROM '.PREFIX.'support where suptitle = "notice_tmpl" ORDER BY id') or die(mysql_error()); $tmpl_data=@mysql_fetch_array($tmpl_rdb); $tpl = $tmpl_data['suptext']; foreach ($tos as $to) { $mail = $tpl; $mail = strtr($mail, array( "{TO}" => trim($to['email']), "{TEXT}" => $text, )); $mail = mailenc($mail); mailx($mail); } die($e->getMessage()); } } ?>
Событие $_EVENT['new_comment'] создается модулем комментариев непосредственно перед записью нового комментария в БД. Далее идет отправка в браузер всего что только можно flush (). А отправить мы можем, собственно, весь Шаблон со всем содержимым, т.к. shadow-модули включаются в работу уже после обработки Шаблона. Мы, конечно, могли бы и не отправлять весь буфер пользователю досрочно, но отправка xmpp-сообщения занимает порой несколько секунд.
Далее формируем текст сообщения, подключаем библиотеку XMPPHP и пробуем отправить сообщение. Если наше jabber-поползновение не увенчивается успехом, просто отправляем оповещение по E-Mail. Никаких сложностей, но есть один минус. Хотелось бы отправлять оповещения и offline-получателям в jabber. У меня как-то не очень получилось подружиться с гугловым service@gtalk2voip.com, если кто знает еще стабильных правильных ботов, – скажите.
Напоследок поделюсь наблюдениями.
Нечаянно испытал что значит register_globals = on. Обнаружил маленький баг, но не стал его исправлять, так что при включенной регистрации глобальных переменных админка работать не будет. Боюсь даже представить, есть ли при этом еще уязвимости.
Еще на одном хосте столкнулся с некорректной работой функции получения ЧПУ lib/lib.php get_sef(). А именно в начале массива появлялись какие-то левые элементы. Не стал ломать голову откуда там ноги растут в этих регулярных выражениях, просто удалил первый элемент получаемого массива array_shift($_URL); и ЧПУ заработали, авторизация и все что связано с «оконной» библиотекой тоже. Все эти preg_replace() мне никогда не нравились.
Понадобилось сделать в одном проекте работу с изображениями привязанными к записям, по дороге написал несколько функций для этого. Суть в следующем. К статье нужно добавить несколько фотографий, при этом необходимо иметь к ним доступ отдельно от контента самой статьи. Решил сделать для изображений отдельную таблицу в БД, и указывать в записях имя файла фотографии и идентификатор статьи, к которой она привязана. Сами фотографии хранятся в папке user/pic, миниатюрные копии фотографий должны создаваться автоматически, положил их в папку user/_thumbs. Пища для ума:
##создаем запись в БД # $fname - имя файла; $item_id - идентификатор статьи function creat_photo ($item_id, $fname) { $sql2 = mysql_query('INSERT into '.PREFIX.'photos (item_id, fname) values ( "'.intval($item_id).'", "'.strval($fname).'" ); '); } ##удаление всех фото для данной статьи. # $item_id - идентификатор статьи function del_photos ($item_id) { $sql = mysql_query('SELECT * FROM '.PREFIX.'photos WHERE item_id="'.intval($item_id).'"'); for ($db=array(); $row=mysql_fetch_assoc($sql); $db[]=$row); //удаляем запись о фото $sql_del = mysql_query('DELETE FROM '.PREFIX.'photos WHERE item_id="'.intval($item_id).'"') or die(mysql_error()); $pic=INDEX_DIR.'/user/pic'; $thumb=INDEX_DIR.'/user/_thumbs'; //удаляем изображения и миниатюры foreach ($db as $v) { $file=$pic.'/'.$v['fname']; unlink($file); $file=$thumb.'/'.$v['fname']; unlink($file); } return true; } ##создаем миниатюру # $pth - абс путь к исходному изображению; $fname - имя файла function crt_thumb($fname, $pth) { $from = imageCreateFromJpeg($pth.'/'.$fname); $maxW=200;//максимальная ширина $maxH=intval(imageSY($from)/(imageSX($from)/$maxW));//высота $to = imageCreateTrueColor($maxW, $maxH); imageCopyResampled( $to, $from, 0, 0, 0, 0, imageSX($to), imageSY($to), imageSX($from), imageSY($from) ); imageJpeg($to, INDEX_DIR.'/user/_thumbs/'.$fname, 90);//сохраняем файл } ##загружаем выбранные файлы # $item_id - идентификатор статьи function upload_files($item_id) { if ($_FILES) { $dir='/pic'; //ограничимся пятью файлами за раз for ($i=0; $i<=5; $i++) { //исходим из предположения, что поля выбора файла имеют атрибут name=1,2,3 и т.д. $file = $_FILES["$i"]['name']; if ($file) { $pth=INDEX_DIR.'/user'.strval($dir); if (is_file($pth.'/'.$_FILES["$i"]['name'])) {//файл с таким именем уже существует? $file = time().'_'.$_FILES["$i"]['name']; } $m=move_uploaded_file ($_FILES["$i"]['tmp_name'], $pth.'/'.$file); creat_photo ($item_id, $file); crt_thumb($file, $pth); } } } }
Удачи!
v2.0
Сеошное введение. Первая CMS, которую мы не спеша пишем уже полтора года, доросла до.. Ну вы поняли, мы большие, CMS мы писали, пишем и писать будем.
Пафосное введение. Tractor Engine v2.0 готов пахать и тарахтеть. Почему с 1.2.1 сразу на 2.0?
1. первое, как вы понимаете, – это красиво)
2. дальше такие аргументы:
* поместил все файлы cms в отдельную папочку «_engine», на движок можно ставить сколько угодно сайтов на хосте;
* панель администрирования интегрировал в движок в качестве м-м-м, пожалуй, Компонента;
* новая сущность shadow-модули;
* о, еще blogConsole основательно доработал, в плане философии в основном;
3. если вы помните что такое WAP, то он тоже с 1.2.1 на 2.0 прыгнул, так что есть прецедент)
Минорные изменения:
- еще сделал три новых блог-шаблона;
- модуль xmpp-оповещений адекватный, про него не забыть рассказать;
- [микро]библиотеки которые заняты генерацией новых окон с информацией о профиле и пр. тоже интегрировал в движок и привел в божеский вид;
- немного повозился с конфигурационным файлом CKEditor’а, точнее с подключением файлового менеджера KCFinder, папка с его загрузками (upload) будет лежать рядом с папкой движка, одна для всех сайтов – минимум путаницы по-моему;
- нативному менеджеру загрузок движка (библиотека upload) добавил ума, про него рассказать ведь тоже надо будет.. А успею я сегодня пост закончить?..
te.Блог
Tractor Engine v1.2.1 готов, друзья. Были претензии к Шаблонизатору, кое-кто его и вовсе не нашел, посему сделаем сегодня с вами Блог) Угу, возьмем трактор и, по возможности, не влезая в его кишечки, построим готовый блог с блекджеком и т.д.
Философия, как и положено в тракторе, утонченная как распредвал и изящная как бензобак)) › Читать полностью
Changelog и недостаток идей
Приветствую! Извините, что давно не писал, сессия, теперь вот практика, все это требует затрат времени и сил. Видели бы вы эту систему охлаждения масла для одного единственного компрессора, там вентиляторы метра четыре диаметром, и радиаторов с десяток))
Что я проделал с Tractor Engine 1.2:
Ядро
-работа с часовыми поясами;
-кошерный адрес rss-фида (SITE_RSS);
-по просьбам начинающих механизаторов проанализировал читабельность кода (проблем не выявлено:))
Модуль комментариев
-исправил баг с добавлением комментария при переходе на страницу статьи по адресу не соответствующему текущему стилю ЧПУ (SEF_TYPE)
Админ-панель
-обновлен раздел настроек в соответствии с обновлениями ядра.
Флуд #4
Приветствую. Не придумал, чем бы с вами поделиться, кодить мне сейчас и в ближайшее время некогда, разберусь со всякими глупостями вроде сессии, и в путь, а пока, – набор мыслей из evernote)
Знаете ли вы что:
По умолчанию Компонент feedback использует E-Mail администратора для обратной связи, так что его желательно указывать.
Если при установке файл config.php уже существует, инсталлятор предпринимает попытку создать указанную в конфигурационном файле базу данных.
В логине и пароле, ровно как и в нике, можно использовать русские символы.
Для каждой рубрики создается отдельная RSS-лента, имя соответствует идентификатору рубрики (category_id). Адрес лент – http://сайт/rss/имя_ленты.rss
Выпуски рассылки не вылетают в трубу при отправке, они сохраняются в таблице subarchive.
Пользователей можно и нужно банить) Если поставить бан «0», то время бана обнулится. Время до конца бана стандартный шаблон умеет показывать в профиле.
Если в самых неожиданных местах появляются неизвестные файлы, значит ваша CMS уже достаточно взрослая.
Зарезервированные переменные:
$page – название текущего Компонента (тип страниц);
$cfg – конфигурационный массив, какой он выходит из БД;
$_URL – разобранный массив ЧПУ;
$key, $desc – meta-теги текущего Компонента;
$tractor – задается true в index.php для последующей проверки в подключаемых файлах;
[микро]Спецификация модуля SkinParser
Модуль представлен одной единственной функцией, задача которой – считать указанный html-файл шаблона и заменить в нем ключевые строки на элементы заданного массива. Ключевые фразы, которые шаблонизатор будет заменять, должны быть заключены в <%специальный тег%>, фраза внутри которого – и есть ключ для массива.
Что будет
Я доделаю миноры предыдущей версии, будет нормальная работа с часовыми поясами и адресом фида (для работы с feedburner, конечно , стараемся).
Jabber-библиотека
Пришла в голову идея поработать с отправкой jabber-сообщений. Вышло вполне сносно, сейчас расскажу как оно было.
Идея оповещений по xmpp-протоколу не нова, нужна php-библиотека для работы с протоколом, собственно, и все, руки еще, разве что, и то необязательно слишком прямые. Сейчас все новые комменты с тестового сайта сразу приходят в мой gtalk.
Логика такая: модуль комментариев, увидев попытку добавления комментария, включает библиотеку “XMPPHP”, которая подключается к определенному (администратор задает вручную) jabber-аккаунту и отправляет с него сообщение по указанному адресу. › Читать полностью
Многоязычный шаблон
Вечер добрый. Надеюсь, ваши будни начались вразумительно) Делал я, кажется, долго и упорно что-то, а похвастаться в итоге могу только новым шаблоном и kcfinder-ом. Шаблон сделал на шаблонизаторе, на двух языках сразу, довольно простой. Вообще, Шаблон в тракторе продолжает оставаться конструктором даже на шаблонезаторе. О чем я говорю? Tractor Engine все еще CMS с замашками фреймворка, конкретной специализации нет, можно сконструировать и каталог статей, и микроблог с визиткой.
Шаблон можно сделать пассивным, взять html-страничку и напичкать <%спец. тегами%>. Но, как вы понимаете, эти теги нужно где-то ассоциировать с реальными функциями движка. Сейчас этим занимается сам же Шаблон, как правило, в файле page.php, так как он единственный обязательный, подключающийся из index.php.



