Files
yavsc/NpgsqlBlogProvider/NpgsqlBlogProvider.cs
Paul Schneider d999ae5a8e Thème clair opé, WIP circles
* animate.css: animations css

* links.css: liens avec le fond blanc qui se déroule

* links.css: WIP liens thème sombre

* GitHub.ico: un petit merci à GitHub

* live-concert-fg.png: image de plan rapproché : les fans

* live-concert-scene.jpg: Image de fond : la scene

* splash-image-2.jpg: image de fond : photo colorée, public de
  concert, vient de totemproduction.fr

* links.css: ficher de définitions globales du style des bouttons
  (encore inutilisé)

* yavsc.user.js: WIP implémente le widget "utilisateur", permettant
l'affichage des liens rapides pour tout nom d'ulitisateur, le cas
  échéant, vers l'ajout à un cercle,
vers son blog, vers des methodes choisies d'administateur, vers ses
  réseaux sociaux, voir plus.

* About.aspx: Implémente une page "à propos"

* Test.aspx: Page de test: désolé pour le bruit, elle n'est compilée
  qu'en mode `Debug` (elle n'est pas accessible en production)

* NpgsqlBlogProvider.cs: Corrige la méthode pour enlever un tag à un
  article ...

* NpgsqlBlogProvider.csproj: .

* NpgsqlCircleProvider.cs: liste les cercles auquels appartient un
  utilisateur.

* BasketController.cs:
* NpgsqlContentProvider.cs: Les commandes sont fortement typée.

* README.md: mise à jour des priorités

* style.css: réécriture du thème clair

* style.css: * implémente un classe css `clickme` pour attirer l'oeil
sur le boutton de validation après la modification d'un champ de
  formulaire.
* enlève tous les coins arrondis
* modifie la chasse de caractères (une seule utilisée pour le moment)
*

