Новый сайт на Друпале и пример создания модуля

July 17th, 2008

Ассоциация юристов РоссииЯ сделал новый сайт на друпале для регионального отделения “Ассоциации юристов России”.

И теперь хочу поделиться с вами некоторыми техническими деталями его реализации. Итак
Я решил делать обособленный тип данных не ввиде термина таксономии, а отдельным модулем.
Мне почему-то кажется это более удобным и логичным.
У меня есть тип данных “документ” – это обыкновенный нод и тип данных “новость” (для этого типа данных создал модуль) – это для раздела новости.
Модуль получился небольшой (около 170 строк), основой его послужили другие модули, а изюминкой стала своя реализация тумбнейла (превьюхи) для новостей, на подобии imagecache, но проще в использовании и узкопрофильнее что-ли (т.е. решение не универсальное, а специализированное).
Суть в том, что производится анализ наличия прикреплённых к документу изображений, первое из них отбирается для создания тумбнейла, созданный тумбнейл сохраняется в кэш и выводится в тизере нода.
Вывод производится таким образом <?php print my_upload_image(&$node); ?>
Для ознакомления и возможного использования его отдельных частей модуль novosti прикадываю – скачать модуль бесплатно.
Список использованных модулейЕщё одно отличие от предыдущего сайта это переход на шестёрку (Drupal 6).
Эта версия друпала конечно интереснее, хотя пока и не имеет такого кол-ва расширений (сторонних модулей) как пятая версия.
Но в моем случае сторонних модулей использовано очень мало (см. рисунок).
Пример модуля (см. оригинальную инструкцию на друпал.орг):

