Reklama

zonerbooks.cz | zoner.cz | czechia.com | regzone.cz | inshop.cz | inmail.cz | zonerpress.cz | zonerantivirus.com | zonerama.cz

interval.cz

Weblog v PHP - vkládání, mazání a úprava článků

21. 01. 2003 | Michal Kebrt | PHP | Komentáře: 3

V posledním článku této série si ukážeme, jakým způsobem vyřešit přidávání nových článků a mazání a úpravu článků již napsaných. Dozvíte se, jak ošetřit uživatelské vstupy tak, aby uživatelé nemohli narušit design ani funkčnost stránek, ale přitom mohli vkládat některé elementy a dlouhé odkazy. Na závěr si budete moci kompletní zdrojové kódy weblogu stáhnout.

Funkční ukázku weblogu najdete na webu Czechie.

Vkládání a mazání článků (index.php)

K rozlišení toho, zda se bude článek vkládat či mazat, použijeme proměnnou $action. Obsahuje-li "post", pak článek vložíme. Nejprve však musíme zkontrolovat, zda byly vyplněny oba povinné údaje (nadpis - title a text článku - article_text) a zda datum vydání není menší než aktuální datum, přičemž necháváme rezervu patnácti minut (lze samozřejmě změnit) na napsání článku. Je-li vše v pořádku, upravíme pomocí funkce Text_Modify(), která bude popsána v závěru, oba vstupní údaje. Následně zjistíme datum prvního dne v týdnu, ve kterém článek vyjde a všechny údaje vložíme do tabulky article. Nakonec, pomocí funkcí popsaných již dříve, vygenerujeme úvodní stránku a příslušnou archivní stránku.

// byla odeslana promenna "action" ?
if(IsSet($_REQUEST['action'])) {
  switch($_REQUEST['action']) {
    // vlozi clanek
    case "post":
      // byly vyplneny oba povinne udaje ?
      if($_POST['title']=="" || $_POST['article_text'] =="") {
        $error = 4;
      // neni datum vydani mensi nez aktualni datum (rezerva 15 min) ?
      } elseif(MkTime($_POST['from_hour'], $_POST['from_minute']+15, 0, $_POST['from_month'], $_POST['from_day'], $_POST['from_year']) < Time()) {
        $error = 5;
      } else {
        // uprava vstupu
        $title = Text_Modify($_POST['title']);
        $article_text = Text_Modify($_POST['article_text']);
        $publish_date = MkTime($_POST['from_hour'], $_POST['from_minute'], 0, $_POST['from_month'], $_POST['from_day'], $_POST['from_year']); // datum vydani
        $day_number = Date("w", $publish_date);
        if($day_number == 0) $day_number = 7;
        $first_day_of_week = MkTime(0,0,0, $_POST['from_month'], $_POST['from_day']-$day_number+1, $_POST['from_year']); // datum prvniho dne v tydnu, ve kterem clanek vychazi
        $query = @MySQL_Query("INSERT INTO article VALUES ('', '$title', '$article_text', '$publish_date', '$user_id', '$first_day_of_week')") or Weblog_Error(2);
        $message = 1;
        
        // vygeneruje staticke stranky
        require "archive.php";
        Create_Archive($first_day_of_week);
        Create_Index("static");
        
        MySQL_Close();
        Header('Location: http://'. $_SERVER['HTTP_HOST'] . '/weblog/admin/index.php?message=' . URLDecode($message) .'&' . SID);  // navrat na uvodni stranku
        exit;
      }
      break;

Pokud proměnná $action obsahuje "delete", příslušný článek se smaže. Ještě než článek smažeme, musíme zjistit, zda přihlášený autor ($user_id) má k danému článku ($article_id) práva. Mohlo by se totiž stát, že by někdo do odkazu vložil id jiného článku a smazal by tak cizí článek. V případě, že přihlášený autor je autorem daného článku nebo je přihlášený autor administrátorem (má práva ke všem článkům), článek smažeme a vygenerujeme statické stránky.

    // smaze clanek
    case "delete":
      $article_id = $_GET['article_id'];
      $query = @MySQL_Query("SELECT author FROM article WHERE id = $article_id") or Weblog_Error(2);  // autor clanku
      $result = MySQL_Fetch_Array($query);
      // ma prihlaseny autor prava k tomuto clanku ?
      if($result["author"] == $user_id || $user_type == "A") {
        $query = @MySQL_Query("SELECT archive_date FROM article WHERE id = $article_id") or Weblog_Error(2);  // tyden, ve kterem clanek vysel
        $result = MySQL_Fetch_Array($query);
        
        $query = @MySQL_Query("DELETE FROM article WHERE id = $article_id") or Weblog_Error(2);
        $message = 2;
    
        // vygeneruje staticke stranky
        require "archive.php";
        Create_Archive($result['archive_date']);
        Create_Index("static");
      } else {
        $message = 4;
      }
      MySQL_Close();
      Header('Location: http://'. $_SERVER['HTTP_HOST'] . '/weblog/admin/index.php?message=' . $message .'&' . SID);  // navrat na uvodni stranku
      exit;
      break;
  }
}

