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.


Reklama


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č.
Reklama
Reklama

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.