<?php
// $Id: novosti.module,v 1.0.0.1 2008/05/21 09:06:51 selikoff Exp $
// Описываем новый тип данных
function novosti_node_info() {
return array(
'novosti' => array(
'name' => t('Novosti'),
'module' => 'novosti',
'description' => "This is an novosti node type with a few fields.",
)
);
}
// Текст подсказки
function novosti_help($section, $arg='') {
switch ($section) {
case 'admin/settings/novosti':
$output = t('<p>Some help in this</p>');
break;
}
return $output;
} // function novosti_help
// новый пункт в административном меню
function novosti_menu($may_cache=null) {
$items['admin/settings/novosti'] = array(
'title' => 'Novosti settings',
'description' => 'Specify a unique layout or splash page based on role type - override your HOME and breadcrumb links - display a custom mission style notice for users who haven\'t visited in a while - disable site and display a \'temporarily offline\' message.',
'page callback' => 'drupal_get_form',
'page arguments' => array('novosti_admin'),
'access arguments' => array('administer site configuration'),
'type' => MENU_NORMAL_ITEM,
);
$items['novosti'] = array(
'title' => t('News'),
'page callback' => 'novosti_all', //'novosti_page_list',
'access arguments' => array('access novosti'),
'type' => MENU_CALLBACK,
); //
return $items;
} // function novosti_menu
// перечисляем разделение прав
function novosti_perm() {
return array('access novosti','create novosti', 'edit novosti', 'edit own novosti');
} // function novosti_perm
// описываем разделение доступа
function novosti_access($op, $node, $account) {
global $user;
if ($op == 'create') {
return user_access('create novosti', $account);
}else if ($op == 'view') {
return user_access('access novosti', $account);
}
if ($op == 'update' || $op == 'delete') {
if (user_access('edit novosti', $account)) {
return TRUE;
}else if (user_access('edit own novosti', $account) && ($user->uid == $node->uid)) {
return TRUE;
}
}
} // function novosti_access
// форма для нашего типа данных
function novosti_form(&$node, &$param) {
$type = node_get_types('type', $node);
// We need to define form elements for the node's title and body.
$form['title'] = array(
'#type' => 'textfield',
'#title' => check_plain($type->title_label),
'#required' => TRUE,
'#default_value' => $node->title,
'#weight' => -5
);
$form['body_filter']['body'] = array(
'#type' => 'textarea',
'#rows' => 15,
'#title' => check_plain($type->body_label),
'#default_value' => $node->body,
'#required' => FALSE
);
$form['body_filter']['filter'] = filter_form($node->format);
// NOTE in node_example there is some addition code here not needed for this simple node-type
return $form;
} // function novosti_form
// представление в виде блока
function novosti_block($op='list', $delta=0) {
// listing of blocks, such as on the admin/block page
if ($op == "list") {
$block[0]["info"] = t('Novosti');
return $block;
} else if ($op == 'view') {
// our block content
$block_content = '';
$limitnum = variable_get('novosti_maxdisp', 3);
$result =  db_query("SELECT nid, title, created FROM {node} WHERE type='novosti' ORDER BY created DESC LIMIT ".$limitnum);
while ($links = db_fetch_object($result)) {
$block_content .=  l($links->title, 'node/'. $links->nid) .'<br />';
}
if ($block_content == '') {
return;
}
$block_content .= "<div class=\"more-link\">". l(t("more"),"novosti",array("title" => t("More novosti.") ) )."</div>";
$block['subject'] = t('Novosti');
$block['content'] = $block_content;
return $block;
}
} // end novosti_block
// административные настройки
function novosti_admin() {
$form['novosti_maxidsp'] = array(
'#type' => 'textfield',
'#title' => t('Maximum number of links'),
'#default_value' => variable_get('novosti_maxdisp', 3),
'#size' => 2,
'#maxlength' => 2,
'#description' => t("The maximum number of links to display in the block."),
'#required' => TRUE,
);
return system_settings_form($form);
}
//
function novosti_nodeapi(&$node, $op, $teaser=null, $page=null) {
if (!drupal_is_front_page()) {
switch ($op) {
case 'view':
if ($node->type=="novosti") menu_set_active_item("novosti");
break;
}
}
}
// представление в виде страницы
function novosti_all() {
global $user;
$output = '';
$result = pager_query(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'novosti' AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"),variable_get('default_nodes_main', 10));
while ($node = db_fetch_object($result)) $output .= node_view(node_load($node->nid), 1);
if ($output) $output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
else drupal_set_message(t('No news entries have been created.'));
return $output;
}
// проверка существования файла в кэше
function my_check_cache($filepath,$filename,$nid) {
$mycachepath = 'mcache/';
$maxw = 120;
$maxh = 111;
$newfilename = $mycachepath.$nid."_".$filename;
if (file_exists($newfilename)) return "<img src='/".$newfilename."'>";
else {
$needaspect = $maxh / $maxw;
$details = image_get_info($filepath);
$aspect = $details['height'] / $details['width'];
if ($aspect<$needaspect) { $neww = $maxh/$aspect; $newh = $maxh; $cropx = ($neww - $maxw)/2; $cropy = 0;}
elseif ($aspect==$needaspect) { $neww = $maxw; $newh = $maxh;  $cropx = ($neww - $maxw)/2; $cropy = ($newh - $maxh)/2; }
elseif ($aspect>$needaspect) { $neww = $maxw; $newh = $maxw*$aspect;  $cropx = 0; $cropy = ($newh - $maxh)/2; }
$ress = image_scale($filepath, $newfilename, $neww, $newh);
if ($ress) $resr = image_crop($newfilename, $newfilename, $cropx, $cropy, $maxw, $maxh);
if ($resr) return "<img src='/".$newfilename."'>";
}
return '<!--error-->';
}
// это моя функция выдергивания изображений
function my_upload_image($node) {
$mims = array('image/jpeg','image/png','image/gif','image/jpg');
if (empty($node->files)) return;
foreach ($node->files as $fil) {
$fil = (object)$fil;
if (in_array($fil->filemime,$mims)) {
return my_check_cache($fil->filepath,$fil->filename,$node->nid);
}
}
?>

Комментирование закрыто.

 
О Сайте

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

Администрирование
Ссылки:
пишите обменяемся.

Спамер, осторожно!