Úprava článku (update.php)

K úpravě napsaných článků použijeme soubor update.php. V úvodu načteme všechny potřebné soubory a do proměnné $article_id vložíme id daného článku.

ini_set('session.use_trans_sid', 1); // zajisti prenos session id
require "checklogin.php"; // je autor prihlasen ?
require "../db.php"; // pripoji k databazi
require "../function.php"; // nacte soubor s dulezitymi funkcemi
require "msg.php"; // chybove hlasky a zpravy
$article_id = $_REQUEST['article_id']; // id clanku

Následně z databáze vybereme nadpis a text daného článku a oba údaje vložíme do poměrně jednoduchého formuláře. Ke zpětné úpravě údajů, které byly modifikovány funkcí Text_Modify(), použijeme funkci un_Text_Modify(), o které bude řeč v závěru.

<?php
// vybere prislusny clanek a zobrazi formular
$query = @MySQL_Query("SELECT title, message FROM article WHERE id = $article_id") or Weblog_Error(2);
$result = MySQL_Fetch_Array($query);
$title = un_Text_Modify($result['title']);
$article_text = un_Text_Modify($result['message']);
?>
<h2 class="heading">Weblog - administrace</h2>
<h3 class="heading">Upravit článek</h3>
<?php
// chybova hlaska
if(IsSet($_GET['error'])) $error = $_GET['error'];
if(IsSet($error) && IsSet($msg_error[$error])) echo  '<p class="error">' . $msg_error[$error] . '</p>';
?>
<form action="update.php" method="post">
<input type="hidden" name="sent" value="">
<input type="hidden" name="article_id" value="<?php echo $article_id; ?>">
<div class="form">
  <div class="formrow">
    <div class="formdesc">Nadpis</div><div class="forminput"><input type="text" name="title" size="30" value="<?php echo $title; ?>" maxlength="150"></div>
  </div>
  <div class="formrow">
    <div class="formdesc">Text</div><div class="forminput"><textarea cols="20" rows="5" name="article_text"><?php echo $article_text; ?></textarea></div>
  </div>
  <div class="formrowsubmit">
    <input type="submit" name="send" value="Upravit" class="submit">
  </div>
</div>
</form>

Pokud byl formulář odeslán, zkontrolujeme, zda byly vyplněny oba údaje a zároveň je upravíme funkcí Text_Modify(). Podobně jako u mazání článku, musíme zkontrolovat, zda-li má přihlášený autor práva k danému článku. Následně provedeme aktualizaci údajů v databázi a vygenerujeme statické stránky.

// byl odeslan formular ?
if(IsSet($_POST['sent'])) {
  // uprava vstupu
  $title = Text_Modify($_POST['title']);
  $article_text = Text_Modify($_POST['article_text']);
  // byly vyplneny oba povinne udaje ?
  if($title=="" || $article_text =="") {
    $error = 4;
  }
  
  // vse je v poradku
  if(!IsSet($error)) {
    $query = @MySQL_Query("SELECT author FROM article WHERE id = $article_id") or Weblog_Error(2);  // autor clanku
    $result = MySQL_Fetch_Array($query);
    
    // ma prihlaseny autor prava k tomuto clanku ?
    if($result["author"] == $user_id || $user_type == "A") {
      $query = @MySQL_Query("UPDATE article SET title = '$title', message = '$article_text' WHERE id = $article_id") or Weblog_Error(2);
      $message = 3;
      
      $query = @MySQL_Query("SELECT archive_date FROM article WHERE id = $article_id") or Weblog_Error(2);  // tyden, ve kterem clanek vysel
      $result = MySQL_Fetch_Array($query);
  
      // vygeneruje staticke stranky
      require "archive.php";
      Create_Archive($result['archive_date']);
      Create_Index("static");
    } else {
      $message = 5;
    }
        
    MySQL_Close();
    Header('Location: http://'. $_SERVER['HTTP_HOST'] . '/weblog/admin/index.php?message=' . URLDecode($message) .'&' . SID);  // navrat na uvodni stranku
    exit;
  }
}

Úprava vstupních údajů

Doposud jsem již několikrát zmínil o funkci Text_Modify(), která provádí úpravu vstupních údajů tak, aby neposlušný uživatel nemohl narušit vzhled ani layout stránky, ale přitom mohl používat některé elementy a vkládat odkazy. Funkci tedy můžete použít v diskusních fórech, návštěvních knihách a podobně.

Postupně se odstraní mezery z obou konců řetězce, nebezpečné znaky se převedou na HTML entity, konce řádků na elementy <br />. S povolením některých elementů, především těch párových, je to o něco složitější. Aby uživatel mohl vložit například text "<em>kurziva <strong>tucna kurziva</strong></em> normal <em>kurziva</em>" a dosáhl požadovaného výsledku "kurziva tucna kurziva normal kurziva", musíme použít regulární výraz podle normy Perl, kde sekvence znaků .*? zajistí, že se funkce zastaví hned u prvního výskytu "</em>". Při použití klasických regulárních výrazů a funkce EregI_Replace() bychom tohoto efektu nedosáhli a v kurzívě by byl celý řetězec. Důležité jsou ještě znaky si, které zajistí to, že funkce nebere ohled na nové řádky a malá a velká písmena. Další podrobnosti týkající se tohoto druhu regulárních výrazů najdete v manuálu PHP. S nepárovými elementy je to o poznání jednodušší, takže můžeme použít známou funkci EregI_Replace().

Dalším problémem jsou dlouhá slova, která dokáží "velmi dobře" narušit vzhled celé stránky. PHP nám sice nabízí funkci Wordwrap(), ale chceme-li uživatelům umožnit vkládání odkazů, které jsou velmi často delší než únosná hranice, musíme použít trošku složitější postup. Celý text nejprve rozdělíme na jednotlivá slova, poté jimi postupně procházíme a testujeme, zda odpovídají tvaru odkazu. Pokud ano, pak obsah elementu <a> rozdělíme, ale parametr href ponecháme nerozdělený. Pokud slovo není odkazem, rozdělíme ho a jednotlivá slova spojíme dohromady.

function Text_Modify($text) {
  $text = Trim($text);  // odstrani mezery z obou koncu retezce
  $text = HTMLSpecialChars($text, ENT_QUOTES);  // prevede nebezpecne znaky
  // nahradi konce radku na tagy <br />
  $text = Str_Replace("\r\n"," <br /> ", $text);
  $text = Str_Replace("\n"," <br /> ", $text);
  
  // umozni vkladat nektere parove tagy
  $tags = Array("b", "u", "i", "small", "big", "strong", "em");
  while(Current($tags)) {
    $tag = Current($tags);
    $text = Preg_Replace('\'<' . $tag . '>(.*?)</' . $tag . '>\''. "si", ' <' . $tag . '>\\1</' . $tag . '> ', $text);
    Next($tags);
  }
  
  // umozni vkladat nektere neparove tagy
  $tags2 = Array("br", "hr");
  while(Current($tags2)) {
    $text = EregI_replace("<" . Current($tags2) . "( /)?>", "<" . Current($tags2) . " />", $text);
    Next($tags2);
  }
  
  $words = Split("[[:blank:]]+", Trim($text));    //rozdeleni textu na slova
  $connect_text = '';
  while(Current($words)) {
    $word = Trim(Current($words));  //odstraneni mezer na konci slova
    if(EregI("http://[^ ]+\.[^< ]+", $word, $part)) {
      $word = Str_Replace($part[0], '<a href="' . $part[0] . '">' . Wordwrap($part[0], 25, " ", 1) . '</a>', $word);
    } elseif(EregI('www\.[^ ]+\.[^< ]+', $word, $part)) {
      $word = Str_Replace($part[0], '<a href="http://' . $part[0] . '">' . Wordwrap($part[0], 25, " ", 1) . '</a>', $word);
    } else {
      $word = Wordwrap($word, 25, " ", 1);
    }
    $connect_text .= $word . " ";
    Next($words);
  }
  return Trim($connect_text);
}

Abychom uživatelům zajistili komfortní úpravu napsaných článků, zpracujeme údaje modifikované funkcí Text_Modify() opačnou funkcí un_Text_Modify. První tři řádky této funkce, které jsou vlastně opakem k funkci HTMLSpecialChars() můžeme klidně vypustit. Entity i původní znaky se totiž ve formuláři zobrazí identicky. V další části pak elementy <br /> nahradíme řádky a elementy <a> pouze vlastními odkazy.

function un_Text_Modify($text) {
  $trans_tbl = Get_HTML_Translation_Table(HTML_SPECIALCHARS);
  $trans_tbl = Array_Flip($trans_tbl);
  $text = StrTr($text, $trans_tbl);
  $text = EregI_Replace(" <br /> ","\n", $text);
  $text = EregI_Replace('<a href="([^"]+)">[^<]+</a>', "\\1", $text);
  return $text;
}

Instalace weblogu

  1. Stažení - aplikační balík
  2. Vytvoření databáze – například pomocí příkazu mysqladmin create weblog
  3. Nastavení databáze – upravte soubor db.php
  4. Vytvoření databázových tabulek – pomocí příkazu mysql weblog spusťte klienta, v něm zapište příkaz \. vase_cesta\weblog.sql; (např. \. c:\lokal\weblog\weblog.sql;), můžete však použít i phpMyAdmin
  5. Administrátor – administrátora můžete vytvořit buď přímo v souboru weblog.sql, kde do příslušného SQL příkazu vložíte dané údaje nebo úpravou daného záznamu v tabulce author tak, že do položky user_type vložíte "A"

Případnou kritiku či náměty na vylepšení weblogu pište, prosím, do diskuse pod článkem.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.


Další aktuální články na interval.cz

Tematicky související články

Dejte vědět i ostatním o článku

Komentáře ke článku

Přidat nový komentář

masterpawn

Autor komentáře: masterpawn

Datum vložení: 18. Srpen 2009, 15:13:13

co s tím je pokažde když chci přidat nějaký článek tak mi to napíše: Nastala chyba při generování statické stránky.

denis

Autor komentáře: denis

Datum vložení: 05. Březen 2010, 14:18:27

no me to vubec nejede. pokazde prazdna obrazovka. zkousel jsem do index.php na zacatku napsat obycejne Ahoj a ani to se mi nezobrazi. co s tim? to budu muset projit cely kod? hruza... :o$

Vojta

Autor komentáře: Vojta

Datum vložení: 10. Prosinec 2010, 19:24:24

Mám stejný problém jako denis a masterpawn.. Po přidání článku nelze vygenerovat statickou stránku.. :(

Zpět na začátek komentářů | Zpět na začátek článku

Přidat nový komentář

Jméno a e-mail jsou nepovinné. Příspěvky obsahující odkaz jsou moderovány.

Zoner AntiVirus Free pro Android
zabezpečte si svůj smartphone, zdarma
Profesionální eshop Zoner inShop od 990 Kč.
Zoner Photo Studio 14 – vyzkoušejte ZDARMA
Reklama
Reklama
Zoner Photo Studio 14

Syndikace

hledáme nové autory | redakce interval.cz | reklama na interval.cz

© ZONER software, a.s., všechna práva vyhrazena, interval.cz dodržuje právní předpisy o ochraně osobních údajů. Powered by WordPress.