1) estructura de grafo, o en su defecto, de árbol. No es para un blog cronológico sino que el contenido se relaciona internamente como un arbol jerarquizado de relaciones.
2) soporte multilenguaje y, preferiblemente, multiformato (p. ej. pueda mostrarse como html, texto plano, o PDF)
3) facilidad del administrador de editar contenidos en línea.
4) principios de SEO
5) extendible con plantillas.
6) extendible con plugins.
7) facilidades para interactuar (básicamente enviar comentarios).
integración con acortador personalizado.
Supongo que en gran medida estaré reinventando la rueda pero, por el momento, ni los CMS que he visto se adaptan a lo que quiero, pero, principalmente, porque es un ejercicio académico.
Comparto, por ahora, el código básico de lo que tengo:
Código PHP :
<?php # a couple of global variables: $sitename = "My Site"; $shortsite = "sho.rt"; # mod_rewrite should give any of the following # name short and unique name for the content (note that multilanguage content might have different or same name for each language) # lang indicated language. If missing, deduce by `name`, user prefered language, site prefered language (in that order) # seo SEO name for the content - not really important for locate the content. # type content type, i.e. txt, html, odf, pdf include 'lib/db.php'; include 'lib/langs.php'; $db = new database('localhost','root','','mydb'); $name = mysql_real_escape_string(mb_strtolower($_GET['name'])); $lang = mysql_real_escape_string(mb_strtolower($_GET['lang'])); $seo = mysql_real_escape_string(mb_strtolower($_GET['seo'])); $type = mysql_real_escape_string(mb_strtolower($_GET['type'])); if(!$type) $type="html"; $action = mb_strtolower($_GET['action']); # PROCEDURE # Locate `name` $tdi = $db->query("SELECT * FROM `nameid` WHERE `name`='$name'") or die("404 - documento inexistente $name"); # Locate `docid` $docid = $tdi[0]['docid']; $dlang = $tdi[0]['deflang']; $tsc = $db->query("SELECT * FROM `idname` WHERE `docid`='$docid'",'lang') or die("500 - database mismatch"); # Get requested language or, otherwise, guess best existing language if (!$lang) $lang=$dlang ? $dlang : 'en'; if (array_key_exists($lang,$tsc)) { $tnod = $tsc[$lang]; } elseif(array_key_exists('',$tsc)) { $tnod = $tsc['']; } elseif(array_key_exists($dlang,$tsc)) { $tnod = $tsc[$dlang]; } else foreach(array('en','es','sv','xb','xc','xi','xt') as $ll) { if (array_key_exists($ll,$tsc)) { $dlang = $ll; $tnod = $tsc[$ll]; break; } } $dseo = $tnod['seo']; # Construct canonical URL $url = $tnod['name'] ? "/".$tnod['name'] : ""; if ($lang!=$dlang) $url .= "/".$lang; if ($dseo) $url .= "/".$tnod['seo'].".".$type; elseif($type!='html') $url .= "/.".$type; else $url .= "/"; # Get Requested URI to compare with Canonical URL $ruri = $_SERVER['REQUEST_URI']; if (($i=strpos($ruri,'?'))!==false) $ruri = substr($ruri,0,$i); # Get any other GET request that should not be mangled by mod_rewrite $urla=array(); foreach($_GET as $key=>$val) if (!in_array($key,array('name','lang','seo','type'))) $urla[] = urlencode($key)."=".urlencode($val); $urla = implode('&',$urla); # NOW We explore some actions. # Action commit is the result of an update if ($action=='commit') { # Incoming data as POST: # title -> should go to content db # name -> should go to idname and nameid dbs after checking inconsistencies # seo -> should go to idname db # content -> should go to content db $newtitle = mysql_real_escape_string($_POST['title']); $newname = mysql_real_escape_string(mb_strtolower($_POST['name'])); $newseo = mysql_real_escape_string(mb_strtolower($_POST['seo'])); $newcont = mysql_real_escape_string($_POST['content']); $db->commit("UPDATE `content` SET `title`='$newtitle', `content`='$newcont' WHERE `docid`=$docid AND `lang`='$lang';"); } # Any action but edit should redirect to canonical URL if ($action!='edit') { if ($url != $ruri) { if($urla) $url .= "?" . $urla; header( "HTTP/1.1 301 Moved Permanently" ); // header( "HTTP/1.1 307 Temporary Redirect" ); header( "Location: http://org.local$url" ); } } # So, now we are either in a redirected page, or an edition page. # We get the content from the content DB. $tco = $db->query("SELECT * FROM `content` WHERE `docid`='$docid';",'lang'); $title = $tco[$lang]['title']; $content = $tco[$lang]['content']; $headtit = $title? $title." | $sitename" : "$sitename"; $baseurl = "http://".$_SERVER['SERVER_NAME']; $shorturl = "http://$shortsite/".$tnod['shortest']; ?> <!DOCTYPE html> <html lang="<?php echo $langs[$lang]['full']?>"> <head> <base href="<?php echo $baseurl?>/"/> <meta charset="utf-8"> <title><?php echo $headtit?></title> <link rel="alternate" href="<?php echo $shorturl?>"/> <link rel="canonical" href="<?php echo $baseurl.$url?>"/> </head> <body> <h1><?php echo $title ? $title : $sitename?></h1> <?php if($action=='edit') { ?> <form method="post" action="?name=<?php echo $name?>&lang=<?php echo $lang?>&action=commit"><table> <tr><td>Title</td><td><input name="title" value="<?php echo $title?>"/></td></tr> <tr><td>URL</td><td><?php echo $baseurl?>/<input name="name" value="<?php echo $tnod['name']?>"/>/<input name="seo" value="<?php echo $tnod['seo']?>"/>.html</td></tr> <tr><td colspan="2"><textarea name="content"><?php echo $content ?></textarea></td></tr> <tr><td colspan="2"><input type="submit"/></td></tr> </table></form> <?php } else { ?> <div><?php echo $content ?></div> <div><a href="/?name=<?php echo $name?>&lang=<?php echo $lang?>&action=edit">edit</a></div> <?php } ?> </body> </html>
recibo cualquier crítica despiadada sobre mis ideas y sobre mi código, entendiendo que por ahora es una prueba de concepto y que sé que carece de elementos de usabilidad, seguridad, robustez, etc.