Revision [14725]

This is an old revision of MinorEditHack made by FishPete on 2006-06-28 18:25:12.

 

Minor Edit Hack

Please Backup your data, I don't see where my code could be harmful, but better be safe than sorry!


PLEASE NOTE:
I have only tested this modification on my local system, I will apply it to my acutal server tonight (following the instruction I give here. Lets see *g*) and post a link as soon as its done!
 

First a warning, I am new to php and mysql, what I did was mostly trial and trial and trial and lots of errors - so if you find redudant code or you have suggestions for improvements , please tell me!



What does it do?

This hack of mine gives the users the possibility to mark pageupdates as minor ones (typos etc.).
I wrote an action called "recentmajorchanges" which allows the user to see only major, only minor or all changes during the last number of days.

What has to be changed?




Change to the MYSQL Database


As a fist step you have to add a cell to the table "pages" in the MYSQL Database called "minorchange", which consists of a boolean value. FALSE or 0 meaning "no minor change", TRUE or !=0 means "minorchange"

the MYSQL Query is:
ALTER TABLE `wikka_pages` ADD `minorchange` BOOL NOT NULL DEFAULT '0';

NOTE: I'm assuming you use the standart table prefix wikka_ here!



The PHP Code


Changes in /libs/wakka.class.php


SavePage
The function SavePage in /libs/wakka.class.php has to be altered to be able to save the minorchange flag. inserted lines are commented
    function SavePage($tag, $body, $note, $minorchange) //editet by FishPete
    {
        if (!isset($minorchange)) $minorchange='0';// inserted by FishPete
    // get current user
        $user = $this->GetUserName();

        // TODO: check write privilege
        if ($this->HasAccess("write", $tag))
        {
            // is page new?
            if (!$oldPage = $this->LoadPage($tag))
            {
                // current user is owner if user is logged in, otherwise, no owner.
                if ($this->GetUser()) $owner = $user;
            }
            else
            {
                // aha! page isn't new. keep owner!
                $owner = $oldPage["owner"];
            }

            // set all other revisions to old
            $this->Query("update ".$this->config["table_prefix"]."pages set latest = 'N' where tag = '".mysql_real_escape_string($tag)."'");

            // add new revision
            $this->Query("insert into ".$this->config["table_prefix"]."pages set ".
                "tag = '".mysql_real_escape_string($tag)."', ".
                "time = now(), ".
                "owner = '".mysql_real_escape_string($owner)."', ".
                "user = '".mysql_real_escape_string($user)."', ".
                "note = '".mysql_real_escape_string($note)."', ".
                "latest = 'Y', ".
                "minorchange = ".$minorchange.", ". // inserted by FishPete
                "body = '".mysql_real_escape_string($body)."'");
      if ($pingdata = $this->GetPingParams($this->config["wikiping_server"], $tag, $user, $note))
                $this->WikiPing($pingdata);
        }
    }


ChangedDuringLastDays

I wrote a function to display changes during the last days to be used instead of LoadRecentlyChanged()
  /*$interval: number of days which should be displayed
  * $show: whether to show all, only major or only minor changes  
  * returns array of pages which were changed during the last ($interval) days and are according to $show criteria
  */

       
