Indefero

Indefero Commit Details

Date:2008-11-12 20:40:58 (5 years 5 months ago)
Author:Loic d'Anterroches
Branch:dev, develop, feature-issue_links, feature.better-home, feature.content-md5, feature.diff-whitespace, feature.download-md5, feature.issue-links, feature.issue-of-others, feature.issue-summary, feature.search-filter, feature.webrepos, feature.wiki-default-page, master, release-1.1, release-1.2, release-1.3
Commit:fa5fe0d6100133b9a4afe9e939070c3bcde69e8a
Parents: 9404309a0ae6795f7c83dde4379140b2cfde6695
Message:Fixed ticket 36, attach a file to a ticket.

It is now possible to attach a file to a ticket.
Changes:
Asrc/IDF/IssueFile.php (full)
Asrc/IDF/Migrations/3Attachments.php (full)
Msrc/IDF/Form/IssueCreate.php (2 diffs)
Msrc/IDF/Form/IssueUpdate.php (2 diffs)
Msrc/IDF/Migrations/Install.php (1 diff)
Msrc/IDF/Views/Issue.php (3 diffs)
Msrc/IDF/conf/idf.php-dist (1 diff)
Msrc/IDF/conf/views.php (1 diff)
Msrc/IDF/relations.php (1 diff)
Msrc/IDF/templates/issues/create.html (1 diff)
Msrc/IDF/templates/issues/view.html (2 diffs)
Mwww/media/idf/css/style.css (1 diff)

File differences

