Move the orig_file_ext field from resource to resourcerev where
it actually belongs. Add an option to download a specific resource revision as attachment in the view. Fix a bug that occurred when displaying an old revision of a resource. Prepare for proper deletion of the original file and the connected resource in case a revision is deleted; mark any previous revision as head in this case. Left-align the summary label in the resource list view.
This commit is contained in:
parent
58ccb93f2d
commit
d6eb7532fd
@ -133,7 +133,6 @@ class IDF_Form_WikiResourceCreate extends Pluf_Form
|
||||
$resource->summary = trim($this->cleaned_data['summary']);
|
||||
$resource->title = trim($this->cleaned_data['title']);
|
||||
$resource->mime_type = $mimeType;
|
||||
$resource->orig_file_ext = $extension;
|
||||
$resource->create();
|
||||
|
||||
// add the first revision
|
||||
@ -142,6 +141,7 @@ class IDF_Form_WikiResourceCreate extends Pluf_Form
|
||||
$rev->submitter = $this->user;
|
||||
$rev->summary = __('Initial resource creation');
|
||||
$rev->filesize = filesize($tempFile);
|
||||
$rev->fileext = $extension;
|
||||
$rev->create();
|
||||
|
||||
$finalFile = $rev->getFilePath();
|
||||
|
161
src/IDF/Form/WikiResourceUpdate.php
Normal file
161
src/IDF/Form/WikiResourceUpdate.php
Normal file
@ -0,0 +1,161 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of InDefero, an open source project management application.
|
||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
|
||||
#
|
||||
# InDefero 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.
|
||||
#
|
||||
# InDefero is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Update a documentation page.
|
||||
*
|
||||
* This add a corresponding revision.
|
||||
*
|
||||
*/
|
||||
class IDF_Form_WikiResourceUpdate extends Pluf_Form
|
||||
{
|
||||
public $user = null;
|
||||
public $project = null;
|
||||
public $page = null;
|
||||
public $show_full = false;
|
||||
|
||||
|
||||
public function initFields($extra=array())
|
||||
{
|
||||
$this->resource = $extra['resource'];
|
||||
$this->user = $extra['user'];
|
||||
$this->project = $extra['project'];
|
||||
|
||||
$this->fields['summary'] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => true,
|
||||
'label' => __('Description'),
|
||||
'help_text' => __('This one line description is displayed in the list of resources.'),
|
||||
'initial' => $this->resource->summary,
|
||||
'widget_attrs' => array(
|
||||
'maxlength' => 200,
|
||||
'size' => 67,
|
||||
),
|
||||
));
|
||||
$this->fields['file'] = new Pluf_Form_Field_File(
|
||||
array('required' => true,
|
||||
'label' => __('File'),
|
||||
'initial' => '',
|
||||
'max_size' => Pluf::f('max_upload_size', 2097152),
|
||||
'move_function_params' => array('upload_path' => $this->getTempUploadPath(),
|
||||
'upload_path_create' => true,
|
||||
'upload_overwrite' => true),
|
||||
));
|
||||
|
||||
$this->fields['comment'] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => true,
|
||||
'label' => __('Comment'),
|
||||
'help_text' => __('One line to describe the changes you made.'),
|
||||
'initial' => '',
|
||||
'widget_attrs' => array(
|
||||
'maxlength' => 200,
|
||||
'size' => 67,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
public function clean_file()
|
||||
{
|
||||
// FIXME: we do the same in IDF_Form_Upload and a couple of other places as well
|
||||
$extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
|
||||
if (strlen($extra)) $extra .= '|';
|
||||
if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) {
|
||||
@unlink($this->getTempUploadPath().$this->cleaned_data['file']);
|
||||
throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.'));
|
||||
}
|
||||
|
||||
list($mimeType, , $extension) = IDF_FileUtil::getMimeType($this->getTempUploadPath().$this->cleaned_data['file']);
|
||||
if ($this->resource->mime_type != $mimeType) {
|
||||
throw new Pluf_Form_Invalid(sprintf(
|
||||
__('The mime type of the uploaded file "%s" does not match the mime type of this resource "%s"'),
|
||||
$mimeType, $this->resource->mime_type
|
||||
));
|
||||
}
|
||||
$this->cleaned_data['fileext'] = $extension;
|
||||
|
||||
if (md5_file($this->getTempUploadPath().$this->cleaned_data['file']) ===
|
||||
md5_file($this->resource->get_current_revision()->getFilePath())) {
|
||||
throw new Pluf_Form_Invalid(__('The current version of the resource and the uploaded file are equal.'));
|
||||
}
|
||||
return $this->cleaned_data['file'];
|
||||
}
|
||||
|
||||
/**
|
||||
* If we have uploaded a file, but the form failed remove it.
|
||||
*
|
||||
*/
|
||||
function failed()
|
||||
{
|
||||
if (!empty($this->cleaned_data['file'])
|
||||
and file_exists($this->getTempUploadPath().$this->cleaned_data['file'])) {
|
||||
@unlink($this->getTempUploadPath().$this->cleaned_data['file']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the model in the database.
|
||||
*
|
||||
* @param bool Commit in the database or not. If not, the object
|
||||
* is returned but not saved in the database.
|
||||
* @return Object Model with data set from the form.
|
||||
*/
|
||||
function save($commit=true)
|
||||
{
|
||||
if (!$this->isValid()) {
|
||||
throw new Exception(__('Cannot save the model from an invalid form.'));
|
||||
}
|
||||
|
||||
$tempFile = $this->getTempUploadPath().$this->cleaned_data['file'];
|
||||
|
||||
$this->resource->summary = trim($this->cleaned_data['summary']);
|
||||
$this->resource->update();
|
||||
|
||||
// add the new revision
|
||||
$rev = new IDF_Wiki_ResourceRevision();
|
||||
$rev->wikiresource = $this->resource;
|
||||
$rev->submitter = $this->user;
|
||||
$rev->summary = $this->cleaned_data['comment'];
|
||||
$rev->filesize = filesize($tempFile);
|
||||
$rev->fileext = $this->cleaned_data['fileext'];
|
||||
$rev->create();
|
||||
|
||||
$finalFile = $rev->getFilePath();
|
||||
if (!is_dir(dirname($finalFile))) {
|
||||
@unlink($tempFile);
|
||||
$rev->delete();
|
||||
throw new Exception('resource path does not exist');
|
||||
}
|
||||
|
||||
if (!@rename($tempFile, $finalFile)) {
|
||||
@unlink($tempFile);
|
||||
$rev->delete();
|
||||
throw new Exception('could not move resource to final location');
|
||||
}
|
||||
|
||||
return $this->resource;
|
||||
}
|
||||
|
||||
private function getTempUploadPath()
|
||||
{
|
||||
return Pluf::f('upload_path').'/'.$this->project->shortname.'/wiki/temp/';
|
||||
}
|
||||
}
|
@ -95,7 +95,7 @@ class IDF_Views_Wiki
|
||||
$pag->action = array('IDF_Views_Wiki::listResources', array($prj->shortname));
|
||||
$pag->edit_action = array('IDF_Views_Wiki::viewResource', 'shortname', 'title');
|
||||
$pag->forced_where = new Pluf_SQL('project=%s', array($prj->id));
|
||||
$pag->extra_classes = array('right', 'a-c', 'a-c', 'a-c');
|
||||
$pag->extra_classes = array('right', 'a-c', 'left', 'a-c');
|
||||
$list_display = array(
|
||||
'title' => __('Resource Title'),
|
||||
'mime_type' => __('MIME type'),
|
||||
@ -347,7 +347,7 @@ class IDF_Views_Wiki
|
||||
if (isset($request->GET['rev']) and preg_match('/^[0-9]+$/', $request->GET['rev'])) {
|
||||
$revision = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_ResourceRevision',
|
||||
$request->GET['rev']);
|
||||
if ($oldrev->wikiresource != $resource->id or $oldrev->is_head == true) {
|
||||
if ($revision->wikiresource != $resource->id or $revision->is_head == true) {
|
||||
return new Pluf_HTTP_Response_NotFound($request);
|
||||
}
|
||||
}
|
||||
@ -382,7 +382,12 @@ class IDF_Views_Wiki
|
||||
return new Pluf_HTTP_Response_NotFound($request);
|
||||
}
|
||||
|
||||
return new Pluf_HTTP_Response_File($rev->getFilePath(), $res->mime_type);
|
||||
$response = new Pluf_HTTP_Response_File($rev->getFilePath(), $res->mime_type);
|
||||
if (isset($request->GET['attachment']) && $request->GET['attachment']) {
|
||||
$response->headers['Content-Disposition'] =
|
||||
'attachment; filename="'.$res->title.'.'.$rev->fileext.'"';
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -425,7 +430,7 @@ class IDF_Views_Wiki
|
||||
}
|
||||
|
||||
/**
|
||||
* View a documentation page.
|
||||
* Update a documentation page.
|
||||
*/
|
||||
public $updatePage_precond = array('IDF_Precondition::accessWiki',
|
||||
'Pluf_Precondition::loginRequired');
|
||||
@ -475,6 +480,54 @@ class IDF_Views_Wiki
|
||||
$request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a documentation resource.
|
||||
*/
|
||||
public $updateResource_precond = array('IDF_Precondition::accessWiki',
|
||||
'Pluf_Precondition::loginRequired');
|
||||
public function updateResource($request, $match)
|
||||
{
|
||||
$prj = $request->project;
|
||||
// Find the page
|
||||
$sql = new Pluf_SQL('project=%s AND title=%s',
|
||||
array($prj->id, $match[2]));
|
||||
$resources = Pluf::factory('IDF_Wiki_Resource')->getList(array('filter'=>$sql->gen()));
|
||||
if ($resources->count() != 1) {
|
||||
return new Pluf_HTTP_Response_NotFound($request);
|
||||
}
|
||||
$resource = $resources[0];
|
||||
$title = sprintf(__('Update %s'), $resource->title);
|
||||
$revision = $resource->get_current_revision();
|
||||
$params = array('project' => $prj,
|
||||
'user' => $request->user,
|
||||
'resource' => $resource);
|
||||
if ($request->method == 'POST') {
|
||||
$form = new IDF_Form_WikiResourceUpdate(array_merge($request->POST, $request->FILES),
|
||||
$params);
|
||||
if ($form->isValid()) {
|
||||
$page = $form->save();
|
||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource',
|
||||
array($prj->shortname, $resource->title));
|
||||
$request->user->setMessage(sprintf(__('The resource <a href="%s">%s</a> has been updated.'),
|
||||
$url, Pluf_esc($resource->title)));
|
||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listResources',
|
||||
array($prj->shortname));
|
||||
return new Pluf_HTTP_Response_Redirect($url);
|
||||
}
|
||||
} else {
|
||||
$form = new IDF_Form_WikiResourceUpdate(null, $params);
|
||||
}
|
||||
|
||||
return Pluf_Shortcuts_RenderToResponse('idf/wiki/updateResource.html',
|
||||
array(
|
||||
'page_title' => $title,
|
||||
'resource' => $resource,
|
||||
'rev' => $revision,
|
||||
'form' => $form,
|
||||
),
|
||||
$request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a Wiki page.
|
||||
*/
|
||||
|
@ -72,14 +72,6 @@ class IDF_Wiki_Resource extends Pluf_Model
|
||||
'verbose' => __('MIME media type'),
|
||||
'help_text' => __('The MIME media type of the resource.'),
|
||||
),
|
||||
'orig_file_ext' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Varchar',
|
||||
'blank' => false,
|
||||
'size' => 10,
|
||||
'verbose' => __('Original file extension'),
|
||||
'help_text' => __('The original file extension of the uploaded resource.'),
|
||||
),
|
||||
'summary' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Varchar',
|
||||
|
@ -70,6 +70,14 @@ class IDF_Wiki_ResourceRevision extends Pluf_Model
|
||||
'default' => 0,
|
||||
'verbose' => __('file size in bytes'),
|
||||
),
|
||||
'fileext' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Varchar',
|
||||
'blank' => false,
|
||||
'size' => 10,
|
||||
'verbose' => __('File extension'),
|
||||
'help_text' => __('The file extension of the uploaded resource.'),
|
||||
),
|
||||
'submitter' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||
@ -105,6 +113,25 @@ class IDF_Wiki_ResourceRevision extends Pluf_Model
|
||||
return '';
|
||||
}
|
||||
|
||||
function preDelete()
|
||||
{
|
||||
// if we kill off a head revision, ensure that we either mark a previous
|
||||
// revision as head or kill off the resource record as well
|
||||
if ($this->is_head) {
|
||||
$sql = new Pluf_SQL('wikiresource=%s and id!=%s', array($this->wikiresource, $this->id));
|
||||
$revs = Pluf::factory('IDF_Wiki_ResourceRevision')->getList(array('filter'=>$sql->gen(), 'order'=>'id DESC'));
|
||||
if ($revs->count() > 0) {
|
||||
$previous = $revs[0];
|
||||
$previous->is_head = true;
|
||||
$previous->update();
|
||||
} else {
|
||||
$this->get_wikiresource()->delete();
|
||||
}
|
||||
}
|
||||
|
||||
@unlink($this->getFilePath());
|
||||
}
|
||||
|
||||
function preSave($create=false)
|
||||
{
|
||||
if ($this->id == '') {
|
||||
@ -135,7 +162,7 @@ class IDF_Wiki_ResourceRevision extends Pluf_Model
|
||||
function getFilePath()
|
||||
{
|
||||
return sprintf(Pluf::f('upload_path').'/'.$this->get_wikiresource()->get_project()->shortname.'/wiki/res/%d/%d.%s',
|
||||
$this->get_wikiresource()->id, $this->id, $this->get_wikiresource()->orig_file_ext);
|
||||
$this->get_wikiresource()->id, $this->id, $this->fileext);
|
||||
}
|
||||
|
||||
function getFileURL()
|
||||
@ -145,11 +172,6 @@ class IDF_Wiki_ResourceRevision extends Pluf_Model
|
||||
array($prj->shortname, $this->id));
|
||||
}
|
||||
|
||||
function preDelete()
|
||||
{
|
||||
@unlink($this->getFilePath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page revisions which contain references to this resource revision
|
||||
*/
|
||||
|
46
src/IDF/templates/idf/wiki/updateResource.html
Normal file
46
src/IDF/templates/idf/wiki/updateResource.html
Normal file
@ -0,0 +1,46 @@
|
||||
{extends "idf/wiki/base.html"}
|
||||
{block docclass}yui-t2{/block}
|
||||
{block body}
|
||||
|
||||
{if $form.errors}
|
||||
<div class="px-message-error">
|
||||
<p>{trans 'The form contains some errors. Please correct them to update the page.'}</p>
|
||||
{if $form.get_top_errors}
|
||||
{$form.render_top_errors|unsafe}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<form method="post" enctype="multipart/form-data" action="." >
|
||||
<table class="form" summary="">
|
||||
<tr>
|
||||
<th><strong>{$form.f.summary.labelTag}:</strong></th>
|
||||
<td>{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if}
|
||||
{$form.f.summary|unsafe}<br />
|
||||
<span class="helptext">{$form.f.summary.help_text}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><strong>{$form.f.file.labelTag}:</strong></th>
|
||||
<td>{if $form.f.file.errors}{$form.f.file.fieldErrors}{/if}
|
||||
{$form.f.file|unsafe}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><strong>{$form.f.comment.labelTag}:</strong></th>
|
||||
<td>{if $form.f.comment.errors}{$form.f.comment.fieldErrors}{/if}
|
||||
{$form.f.comment|unsafe}<br />
|
||||
<span class="helptext">{$form.f.comment.help_text}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>{* float left is a fix for Firefox < 3.5 *}
|
||||
<span style="float: left;"> <input type="submit" value="{trans 'Update Resource'}" name="submit" /> | <a href="{url 'IDF_Views_Wiki::viewResource', array($project.shortname, $resource.title)}">{trans 'Cancel'}</a></span>{if $isOwner or $isAdmin or $isMember}
|
||||
{aurl 'url', 'IDF_Views_Wiki::deleteResource', array($project.shortname, $resource.id)}
|
||||
<span class="dellink"><a href="{$url}" title="{trans 'Delete this resource'}"><img src="{media '/idf/img/trash.png'}" style="vertical-align: text-bottom;" alt="{trans 'Trash'}" /></a> <a href="{$url}" title="{trans 'Delete this resource'}">{trans 'Delete this resource'}</a></span>{/if}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
{/block}
|
@ -8,7 +8,7 @@
|
||||
|
||||
{block body}
|
||||
{if !$rev.is_head}
|
||||
{ashowuser 'submitter', $oldrev.get_submitter(), $request}{aurl 'url', 'IDF_Views_Wiki::viewResource', array($project.shortname, $resource.title)}
|
||||
{ashowuser 'submitter', $rev.get_submitter(), $request}{aurl 'url', 'IDF_Views_Wiki::viewResource', array($project.shortname, $resource.title)}
|
||||
<div class="old-rev">
|
||||
<p>{blocktrans}You are looking at an old revision of the resource
|
||||
<a href="{$url}">{$resource.title}</a>. This revision was created
|
||||
@ -21,9 +21,11 @@ by {$submitter}.{/blocktrans}</p>
|
||||
|
||||
<p class="preview">{$rev.render()|unsafe}</p>
|
||||
|
||||
{aurl 'url', 'IDF_Views_Wiki::rawResource', array($project.shortname, $rev.id), array('attachment' => 1)}
|
||||
<ul>
|
||||
<li>{trans 'File size'}: {$rev.filesize|size}</li>
|
||||
<li>{trans 'MIME type'}: {$resource.mime_type}</li>
|
||||
<li><a href="{$url}">{trans 'Download this file'}</a></li>
|
||||
</ul>
|
||||
{if ($isOwner or $isAdmin) and !$rev.is_head}{aurl 'url', 'IDF_Views_Wiki::deleteResourceRev', array($project.shortname, $rev.id)}
|
||||
<p class="delp"><a href="{$url}" title="{trans 'Delete this revision'}"><img src="{media '/idf/img/trash.png'}" style="vertical-align: text-bottom;" alt="{trans 'Trash'}" /></a> <a href="{$url}">{trans 'Delete this revision'}</a></p>
|
||||
|
Loading…
Reference in New Issue
Block a user