Revision [16032]

This is an old revision of WikiFile made by ChewBakka on 2007-02-02 17:31:14.

 

In Wikka, almost everything is a page.

For example, a category is a page to which other pages link. If you want to stat a new category, you do not need to learn something new - just create the category page and link your pages to it.

Here I would like to present a solution where files are represented by pages too. I will first give a description on how to use it, then the necessary pieces of code.

Description

On the server side, there are no file names any more - any file is "contained" in a particular page and referenced using only the page name. If the file is an image, it is visible in the page (through the { {file} } action) along with explaining text which is writen in the page as usual. The access rights for viewing and mpdifying files are just the page rights.

I order to add a screenshot (or any other file) to your wiki, you will first create a page for it. This is something youshould do anyway, because you should write some explaining text about your screenshot. The page should include a { {file} } action to your page, although this is not necessary for being a file page - it is just for file pages what the { {category} } action is for category pages.

The page footer reads Edit page :: File :: Stats :: Referrers and so on - note the addition of File. Clicking on it opens the file handler, which displays informations about the file (if there is already a file in the page) and an upload form; uploading a file into a page which already contains a file causes the old file to be replaced with the new file - there can be only one file per page.

Code

Below are five pieces of code. The files Wakka.class.php and footer.php are parts of the Wikka software; I have extended them without changing existing functions (hopefully). I have also added two files: actions/file.php and handlers/page/file.php.

Here comes the modification of actions/footer.php; lines 5,6,7 are added, anything else remains unchanged. This adds File:: to the footer.
  1. <div class="footer">
  2. <?php
  3.     echo $this->FormOpen("", "TextSearch", "get");
  4.     echo $this->HasAccess("write") ? "<a href=\"".$this->href("edit")."\" title=\"Click to edit this page\">Edit page</a> ::\n" : "";
  5.     echo ($this->HasAccess("write") || $this->HasAccess("read"))
  6.         ? '<a href="' . $this->href("file"). '" title="Click to view/edit the file in this page">File</a> ::' . "\n"
  7.         : '';
  8.     // ...


In Wakka.class.php I have extended the FormOpen function, because the html form must include an encoding attribute if you want to upload files. I have added a fourth parameter named $withFiles. This is the extended function:
  1.     function FormOpen($method = "", $tag = "", $formMethod = "post", $withFile = false )
  2.     {
  3.         $enctype = '';
  4.         if ($withFile) $enctype = ' enctype="multipart/form-data"';
  5.         $result = "<form action=\"".$this->Href($method, $tag)."\" method=\"".$formMethod."\"$enctype>\n";
  6.         if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wakka\" value=\"".$this->MiniHref($method, $tag)."\" />\n";
  7.         return $result;
  8.     }


Also in Wakka.class.php I have added four functions which perform the most basic file handling without access right checking. (One function is actually only a workaround for probllems with mime_content_type() which I experienced). I have just added them and the end of the class, and they look like this:
  1.     /**
  2.      * Return mime type for the given file extension.
  3.      * Slow, but useful if PHP's mime_content_type() cannot be used.
  4.      * Uses Wikka's mime_types.txt and some hardcoded associations.
  5.      *
  6.      * @author  {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
  7.      * @input   $extension file extension, e.g. 'png', 'jpg', 'ogg'
  8.      * @output  mime content type, e.g. 'image/png', or empty string.
  9.      */
  10.     function MimeTypeFromExtension( $extension )
  11.     {
  12.         // Quick resonse for most frequently used file types
  13.         if ($extension == 'png') return 'image/png';
  14.         if ($extension == 'jpg') return 'image/jpeg';
  15.         if ($extension == 'ogg') return 'application/ogg';
  16.         // If not recoginzed, use mime_types.txt
  17.         if (file_exists( $this->config['mime_types'] ))
  18.         {
  19.             foreach (explode("\n",file_get_contents($this->config['mime_types'])) as $line)
  20.             {
  21.                 $line = trim($line);
  22.                 if ($line != '' && substr($line,0,1) != '#' && strpos($line,$extension))
  23.                 {
  24.                     $a = explode( ' ', str_replace(chr(9),' ',$line) );
  25.                     if (in_array( $extension, $a ))
  26.                     {
  27.                         return $a[0];
  28.                     }
  29.                 }
  30.             }
  31.         }
  32.         return ''; // if nothing was found
  33.     }
  34.  
  35.     /**
  36.      * Return an array describing the file which is stored in a page.
  37.      *
  38.      * @author  {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
  39.      * @input   $tag name of the page; default = current page.
  40.      * @output  Array or (if no file in page) null. Keys:
  41.      *          extension     file extension, e.g. 'png', 'jpg', 'ogg'
  42.      *          content-type  mime content type, e.g. 'image/png'
  43.      *          uploaded      when and who,. e.g. '2007-01-31 ChewBakka'
  44.      *          image         'yes' or 'no'
  45.      *          width         Width in pixels (images only)
  46.      *          height        Height in pixels (images only)
  47.      *          filename      PageName.extension
  48.      *          path          upload_path/PageName.extension
  49.      *          url           'http://..../PageName/file?action=get'
  50.      */
  51.     function GetFile( $tag = '' )
  52.     {
  53.         $data = null; // this variable will be returned
  54.         if (!$tag) $tag = $this->tag;
  55.         $metafile = $this->config['upload_path'].'/'.$tag.'.file';  // metadata
  56.         if (file_exists($metafile) && $contents = file_get_contents($metafile))
  57.         {
  58.             $lines = explode( "\n", $contents );
  59.             // Lines look like "key: value" -> convert into array
  60.             $data = array(
  61.                 'extension'    => '',
  62.                 'content-type' => '',
  63.                 'uploaded'     => '',
  64.                 'image'        => 'false',
  65.                 'width'        => '',
  66.                 'height'       => '',
  67.                 'filename'     => '',
  68.                 'path'         => '',
  69.                 'url'          => ''
  70.             );
  71.             foreach ($lines as $line)
  72.             {
  73.                 $a = explode( ":", trim($line), 2 );
  74.                 if( count($a) == 2 )
  75.                 {
  76.                     $data[ $a[0] ] = trim( $a[1] );
  77.                 }
  78.             }
  79.             // Convenient attributes which can not be stored permanently
  80.             $data['filename'] = $tag . '.' . $data['extension'];
  81.             $data['path'] = $this->config['upload_path'] .'/' . $data['filename'];
  82.             $data['url'] = $this->config['base_url'] . $tag .  '/file' .
  83.                 ($this->config['rewrite_mode']=='1' ? '?' : '&') .
  84.                 'action=get';
  85.             // Final check: file must exist.
  86.             if (! file_exists( $data['path'] ) )
  87.             {
  88.                 $data = null;
  89.             }
  90.         }
  91.         return $data;
  92.     }
  93.  
  94.     /**
  95.      * Remove the file from the current page.
  96.      *
  97.      * @author  {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
  98.      * @input   none
  99.      * @output  none
  100.      */
  101.     function RemoveFile()
  102.     {
  103.         if ($data = $this->GetFile())
  104.         {
  105.             unlink( $this->config['upload_path'] . '/' . $this->tag . '.file' );
  106.             unlink( $this->config['upload_path'] . '/' . $data['filename'] );
  107.         }
  108.     }
  109.  
  110.     /**
  111.      * Store an http-uploaded file in the current page.
  112.      * Any previous file will be replaced with the new file.
  113.      *
  114.      * @author  {@link http://wikkawiki.org/ChewBakka ChewBakka} (first draft)
  115.      * @input   $uploaded_file An item from PHP's $_FILES array (see there)
  116.      * @output  None
  117.      */
  118.     function SaveFile( $uploaded_file )
  119.     {
  120.         $this->RemoveFile();
  121.         $pathinfo = pathinfo( $uploaded_file['name'] );
  122.         $extension = strtolower( $pathinfo['extension'] );
  123.         $pathname = $this->config['upload_path'] . '/' . $this->tag;
  124.         $path = $pathname . '/' . $extension;
  125.         if (move_uploaded_file( $uploaded_file['tmp_name'], $path ))
  126.         {
  127.             $contenttype = mime_content_type($path);
  128.             if( ! $contenttype  )
  129.             {
  130.                 $contenttype = $this->MimeTypeFromExtension( $extension );
  131.             }
  132.             // build an array with metadata
  133.             $data = array(
  134.                 'extension'    => $extension,
  135.                 'content-type' => $contenttype,
  136.                 'uploaded'     => date('Y-m-d H:i') . ' ' . $this->GetUserName(),
  137.                 'image'        => 'false'
  138.             );
  139.             if( substr($data['content-type'],0,6) == 'image/'  )
  140.             {
  141.                 $data['image'] = 'true';
  142.                 $size = getimagesize($path);
  143.                 $data['width']  = $size[0];
  144.                 $data['height'] = $size[1];
  145.             }
  146.             // Create metadata file
  147.             $contents = '';
  148.             foreach ($data as $key => $value)
  149.             {
  150.                 $contents .= ($key . ': ' . $value . "\n");
  151.             }
  152.             file_put_contents( $pathname . '.file', $contents );
  153.         }
  154.     }
There are no comments on this page.
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki