Search

I have added an “approved” field to my comments section with the intention of manually approving comments.

With this in mind I have 2 problems: -

  1. how do I default this field to be “no”? Is this done in the event code or is there a way within the CMS interface?
  2. How do I get the comments attribute on my article to reflect the count of approved comments, not the total linked comments?

Any pointers would be greatly appreciated.

how do I default this field to be “no”?

At the moment you cannot safely set defaults without writing a little bit o’ PHP. A checkbox will be No by default. However you should explicitly send its default value in your form POST:

<input type="hidden" name="approved" value="no" />

Of course, users can inspect and change this. So yo can set it inside the Event explicitly. Inside the __trigger function, before the include add the line:

$_POST['fields']['approved'] = 'no';

This will have the same effect. Be sure to also set the allowEditorToParse() function to return false now that you have modified the Event code manually.

I think Allen has mentioned that a future improvement to Events will be the ability to provide default values from within Symphony itself.

How do I get the comments attribute on my article to reflect the count of approved comments, not the total linked comments?

Unfortunately you can’t. There’s no way of adding a filter into the query that creates this count. You therefore have two options: one native and one custom.

  1. Create another DS filtering your Comments section with the “Approved” checbox filtering no, but just include the pagination element, which has a total-entries attribute in your XML.
  2. If you’re comfortable with PHP, customise the DS to parse the XML and do a database query yourself, adding the result back into the DOM.

I’ve done both on separate projects, and tend to favour #2 since it keeps the number of DSs to a minimum.

Here is an example of #2. I had four DSs used to get Posts (in various places around the site). In all instances, I wanted to get the number of approved comments. Instead of modifying all four Posts DSs I created a new DS:

http://gist.github.com/257872

The four Posts DSs output System ID as their Output Parameter. The DS code above then declares these four DSs as being dependencies, so that it will run after them.

Depending on the Post DS that is running, I get the list of IDs from the param pool and loop over them. For each post ID I do a lookup in the database joining the Select Box Link and Approved (a select box with values “Approved”, “Pending”, “Declined”) tables together, counting the number of rows.

The output of this DS is something like:

<blog-post-moderated-comment-count>
    <post id="1" approved-comments="12"/>
    <post id="2" approved-comments="4"/>
    <post id="3" approved-comments="99"/>
</blog-post-moderated-comment-count>

Which can be cross-referenced using XPath queries, based on the post ID.

Cheers Nick, I’ll get stuck into that lot and see how I get on.

I’m sure this will make a good starting point to do some more complicated trickery.

I am now so close I can taste it!!

I have my custom DS working and generating the correct output, but now I can’t work out how to reference the article ID to plug into the XPATH.

THis works: -

<xsl:value-of select="../../comments/article[@id=16]/@approved-comments"/>

But I need to plug the article ID where 16 is, where the ID is an attribute in the current context. My terminology might be dodgy bad, but essentially the ID I want is at ./@id from the location this XSL element is located.

I hope this makes sense!!

You could save yourself a headache and use an absolute path from the route:

<xsl:value-of select="/data/comments/article[@id=current()/@id]/@approved-comments"/>

current() assumes the current context node is an <entry> you are looping over, or matching.

This can make your XSLT more robust, since it doesn’t matter where your context <entry> resides in the XML. The comments element is never going to move, but your context node might… so it makes sense to use an absolute path to comments.

Thanks a lot Nick, that’s nailed it.

I am loving working with Symphony and the help I get here is a huge part of that, as it means I am making progress at a good rate.

Cheers.

Thanks a lot Nick, that’s nailed it.

Rock and roll :-) You’re welcome.

This may or may not be of use to anyone but I’ve done the comment count through XSL only. To avoid spamming I did the same as Robphilp above and added an “Approved” checkbox to my comments section. I then filter my comments data source only with this value allowed to be “yes”. Assuming you are using a similar setup to the get-articles utility that ships with the sample workspace this solution may work for you.

In my case I had my comments at the following path in my XML: “/data/comments/entry/”

And my article entries could be located here: “/data/article/entry”

At the beggining of the template match for the utility get-article.xsl I store a variable with the current article entry ID like so:

<xsl:variable name="entry-id" select="@id" />

It’s worth mentioning that my comments data includes the article entry ID. So all I need to do now is count the total amount of comments for each article ID. And I do this like so:

<xsl:text> Comments(</xsl:text>
<xsl:value-of select="count(/data/comments/entry/article/item[@id = $entry-id])" />
<xsl:text>)</xsl:text>

The above code happens within the template-match for “article/entry” as it needs to happen for each article I add.

Maybe this could be an alternative solution if you don’t want to change the PHP.

Thanks for sharing wezside. This method will work great for small numbers of comments, but you will undoubtedly see a performance deficit with larger quantities. It is more performant to count at the database level than “select all”. That said, if your site isn’t too big and it works for you then great :-)

You’re absolutely right Nick, haven’t thought of that use case. Is there any chance this will be included into a future release for symphony? I’m not a big fan of changing the PHP as it impacts on any future maintenance or updates that has to be made to a site.

Is there any chance this will be included into a future release for symphony?

Can’t say for sure. I guess a “Moderation” field/extension would be useful here.

An extension idea that has popped in and out of my head over the last few years has been a generic “Entry Attribute Builder” which allows a developer to take a Data Source and say “for every <entry> in this Data Source, add a new attribute of this name, use this SQL or filter for the value”. It’s a pretty complex problem without an elegant solution. The trick is to make it as easy and robust as possible for people to use without having to understand SQL.

That sounds like a useful extension. My initial thoughts were that it’ll be good if the data source option “Include a count of entries in associated sections” has an optional filter field but I have no idea how difficult this is to implement and appreciate that simple features like that isn’t always as straight forward as they may seem. Your extension idea essentially sounds like one would be able to do exactly this.

Anyways - for now this is working well for me and until I have more PHP experience, I might take on an extension of my own.

I had a stab at implementing this and got quite far.

http://github.com/nickdunn/entry_attribute_counts

It uses the concept of pairs of Data Sources: parent (the DS you want to add the count to) and child (the DS from which the count will come). To take the use case of Articles and Comments, where your Comments section has an “Approved” checkbox. You only want to show approved comments.

Let’s say you want to create a list of articles, and the number of approved comments for each. You will likely already have the following:

  • an “Articles” Data Source that returns all articles, but also has a filter on article title by a URL Parameter (i.e. re-using this DS to get a list of all articles, as well as a single article). This DS will also have “System ID” set as its output parameter, creating a param named $ds-articles
  • a “Comments” Data Source that filters your comments by a Select Box Link using the value of the $ds-articles param, and filtering the “Approved” checkbox with a value of yes. This DS will return all approved comments on the single article display page

The problem is, if you enable the “Include a count of entries in associated sections” checkbox on your Articles DS then it will return a count of all comments, and not just the approved ones.

You can give this extension a go with the following steps:

  • you’ll need a little change to the core, documented in the README
  • install the extension and see an XML file created in /manifest

E.g.

<?xml version="1.0" encoding="UTF-8" ?>
<datasource-pairs>
    <pair add-attribute-to="articles" get-count-from="comments"/>
</datasource-pairs>

This uses the concept of pairs of Data Sources. You are pairing your Articles data source with your Comments data source. The extension will make the following assumptions:

  • that your “parent” Data Source (e.g. Articles) has its System ID field as its Output Parameter
  • that the “child” Data Source (e.g. Comments) has a field (e.g. a Select Box Link) that is filtering on the above Output Parameter (e.g. {$ds-articles})

If the above conditions match, then this extension should run the Comments data source for every entry returned from the Articles data source, adding the count of returned entries as an attribute in the XML.

This is totally experimental, but it’s a working proof of concept. It’s a neat approach because it requires almost zero configuration. Just build your DSs as usual and pair them up in the XML file.

And for the performance junkies amongst you, this extension seems to use only two database queries for each count, so in Symphony terms it is cheap.

Nice work, Nick! A very elegant solution to this thorny, recurring problem. :-)

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details