* style.css: * integre la référence à la feuille de style des
  [animations](https://daneden.github.io/animate.css/)
* corrige des marges, alignements
* supprime ce qui reste de coin arrondi
* néttoye les définitions obsolètes
* définit la classe `username`
* corrige le survol à la suppression de tag

* FrontOfficeController.cs: renomme des methodes, refabriqué pour
  s'adapter aux changements de l'API du workflow,
WIP propose les cercles utilisateurs pour l'ajout des profiles
  préstataires aux cercles.

* HomeController.cs: implémente une page "à propos"

* T.cs: re-autorise le titre vide de page, au cas où ... car ce n'est
  pas un véritable
défaut fonctionnel.

* YavscHelpers.cs: Implemente un outil de presentation des liens
  action traduits. Tous les liens action utilisent maintenant cette
  nouvelle methode,
au profile de celle du framework `HtmlHelpers.ActionLink`

* App.master: corrige l'usage du contrôle utilisateur des cotes dans
  le cadre des cotes de billet.

* AppAdmin.master:
* Index.aspx:
* Service.aspx:
* ProductCategory.aspx: traduction des liens action

* NoLogin.master: * traduction des liens action
* suppression des liens de remerciement dans le bas de page, cette
  information a été déplacée dans la page `/Home/Credits`

* to-markdown.js: transforme maintenant les noeuds Html `div` en
  paragraphes Markdown.

* yavsc.hidefieldset.js: Le script règle la forme de la souris au
  survol du bouton,
le cas échéant.

* yavsc.js: nouvelle fonction javascript pour logger un objet
  arbitraire.

* yavsc.rate.js: Fixe la possibilité de mettre des cotes très basses
  ou très hautes (reste encore un mieux à faire),
Affiche au survol des descriptions optionnelles de la cote.

* Title.aspx:
* UserPost.aspx:
* Edit.aspx:
* Index.aspx:
* Brand.aspx:
* Index.aspx:
* PostActions.ascx:
* TitleNotFound.aspx:
* Booking.aspx:
* Command.aspx:
* ChangePasswordSuccess.aspx: Traduction des liens action

* Login.aspx: * Traduction des liens actionTraduction des liens action

* Profile.aspx: * Traduction des liens actionTraduction des liens
  action
* utilisation de la classe css `mayhide` qui autorise maintenant un
  champ d'entrées de formulaire à être plié/déplié au click sur sa
  légende.

* Admin.aspx: Traduction des liens actionTraduction des liens
  actionTraduction des liens actionTraduction des liens
  actionTraduction des liens actionTraduction des liens action

* Backups.aspx:
* RoleList.aspx:
* UserList.aspx:
* Index.aspx: Traduction des liens actionTraduction des liens action

* Edit.aspx: * refabrication de la structure Html
* Traduction des liens actionTraduction des liens action

* Index.aspx: Simlpification des apperçus de blog

* TagControl.ascx: refabrication pour simplifier l'implémentation du
  contrôle utilisateur des tags

* UserPosts.aspx: Traduction des liens action, et simplification du
  listing de blog

* Basket.aspx: Affiche les articles du panier de commandes avec leur
  vue
dédiée à leur type (les commande sont maintenant fortement typées)

* Catalog.aspx: Traduction des liens action, correctin du lien vers le
  produit
(cassé depuis une vielle refabrication des routes)

* DoAnEstimate.aspx: refabrication de la vue de création du devis:
  renommée depuis `Estimate`

* Performer.ascx: * un message supplementaire à l'absence de
  compétence affichée par un préstataire
* des guillemets autour du commentaire du préstataire sur sa
  compétence
* ajout du préstataire au cercles

* Performers.aspx: Décrit en détail les informations sur la
  disponibilité d'un préstataire,
à la date demandée.

* YourEstimates.aspx: renomage de cette page, pour préciser sa
  fonction : Vos devis.

* Contact.aspx: structure Html de la page de contact

* Credits.aspx: Ajoute les remerciements aux communauté du libre

* Index.aspx: ne fait rien

* Web.config: * import de `System.Transactions`
* mise à jour des credits libres

* WebDeploy.targets: utilise les séparateurs de chemin vers ficher à
  la POSIX, ne change rien pour ma config ... (TODO tester sous
  WoinDose)

* Yavsc.csproj: déploie des pages des scripts Javascript et des images
  et feuilles de style en plus.

* CircleManager.cs: implémente les methodes utilisées à la
  construction du contrôle utilisateur.

* CircleProvider.cs: * doc xml
* extension de interface

* Commande.cs: l'objet `Command` devient abstrait, pour exister (être
  instanciée), une commande doit maintenant hériter de cet objet
  abstrait.

* LocalizedText.resx:
* LocalizedText.fr.resx:
* LocalizedText.Designer.cs:
* LocalizedText.fr.Designer.cs: traductions

* IContentProvider.cs: doc xml

* SiteSkills.aspx: renomage de cette page, pour préciser sa fonction :
  les compétences sur ce site.
2015-12-09 13:26:02 +01:00

837 lines
28 KiB
C#

using System;
using System.Configuration;
using System.Configuration.Provider;
using Npgsql;
using System.Collections.Generic;
using Yavsc.Model.Blogs;
using Yavsc.Model.Circles;
using NpgsqlTypes;
using System.Linq;
namespace Npgsql.Web.Blog
{
/// <summary>
/// Npgsql blog provider.
/// </summary>
public class NpgsqlBlogProvider : BlogProvider
{
string applicationName;
string connectionString;
#region implemented abstract members of BlogProvider
/// <summary>
/// Gets the public post count.
/// </summary>
/// <returns>The public post count.</returns>
/// <param name="bloggerName">Blogger name.</param>
public override long GetPublicPostCount (string bloggerName)
{
long result = -1;
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = @"
Select count(*)
FROM blog b
LEFT OUTER JOIN blog_access a ON a.post_id = b._id
WHERE a.post_id IS NULL
AND b.visible = TRUE
AND b.username = :bname
AND b.applicationname = :app
";
cmd.Parameters.AddWithValue ("bname", bloggerName);
cmd.Parameters.AddWithValue ("app", applicationName);
cnx.Open ();
result = (long) cmd.ExecuteScalar ();
cnx.Close ();
}
return result;
}
/// <summary>
/// Updates the post.
/// </summary>
/// <param name="be">Be.</param>
public override void UpdatePost (BlogEntry be)
{
// TODO Tags and rate should not be ignored
UpdatePost (be.Id, be.Title, be.Content, be.Visible, be.AllowedCircles);
}
/// <summary>
/// Note the specified postid and note.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="rate">rate.</param>
public override void Rate (long postid, int rate)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "update blog set rate = :rate where _id = :pid";
cmd.Parameters.AddWithValue ("rate", rate);
cmd.Parameters.AddWithValue ("pid", postid);
cnx.Open ();
cmd.ExecuteNonQuery ();
cnx.Close ();
}
}
/// <summary>
/// Tag the specified post by identifier
/// using the given tag.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="tagname">Tag name.</param>
public override long Tag (long postid, string tagname)
{
long tid = GetOrCreateTagId (tagname);
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "INSERT INTO tagged (tagid,postid) VALUES (:tid,:pid)";
cmd.Parameters.AddWithValue ("tid", tid);
cmd.Parameters.AddWithValue ("pid", postid);
cnx.Open ();
cmd.ExecuteNonQuery ();
return tid;
}
}
/// <summary>
/// Uns the tag.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="tagid">Tagid.</param>
/// <param name="name">Name.</param>
override public void Untag (long postid, string name)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "DELETE FROM tagged WHERE tagged.postid = :pid AND tagged.tagid = (select tag._id FROM tag WHERE tag.name = :tnm)";
cmd.Parameters.AddWithValue ("pid", postid);
cmd.Parameters.AddWithValue ("tnm", name);
cnx.Open ();
cmd.ExecuteNonQuery ();
}
}
/// <summary>
/// Uns the tag.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="tagid">Tagid.</param>
/// <param name="tid">Tid.</param>
override public void Untag (long postid, long tid)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "DELETE FROM tagged WHERE postid = :pid AND tagid = :tid";
cmd.Parameters.AddWithValue ("pid", postid);
cmd.Parameters.AddWithValue ("tid", tid);
cnx.Open ();
cmd.ExecuteNonQuery ();
}
}
/// <summary>
/// Gets the comments.
/// </summary>
/// <returns>The comments.</returns>
/// <param name="postid">Postid.</param>
/// <param name="getHidden">If set to <c>true</c> get hidden.</param>
public override Comment[] GetComments (long postid, bool getHidden)
{
List<Comment> cmts = new List<Comment> ();
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "select _id, username, bcontent, modified, posted, visible from comment " +
"where applicationname = :appname and postid = :id" +
((getHidden) ? " and visible = true " : " ") +
"order by posted asc";
cmd.Parameters.AddWithValue ("appname", applicationName);
cmd.Parameters.AddWithValue ("id", postid);
cnx.Open ();
using (NpgsqlDataReader rdr = cmd.ExecuteReader ()) {
while (rdr.Read ()) {
Comment c = new Comment ();
c.CommentText = rdr.GetString (rdr.GetOrdinal ("bcontent"));
c.From = rdr.GetString (rdr.GetOrdinal ("username"));
c.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified"));
c.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted"));
c.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible"));
c.PostId = postid;
c.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id"));
cmts.Add (c);
}
}
}
return cmts.ToArray ();
}
/// <summary>
/// Updates the post.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="title">Title.</param>
/// <param name="content">Content.</param>
/// <param name="visible">If set to <c>true</c> visible.</param>
/// <param name="cids">Circle identifiers</param>
public override void UpdatePost (long postid, string title, string content,
bool visible, long[] cids)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) {
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
DateTime now = DateTime.Now;
cmd.CommandText =
"update blog set modified=:now," +
" title = :title," +
" bcontent = :content, " +
" visible = :visible " +
"where _id = :id";
cmd.Parameters.AddWithValue ("now", now);
cmd.Parameters.AddWithValue ("title", title);
if (content == null)
content = "";
cmd.Parameters.AddWithValue ("content", content);
cmd.Parameters.AddWithValue ("visible", visible);
cmd.Parameters.AddWithValue ("id", postid);
cnx.Open ();
cmd.ExecuteNonQuery ();
}
cnx.Close ();
}
if (cids != null) UpdatePostCircles (postid, cids);
}
/// <summary>
/// Removes the post.
/// </summary>
/// <param name="postid">Postid.</param>
public override void RemovePost (long postid)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "delete from blog where _id = :id";
cmd.Parameters.AddWithValue ("id", postid);
cnx.Open ();
cmd.ExecuteNonQuery ();
}
}
/// <summary>
/// Comment the specified from, postid and content.
/// </summary>
/// <param name="from">From.</param>
/// <param name="postid">Postid.</param>
/// <param name="content">Content.</param>
public override long Comment (string from, long postid, string content)
{
if (from == null)
throw new ArgumentNullException ("from");
if (content == null)
throw new ArgumentNullException ("content");
bool visible = AutoValidatesComments;
using (NpgsqlConnection cnx =
new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "insert into comment (postid,bcontent," +
"modified,posted,visible,username,applicationname)" +
"values (:postid,:bcontent,:modified,:posted," +
":visible,:username,:appname) returning _id";
cmd.Parameters.AddWithValue ("postid", postid);
cmd.Parameters.AddWithValue ("bcontent", content);
DateTime now = DateTime.Now;
cmd.Parameters.AddWithValue ("modified", now);
cmd.Parameters.AddWithValue ("posted", now);
cmd.Parameters.AddWithValue ("visible", visible);
cmd.Parameters.AddWithValue ("username", from);
cmd.Parameters.AddWithValue ("appname", applicationName);
cnx.Open ();
return (long)cmd.ExecuteScalar ();
}
}
/// <summary>
/// Validates the comment.
/// </summary>
/// <param name="cmtid">Cmtid.</param>
public override void ValidateComment (long cmtid)
{
throw new NotImplementedException ();
}
/// <summary>
/// Updates the comment.
/// </summary>
/// <param name="cmtid">Cmtid.</param>
/// <param name="content">Content.</param>
/// <param name="visible">If set to <c>true</c> visible.</param>
public override void UpdateComment
(long cmtid, string content, bool visible)
{
throw new NotImplementedException ();
}
private bool autoValidateComment = true;
/// <summary>
/// Gets or sets a value indicating whether this <see cref="Npgsql.Web.Blog.NpgsqlBlogProvider"/> auto validate comment.
/// </summary>
/// <value><c>true</c> if auto validate comment; otherwise, <c>false</c>.</value>
public override bool AutoValidatesComments {
get {
return autoValidateComment;
}
set {
autoValidateComment = value;
}
}
/// <summary>
/// Blogs the title.
/// </summary>
/// <returns>The title.</returns>
/// <param name="username">Username.</param>
public override string BlogTitle
(string username)
{
throw new NotImplementedException ();
}
#endregion
/// <summary>
/// Initialize the specified name and config.
/// </summary>
/// <param name="name">Name.</param>
/// <param name="config">Config.</param>
public override void Initialize
(string name, System.Collections.Specialized.NameValueCollection config)
{
string cnxName = config ["connectionStringName"];
connectionString = ConfigurationManager.ConnectionStrings [cnxName].ConnectionString;
config.Remove ("connectionStringName");
applicationName = config ["applicationName"];
config.Remove ("applicationName");
defaultPageSize = int.Parse (config ["pageLen"] ?? "10");
base.Initialize (name, config);
}
#region implemented abstract members of BlogProvider
/// <summary>
/// Gets the post.
/// </summary>
/// <returns>The post.</returns>
/// <param name="postid">Postid.</param>
public override BlogEntry GetPost (long postid)
{
BlogEntry be = null;
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "select username, title, bcontent, modified, " +
"posted, visible, photo, rate from blog " +
"where applicationname = :appname and _id = :id";
cmd.Parameters.AddWithValue ("appname", applicationName);
cmd.Parameters.AddWithValue ("id", postid);
cnx.Open ();
using (NpgsqlDataReader rdr = cmd.ExecuteReader ()) {
if (rdr.Read ()) {
be = new BlogEntry ();
be.Title = rdr.GetString (rdr.GetOrdinal ("title"));
be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent"));
be.Author = rdr.GetString (rdr.GetOrdinal ("username"));
be.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified"));
be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted"));
be.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible"));
be.Rate = rdr.GetInt32 (rdr.GetOrdinal ("rate"));
int oph = rdr.GetOrdinal ("photo");
if (!rdr.IsDBNull (oph))
be.Photo = rdr.GetString (oph);
be.Id = postid;
}
}
}
if (be != null)
Populate (be);
return be;
}
/// <summary>
/// Removes the comment.
/// </summary>
/// <returns>The comment.</returns>
/// <param name="cmtid">Cmtid.</param>
public override long RemoveComment (long cmtid)
{
long postid = 0;
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "delete from comment where _id = :id returning postid";
cmd.Parameters.AddWithValue ("id", cmtid);
cnx.Open ();
postid = (long)cmd.ExecuteScalar ();
}
return postid;
}
/// <summary>
/// Gets the post.
/// </summary>
/// <returns>The post.</returns>
/// <param name="username">Username.</param>
/// <param name="title">Title.</param>
public override UUTBlogEntryCollection GetPost (string username, string title)
{
UUTBlogEntryCollection bec = new UUTBlogEntryCollection (username, title);
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) {
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "select _id,bcontent,modified,posted,visible,photo,rate from blog " +
"where applicationname = :appname and username = :username and title = :title order by rate desc";
cmd.Parameters.AddWithValue ("appname", NpgsqlDbType.Varchar, applicationName);
cmd.Parameters.AddWithValue ("username", NpgsqlDbType.Varchar, username);
cmd.Parameters.AddWithValue ("title", NpgsqlDbType.Varchar, title);
cnx.Open ();
cmd.Prepare ();
using (NpgsqlDataReader rdr = cmd.ExecuteReader ()) {
while (rdr.Read ()) {
BlogEntry be = new BlogEntry ();
be.Title = title;
be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent"));
be.Author = username;
be.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified"));
be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted"));
be.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible"));
be.Rate = rdr.GetInt32 (rdr.GetOrdinal ("rate"));
be.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id"));
{
int oph = rdr.GetOrdinal ("photo");
if (!rdr.IsDBNull (oph))
be.Photo = rdr.GetString (oph);
}
bec.Add (be);
}
rdr.Close ();
}
}
if (bec.Count != 0) {
Populate (bec);
}
}
return bec;
}
private void SetCirclesOn (BasePost be)
{
List<long> circles = new List<long> ();
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmdcircles = cnx.CreateCommand ()) {
cmdcircles.CommandText = "select a.circle_id from blog_access a " +
"where a.post_id = :pid";
cmdcircles.Parameters.AddWithValue ("pid", be.Id);
cnx.Open ();
using (NpgsqlDataReader rdr = cmdcircles.ExecuteReader ()) {
while (rdr.Read ()) {
circles.Add (rdr.GetInt64 (0));
}
}
}
be.AllowedCircles = circles.ToArray ();
}
/// <summary>
/// Removes the tag.
/// </summary>
/// <param name="tagid">Tagid.</param>
public override void DropTag (long tagid)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "DELETE from public.tag where _id = :tid";
cmd.Parameters.AddWithValue ("tagid", tagid);
cnx.Open ();
cmd.ExecuteNonQuery ();
cnx.Close ();
}
}
private static string SelectTagsSql = "SELECT tag.name, tag._id FROM public.tag WHERE name like :name";
private IEnumerable<string> GetSuggestion (string pattern)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = SelectTagsSql;
throw new NotImplementedException ();
}
}
private static string InsertTagSql = "INSERT INTO tag (name) VALUES (:name) returning _id";
private void InsertTag (long postid, long tagid)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = InsertTagSql;
throw new NotImplementedException ();
}
}
private long GetTagId (string tagname)
{
// FIXME null pointer at cmd.ExecuteScalar!
if (tagname == null)
throw new NullReferenceException ("This tag name is null");
long id = 0;
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) {
cnx.Open ();
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "SELECT _id FROM tag WHERE name LIKE :tn";
cmd.Parameters.AddWithValue ("tn",NpgsqlDbType.Varchar, tagname);
id = (long) cmd.ExecuteScalar ();
}
cnx.Close ();
}
return id;
}
private long GetOrCreateTagId (string tagname)
{
if (tagname == null)
throw new NullReferenceException ("This tag name is null");
long id = 0;
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) {
try {
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "SELECT tag._id FROM public.tag WHERE name = :name";
cmd.Parameters.AddWithValue ("name", tagname);
cnx.Open ();
id = (long)cmd.ExecuteScalar ();
}
} catch (NullReferenceException) {
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "INSERT INTO public.tag(name) VALUES (:name) RETURNING _id";
cmd.Parameters.AddWithValue ("name", tagname);
id = (long)cmd.ExecuteScalar ();
}
}
}
return id;
}
private static string SelectPostTagsSql = "SELECT tag.name FROM public.tag, public.tagged\n" +
"WHERE tag._id = tagged.tagid AND tagged.postid = :pid \n";
private void SetTagsOn (BlogEntryCollection bec)
{
foreach (BlogEntry be in bec) {
SetTagsOn (be);
}
}
private void SetTagsOn (BasePost be)
{
List<string> tags = new List<string> ();
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmdtags = cnx.CreateCommand ()) {
cmdtags.CommandText = SelectPostTagsSql;
cmdtags.Parameters.AddWithValue ("pid", be.Id);
cnx.Open ();
using (NpgsqlDataReader rdr = cmdtags.ExecuteReader ()) {
while (rdr.Read ()) {
tags.Add (rdr.GetString (0));
}
}
}
be.Tags = tags.ToArray ();
}
// Assert(bec!=null);
private void Populate (BlogEntryCollection bec)
{
foreach (BlogEntry be in bec)
Populate (be);
}
private void Populate (BasePost be)
{
SetTagsOn (be);
SetCirclesOn (be);
}
/// <summary>
/// Post the specified username, title, content and visible.
/// </summary>
/// <param name="username">Username.</param>
/// <param name="title">Title.</param>
/// <param name="content">Content.</param>
/// <param name="visible">If set to <c>true</c> visible.</param>
/// <param name="circles">.</param>
public override long Post (string username, string title, string content, bool visible, long[] circles)
{
long pid = 0;
if (username == null)
throw new ArgumentNullException ("username");
if (title == null)
throw new ArgumentNullException ("title");
if (content == null)
content = "";
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) {
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "insert into blog (title,bcontent,modified,posted,visible,username,applicationname)" +
"values (:title,:bcontent,:modified,:posted,:visible,:username,:appname) returning _id";
cmd.Parameters.AddWithValue ("title", title);
cmd.Parameters.AddWithValue ("bcontent", content);
DateTime now = DateTime.Now;
cmd.Parameters.AddWithValue ("modified", now);
cmd.Parameters.AddWithValue ("posted", now);
cmd.Parameters.AddWithValue ("visible", visible);
cmd.Parameters.AddWithValue ("username", username);
cmd.Parameters.AddWithValue ("appname", applicationName);
cnx.Open ();
pid = (long)cmd.ExecuteScalar ();
}
cnx.Close ();
}
if (circles != null)
UpdatePostCircles (pid, circles);
return pid;
}
/// <summary>
/// Updates the post photo.
/// </summary>
/// <param name="pid">Pid.</param>
/// <param name="photo">Photo.</param>
public override void UpdatePostPhoto (long pid, string photo)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) {
cnx.Open ();
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
if (photo == null)
cmd.CommandText = "update blog set photo = NULL where _id = :pid";
else {
cmd.CommandText = "update blog set photo = :photo where _id = :pid";
cmd.Parameters.AddWithValue ("photo", photo);
}
cmd.Parameters.AddWithValue ("pid", pid);
cmd.ExecuteNonQuery ();
}
cnx.Close ();
}
}
private void UpdatePostCircles (long pid, long[] circles)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) {
cnx.Open ();
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "delete from blog_access where post_id = :pid";
cmd.Parameters.AddWithValue ("pid", pid);
cmd.ExecuteNonQuery ();
}
if (circles != null)
if (circles.Length > 0)
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "insert into blog_access (post_id,circle_id) values (:pid,:cid)";
cmd.Parameters.AddWithValue ("pid", NpgsqlTypes.NpgsqlDbType.Bigint, pid);
cmd.Parameters.Add ("cid", NpgsqlTypes.NpgsqlDbType.Bigint);
cmd.Prepare ();
foreach (long ci in circles) {
cmd.Parameters ["cid"].Value = ci;
cmd.ExecuteNonQuery ();
}
}
cnx.Close ();
}
}
/// <summary>
/// Finds the post.
/// </summary>
/// <returns>The post.</returns>
/// <param name="readersName">Reader's Name.</param>
/// <param name="pattern">Pattern.</param>
/// <param name="searchflags">Searchflags.</param>
/// <param name="pageIndex">Page index.</param>
/// <param name="pageSize">Page size.</param>
/// <param name="totalRecords">Total records.</param>
public override BlogEntryCollection FindPost (string readersName, string pattern, FindBlogEntryFlags searchflags, int pageIndex, int pageSize, out int totalRecords)
{
BlogEntryCollection c = new BlogEntryCollection ();
totalRecords = 0;
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
if (readersName != null) {
cmd.CommandText = "select _id, title,bcontent, modified," +
"posted,username,visible,photo,rate " +
"from blog b left outer join " +
"(select count(*)>0 acc, a.post_id pid " +
"from blog_access a," +
" circle_members m, users u where m.circle_id = a.circle_id " +
" and m.member = u.username and u.username = :uname " +
" and u.applicationname = :appname " +
" group by a.post_id) ma on (ma.pid = b._id) " +
"where ( ((ma.acc IS NULL or ma.acc = TRUE) and b.Visible IS TRUE ) or b.username = :uname) ";
cmd.Parameters.AddWithValue ("uname", readersName);
} else {
cmd.CommandText = "select _id, title,bcontent,modified," +
"posted,username,visible,photo,rate " +
"from blog b left outer join " +
"(select count(*)>0 acc, a.post_id pid " +
"from blog_access a" +
" group by a.post_id) ma on (ma.pid = b._id)" +
" where " +
" ( ma.acc IS NULL and " +
" b.Visible IS TRUE and " +
" applicationname = :appname ) ";
}
cmd.Parameters.AddWithValue ("appname", applicationName);
if (pattern != null) {
if ((searchflags & FindBlogEntryFlags.MatchTag) > 0) {
cmd.CommandText +=
" AND EXISTS (SELECT tag._id FROM tag, tagged \n" +
" WHERE tag._id = tagged.tagid \n" +
" AND tagged.postid = b._id \n" +
" AND tag.name like :tagname) \n";
cmd.Parameters.AddWithValue ("tagname", pattern);
}
if ((searchflags & FindBlogEntryFlags.MatchContent) > 0) {
cmd.CommandText += " and bcontent like :bcontent \n";
cmd.Parameters.AddWithValue ("bcontent", pattern);
}
if ((searchflags & FindBlogEntryFlags.MatchTitle) > 0) {
cmd.CommandText += " and title like :title";
cmd.Parameters.AddWithValue ("title", pattern);
}
if ((searchflags & FindBlogEntryFlags.MatchUserName) > 0) {
cmd.CommandText += " and username like :username \n";
cmd.Parameters.AddWithValue ("username", pattern);
}
}
if (((searchflags & FindBlogEntryFlags.MatchInvisible) == 0) &&
(readersName == null) ) {
cmd.CommandText += " and visible = true \n";
}
cmd.CommandText += " order by rate desc";
cnx.Open ();
using (NpgsqlDataReader rdr = cmd.ExecuteReader ()) {
// pageIndex became one based
int firstrec = pageIndex * pageSize;
int lastrec = firstrec + pageSize - 1;
while (rdr.Read ()) {
if (totalRecords >= firstrec && totalRecords <= lastrec) {
BlogEntry be = new BlogEntry ();
be.Title = rdr.GetString (rdr.GetOrdinal ("title"));
be.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id"));
be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent"));
be.Author = rdr.GetString (rdr.GetOrdinal ("username"));
be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted"));
be.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified"));
be.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible"));
be.Rate = rdr.GetInt32 (rdr.GetOrdinal ("rate"));
{
int oph = rdr.GetOrdinal ("photo");
if (!rdr.IsDBNull (oph))
be.Photo = rdr.GetString (oph);
}
c.Add (be);
}
totalRecords++;
}
rdr.Close ();
}
}
if (c != null)
Populate (c);
return c;
}
/// <summary>
/// Removes the post.
/// </summary>
/// <param name="username">Username.</param>
/// <param name="title">Title.</param>
public override void RemoveTitle (string username, string title)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "delete from blog where username = :username and applicationname = :appname and title=:title";
cmd.Parameters.AddWithValue ("username", username);
cmd.Parameters.AddWithValue ("appname", applicationName);
cmd.Parameters.AddWithValue ("title", title);
cnx.Open ();
cmd.ExecuteNonQuery ();
cnx.Close ();
}
}
int defaultPageSize = 10;
/// <summary>
/// Lasts the posts.
/// </summary>
/// <returns>The posts.</returns>
/// <param name="pageIndex">Page index.</param>
/// <param name="pageSize">Page size.</param>
/// <param name="totalRecords">Total records.</param>
public override BlogEntryCollection LastPosts (int pageIndex, int pageSize, out int totalRecords)
{
BlogEntryCollection c = new BlogEntryCollection ();
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "select * " +
"from blog where applicationname = :appname and visible = true " +
" order by modified desc limit :len";
cmd.Parameters.AddWithValue ("appname", applicationName);
cmd.Parameters.AddWithValue ("len", defaultPageSize * 10);
cnx.Open ();
using (NpgsqlDataReader rdr = cmd.ExecuteReader ()) {
totalRecords = 0;
int firstrec = pageIndex * pageSize;
int lastrec = firstrec + pageSize - 1;
while (rdr.Read ()) {
if (totalRecords >= firstrec && totalRecords <= lastrec) {
BlogEntry be = new BlogEntry ();
be.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id"));
be.Title = rdr.GetString (rdr.GetOrdinal ("title"));
be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent"));
be.Author = rdr.GetString (rdr.GetOrdinal ("username"));
be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted"));
be.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified"));
be.Visible = true; // because of sql code used
be.Rate = rdr.GetInt32(rdr.GetOrdinal("rate"));
{
int oph = rdr.GetOrdinal ("photo");
if (!rdr.IsDBNull (oph))
be.Photo = rdr.GetString (oph);
}
SetTagsOn (be);
SetCirclesOn (be);
c.Add (be);
}
totalRecords++;
}
}
}
if (c != null)
Populate (c);
return c;
}
#endregion
}
}