Subversion Repositories travelsized

Rev

Rev 441 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?PHP
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * This file is part of Travelsized CMS
 *              A content management system with modules, based on wiki syntax
 *
 * Author: Dan Jensen <admin@leinir.dk>
 * Copyright 2003/2004
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * The GNU General Public License is available at: http://www.gnu.org/copyleft/
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */


/**
 * Class to hangle recursive comments. Use instructions as follows:
 *
 * $commenthandler = new commentHandler($yourCommentsArray, $yourCommentsOwner, $commentingAllowanceLevel, $editingAllowanceLevel); // This is where you input the comments data (to start it off, simply pass an empty array)
 * $commenthandler->renderComments(); // Put this where you wish to show the actual comments
 * $commenthandler->renderCommentsAdder(); // Put this where you wish to show the form for adding a new comment
 * if ($commenthandler->commentsChanged) { // If the comments have changed... You don't actually have to check, but it's good for efficiency
 *      $yourCommentsArray = $commenthandler->comments; // Remember to save your comments again, commentHandler does not do that for you!
 *      fileSave($commentfilename, array_export($yourCommentsArray, "yourCommentsArray")); // Use for example array_export for saving it to file
 * }
 */

class commentHandler
{
        var $commentsOwner; ///< Who owns that which is being edited? Used to check commenting and editing allowance levels against
        var $commentLevel; ///< The access level for editing the comments
        var $editLevel; ///< The access level for editing the comments data
        var $comments; ///< The array containing blog data. Just let commentHandler handle this - black box stuff, no need to know what's inside ;)
        var $thisPageURL; ///< This can be set by the user, in case thisPageURL() doesn't return enough information (such as sub-items in a blog entry or gallery items or...)
       
        var $commentsChanged = false; ///< This starts false, and will be set to true if the comments have changed (edited, hidden/shown, added, removed...)
        var $lastCommenter; ///< The person who made a comment (set if commentsChanged == true)
        var $lastComment; ///< The last comment
       
        var $allowNesting = true; ///< Do we allow nesting the comments?
       
        /**
         * Constructor for the comments handler. Use the comments handler as described in the class documentation
         *
         * @param       comments        Comments data array. If you have no array to begin with, simply pass an empty array.
         * @param       commentsOwner   String comtaining the user id of the parent data
         * @param       commentLevel    Integer containing an allowance level relative to commentsOwner for who is allowed to comment
         * @param       editLevel       Integer containing an allowance level relative to commentsOwner for who is allowed to edit the comments
         *
         * @return      void
         */

        function commentHandler($comments, $commentsOwner, $commentLevel, $editLevel)
        {
                $this->comments = $comments;
                $this->commentsOwner = $commentsOwner;
                $this->commentLevel = $commentLevel;
                $this->editLevel = $editLevel;
                $this->thisPageURL = thisPageURL();
               
                if( userAllows( $this->commentsOwner, $this->editLevel ) ) { // Only ever do this if, of course, the user is allowed to actually well... do this :)
                        if( array_key_exists( "deletecomment", $_REQUEST) )
                        {
                                if ( array_key_exists( "confirm_delete", $_REQUEST ) && $_REQUEST["confirm_delete"] == "true" )
                                        $new_comment = $this->deleteComment();
                        }
                        else if( array_key_exists( "editcomment", $_REQUEST ) )
                        {
                                if ( array_key_exists( "save_comment", $_POST ) )
                                        $new_comment = $this->editComment();
                        }
                        else if( array_key_exists( "hideshow", $_REQUEST ) && array_key_exists( "commentid", $_REQUEST ) )
                        {
                                if( $_REQUEST["hideshow"] == "hide" )
                                        $hidden = "true";
                                if( $_REQUEST["hideshow"] == "show" )
                                        $hidden = "";
                               
                                $new_comment = $_REQUEST["commentid"] . "[hidden]=" . $hidden;
                                $new_comment = $new_comment;
                               
                                parse_str($new_comment, $new_comment);
                                $new_comment = $new_comment["comments"];
                        }
                       
                        if( ( array_key_exists( "deletecomment", $_REQUEST ) && array_key_exists( "confirm_delete", $_REQUEST ) ) || ( array_key_exists( "editcomment", $_REQUEST ) && array_key_exists( "save_comment", $_POST ) ) || ( array_key_exists( "hideshow", $_REQUEST ) && array_key_exists( "commentid", $_REQUEST) ) )
                        {
                                $this->comments = array_merge_n($this->comments, $new_comment); // Merge the newly created, edited, deleted, hidden, shown comment into the comments array data
                                $this->comments = $this->cleanComments($this->comments); // Clean up the comments data - we need to do this to get rid of empty items (for example deleted entries)
                                $this->commentsChanged = true; // Make sure to tell the caller that the comments have, in fact, changed
                                header("Location: " . thisPageURL(true) );
                        }
                }
       
        if( userAllows( $this->commentsOwner, $this->commentLevel ) && array_key_exists( "newname", $_POST ) && array_key_exists( "newemail", $_POST ) && array_key_exists( "newcomment", $_POST ) )
                {
                        $new_comment = $this->addComment();
                        $this->comments = array_merge_n($this->comments, $new_comment); // Merge the newly created, edited, deleted, hidden, shown comment into the comments array data
                        $this->comments = $this->cleanComments($this->comments); // Clean up the comments data - we need to do this to get rid of empty items (for example deleted entries)
                        $this->lastCommenter = stripslashes($_POST["newname"]);
                        $this->lastComment = stripslashes($_POST["newcomment"]);
                        $this->commentsChanged = true; // Make sure to tell the caller that the comments have, in fact, changed
                        header("Location: " . thisPageURL(true) );
                }
        }
       
        /**
         * Internal function used for adding a new comment
         *
         * @return      array The new comments data array, ready for merging
         */

        function addComment()
        {
                $replyto = str_replace($_REQUEST["newcommentid"], time(), stripslashes($_REQUEST["replyto"]));
               
                $new_commentname = $replyto . "[name]=" . str_replace("%", "%25", stripslashes($_POST["newname"]));
                $new_commentemail = $replyto . "[email]=" . str_replace("%", "%25", stripslashes($_POST["newemail"]));
                $new_commentcomment = $replyto ."[comment]=" . str_replace("%", "%25", stripslashes($_POST["newcomment"]));
               
                parse_str($new_commentname, $new_commentname);
                parse_str($new_commentemail, $new_commentemail);
                parse_str($new_commentcomment, $new_commentcomment);
               
                $new_comment = array();
                array_merge_2($new_comment, $new_commentname);
                array_merge_2($new_comment, $new_commentemail);
                array_merge_2($new_comment, $new_commentcomment);
               
                return $new_comment["comments"];
        }
       
        /**
         * Internal function used for editing an existing comment
         *
         * @return      array The new comments data array, ready for merging
         */

        function editComment()
        {
                $edit_comment = $_REQUEST["editcomment"];
               
                $edit_commentname = $edit_comment . "[name]=" . str_replace("%", "%25", stripslashes($_POST["editcommentname"]));
        $edit_commentemail = $edit_comment . "[email]=" . str_replace("%", "%25", stripslashes($_POST["editcommentemail"]));
        $edit_commentcomment = $edit_comment ."[comment]=" . str_replace("%", "%25", stripslashes($_POST["editcommentcomment"]));
        $edit_commenthidden = $edit_comment ."[hidden]=" . str_replace("%", "%25", stripslashes($_POST["edit_commenthidden"]));
               
                parse_str($edit_commentname, $edit_commentname);
                parse_str($edit_commentemail, $edit_commentemail);
                parse_str($edit_commentcomment, $edit_commentcomment);
                parse_str($edit_commenthidden, $edit_commenthidden);
               
                $new_comment = array();
                array_merge_2($new_comment, $edit_commentname);
                array_merge_2($new_comment, $edit_commentemail);
                array_merge_2($new_comment, $edit_commentcomment);
                array_merge_2($new_comment, $edit_commenthidden);
               
                return $new_comment["comments"];
        }
       
        /**
         * Internal function used for deleting an existing comment
         *
         * @return      array The new comments data array, ready for merging
         */

        function deleteComment()
        {
                $new_comment = $_REQUEST["deletecomment"];
               
                $new_commentname = $new_comment . "[name]=";
                $new_commentemail = $new_comment . "[email]=";
                $new_commentcomment = $new_comment ."[comment]=";
                $new_commenthidden = $new_comment . "[hidden]=";
               
                parse_str($new_commentname, $new_commentname);
                parse_str($new_commentemail, $new_commentemail);
                parse_str($new_commentcomment, $new_commentcomment);
                parse_str($new_commenthidden, $new_commenthidden);
               
                $new_comment = array();
                array_merge_2($new_comment, $new_commentname);
                array_merge_2($new_comment, $new_commentemail);
                array_merge_2($new_comment, $new_commentcomment);
                array_merge_2($new_comment, $new_commenthidden);
               
                return $new_comment["comments"];
        }
       
        /**
         * Internal function used for cleaning up comments data
         *
         * @param       comments        Uncleaned comments data array
         *
         * @return      array   Cleaned up comments data array
         */

        function cleanComments($comments)
        {
                $result = array();
                if( is_array( $comments ) )
                {
                        foreach( $comments as $key => $value )
                        {
                                $value["name"] = stripslashes($value["name"]);
                                $value["email"] = stripslashes($value["email"]);
                                $value["comment"] = stripslashes($value["comment"]);
                               
                                if ( !( $value["name"] == "" && $value["email"] == "" && $value["comment"] == "" ) )
                                        $result[$key] = $value;
                               
                                if( is_array( $value["comments"] ) && count( $value["comments"] ) > 0)
                                        $result[$key]["comments"] = $this->cleanComments($value["comments"]);
                        }
                }
                return $result;
        }
       
        /**
         * Internal function used for creating the replyto targets
         */

        function replyto($comments, $depth = "", $commentlink, $newcommentid)
        {
                $i = 1;
        $data = "";
                if( is_array( $comments ) )
                {
                        foreach( $comments as $key => $value )
                        {
                                $data .= "<option value=\"{$commentlink}[$key][comments][$newcommentid]\">#$depth$i&nbsp;-&nbsp;" . parse_profilelinks($value['name']) . "</option>";
                if( array_key_exists( "comments", $value) && is_array( $value["comments"] ) && count( $value["comments"] ) > 0 )
                                        $data .= $this->replyto($value["comments"], "$depth$i.", $commentlink . "[$key][comments]", $newcommentid);
                                $i++;
                        }
                }
                return $data;
        }
       
        /**
         * Function which returns the number of comments in the current instance
         *
         * @return      int     Number of comments
         */

        function numberOfComments()
        {
                return $this->countComments($this->comments);
        }
       
        /**
         * Internal function used above for counting the comments (the numberOfComments function is a dummy function created to make the API a little prettier)
         *
         * @param       comments        Input a comments data array
         *
         * @return      int     Number of comments in the comments data array
         */

        function countComments($comments)
        {
                $data = 0;
                if( !is_array($comments) )
                        return 0;
               
                foreach( $comments as $key => $value )
                {
                        $data++;
                        if( array_key_exists( "comments", $value ) && is_array( $value["comments"] ) && count( $value["comments"] ) > 0 )
                                $data += $this->countComments($value["comments"]);
                }
                return $data;
        }
       
        /**
         * Internal function used to get a single comment's data
         *
         * @param       whatcomment     Which comment do you want to grab?
         * @param       comments        A comments data structure to get the comment from
         *
         * @return      array   An array containing the single comment
         */

        function getComment($whatcomment, $comments)
        {
                foreach( $whatcomment as $key => $value )
                {
                        if( is_array( $value["comments"] ) )
                                $thecomment = $this->getComment($value["comments"], $comments[$key]["comments"]);
                        else
                                $thecomment = $comments[$key];
                }
                return $thecomment;
        }
       
        /**
         * renderComments renders the comments
         *
         * @return      string          The rendered comments
         */

        function renderComments()
        {
                $listid = 0;
                if( count($this->comments) < 1 )
                        return "";
                return $this->renderCommentsActual($this->comments, $listid, "comments", "");
        }
       
        /**
         * The actual comments rendering function. The renderComments function is a dummy function that makes the API a little more pleasant
         *
         * @param       $comments       The comments data
         * @param       $commentlink    The link... Just pass "" to this - used internally for recursion
         * @param       $depth          How deep are we? Just pass "" to this - used internally for recursion
         * @param       $listid The comment index. Pass a variable $listid = 0 to this - used internally for recursion, for javascript replyto links
         *
         * @return      string          The rendered comments
         */

        function renderCommentsActual($comments, &$listid, $commentlink = "", $depth = "")
        {
                $data = "<ul class=\"comments\">";
                $i = 1;
                foreach($comments as $key => $value)
                {
                        $listid++;
                        if( ($value["name"] != "" && $value["email"] != "" && $value["comment"] != "") || is_array($value["comments"]) && count($value["comments"]) > 0 )
                        {
                                $data .= "
                                <li class=\"comment\">"
;
                               
                                // Are we deleting the comment?
                                if( $_REQUEST["deletecomment"] == $commentlink . "[$key]" )
                                        $data .= $this->renderCommentsDelete();
                               
                                // Are we editing the comment?
                                if ($_REQUEST["editcomment"] == $commentlink . "[$key]")
                                        $data .= $this->renderCommentEditor();
                                // If not, just show it
                                else
                                {
                                        $data .= "<div style=\"float: right;\" class=\"comment-commands\">";
                                        if( userAllows( $this->commentsOwner, $this->editLevel ) )
                                        {
                                                $data .= "
                                                <a class=\"command\" href=\""
. $this->thisPageURL . "&amp;deletecomment=" . $commentlink . "[$key]#deletecomment\">[" . i18n("Delete") . "]</a>
                                                "
;
                                                if( $value["hidden"] != true )
                                                        $data .= "
                                                        <a class=\"command\" href=\""
. $this->thisPageURL . "&amp;hideshow=hide&amp;commentid=" . $commentlink . "[$key]#" . $commentlink . "[comments][$key]\">[" . i18n("Hide") . "]</a>";
                                                else
                                                        $data .= "
                                                        <a class=\"command\" href=\""
. $this->thisPageURL . "&amp;hideshow=show&amp;commentid=" . $commentlink . "[$key]#" . $commentlink . "[comments][$key]\">[" . i18n("Show") . "]</a>";
                                               
                                                $data .= "
                                                <a class=\"command\" href=\""
. $this->thisPageURL . "&amp;editcomment=" . $commentlink . "[$key]#editcomment\">[" . i18n("Edit") . "]</a>";
                                        }
                                        if( userAllows( $this->commentsOwner, $this->commentLevel ) )
                                        {
                                                $data .= "
                                                <script language=\"javascript\">
                                                document.write('<a class=\"command\" href=\"#comment\" onClick=\"document.getElementById(\\'replyto\\').selectedIndex=$listid;\">["
. i18n("Reply") . "]</a>');
                                                </script>"
;
                                        }
                                        $data .= "</div>";
                                        if( $value["hidden"] != true )
                                        {
                                                $data .=  parse_page_data($value["comment"]) . "<div class=\"comment-name\">
                                                <a class=\"comment-link\" name=\"comment$depth$i\" href=\""
. $this->thisPageURL . "#comment$depth$i\">#$depth$i</a>
                                                "
. parse_profilelinks($value["name"]) . " (" . $value["email"] . ") - " . formatTime( $key ) . "
                                                </div>"
;
                                        }
                                        else
                                        {
                                                $data .= "<div class=\"comment-name\">
                                                <a class=\"comment-link\" name=\"comment$depth$i\" href=\""
. $this->thisPageURL . "#comment$depth$i\">#$depth$i</a>
                                                <small class=\"comment\">"
. i18n("This comment has been hidden") . "</small></div>";
                                        }
                                }
                               
                                if( array_key_exists( "comments", $value) && is_array($value["comments"]) && count($value["comments"]) > 0 )
                                        $data .= $this->renderCommentsActual($value["comments"], $listid, $commentlink . "[$key][comments]", "$depth$i.");
                               
                                $data .= "</li>";
                                $i++;
                        }
                }
                $data .= "</ul>";
                return $data;
        }
       
        function renderCommentsAdder()
    {
                global $formatting_toolbar, $permissionlevels_array, $systemOptions;
                if (userAllows($this->commentsOwner, $this->commentLevel))
                {
                        $commenting_username = currentUser();
                        if ($commenting_username != "")
                        {
                                $commenting_email = str_replace(".", " dot ", str_replace("@", " ad ", getUserInfo($commenting_username, "email")));
                                $commenting_username = "%%$commenting_username%%";
                        }
                        $newcommentid = time() + 1; //Add one to the time, otherwise it will break when adding a comment to the comment a user added now
                        $commenting_replyto = "<option value=\"comments[$newcommentid]\">" . i18n("Top level") . "</option>";
                        if( $this->allowNesting )
                                $commenting_replyto .= $this->replyto($this->comments, "", "comments", $newcommentid);
                       
                        $data = "
                        <form name=\"commentform\" method=\"post\" action=\""
. $this->thisPageURL . "\">
                        <input type=\"hidden\" name=\"newcommentid\" value=\"$newcommentid\" />
                        <table class=\"editcomment\">
                        <tr class=\"editcomment\">
                                <td class=\"editcomment\" width=\"50%\">"
. i18n("Reply to") . ":<a class=\"namedanchor\" name=\"comment\">&nbsp;</a></td>
                                <td class=\"editcomment\" width=\"50%\"><select style=\"width: 100%\" id=\"replyto\" name=\"replyto\">$commenting_replyto</select></td>
                        </tr>
                        <tr class=\"editcomment\">
                                <td class=\"editcomment\">"
. i18n("Your name") . ":</td>
                                <td class=\"editcomment\"><input style=\"width: 100%\" type=\"text\" name=\"newname\" value=\"$commenting_username\" /></td>
                        </tr>
                        <tr class=\"editcomment\">
                                <td class=\"editcomment\">"
. i18n("Your email address") . ":</td>
                                <td class=\"editcomment\"><input style=\"width: 100%\" type=\"text\" name=\"newemail\" value=\"$commenting_email\" /></td>
                        </tr>
                        <tr class=\"editcomment\">
                                <td class=\"editcomment\" colspan=\"2\">"
. i18n("Your comment") . ":
                        </tr>
                        $formatting_toolbar
                        <tr class=\"editcomment\">
                                <td class=\"editcomment\" colspan=\"2\">
                                <textarea rows=\"10\" cols=\"70\" style=\"width: 100%;\" id=\"edit\" name=\"newcomment\">\n\n---\n"
. getUserInfo(currentUser(), "signature", getUserInfo(currentUser(), "name", i18n("Posted by Anonymous on ##0##", array(formatTime(time())))) ) . "</textarea>
                                </td>
                        </tr>
                        <tr class=\"editcomment\">
                                <td class=\"editcommentbottom\"><input type=\"submit\" value=\""
. i18n("Create comment") . "\" /></td>
                                <td class=\"editcommentbottom wikirightalign\"><input type=\"reset\" value=\""
. i18n("Reset") . "\" /></td>
                        </tr>
                        </table>
                        </form>
                        "
;
                       
                        $data = renderInformationBox( i18n("New Comment"), $data, false );
                }
                else if( $systemOptions["permissionmessages"] == 1 )
                        $data = "<p><small class=\"comment\">" . i18n("##0## has disallowed commenting for users that do not fit the following description", array(getUserInfo($this->commentsOwner, "name"))) . ": <strong>" . $permissionlevels_array[$this->commentLevel] . "</strong></small></p>";
               
                return $data;
        }
       
        /**
         * Internal function used for showing the inline comment deletion comfirmation dialog
         *
         * @return string       The dialog
         */

        function renderCommentsDelete()
        {
                if( !$_REQUEST["confirm_delete"] )
                {
                        $question = "<p><a class=\"namedanchor\" name=\"deletecomment\">&nbsp;</a>" . i18n("Please confirm that you wish to delete this comment. Please note - this will delete ALL sub-comments. If you wish to allow people to still see the sub-comments, simply hide the comment in stead.") . "</p>
                        <div class=\"wikicenteralign\">
                        <a class=\"command\" href=\""
. $this->thisPageURL . "&amp;deletecomment={$_REQUEST['deletecomment']}&amp;confirm_delete=true\">[" . i18n("Confirm delete") . "]</a>
                        <a class=\"command\" href=\""
. $this->thisPageURL . "\">[" . i18n("Abort delete") . "]</a>
                        </div>"
;
                        $data = renderQuestionBox( i18n("Delete comment?"), $question, false );
                }
                return $data;
        }
       
        /**
         * Internal function used for showing the inline comment editing dialog
         *
         * @return string       The dialog
         */

        function renderCommentEditor()
        {
                global $formatting_toolbar;
                if( !$_POST["save_comment"] )
                {
                        $edit_comment = $_REQUEST["editcomment"];
                        parse_str($edit_comment, $edit_comment);
                        $edit_comment = $this->getComment($edit_comment["comments"], $this->comments);
                       
                        $data .= "
                        <form action=\""
. $this->thisPageURL . "&amp;editcomment={$_REQUEST['editcomment']}\" method=\"post\">
                        <table class=\"editcomment\">
                        <tr class=\"editcomment\"><th class=\"editcomment\" colspan=\"2\"><a class=\"namedanchor\" name=\"editcomment\">&nbsp;</a>"
. i18n("Edit comment") . "</th></tr>
                        <tr class=\"editcomment\">
                                <td class=\"editcomment\">"
. i18n("Commenter's name") . ":</td>
                                <td class=\"editcomment\"><input style=\"width: 100%\" type=\"text\" name=\"editcommentname\" value=\"{$edit_comment['name']}\" /></td>
                        </tr>
                        <tr class=\"editcomment\">
                                <td class=\"editcomment\">"
. i18n("Commentor's email address") . ":</td>
                                <td class=\"editcomment\"><input style=\"width: 100%\" type=\"text\" name=\"editcommentemail\" value=\"{$edit_comment['email']}\" /></td>
                        </tr>
                        <tr class=\"editcomment\">
                                <td class=\"editcomment\" colspan=\"2\">"
. i18n("The comment") . ":
                        </tr>
                        $formatting_toolbar
                        <tr class=\"editcomment\">
                                <td class=\"editcomment\" colspan=\"2\">
                                <textarea rows=\"10\" cols=\"70\" style=\"width: 100%;\" id=\"edit\" name=\"editcommentcomment\">{$edit_comment['comment']}</textarea>
                                </td>
                        </tr>
                        <tr class=\"editcomment\">
                                <td class=\"editcommentbottom\"><input type=\"submit\" name=\"save_comment\" value=\""
. i18n("Save comment") . "\" /></td>
                                <td class=\"editcommentbottom wikirightalign\"><input type=\"reset\" value=\""
. i18n("Reset") . "\" /></td>
                        </tr>
                        </table>
                        </form>"
;
                }
                return $data;
        }
}
?>