function LoadChangedDuringLastDays($interval, $show)
    {
    switch ($show)
    {
      case 'all':
        $param=''; //no additional parameter in the MYSQL Query
        break;
      case 'major':
        $param='AND minorchange = 0'; //to be used in the MYSQL Query
        break;
      case 'minor':
        $param='AND minorchange !=0'; //to be used in the MYSQL Query
        break;
    }
    if ($pages = $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where time> DATE_SUB(now(),INTERVAL ".$interval." DAY) ".$param." order by time desc"))
        {
          foreach ($pages as $page)
            {
                $this->CachePage($page);
            }
            return $pages;
        }
    }




Changes in /handlers/page/edit.php


The next thing to do is add a checkbox to /handlers/pages/edit.php which allows the user to mark a change as a minor one. Since the little code changes are all over the place in this file I'll post the whole file. The lines I changed are commented with " edited by FishPete. Just search for FishPete in the file and it should take you to the new lines.
<?php
/**
 * Display a form to edit the current page.
 *
 * @package     Handlers
 * @name        Edit
 *
 * @author      {@link http://wikkawiki.org/JsnX Jason Tourtelotte} (original code)
 * @author      {@link http://wikkawiki.org/Dartar Dario Taraborelli} (preliminary code cleanup, i18n)
 * @author      {@link http://wikkawiki.org/DotMG Mahefa Randimbisoa} (bugfixes)
 * @author      {@link http://wikkawiki.org/FishPete Peter Fischaleck} (Minor Edit Hack)
 * @since       Wikka 1.1.6.2
 *
 * @todo        - move main <div> to templating class;
 *          - optimization using history.back();
 *          - use central regex library for validation;
 */


// defaults
if(!defined('VALID_PAGENAME_PATTERN')) define ('VALID_PAGENAME_PATTERN', '/^[A-Za-zÄÖÜßäöü]+[A-Za-z0-9ÄÖÜßäöü]*$/s');
if(!defined('MAX_TAG_LENGTH')) define ('MAX_TAG_LENGTH', 75);
if(!defined('MAX_EDIT_NOTE_LENGTH')) define ('MAX_EDIT_NOTE_LENGTH', 50);

//i18n
if(!defined('PREVIEW_HEADER')) define('PREVIEW_HEADER', 'Preview');
if(!defined('LABEL_EDIT_NOTE')) define('LABEL_EDIT_NOTE', 'Please add a note on your edit');
if (!defined('INPUT_ERROR_STYLE')) define('INPUT_ERROR_STYLE', 'class="highlight"');
if(!defined('ERROR_INVALID_PAGENAME')) define('ERROR_INVALID_PAGENAME', 'This page name is invalid. Valid page names must start with a letter and contain only letters and numbers.');
if(!defined('ERROR_OVERWRITE_ALERT')) define('ERROR_OVERWRITE_ALERT', 'OVERWRITE ALERT: This page was modified by someone else while you were editing it.<br /> Please copy your changes and re-edit this page.');
if(!defined('ERROR_MISSING_EDIT_NOTE')) define('ERROR_MISSING_EDIT_NOTE', 'MISSING EDIT NOTE: Please fill in an edit note!');
if(!defined('ERROR_TAG_TOO_LONG')) define('ERROR_TAG_TOO_LONG', 'Tag too long! %d characters max.');
if(!defined('ERROR_NO_WRITE_ACCESS')) define('ERROR_NO_WRITE_ACCESS', 'You don\'t have write access to this page. You might need to register an account to be able to edit this page.');
if(!defined('MESSAGE_AUTO_RESIZE')) define('MESSAGE_AUTO_RESIZE', 'Clicking on %s will automatically truncate the tag to the correct size');
if(!defined('INPUT_SUBMIT_PREVIEW')) define('INPUT_SUBMIT_PREVIEW', 'Preview');
if(!defined('INPUT_SUBMIT_STORE')) define('INPUT_SUBMIT_STORE', 'Store');
if(!defined('INPUT_SUBMIT_REEDIT')) define('INPUT_SUBMIT_REEDIT', 'Re-edit');
if(!defined('INPUT_BUTTON_CANCEL')) define('INPUT_BUTTON_CANCEL', 'Cancel');
if(!defined('INPUT_SUBMIT_RENAME')) define('INPUT_SUBMIT_RENAME', 'Rename');
if(!defined('ACCESSKEY_STORE')) define('ACCESSKEY_STORE', 's');
if(!defined('ACCESSKEY_REEDIT')) define('ACCESSKEY_REEDIT', 'r');
if(!defined('ACCESSKEY_PREVIEW')) define('ACCESSKEY_PREVIEW', 'p');
if(!defined('SHOWCODE_LINK')) define('SHOWCODE_LINK', 'View formatting code for this page');
if(!defined('SHOWCODE_LINK_TITLE')) define('SHOWCODE_LINK_TITLE', 'Click to view page formatting code');

if(!defined('MINOR_CHANGE_FLAG_TEXT')) define('MINOR_CHANGE_FLAG_TEXT', 'Please check if your change is a minor one');//edit by FishPete


//initialization
$error = '';
$highlight_note = '';
$ondblclick = ''; //#123
if (isset($_POST['submit']) && ($_POST['submit'] == 'Preview') && ($user = $this->GetUser()) && ($user['doubleclickedit'] != 'N'))
{
    $ondblclick = ' ondblclick=\'document.getElementById("reedit_id").click();\'';
    //history.back() not working on IE. (changes are lost)
    //however, history.back() works fine in FF, and this is the optimized choice
    //TODO Optimization: Look $_SERVER['HTTP_USER_AGENT'] and use history.back() for good browsers like FF.
}
?>
<div class="page"<?php echo $ondblclick;?>>
<?php
if (!(preg_match(VALID_PAGENAME_PATTERN, $this->tag))) { //TODO use central regex library
    echo '<em>'.ERROR_INVALID_PAGENAME.'</em>';
}
elseif ($this->HasAccess("write") && $this->HasAccess("read"))
{
    $newtag = $output = '';
    if (isset($_POST['newtag'])) $newtag = $_POST['newtag'];
    if ($newtag !== '') $this->Redirect($this->Href('edit', $newtag));
    if ($_POST)
    {
        // strip CRLF line endings down to LF to achieve consistency ... plus it saves database space.
        // Note: these codes must remain enclosed in double-quotes to work!
        $body = str_replace("\r\n", "\n", $_POST['body']);

        $body = preg_replace("/\n[ ]{4}/", "\n\t", $body);  // @@@ FIXME: misses first line and multiple sets of four spaces

        // we don't need to escape here, we do that just before display (i.e., treat note just like body!)
        $note = trim($_POST['note']);

        // only if saving:
        if ($_POST['submit'] == 'Store')
        {
            // check for overwriting
            if ($this->page)
            {
                if ($this->page['id'] != $_POST['previous'])
                {
                    $error = ERROR_OVERWRITE_ALERT;
                }
            }
            // check for edit note
            if (($this->config['require_edit_note'] == 1) && $_POST['note'] == '')
            {
                $error .= ERROR_MISSING_EDIT_NOTE;
                $highlight_note= INPUT_ERROR_STYLE;
            }
            // store
            if (!$error)
            {
                // only save if new body differs from old body
                if ($body != $this->page['body']) {

                    // add page (revisions)
                   

//begin edit by FishPete                   
          //$this->SavePage($this->tag, $body, $note);
          if ($_POST['minor_change_flag']=='minor_change') //checkbox 'minor_change_flag' was cklicked by User
                    {
            $this->SavePage($this->tag, $body, $note, '1');// save page as a minor change
          }
          else //checkbox was not clicked
          {
            $this->SavePage($this->tag, $body, $note, '0');// save page as major change
          }                                                
// end edit by FishPete          
                   
          // now we render it internally so we can write the updated link table.
                    $this->ClearLinkTable();
                    $this->StartLinkTracking();
                    $dummy = $this->Header();
                    $dummy .= $this->Format($body);
                    $dummy .= $this->Footer();
                    $this->StopLinkTracking();
                    $this->WriteLinkTable();
                    $this->ClearLinkTable();
                }

                // forward
                $this->Redirect($this->Href());
            }
        }
    }

    // fetch fields
    $previous = $this->page['id'];
    if (isset($_POST['previous'])) $previous = $_POST['previous'];
    if (!isset($body)) $body = $this->page['body'];
    $body = preg_replace("/\n[ ]{4}/", "\n\t", $body);  // @@@ FIXME: misses first line and multiple sets of four spaces - JW 2005-01-16


    if ($result = mysql_query("describe ".$this->config['table_prefix']."pages tag")) {
        $field = mysql_fetch_assoc($result);
        if (preg_match("/varchar\((\d+)\)/", $field['Type'], $matches)) $maxtaglen = $matches[1];
    }
    else
    {
        $maxtaglen = MAX_TAG_LENGTH;
    }

    if (isset($_POST['submit']) && $_POST['submit'] == INPUT_SUBMIT_PREVIEW) # preview output
    {
        $preview_buttons = '<hr />'."\n";
        // We need to escape ALL entity refs before display so we display them _as_ entities instead of interpreting them
        // so we use htmlspecialchars on the edit note (as on the body)
        if ($this->config['require_edit_note'] != 2) //check if edit_notes are enabled
        {
            $preview_buttons .= '<input size="'.MAX_EDIT_NOTE_LENGTH.'" type="text" name="note" value="'.htmlspecialchars($note).'" '.$highlight_note.'/>'.LABEL_EDIT_NOTE.'<br />'."\n";
        }
        $preview_buttons .= '<input name="submit" type="submit" value="'.INPUT_SUBMIT_STORE.'" accesskey="'.ACCESSKEY_STORE.'" />'."\n".
            '<input name="submit" type="submit" value="'.INPUT_SUBMIT_REEDIT.'" accesskey="'.ACCESSKEY_REEDIT.'" id="reedit_id" />'."\n".
            '<input type="button" value="'.INPUT_BUTTON_CANCEL.'" onclick="document.location=\''.$this->href('').'\';" />'."\n";

        $output .= '<div class="previewhead">'.PREVIEW_HEADER.'</div>'."\n";

        $output .= $this->Format($body);

        $output .=
            $this->FormOpen('edit')."\n".
            '<input type="hidden" name="previous" value="'.$previous.'" />'."\n".
            // We need to escape ALL entity refs before display so we display them _as_ entities instead of interpreting them
            // hence htmlspecialchars() instead of htmlspecialchars_ent() which UNescapes entities!
            '<input type="hidden" name="body" value="'.htmlspecialchars($body).'" />'."\n";


        $output .= "<br />\n".$preview_buttons.$this->FormClose()."\n";
    }
    elseif (!$this->page && strlen($this->tag) > $maxtaglen) # rename page
    {
        $this->tag = substr($this->tag, 0, $maxtaglen); // truncate tag to feed a backlinks-handler with the correct value. may be omited. it only works if the link to a backlinks-handler is built in the footer.
        $output  = '<em class="error">'.sprintf(ERROR_TAG_TOO_LONG, $maxtaglen).'</em><br />'."\n";
        $output .= sprintf(MESSAGE_AUTO_RESIZE, INPUT_SUBMIT_RENAME).'<br /><br />'."\n";
        $output .= $this->FormOpen('edit');
        $output .= '<input name="newtag" size="'.MAX_TAG_LENGTH.'" value="'.$this->htmlspecialchars_ent($this->tag).'" />';
        $output .= '<input name="submit" type="submit" value="'.INPUT_SUBMIT_RENAME.'" />'."\n";
        $output .= $this->FormClose();
    }
    else     # edit page
    {
        // display form
        if ($error)
        {
            $output .= '<em class="error">'.$error.'</em>'."\n";
        }

        // append a comment?
        if (isset($_REQUEST['appendcomment']))
        {
            $body = trim($body)."\n\n----\n\n--".$this->GetUserName().' ('.strftime("%c").')';
        }

        $output .=
            $this->FormOpen('edit').
            '<input type="hidden" name="previous" value="'.$previous.'" />'."\n".
            // We need to escape ALL entity refs before display so we display them _as_ entities instead of interpreting them
            // hence htmlspecialchars() instead of htmlspecialchars_ent() which UNescapes entities!
            '<textarea id="body" name="body">'.htmlspecialchars($body).'</textarea><br />'."\n";
            //note add Edit
            // We need to escape ALL entity refs before display so we display them _as_ entities instead of interpreting them
            // so we use htmlspecialchars on the edit note (as on the body)
        if ($this->config['require_edit_note'] != 2) //check if edit_notes are enabled
        {
            $output .= '<input size="'.MAX_EDIT_NOTE_LENGTH.'" type="text" name="note" value="'.htmlspecialchars($note).'" '.$highlight_note.'/> '.LABEL_EDIT_NOTE.'<br />'."\n";
        }
   
 
          $output .= '<input type="checkbox" name="minor_change_flag" value="minor_change"> '.MINOR_CHANGE_FLAG_TEXT.'<br>'."\n";// Edit by FishPete
                 
 
    //finish
        $output .=  '<input name="submit" type="submit" value="'.INPUT_SUBMIT_STORE.'" accesskey="'.ACCESSKEY_STORE.'" /> <input name="submit" type="submit" value="'.INPUT_SUBMIT_PREVIEW.'" accesskey="'.ACCESSKEY_PREVIEW.'" /> <input type="button" value="'.INPUT_BUTTON_CANCEL.'" onclick="document.location=\''.$this->Href('').'\';" />'."\n".
            $this->FormClose();

        if ($this->config['gui_editor'] == 1)
        {
            $output .= '<script type="text/javascript" src="3rdparty/plugins/wikiedit/protoedit.js"></script>'."\n".
                    '<script type="text/javascript" src="3rdparty/plugins/wikiedit/wikiedit2.js"></script>'."\n";
            $output .= '<script type="text/javascript">'."  wE = new WikiEdit(); wE.init('body','WikiEdit','editornamecss');".'</script>'."\n";
        }
    }

    echo $output;
}
else
{
    $message =  '<em>'.ERROR_NO_WRITE_ACCESS.'</em><br />'."\n".
            "<br />\n".
            '<a href="'.$this->Href('showcode').'" title="'.SHOWCODE_LINK_TITLE.'">'.SHOWCODE_LINK.'</a>'.
            "<br />\n";
    echo $message;
}
?>
</div>


the
installableactiontemplate_version => '1.0'
random_setting => 'this will be added to the main config array'
<?php
    echo $this->config['random_setting'];
    echo '<p class="easier">Other typical wiki stuff goes here...</p>';
?>



There is one comment on this page. [Display comment]
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki