Publishboard: a drupal.hu szerkesztőségi segítője

Hojtsy Gábor képe

A Drupal.hu indulásakor a webhely egyik funkciója az új tartalmak beérkezése esetén az adminisztrátorok értesítése (notify) volt. Ezt egyrészt a megnövekedett link beküldés szám, másrészt pedig az akkor használt modul hátrahagyottsága (a frissítés elmaradása miatt) nem használtuk tovább. Így viszont, és a kis szerkesztőség kevés idejének is betudhatóan nem követtük a beérkező tartalmakat, sokszor külön emailben értesültünk, hogy valamilyen cikket vagy hírt most már át kellene nézni, és meg kellene jelentetni.

Amikor a drupal.hu szerkesztőségét bővítettük (mely ma már a legtöbb kiemelten aktív drupal.hu tagot magában foglalva hét tagot számlál), ez a gond még erősebben jelentkezett. Úgy döntöttünk, hogy email értesítés helyett folyamatosan szem előtt lévő összefoglalót alakítunk ki. Ennek a fejlesztését én vállaltam, s a néhány hónapja használt Publishboard modulunk meglátásom szerint beváltotta a hozzá fűzött reményeket.


A publishboard blokk megjelenése

A feladat tehát a beküldött tartalmak összefoglalása volt, hogy értesülhessünk a beküldött új tartalmakról, és minél hamarabb cselekedhessünk ezeket illetően. Természetesen belefoghattunk volna valamilyen általános modullal összevarázsolni a saját eszközünket, de az eredményként született jól kommentezve is csupán 115 soros modul karcsúbb és célratörőbb lett.

Először is természetesen szükségünk volt egy .info fájlra a modulhoz:


name = Publishboard
description = Beküldött tartalmak kezelését segíti
package = "Drupal.hu"
core = 6.x

Itt látszik, hogy a drupal.hu számára kifejlesztett moduljainkat egy csomagban fogjuk össze.

A számunkra lényeges információ az, hogy mennyi még megjelenésre váró tartalom van, illetve ezek közül mennyi új és régi. Drupal terminológiával most újnak tekintünk minden tartalmat, amit az aktuálisan belépett felhasználó még nem látott vagy amióta látta, azóta változtattak rajta. Ennek érdekében a következő összesítő kódot alakítottuk ki:

/**
* A nem olvasott tartalmak számának összesítése.
*/
function publishboard_unread_counters() {
global $user;
// Üres tömbökkel indulunk.
$unchanged = $changed = $list = $types = array();
// Az összes most nem közzétett node néhány adatára van szükség és a típusaik listájára.
$result = db_query('SELECT nid, type, changed FROM {node} WHERE status = 0');
while ($node = db_fetch_object($result)) {
$list[$node->nid] = $node;
if (!in_array($node->type, $types)) {
$types[] = $node->type;
}
}
// Ha van bármilyen nem közzétett tartalom.
if (count($types)) {
// Nézzük, hogy az éppen látogató felhasználó melyeket látta már ezekből legutóbbi
// módosításuk óta (melyek így tényleg újak a számára). Az IN() tartalma biztos számokból áll
// a fenti kód alapján, ezért azt biztonságos az SQL-ben közvetlenül használni.
$part = join(", ", array_keys($list));
$result = db_query("SELECT nid, timestamp FROM {history} WHERE uid = %d AND nid IN ($part)", $user->uid);
while($history = db_fetch_object($result)) {
if ($list[$history->nid]->changed > $history->timestamp) {
// Van róla adatunk, és régebben látta, mint amikor legutóbb változott.
$changed[$list[$history->nid]->type]++;
}
else {
// Volt róla adat, de a változás régebbi, mint a látogatás.
$unchanged[$list[$history->nid]->type]++;
}
// Kezeltük a history tábla alapján.
unset($list[$history->nid]);
}
}
// Ezeket nem találtuk meg a history táblában, azaz soha nem látta a user,
// vagy nagyon régen látta, és már a history táblában nincs benne a bejegyzés.
// Csak a limitet tudjuk alapul venni az ellenőrzéshez.
foreach ($list as $node) {
if ($list[$node->nid]->changed > NODE_NEW_LIMIT) {
$changed[$node->type]++;
}
else {
$unchanged[$node->type]++;
}
}
// A típusok listájával és a számolások eredményével térünk vissza.
return array($types, $changed, $unchanged);
}
?>

Ezekről az adatokról egy emberileg olvasható blokkban szeretnénk információkat megjeleníteni:

/**
* hook_block() megvalósítás.
*/
function publishboard_block($op = 'list', $delta = 0, $edit = array()) {
if ($op == 'list') {
// Egy blokkot biztosítunk a rendszer számára.
return array(0 => array('info' => 'Beküldött tartalmak',
'weight' => -100, 'enabled' => 1, 'region' => 'right'));
}
elseif ($op == 'view' && user_access("access administration pages")) {
// Csak adminisztrátoroknak mutatjuk meg ezt a blokkot.
$items = array();
// Emberek számára olvasható nevek praktikusabbak, mint a gépi nevek.
$names = node_get_types('names');
// Alapadatok lekérdezése.
list($types, $changed, $unchanged) = publishboard_unread_counters();
foreach ($types as $type) {
$title = '';
// Elvileg valamelyik be van állítva, de azért menjünk biztosra.
if (isset($unchanged[$type]) || isset($changed[$type])) {
if (isset($unchanged[$type])) {
$title .= $unchanged[$type] .' régi'. (isset($changed[$type]) ? ', ' : ' ');
}
if (isset($changed[$type])) {
$title .= $changed[$type] .' új ';
}
$items[] = l($title . $names[$type], 'publishboard/'. $type);
}
}
if (count($items)) {
// Vannak megjelenítendő linkek.
return array(
'subject' => 'Beküldött tartalmak',
'content' => theme('item_list', $items),
);
}
}
}
?>

A blokk funkciója természetesen nem csak az információ átadása, hanem a szerkesztőség segítése is, tehát olyan linkeket kellett kialakítani, amik az adminisztrációs felület megfelelő oldalára vezetnek. A tartalmak kezelőfelülete azonban nem linkelhető a webcímbe helyezett olyan kritériumokkal, mint, hogy adott típusú, nem publikált tartalmakra van szükségünk. Ezért kellett bevezetni az előző kódban látható publishboard címen a köztes oldalunkat, ami a megfelelő beállításokkal átirányít a tartalmak adminisztrációs oldalára.

/**
* hook_menu() megvalósítás.
*/
function publishboard_menu($may_cache) {
$items = array();
// Cached menu items
if (!$may_cache) {
$items[] = array(
'path' => 'publishboard',
'title' => 'Beküldött tartalmak',
'callback' => 'publishboard_page',
'access' => user_access("access administration pages"),
'type' => MENU_CALLBACK,
);
}
return $items;
}
?>

Itt egy menüben meg nem jelenő, a publishboard_page()-et hívó webcím kezelőt állítottunk be. Az pedig egyszerűen:

function publishboard_page($type) {
// A tartalom lista szűrése meg nem jelent $type típusú elemekre, a node.module kódja alapján.
$_SESSION['node_overview_filter'] = array(
array('status', 'status-0'),
array('type', $type),
);
// Átirányítás a céloldalra.
drupal_goto('admin/content/node');
}
?>

Ennyivel meg is oldottuk a funkcionalitást. Rendelkezésünkre áll egy blokk, ami kijelzi a meg nem jelent tartalmakat, és a linkekre kattintva az adminisztrációs felületre vezet. Bekapcsolhatjuk a blokkot akár minden felhasználó számára, hiszen maga a blokk akadályozza meg, hogy nem adminisztrátorok részére is láthatóvá válljon. Számunkra még egy fontos elem volt: emeljük ki a blokkot a többi közül, megkönnyítve a szemünk számára a blokk azonosítását. Ezt a következő egyszerű CSS szabályok sminkünkbe helyezésével értük el:


/* Publishboard */
#sidebar #block-publishboard-0 {
background-color: #ffc;
padding: 0.8em;
}
#sidebar #block-publishboard-0 .item-list ul {
margin: 0;
}
#sidebar #block-publishboard-0 a {
color: #036;
font-weight: bold;
}

Ezzel egy figyelemfelkeltő sárga háttérrel megjelenő blokkot kaptunk, mely a fent látott módon fest.

Hozzászólások

thamas képe

Az ötlet hasznos, és a kóderek nyilván értékelik a modul leírást!

Majd igyekszünk, hogy mindig legyen tartalma a Publishboard blokknak! ;o)

Üdvözlettel:
Hajas Tamás

Üdvözlettel:
Hajas Tamás

vikicica22 képe

Sziasztok!

Nekem nem működik a dolog most akartam kipróbálni de ez nem működik nekem valamiért.
Létre hoztam egy publishboard – könyvtárat abban egy publishboard.info-t és egy publishboard.modult.
Az info bele másoltam a fentebb leirt 3 soros mondatott utána pedig a modulba a kódokat.
Moduloknál meg is jelenik ez Drupal.hu / Publishboard ezt kipipáltam.
A blokkoknál megjelenik, a Beküldött tartalmak azt kiteszem pl. jobb oldalra, de nem jelenik meg semmi. Mit rontottam el szerintetek? Drupal 5.3-as van fent.

Esetleg ha valakinek van egy működő modulja és azt ha megtenné hogy eltudná, nekem küldeni egy zip file-ban azt megköszönném.

üdv.: viki

Hojtsy Gábor képe

A modul csak a még meg nem jelent (nem közzétett) tartalmakat jeleníti meg. Neked vannak ilyenek az adatbázisban?

vikicica22 képe

Azt a béna mindenit, hogy lehet ilyen amatőr :( Tényleg szégyen hozok a szőke női nemre.
Én azt hittem, hogy azt jeleníti, meg oldalt hogy hány Tartalom beküldés volt eddig pl.:

Oldal. 3 db.
Hírek: 4 db.
Linkek: 6db.
Stb.… stb.…

létezik ilyen modul?
üdv.: viki

pp képe

Picit módosítasz rajta neked is menni fog szerintem.

 // Az összes most nem közzétett node néhány adatára van szükség és a típusaik listájára.
  $result = db_query('SELECT nid, type, changed FROM {node} WHERE status = 0');

itt a végén vagy töröld a WHERE status = 0 kódrészletet (minden tartalom) vagy írd át 1-re(közzétett tartalmak).

pp

vikicica22 képe

Köszönöm! Nagyon szépen működik
Hojtsy Gábor féle is működik és a Palócz István (pp) segítsége is működik.
Ezek csak akkor láthatóak ha adminként vagyok lépve a rendszerbe.
Azt hogyan lehet előcsalni, hogy nem csak akkor, lehessen látni ezeket, hanem sima felhasználóként is.
üdv.: viki

pp képe

Nem meglepő módon:
publishboard_menu függvényt kell módosítani.

 
        'access'   => user_access("access administration pages"),

ezt, erre:
 
        'access'   => user_access("access content"),
Hojtsy Gábor képe

// $Id$
 
/**
 * @file
 *   Adminisztrációt segítő funkciók a Drupal.hu számára.
 */
 
/**
 * hook_menu() megvalósítás.
 */
function publishboard_menu() {
  $items['publishboard/%'] = array(
    'title'            => 'Beküldött tartalmak',
    'page callback'    => 'publishboard_page',
    'page arguments'   => array(1),
    'access arguments' => array('access administration pages'),
    'type'             => MENU_CALLBACK,
  );
  return $items;
}
 
/**
 * hook_block() megvalósítás.
 */
function publishboard_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    return array(0 => array('info' => 'Beküldött tartalmak',
      'weight' => -100, 'enabled' => 1, 'region' => 'right'));
  }
  elseif ($op == 'view' && user_access("access administration pages")) {
    $items = array();
    $names = node_get_types('names');
    list($types, $changed, $unchanged) = publishboard_unread_counters();
    foreach ($types as $type) {
      $title = '';
      if (isset($unchanged[$type]) || isset($changed[$type])) {
        if (isset($changed[$type])) {
          $title .= '<span class="marker">'. $changed[$type] .' új</span>'. (isset($unchanged[$type]) ? ', ' : ' ');
        }
        if (isset($unchanged[$type])) {
          $title .= $unchanged[$type] .' régi ';
        }
        $items[] = @l($title . check_plain($names[$type]), 'publishboard/'. $type, array('html' => true));
      }
    }
    if (count($items)) {
      return array(
        'subject' => 'Beküldött tartalmak',
        'content' => theme('item_list', $items),
      );
    }
  }
}
 
function publishboard_page($type) {
  $_SESSION['node_overview_filter'] = array(
    array('status', 'status-0'),
    array('type', $type),
  );
  drupal_goto('admin/content/node');
}
 
/**
 * A nem olvasott tartalmak számának összesítése.
 */
function publishboard_unread_counters() {
  global $user;
 
  $unchanged = $changed = $list = $types = array();
 
  $result = db_query('SELECT nid, type, changed FROM {node} WHERE status = 0');
  while ($node = db_fetch_object($result)) {
    $list[$node->nid] = $node;
    if (!in_array($node->type, $types)) {
      $types[] = $node->type;
    }
  }
 
  if (count($types)) {
    // Nézzük, hogy az éppen látogató user melyeket látta már ezekből legutóbbi
    // módosításuk óta (melyek így tényleg újak a számára).
    $part = join(", ", array_keys($list));
    $result = db_query("SELECT nid, timestamp FROM {history} WHERE uid = %d AND nid IN ($part)", $user->uid);
    while ($history = db_fetch_object($result)) {
      if ($list[$history->nid]->changed > $history->timestamp) {
        // Van róla adatunk, és régebben látta, mint amikor legutóbb változott.
        @$changed[$list[$history->nid]->type]++;
      }
      else {
        // Volt róla adat, de a változás régebbi, mint a látogatás.
        @$unchanged[$list[$history->nid]->type]++;
      }
      // Kezeltük a history tábla alapján.
      unset($list[$history->nid]);
    }
  }
 
  // Ezeket nem találtuk meg a history táblában, azaz soha nem látta a user,
  // vagy nagyon régen látta. Csak a limitet tudjuk alapul venni.
  foreach ($list as $node) {
    if ($list[$node->nid]->changed > NODE_NEW_LIMIT) {
      @$changed[$node->type]++;
    }
    else {
      @$unchanged[$node->type]++;
    }
  }
 
  return array($types, $changed, $unchanged);
}