src/IDF/Form/IssueCreate.php
6464
6565
6666
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
6787
6888
6989
......
226246
227247
228248
249
250
251
252
253
254
255
256
257
229258
230259
231260
'rows' => 13,
),
));
$upload_path = Pluf::f('upload_issue_path', false);
if (false === $upload_path) {
throw new Pluf_Exception_SettingError(__('The "upload_issue_path" configuration variable was not set.'));
}
$md5 = md5(rand().microtime().Pluf_Utils::getRandomString());
// We add .dummy to try to mitigate security issues in the
// case of someone allowing the upload path to be accessible
// to everybody.
$filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
$this->fields['attachment'] = new Pluf_Form_Field_File(
array('required' => false,
'label' => __('Attach a file'),
'move_function_params' =>
array('upload_path' => $upload_path,
'upload_path_create' => true,
'file_name' => $filename,
)
)
);
if ($this->show_full) {
$this->fields['status'] = new Pluf_Form_Field_Varchar(
array('required' => true,
$comment->content = $this->cleaned_data['content'];
$comment->submitter = $this->user;
$comment->create();
// If we have a file, create the IDF_IssueFile and attach
// it to the comment.
if ($this->cleaned_data['attachment']) {
$file = new IDF_IssueFile();
$file->attachment = $this->cleaned_data['attachment'];
$file->submitter = $this->user;
$file->comment = $comment;
$file->create();
}
return $issue;
}
throw new Exception(__('Cannot save the model from an invalid form.'));
src/IDF/Form/IssueUpdate.php
6060
6161
6262
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
6383
6484
6585
......
257277
258278
259279
280
281
282
283
284
285
286
260287
261288
262289
'rows' => 9,
),
));
$upload_path = Pluf::f('upload_issue_path', false);
if (false === $upload_path) {
throw new Pluf_Exception_SettingError(__('The "upload_issue_path" configuration variable was not set.'));
}
$md5 = md5(rand().microtime().Pluf_Utils::getRandomString());
// We add .dummy to try to mitigate security issues in the
// case of someone allowing the upload path to be accessible
// to everybody.
$filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
$this->fields['attachment'] = new Pluf_Form_Field_File(
array('required' => false,
'label' => __('Attach a file'),
'move_function_params' =>
array('upload_path' => $upload_path,
'upload_path_create' => true,
'file_name' => $filename,
)
)
);
if ($this->show_full) {
$this->fields['status'] = new Pluf_Form_Field_Varchar(
array('required' => true,
$this->issue->submitter != $this->user->id) {
$this->issue->setAssoc($this->user); // interested user.
}
if ($this->cleaned_data['attachment']) {
$file = new IDF_IssueFile();
$file->attachment = $this->cleaned_data['attachment'];
$file->submitter = $this->user;
$file->comment = $comment;
$file->create();
}
return $this->issue;
}
throw new Exception(__('Cannot save the model from an invalid form.'));
src/IDF/IssueFile.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?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 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 ***** */
/**
* A file uploaded with an issue or a comment to an issue.
*
*/
class IDF_IssueFile extends Pluf_Model
{
public $_model = __CLASS__;
function init()
{
$this->_a['table'] = 'idf_issuefiles';
$this->_a['model'] = __CLASS__;
$this->_a['cols'] = array(
// It is mandatory to have an "id" column.
'id' =>
array(
'type' => 'Pluf_DB_Field_Sequence',
//It is automatically added.
'blank' => true,
),
'comment' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
'model' => 'IDF_IssueComment',
'blank' => false,
'verbose' => __('comment'),
'relate_name' => 'attachment',
),
'submitter' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
'model' => 'Pluf_User',
'blank' => false,
'verbose' => __('submitter'),
),
'filename' =>
array(
'type' => 'Pluf_DB_Field_Varchar',
'blank' => true,
'size' => 100,
'verbose' => __('file name'),
),
'attachment' =>
array(
'type' => 'Pluf_DB_Field_File',
'blank' => false,
'verbose' => __('the file'),
),
'filesize' =>
array(
'type' => 'Pluf_DB_Field_Integer',
'blank' => true,
'verbose' => __('file size'),
'help_text' => 'Size in bytes.',
),
'type' =>
array(
'type' => 'Pluf_DB_Field_Varchar',
'blank' => false,
'size' => 10,
'verbose' => __('type'),
'choices' => array(
__('Image') => 'img',
__('Other') => 'other',
),
'default' => 'other',
'help_text' => 'The type is to display a thumbnail of the image.',
),
'creation_dtime' =>
array(
'type' => 'Pluf_DB_Field_Datetime',
'blank' => true,
'verbose' => __('creation date'),
),
'modif_dtime' =>
array(
'type' => 'Pluf_DB_Field_Datetime',
'blank' => true,
'verbose' => __('modification date'),
),
);
}
function preSave($create=false)
{
if ($this->id == '') {
$this->creation_dtime = gmdate('Y-m-d H:i:s');
$file = Pluf::f('upload_issue_path').'/'.$this->attachment;
$this->filesize = filesize($file);
// remove .dummy
$this->filename = substr(basename($file), 0, -6);
$img_extensions = array('jpeg', 'jpg', 'png', 'gif');
$info = pathinfo($this->filename);
if (in_array(strtolower($info['extension']), $img_extensions)) {
$this->type = 'img';
} else {
$this->type = 'other';
}
}
$this->modif_dtime = gmdate('Y-m-d H:i:s');
}
}
src/IDF/Migrations/3Attachments.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?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 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 ***** */
/**
* Add the download of files.
*/
function IDF_Migrations_3Attachments_up($params=null)
{
$models = array(
'IDF_IssueFile',
);
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
foreach ($models as $model) {
$schema->model = new $model();
$schema->createTables();
}
}
function IDF_Migrations_3Attachments_down($params=null)
{
$models = array(
'IDF_IssueFile',
);
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
foreach ($models as $model) {
$schema->model = new $model();
$schema->dropTables();
}
}
src/IDF/Migrations/Install.php
3737
3838
3939
40
4041
4142
4243
'IDF_Conf',
'IDF_Upload',
'IDF_Search_Occ',
'IDF_IssueFile',
);
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
src/IDF/Views/Issue.php
141141
142142
143143
144
144
145
146
145147
146148
147149
......
246248
247249
248250
249
251
252
253
250254
251255
252256
......
307311
308312
309313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
310330
311331
312332
'project' => $prj,
'user' => $request->user);
if ($request->method == 'POST') {
$form = new IDF_Form_IssueCreate($request->POST, $params);
$form = new IDF_Form_IssueCreate(array_merge($request->POST,
$request->FILES),
$params);
if ($form->isValid()) {
$issue = $form->save();
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::index',
'issue' => $issue,
);
if ($request->method == 'POST') {
$form = new IDF_Form_IssueUpdate($request->POST, $params);
$form = new IDF_Form_IssueUpdate(array_merge($request->POST,
$request->FILES),
$params);
if ($form->isValid()) {
$issue = $form->save();
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::index',
$request);
}
/**
* Download a given attachment.
*/
public $getAttachment_precond = array('IDF_Precondition::accessIssues');
public function getAttachment($request, $match)
{
$prj = $request->project;
$attach = Pluf_Shortcuts_GetObjectOr404('IDF_IssueFile', $match[2]);
$prj->inOr404($attach->get_comment()->get_issue());
$res = new Pluf_HTTP_Response_File(Pluf::f('upload_issue_path').'/'.$attach->attachment,
'application/octet-stream');
$res->headers['Content-Disposition'] = 'attachment; filename="'.$attach->filename.'"';
return $res;
}
/**
* View list of issues for a given project with a given status.
*/
src/IDF/conf/idf.php-dist
8787
8888
8989
90
91
92
93
94
95
96
9097
9198
9299
$cfg['url_upload'] = 'http://projects/ceondo.com/media/upload';
$cfg['upload_path'] = '/path/to/media/upload';
#
# The following path *MUST NOT* be accessible through a web browser
# as user will be able to upload .html, .php files and this can
# create *TERRIBLE* security issues.
#
$cfg['upload_issue_path'] = '/path/to/attachments';
$cfg['login_success_url'] = $cfg['url_base'].$cfg['idf_base'];
$cfg['after_logout_page'] = $cfg['url_base'].$cfg['idf_base'];
src/IDF/conf/views.php
133133
134134
135135
136
137
138
139
140
141
136142
137143
138144
'model' => 'IDF_Views_Issue',
'method' => 'myIssues');
$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/attachment/(\d+)/(.*)$#',
'base' => $base,
'priority' => 4,
'model' => 'IDF_Views_Issue',
'method' => 'getAttachment');
// ---------- SCM ----------------------------------------
$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/tree/(\w+)/$#',
src/IDF/relations.php
2626
2727
2828
29
2930
3031
3132
$m['IDF_Issue'] = array('relate_to' => array('IDF_Project', 'Pluf_User', 'IDF_Tag'),
'relate_to_many' => array('IDF_Tag', 'Pluf_User'));
$m['IDF_IssueComment'] = array('relate_to' => array('IDF_Issue', 'Pluf_User'));
$m['IDF_IssueFile'] = array('relate_to' => array('IDF_IssueComment', 'Pluf_User'));
$m['IDF_Upload'] = array('relate_to' => array('IDF_Project', 'Pluf_User'),
'relate_to_many' => array('IDF_Tag'));
$m['IDF_Search_Occ'] = array('relate_to' => array('IDF_Project'),);
src/IDF/templates/issues/create.html
2323
2424
2525
26
27
28
29
30
31
2632
2733
2834
<td>{if $form.f.content.errors}{$form.f.content.fieldErrors}{/if}
{$form.f.content|unsafe}
</td>
</tr>
<tr>
<th>{$form.f.attachment.labelTag}:</th>
<td>{if $form.f.attachment.errors}{$form.f.attachment.fieldErrors}{/if}
{$form.f.attachment|unsafe}
</td>
</tr>{if $isOwner or $isMember}
<tr>
<th><strong>{$form.f.status.labelTag}:</strong></th>
src/IDF/templates/issues/view.html
1515
1616
1717
18
18
19
20
21
22
23
1924
2025
2126
......
5459
5560
5661
57
62
63
64
65
66
67
5868
5969
6070
{/if}
<pre class="issue-comment-text">{if strlen($c.content) > 0}{issuetext $c.content, $request}{else}<i>{trans '(No comments were given for this change.)'}</i>{/if}</pre>
{assign $attachments = $c.get_attachment_list()}
{if $attachments.count() > 0}
<div class="attach">
<ul>
{foreach $attachments as $a}<li><a href="{url 'IDF_Views_Issue::getAttachment', array($project.shortname, $a.id, $a.filename)}">{$a.filename}</a> - {$a.filesize|size}</li>{/foreach}
</ul></div>{/if}
{if $i> 0 and $c.changedIssue()}
<div class="issue-changes">
{foreach $c.changes as $w => $v}
{$form.f.content|unsafe}
</td>
</tr>
{if $isOwner or $isMember}
<tr>
<th>{$form.f.attachment.labelTag}:</th>
<td>{if $form.f.attachment.errors}{$form.f.attachment.fieldErrors}{/if}
{$form.f.attachment|unsafe}
</td>
</tr>{if $isOwner or $isMember}
<tr>
<th><strong>{$form.f.summary.labelTag}:</strong></th>
<td>{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if}
www/media/idf/css/style.css
228228
229229
230230
231
232
233
234
235
231236
232237
233238
hr { visibility: hidden; }
div.attach {
border-top: 2px solid #d3d7cf;
width: 40%;
}
textarea {
font-family: monospace;
}

Archive Download the corresponding diff file